]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: use one function to all symlinks
authorKarel Zak <kzak@redhat.com>
Wed, 8 Sep 2021 12:32:31 +0000 (14:32 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 6 Oct 2021 09:01:54 +0000 (11:01 +0200)
This commit introduces collect_file_symlink() to gather info from
arbitrary symlink (e.g. /proc/#/exe, /proc/#/fd/1).

Signed-off-by: Karel Zak <kzak@redhat.com>
misc-utils/lsfd.c

index 0665f05c5de8fba2a8d8b054a397b3959d2d7bf9..3f9f03f3cc5377f5c06c260b8af1a8fa20a201d8 100644 (file)
@@ -321,9 +321,6 @@ static void free_proc(struct proc *proc)
        free(proc);
 }
 
-
-
-
 static void read_fdinfo(struct file *file, FILE *fdinfo)
 {
        const struct file_class *class;
@@ -348,45 +345,40 @@ static void read_fdinfo(struct file *file, FILE *fdinfo)
        }
 }
 
-static struct file *collect_fd_file(struct proc *proc, int dd, struct dirent *dp, void *data)
+static struct file *collect_file_symlink(struct path_cxt *pc,
+                                        struct proc *proc,
+                                        const char *name,
+                                        int assoc)
 {
-       long num;
-       char *endptr = NULL;
-       struct stat sb, lsb;
-       ssize_t len;
-       char sym[PATH_MAX];
+       char sym[PATH_MAX] = { '\0' };
+       struct stat sb;
        struct file *f;
-       int *fdinfo_dd = data;
-       FILE *fdinfo_fp;
-
-       /* care only for numerical descriptors */
-       num = strtol(dp->d_name, &endptr, 10);
-       if (num == 0 && endptr == dp->d_name)
-               return NULL;
 
-       if (fstatat(dd, dp->d_name, &sb, 0) < 0)
+       if (ul_path_stat(pc, &sb, 0, name) < 0)
                return NULL;
-
-       memset(sym, 0, sizeof(sym));
-       if ((len = readlinkat(dd, dp->d_name, sym, sizeof(sym) - 1)) < 0)
+       if (ul_path_readlink(pc, sym, sizeof(sym), name) < 0)
                return NULL;
 
-       f = new_file(proc, &sb, sym, NULL, (int) num);
+       f = new_file(proc, &sb, sym, NULL, assoc);
        if (!f)
                return NULL;
 
-       if (fstatat(dd, dp->d_name, &lsb, AT_SYMLINK_NOFOLLOW) == 0)
-               f->mode = lsb.st_mode;
+       if (is_association(f, EXE))
+               proc->uid = sb.st_uid;
 
-       if (*fdinfo_dd < 0)
-               return f;
+       else if (assoc >= 0) {
+               /* file-descriptor based association */
+               FILE *fdinfo;
 
-       fdinfo_fp = fopen_at(*fdinfo_dd, dp->d_name, O_RDONLY, "r");
-       if (fdinfo_fp) {
-               read_fdinfo(f, fdinfo_fp);
-               fclose(fdinfo_fp);
-       }
+               if (ul_path_stat(pc, &sb, AT_SYMLINK_NOFOLLOW, name) == 0)
+                       f->mode = sb.st_mode;
 
+               fdinfo = ul_path_fopenf(pc, "r", "fdinfo/%d", assoc);
+               if (fdinfo) {
+                       read_fdinfo(f, fdinfo);
+                       fclose(fdinfo);
+               }
+       }
        return f;
 }
 
@@ -460,19 +452,23 @@ static void collect_fd_files_generic(struct proc *proc, const char *proc_templat
        closedir(dirp);
 }
 
-static void collect_fd_files(struct proc *proc)
+/* read symlinks from /proc/#/fd
+ */
+static void collect_fd_files(struct path_cxt *pc, struct proc *proc)
 {
-       DIR *dirp;
-       int dd = -1;
+       DIR *sub = NULL;
+       struct dirent *d = NULL;
+       char path[sizeof("fd/") + sizeof(stringify_value(UINT64_MAX))];
 
-       dirp = opendirf("/proc/%d/fdinfo/", proc->pid);
-       if (dirp)
-               dd = dirfd(dirp);
+       while (ul_path_next_dirent(pc, &sub, "fd", &d) == 0) {
+               uint64_t num;
 
-       collect_fd_files_generic(proc, "/proc/%d/fd/", collect_fd_file, &dd);
+               if (ul_strtou64(d->d_name, &num, 10) != 0)      /* only numbers */
+                       continue;
 
-       if (dirp)
-               closedir(dirp);
+               snprintf(path, sizeof(path), "fd/%ju", (uintmax_t) num);
+               collect_file_symlink(pc, proc, path, num);
+       }
 }
 
 static struct map* new_map(unsigned long mem_addr_start, unsigned long long file_offset,
@@ -553,28 +549,6 @@ static void collect_mem_files(struct proc *proc)
        free_maps(&maps);
 }
 
-static struct file *collect_outofbox_file(struct path_cxt *pc,
-                                         struct proc *proc,
-                                         const char *name, int assoc)
-{
-       char sym[PATH_MAX] = { '\0' };
-       struct stat sb;
-       struct file *f;
-
-       if (ul_path_stat(pc, &sb, 0, name) < 0)
-               return NULL;
-       if (ul_path_readlink(pc, sym, sizeof(sym), name) < 0)
-               return NULL;
-
-       f = new_file(proc, &sb, sym, NULL, assoc);
-       if (!f)
-               return NULL;
-
-       if (is_association(f, EXE))
-               proc->uid = sb.st_uid;
-
-       return f;
-}
 
 static void collect_outofbox_files(struct path_cxt *pc,
                                   struct proc *proc,
@@ -585,7 +559,7 @@ static void collect_outofbox_files(struct path_cxt *pc,
        size_t i;
 
        for (i = 0; i < count; i++)
-               collect_outofbox_file(pc, proc, names[assocs[i]], assocs[i] * -1);
+               collect_file_symlink(pc, proc, names[assocs[i]], assocs[i] * -1);
 }
 
 static void collect_execve_file(struct path_cxt *pc, struct proc *proc)
@@ -922,7 +896,7 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc,
 
        if (proc->pid == proc->leader->pid
            || kcmp(proc->leader->pid, proc->pid, KCMP_FILES, 0, 0) != 0)
-               collect_fd_files(proc);
+               collect_fd_files(pc, proc);
 
        list_add_tail(&proc->procs, &ctl->procs);