From f7fb89d957e5a022f27b7dff573e3256dba2c0f2 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sun, 31 Aug 2025 03:18:32 +0900 Subject: [PATCH] lsfd: revise the code disabling hyperlinks In the original code, the code was at file.c. This change lifts up the code to upper layer. As a result the fill_column method of struct file becomes simple. As a side effect. this change disables hyperlinks for the entries of UNKN type (e.g. eventpool, or pidfd). This is a bug fix. Signed-off-by: Masatake YAMATO --- lsfd-cmd/bdev.c | 3 +- lsfd-cmd/cdev.c | 3 +- lsfd-cmd/fifo.c | 3 +- lsfd-cmd/file.c | 35 +++----------- lsfd-cmd/lsfd.c | 46 ++++++++++++++----- lsfd-cmd/lsfd.h | 3 +- lsfd-cmd/sock.c | 3 +- lsfd-cmd/unkn.c | 3 +- .../lsfd/option-hyperlink-UNKN-type-file | 7 +++ tests/ts/lsfd/option-hyperlink | 18 ++++++++ 10 files changed, 73 insertions(+), 51 deletions(-) create mode 100644 tests/expected/lsfd/option-hyperlink-UNKN-type-file diff --git a/lsfd-cmd/bdev.c b/lsfd-cmd/bdev.c index fc1bb6880..934c73335 100644 --- a/lsfd-cmd/bdev.c +++ b/lsfd-cmd/bdev.c @@ -33,8 +33,7 @@ static bool bdev_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file __attribute__((__unused__)), struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; const char *partition, *devdrv; diff --git a/lsfd-cmd/cdev.c b/lsfd-cmd/cdev.c index 0f4d34fe7..1405f4c65 100644 --- a/lsfd-cmd/cdev.c +++ b/lsfd-cmd/cdev.c @@ -67,8 +67,7 @@ static bool cdev_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { struct cdev *cdev = (struct cdev *)file; const struct cdev_ops *ops = cdev->cdev_ops; diff --git a/lsfd-cmd/fifo.c b/lsfd-cmd/fifo.c index 45821630c..b78e6d487 100644 --- a/lsfd-cmd/fifo.c +++ b/lsfd-cmd/fifo.c @@ -45,8 +45,7 @@ static bool fifo_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; diff --git a/lsfd-cmd/file.c b/lsfd-cmd/file.c index 841991e6e..2857c9410 100644 --- a/lsfd-cmd/file.c +++ b/lsfd-cmd/file.c @@ -116,8 +116,7 @@ static bool abst_fill_column(struct proc *proc, struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; @@ -261,8 +260,7 @@ static bool error_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file __attribute__((__unused__)), struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; const char *ename; @@ -303,8 +301,7 @@ static bool readlink_error_fill_column(struct proc *proc __attribute__((__unused struct file *file __attribute__((__unused__)), struct libscols_line *ln __attribute__((__unused__)), int column_id, - size_t column_index __attribute__((__unused__)), - const char *uri __attribute__((__unused__))) + size_t column_index __attribute__((__unused__))) { switch(column_id) { case COL_NAME: @@ -405,8 +402,7 @@ static bool file_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; mode_t ftype; @@ -424,11 +420,6 @@ static bool file_fill_column(struct proc *proc __attribute__((__unused__)), *d = '('; if (r) err(EXIT_FAILURE, _("failed to add output data")); - if (uri) { - struct libscols_cell *ce = scols_line_get_cell(ln, column_index); - if (ce) - scols_cell_disable_uri(ce, 1); - } return true; } } @@ -437,15 +428,6 @@ static bool file_fill_column(struct proc *proc __attribute__((__unused__)), if (file->name && scols_line_set_data(ln, column_index, file->name)) err(EXIT_FAILURE, _("failed to add output data")); - - ftype = file->stat.st_mode & S_IFMT; - if (uri && (!file->name || *file->name != '/' - || (ftype != S_IFREG && ftype != S_IFDIR) - || file->stat.st_nlink == 0)) { - struct libscols_cell *ce = scols_line_get_cell(ln, column_index); - if (ce) - scols_cell_disable_uri(ce, 1); - } return true; case COL_STTYPE: case COL_TYPE: @@ -815,8 +797,7 @@ static bool nsfs_file_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { struct nsfs_file *nsfs_file = (struct nsfs_file *)file; char *name = NULL; @@ -893,8 +874,7 @@ static bool mqueue_file_fill_column(struct proc *proc __attribute__((__unused__) struct file *file __attribute__((__unused__)), struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { switch (column_id) { case COL_TYPE: @@ -1006,8 +986,7 @@ static bool pidfs_file_fill_column(struct proc *proc __attribute__((__unused__)) struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { struct pidfs_file *pidfs_file = (struct pidfs_file *)file; char *buf = NULL; diff --git a/lsfd-cmd/lsfd.c b/lsfd-cmd/lsfd.c index bca615abd..d6d6a4f01 100644 --- a/lsfd-cmd/lsfd.c +++ b/lsfd-cmd/lsfd.c @@ -171,6 +171,7 @@ struct colinfo { int flags; int json_type; const char *help; + bool hyperlink; }; /* columns descriptions */ @@ -264,7 +265,8 @@ static const struct colinfo infos[] = { N_("list of monitoring inodes (raw, don't decode devices)") }, [COL_KNAME] = { "KNAME", 0.4, SCOLS_FL_TRUNC, SCOLS_JSON_STRING, - N_("name of the file (raw)") }, + N_("name of the file (raw)"), + .hyperlink = true }, [COL_KTHREAD] = { "KTHREAD", 0, SCOLS_FL_RIGHT, SCOLS_JSON_BOOLEAN, N_("opened by a kernel thread") }, @@ -285,7 +287,8 @@ static const struct colinfo infos[] = { N_("access mode (rwx)") }, [COL_NAME] = { "NAME", 0.4, SCOLS_FL_TRUNC, SCOLS_JSON_STRING, - N_("name of the file (cooked)") }, + N_("name of the file (cooked)"), + .hyperlink = true }, [COL_NETLINK_GROUPS] = { "NETLINK.GROUPS", 0, SCOLS_FL_RIGHT, SCOLS_JSON_NUMBER, N_("netlink multicast groups") }, @@ -575,7 +578,7 @@ static const struct counter_spec default_counter_specs[] = { struct filler_data { struct proc *proc; struct file *file; - const char *uri; + bool hyperlink_enabled; }; struct lsfd_control { @@ -664,7 +667,7 @@ static struct libscols_column *add_column(struct libscols_table *tb, scols_column_set_safechars(cl, "\n"); } if (!(extra & SCOLS_FL_HIDDEN) && uri && - (id == COL_NAME || id == COL_KNAME)) + col->hyperlink) scols_column_set_uri(cl, uri); } @@ -1482,20 +1485,40 @@ void add_endpoint(struct ipc_endpoint *endpoint, struct ipc *ipc) } +static bool should_disable_hyperlink(const struct file * file) +{ + mode_t ftype = file->stat.st_mode & S_IFMT; + + return (file->name == NULL + || file->stat.st_nlink == 0 + || *file->name != '/' + || (ftype != S_IFREG && ftype != S_IFDIR)); +} + static void fill_column(struct proc *proc, struct file *file, struct libscols_line *ln, int column_id, size_t column_index, - const char *uri __attribute__((__unused__))) + bool hyperlink_enabled) { const struct file_class *class = file->class; while (class) { if (class->fill_column && class->fill_column(proc, file, ln, - column_id, column_index, uri)) + column_id, column_index)) { + + if (hyperlink_enabled + && infos[column_id].hyperlink + && should_disable_hyperlink(file)) { + struct libscols_cell *ce = scols_line_get_cell(ln, column_index); + if (ce) + scols_cell_disable_uri(ce, 1); + } + break; + } class = class->super; } } @@ -1509,14 +1532,14 @@ static int filter_filler_cb( struct filler_data *fid = (struct filler_data *) userdata; fill_column(fid->proc, fid->file, ln, get_column_id(colnum), colnum, - fid->uri); + fid->hyperlink_enabled); return 0; } static void convert_file(struct proc *proc, struct file *file, struct libscols_line *ln, - const char *uri __attribute__((__unused__))) + bool hyperlink_enabled) { size_t i; @@ -1524,13 +1547,14 @@ static void convert_file(struct proc *proc, for (i = 0; i < ncolumns; i++) { if (scols_line_is_filled(ln, i)) continue; - fill_column(proc, file, ln, get_column_id(i), i, uri); + fill_column(proc, file, ln, get_column_id(i), i, hyperlink_enabled); } } static void convert(struct list_head *procs, struct lsfd_control *ctl) { struct list_head *p; + bool hyperlink_enabled = (ctl->uri != NULL); list_for_each (p, procs) { struct proc *proc = list_entry(p, struct proc, procs); @@ -1548,7 +1572,7 @@ static void convert(struct list_head *procs, struct lsfd_control *ctl) struct filler_data fid = { .proc = proc, .file = file, - .uri = ctl->uri, + .hyperlink_enabled = hyperlink_enabled, }; scols_filter_set_filler_cb(ctl->filter, @@ -1561,7 +1585,7 @@ static void convert(struct list_head *procs, struct lsfd_control *ctl) } } - convert_file(proc, file, ln, ctl->uri); + convert_file(proc, file, ln, hyperlink_enabled); if (!ctl->ct_filters) continue; diff --git a/lsfd-cmd/lsfd.h b/lsfd-cmd/lsfd.h index 4aa7bf2bb..916ad2d76 100644 --- a/lsfd-cmd/lsfd.h +++ b/lsfd-cmd/lsfd.h @@ -235,8 +235,7 @@ struct file_class { struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri); + size_t column_index); int (*handle_fdinfo)(struct file *file, const char *key, const char* value); void (*attach_xinfo)(struct file *file); void (*initialize_content)(struct file *file); diff --git a/lsfd-cmd/sock.c b/lsfd-cmd/sock.c index db789bbb3..2780c9f34 100644 --- a/lsfd-cmd/sock.c +++ b/lsfd-cmd/sock.c @@ -51,8 +51,7 @@ static bool sock_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; struct sock *sock = (struct sock *)file; diff --git a/lsfd-cmd/unkn.c b/lsfd-cmd/unkn.c index 76731d291..efd6d402c 100644 --- a/lsfd-cmd/unkn.c +++ b/lsfd-cmd/unkn.c @@ -82,8 +82,7 @@ static bool unkn_fill_column(struct proc *proc, struct file *file, struct libscols_line *ln, int column_id, - size_t column_index, - const char *uri __attribute__((__unused__))) + size_t column_index) { char *str = NULL; struct unkn *unkn = (struct unkn *)file; diff --git a/tests/expected/lsfd/option-hyperlink-UNKN-type-file b/tests/expected/lsfd/option-hyperlink-UNKN-type-file new file mode 100644 index 000000000..90c584534 --- /dev/null +++ b/tests/expected/lsfd/option-hyperlink-UNKN-type-file @@ -0,0 +1,7 @@ +# NAME +00000000 74 66 64 73 3d 34 2c 35 0a |tfds=4,5.| +00000009 +# KNAME +00000000 61 6e 6f 6e 5f 69 6e 6f 64 65 3a 5b 65 76 65 6e |anon_inode:[even| +00000010 74 70 6f 6c 6c 5d 0a |tpoll].| +00000017 diff --git a/tests/ts/lsfd/option-hyperlink b/tests/ts/lsfd/option-hyperlink index 4529d2f00..12e9caa03 100755 --- a/tests/ts/lsfd/option-hyperlink +++ b/tests/ts/lsfd/option-hyperlink @@ -95,4 +95,22 @@ ts_init_subtest "deleted-file" wait "${MKFDS_PID}" ts_finalize_subtest +ts_init_subtest "UNKN-type-file" +{ + coproc MKFDS { "$TS_HELPER_MKFDS" eventpoll $FD $((FD + 1)) $((FD + 2)); } + if read -r -u "${MKFDS[0]}" PID; then + for o in NAME KNAME; do + echo "# $o" + "${TS_CMD_LSFD}" -n --hyperlink=always -o "$o" -p "${PID}" -Q "$EXPR" \ + | replace_hostname \ + | replace_filename \ + | "$TS_CMD_HEXDUMP" -C + done + echo DONE >&"${MKFDS[1]}" + fi +} > "$TS_OUTPUT" 2>&1 +wait "${MKFDS_PID}" +ts_finalize_subtest + + ts_finalize -- 2.47.3