]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: fill ENDPOINTS column for FIFOs
authorMasatake YAMATO <yamato@redhat.com>
Mon, 7 Mar 2022 13:19:28 +0000 (22:19 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Mon, 4 Apr 2022 17:51:02 +0000 (02:51 +0900)
For FIFO type files, lsof can fill ENDPOINTS as following:

  _PID_,_COMMAND_,_ASSOC_[-r][-w]

Example output:

  $ dd if=/dev/zero | nc -l 127.0.0.1 9091 > /dev/null &
  [1] 1707808 1707809

  $ ./lsfd -p "1707808 1707809" -o+ENDPOINTS -Q '(type == "FIFO")'
  COMMAND     PID   USER ASSOC MODE TYPE SOURCE MNTID    INODE NAME            ENDPOINTS
  dd      1707808 yamato     1  -w- FIFO pipefs    14 73477636 pipe:[734776361707809,nc,0r-
  nc      1707809 yamato     0  r-- FIFO pipefs    14 73477636 pipe:[734776361707808,dd,1-w

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-fifo.c
misc-utils/lsfd.1.adoc
misc-utils/lsfd.c

index 63eb18c7c065ceb4fc7dd8b633579442cff8e64e..3799313cdb2f930b575e67abde7434edf0f9c274 100644 (file)
 
 #include "lsfd.h"
 
+struct fifo {
+       struct file file;
+       struct ipc_endpoint endpoint;
+};
+
+struct fifo_ipc {
+       struct ipc ipc;
+       ino_t ino;
+};
+
+static inline char *fifo_xstrendpoint(struct file *file)
+{
+       char *str = NULL;
+       xasprintf(&str, "%d,%s,%d%c%c",
+                 file->proc->pid, file->proc->command, file->association,
+                 (file->mode & S_IRUSR)? 'r': '-',
+                 (file->mode & S_IWUSR)? 'w': '-');
+       return str;
+}
+
 static bool fifo_fill_column(struct proc *proc __attribute__((__unused__)),
                             struct file *file,
                             struct libscols_line *ln,
@@ -45,6 +65,24 @@ static bool fifo_fill_column(struct proc *proc __attribute__((__unused__)),
                        break;
                }
                return false;
+       case COL_ENDPOINTS: {
+               struct fifo *this = (struct fifo *)file;
+               struct list_head *e;
+               char *estr;
+               list_for_each_backwardly(e, &this->endpoint.ipc->endpoints) {
+                       struct fifo *other = list_entry(e, struct fifo, endpoint.endpoints);
+                       if (this == other)
+                               continue;
+                       if (str)
+                               xstrputc(&str, '\n');
+                       estr = fifo_xstrendpoint(&other->file);
+                       xstrappend(&str, estr);
+                       free(estr);
+               }
+               if (!str)
+                       return false;
+               break;
+       }
        default:
                return false;
        }
@@ -56,9 +94,55 @@ static bool fifo_fill_column(struct proc *proc __attribute__((__unused__)),
        return true;
 }
 
+static unsigned int fifo_get_hash(struct file *file)
+{
+       return (unsigned int)(file->stat.st_ino % UINT_MAX);
+}
+
+static bool fifo_is_suitable_ipc(struct ipc *ipc, struct file *file)
+{
+       return ((struct fifo_ipc *)ipc)->ino == file->stat.st_ino;
+}
+
+static struct ipc_class *fifo_get_ipc_class(struct file *file __attribute__((__unused__)))
+{
+       static struct ipc_class fifo_ipc_class = {
+               .get_hash = fifo_get_hash,
+               .is_suitable_ipc = fifo_is_suitable_ipc,
+               .free = NULL,
+       };
+       return &fifo_ipc_class;
+}
+
+static void fifo_initialize_content(struct file *file)
+{
+       struct fifo *fifo = (struct fifo *)file;
+       struct ipc *ipc;
+       unsigned int hash;
+
+       INIT_LIST_HEAD(&fifo->endpoint.endpoints);
+       ipc = get_ipc(file);
+       if (ipc)
+               goto link;
+
+       ipc = xmalloc(sizeof(struct fifo_ipc));
+       ipc->class = fifo_get_ipc_class(file);
+       INIT_LIST_HEAD(&ipc->endpoints);
+       INIT_LIST_HEAD(&ipc->ipcs);
+       ((struct fifo_ipc *)ipc)->ino = file->stat.st_ino;
+
+       hash = fifo_get_hash(file);
+       add_ipc(ipc, hash);
+ link:
+       fifo->endpoint.ipc = ipc;
+       list_add(&fifo->endpoint.endpoints, &ipc->endpoints);
+}
+
 const struct file_class fifo_class = {
        .super = &file_class,
-       .size = sizeof(struct file),
+       .size = sizeof(struct fifo),
        .fill_column = fifo_fill_column,
+       .initialize_content = fifo_initialize_content,
        .free_content = NULL,
+       .get_ipc_class = fifo_get_ipc_class,
 };
index ca9d8287d43fd635255d1f1a473f9c15b7173690..146908c33f089eaf407b9f0af5d52341d9976d8a 100644 (file)
@@ -135,6 +135,17 @@ Device type (_blk_, _char_, or _nodev_).
 
 ENDPOINT <__string__>::
 IPC endpoints information communicated with the fd.
+The format of the column depends on the object associated
+with the fd:
+
+ FIFO type::: _PID_,_COMMAND_,_ASSOC_[-r][-w]
+
+ The last characters ([-r][-w]) represents the read and/or
+ write mode of the endpoint.
+
+*lsfd* collects endpoints within the processes that
+*lsfd* scans; *lsfd* may miss some endpoints
+if you limits the processes with *-p* option.
 
 FD <__number__>::
 File descriptor for the file.
index 88b9205cb14c713d8278c3d5463aa866856153cc..0022ead6dc922632af3b9b0802f36aa3688f4a84 100644 (file)
@@ -133,7 +133,7 @@ static struct colinfo infos[] = {
                N_("ID of device containing file") },
        [COL_DEVTYPE] = { "DEVTYPE",  0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                N_("device type (blk, char, or nodev)") },
-       [COL_ENDPOINTS] ={"ENDPOINTS",0,              0, SCOLS_JSON_STRING,
+       [COL_ENDPOINTS] ={"ENDPOINTS",0,  SCOLS_FL_WRAP, SCOLS_JSON_STRING,
                N_("IPC endpoints information communicated with the fd") },
        [COL_FLAGS]   = { "FLAGS",    0, SCOLS_FL_RIGHT, SCOLS_JSON_STRING,
                N_("flags specified when opening the file") },
@@ -347,8 +347,16 @@ static struct libscols_column *add_column(struct libscols_table *tb, const struc
        int flags = col->flags;
 
        cl = scols_table_new_column(tb, col->name, col->whint, flags);
-       if (cl)
+       if (cl) {
                scols_column_set_json_type(cl, col->json_type);
+               if (col->flags & SCOLS_FL_WRAP) {
+                       scols_column_set_wrapfunc(cl,
+                                                 scols_wrapnl_chunksize,
+                                                 scols_wrapnl_nextchunk,
+                                                 NULL);
+                       scols_column_set_safechars(cl, "\n");
+               }
+       }
 
        return cl;
 }