bin_PROGRAMS += lsfd
# MANPAGES += misc-utils/lsfd.1
lsfd_SOURCES = \
- misc-utils/lsfd.c
+ misc-utils/lsfd.c \
+ misc-utils/lsfd.h \
+ misc-utils/lsfd-file.c \
+ misc-utils/lsfd-fd-file.c \
+ misc-utils/lsfd-regular-fd-file.c
lsfd_LDADD = $(LDADD) libsmartcols.la libcommon.la
lsfd_LDFLAGS = -pthread
lsfd_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) -pthread
--- /dev/null
+/*
+ * lsfd(1) - list file descriptors
+ *
+ * Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+ * Written by Masatake YAMATO <yamato@redhat.com>
+ *
+ * Very generally based on lsof(8) by Victor A. Abell <abe@purdue.edu>
+ * It supports multiple OSes. lsfd specializes to Linux.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xalloc.h"
+#include "nls.h"
+#include "libsmartcols.h"
+
+#include "lsfd.h"
+
+static bool fd_file_fill_column(struct proc *proc __attribute__((__unused__)),
+ struct file *file,
+ struct libscols_line *ln,
+ int column_id,
+ size_t column_index)
+{
+ char *str = NULL;
+ struct fd_file * fd_file = (struct fd_file *)file;
+
+ switch(column_id) {
+ case COL_FD:
+ xasprintf(&str, "%d", fd_file->fd);
+ if (!str)
+ err(EXIT_FAILURE, _("failed to add output data"));
+ if (scols_line_refer_data(ln, column_index, str))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ return true;
+ };
+
+ return false;
+}
+
+const struct file_class fd_file_class = {
+ .super = &file_class,
+ .size = sizeof(struct fd_file),
+ .fill_column = fd_file_fill_column,
+ .free_content = NULL,
+};
+
+struct file *make_fd_file(const struct file_class *class,
+ struct stat *sb, const char *name, int fd)
+{
+ struct file *file = make_file(class? class: &fd_file_class,
+ sb, name);
+
+ ((struct fd_file *)(file))->fd = fd;
+
+ return file;
+}
--- /dev/null
+/*
+ * lsfd(1) - list file descriptors
+ *
+ * Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+ * Written by Masatake YAMATO <yamato@redhat.com>
+ *
+ * Very generally based on lsof(8) by Victor A. Abell <abe@purdue.edu>
+ * It supports multiple OSes. lsfd specializes to Linux.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xalloc.h"
+#include "nls.h"
+
+#include "libsmartcols.h"
+
+#include "lsfd.h"
+
+static const char *strftype(mode_t ftype)
+{
+ switch (ftype) {
+ case S_IFBLK:
+ return "BLK";
+ case S_IFCHR:
+ return "CHR";
+ case S_IFDIR:
+ return "DIR";
+ case S_IFIFO:
+ return "FIFO";
+ case S_IFLNK:
+ return "LINK";
+ case S_IFREG:
+ return "REG";
+ case S_IFSOCK:
+ return "SOCK";
+ default:
+ return "UNKN";
+ }
+}
+
+static bool file_fill_column(struct proc *proc,
+ struct file *file,
+ struct libscols_line *ln,
+ int column_id,
+ size_t column_index)
+{
+ char *str = NULL;
+ mode_t ftype;
+
+ switch(column_id) {
+ case COL_COMMAND:
+ if (proc->command && scols_line_set_data(ln, column_index, proc->command))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ return true;
+ case COL_NAME:
+ if (file->name && scols_line_set_data(ln, column_index, file->name))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ return true;
+ case COL_TYPE:
+ ftype = file->stat.st_mode & S_IFMT;
+ if (scols_line_set_data(ln, column_index, strftype(ftype)))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ return true;
+ case COL_PID:
+ xasprintf(&str, "%d", (int)proc->pid);
+ if (!str)
+ err(EXIT_FAILURE, _("failed to add output data"));
+ if (scols_line_refer_data(ln, column_index, str))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ return true;
+ };
+
+ return false;
+}
+
+static void file_free_content(struct file *file)
+{
+ free(file->name);
+}
+
+struct file *make_file(const struct file_class *class,
+ struct stat *sb, const char *name)
+{
+ struct file *file = xcalloc(1, class->size);
+
+ file->class = class;
+ file->name = xstrdup(name);
+ file->stat = *sb;
+ return file;
+}
+
+const struct file_class file_class = {
+ .super = NULL,
+ .size = 0,
+ .fill_column = file_fill_column,
+ .free_content = file_free_content,
+};
--- /dev/null
+/*
+ * lsfd(1) - list file descriptors
+ *
+ * Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+ * Written by Masatake YAMATO <yamato@redhat.com>
+ *
+ * Very generally based on lsof(8) by Victor A. Abell <abe@purdue.edu>
+ * It supports multiple OSes. lsfd specializes to Linux.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "xalloc.h"
+#include "nls.h"
+#include "libsmartcols.h"
+
+#include "lsfd.h"
+
+static bool regular_fd_file_fill_column(struct proc *proc __attribute__((__unused__)),
+ struct file *file __attribute__((__unused__)),
+ struct libscols_line *ln,
+ int column_id,
+ size_t column_index)
+{
+ switch(column_id) {
+ case COL_TYPE:
+ if (scols_line_set_data(ln, column_index, "REG"))
+ err(EXIT_FAILURE, _("failed to add output data"));
+ return true;
+ }
+
+ return false;
+}
+
+const struct file_class regular_fd_file_class = {
+ .super = &fd_file_class,
+ .size = sizeof(struct fd_file),
+ .fill_column = regular_fd_file_fill_column,
+ .free_content = NULL,
+};
+
+struct file *make_regular_fd_file(const struct file_class *class,
+ struct stat *sb, const char *name, int fd)
+{
+ return make_fd_file(class? class: ®ular_fd_file_class,
+ sb, name, fd);
+}
#include <stdio.h>
#include <sys/types.h>
-#include <dirent.h>
#include <inttypes.h>
#include <pthread.h>
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
-#include <stdbool.h>
#include "c.h"
#include "nls.h"
#include "libsmartcols.h"
-#define list_free(LIST,TYPE,MEMBER,FREEFN) \
- do { \
- struct list_head *__p, *__pnext; \
- \
- list_for_each_safe (__p, __pnext, (LIST)) { \
- TYPE *__elt = list_entry(__p, TYPE, MEMBER); \
- list_del(__p); \
- FREEFN(__elt); \
- } \
- } while (0)
-
-DIR *opendirf(const char *format, ...) __attribute__((format (printf, 1, 2)));
+#include "lsfd.h"
/*
* Multi-threading related stuffs
* Column related stuffs
*/
-/* column IDs */
-enum {
- COL_PID,
- COL_FD,
- COL_NAME,
- COL_COMMAND,
-};
-
/* column names */
struct colinfo {
const char *name;
[COL_FD] = { "FD", 5, SCOLS_FL_RIGHT, N_("file descriptor for the file") },
[COL_NAME] = { "NAME", 30, 0, N_("name of the file") },
[COL_COMMAND] = { "COMMAND", 10, 0, N_("command of the process opening the file") },
+ [COL_TYPE] = { "TYPE", 7, 0, N_("file type") },
};
static int columns[ARRAY_SIZE(infos) * 2] = {-1};
return &infos[ get_column_id(num) ];
}
-struct proc {
- pid_t pid;
- char *command;
- struct list_head procs;
- struct list_head files;
-};
-
-/*
- * File classes
- */
-struct file {
- struct list_head files;
- const struct file_class *class;
- char *name;
-};
-
-struct fd_file {
- struct file file;
- int fd;
-};
-
-struct file_class {
- const struct file_class *super;
- size_t size;
- bool (*fill_column)(struct proc *proc,
- struct file *file,
- struct libscols_line *ln,
- int column_id,
- size_t column_index);
- void (*free_content)(struct file *file);
-};
-
-static bool file_fill_column(struct proc *proc,
- struct file *file,
- struct libscols_line *ln,
- int column_id,
- size_t column_index);
-static void file_free_content(struct file *file);
-static const struct file_class file_class = {
- .super = NULL,
- .size = 0,
- .fill_column = file_fill_column,
- .free_content = file_free_content,
-};
-
-static bool fd_file_fill_column(struct proc *proc,
- struct file *file,
- struct libscols_line *ln,
- int column_id,
- size_t column_index);
-static const struct file_class fd_file_class = {
- .super = &file_class,
- .size = sizeof(struct fd_file),
- .fill_column = fd_file_fill_column,
- .free_content = NULL,
-};
-
-static struct file *make_file(const struct file_class *class, const char *name)
-{
- struct file *file = xcalloc(1, class->size);
-
- file->class = class;
- file->name = xstrdup(name);
- return file;
-}
-
-static void file_free_content(struct file *file)
-{
- free(file->name);
-}
-
-static struct file *make_fd_file(int fd, const char *name)
-{
- struct file *file = make_file(&fd_file_class, name);
-
- ((struct fd_file *)(file))->fd = fd;
-
- return file;
-
-}
-
static struct proc *make_proc(pid_t pid)
{
struct proc *proc = xcalloc(1, sizeof(*proc));
if ((len = readlinkat(dd, dp->d_name, sym, sizeof(sym) - 1)) < 0)
return NULL;
- return make_fd_file((int)num, sym);
+ switch (sb.st_mode & S_IFMT) {
+ case S_IFREG:
+ return make_regular_fd_file(NULL, &sb, sym, (int)num);
+ }
+
+ return make_fd_file(NULL, &sb, sym, (int)num);
}
static void enqueue_file(struct proc *proc, struct file * file)
collect_files(proc);
}
+
static void *fill_procs(void *arg)
{
struct list_head *procs = arg;
return NULL;
}
-static bool file_fill_column(struct proc *proc,
- struct file *file,
- struct libscols_line *ln,
- int column_id,
- size_t column_index)
-{
- char *str = NULL;
-
- switch(column_id) {
- case COL_COMMAND:
- if (proc->command && scols_line_set_data(ln, column_index, proc->command))
- err(EXIT_FAILURE, _("failed to add output data"));
- return true;
- case COL_NAME:
- if (file->name && scols_line_set_data(ln, column_index, file->name))
- err(EXIT_FAILURE, _("failed to add output data"));
- return true;
- case COL_PID:
- xasprintf(&str, "%d", (int)proc->pid);
- if (!str)
- err(EXIT_FAILURE, _("failed to add output data"));
- if (scols_line_refer_data(ln, column_index, str))
- err(EXIT_FAILURE, _("failed to add output data"));
- return true;
- };
-
- return false;
-}
-
-static bool fd_file_fill_column(struct proc *proc __attribute__((__unused__)),
- struct file *file,
- struct libscols_line *ln,
- int column_id,
- size_t column_index)
-{
- char *str = NULL;
- struct fd_file * fd_file = (struct fd_file *)file;
-
- switch(column_id) {
- case COL_FD:
- xasprintf(&str, "%d", fd_file->fd);
- if (!str)
- err(EXIT_FAILURE, _("failed to add output data"));
- if (scols_line_refer_data(ln, column_index, str))
- err(EXIT_FAILURE, _("failed to add output data"));
- return true;
- };
-
- return false;
-}
-
static void fill_column(struct proc *proc,
struct file *file,
struct libscols_line *ln,
columns[ncolumns++] = COL_COMMAND;
columns[ncolumns++] = COL_PID;
columns[ncolumns++] = COL_FD;
+ columns[ncolumns++] = COL_TYPE;
columns[ncolumns++] = COL_NAME;
}
--- /dev/null
+/*
+ * lsfd(1) - list file descriptors
+ *
+ * Copyright (C) 2021 Red Hat, Inc. All rights reserved.
+ * Written by Masatake YAMATO <yamato@redhat.com>
+ *
+ * Very generally based on lsof(8) by Victor A. Abell <abe@purdue.edu>
+ * It supports multiple OSes. lsfd specializes to Linux.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef UTIL_LINUX_LSFD_H
+#define UTIL_LINUX_LSFD_H
+
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "list.h"
+
+/*
+ * Utilities
+ */
+#define list_free(LIST,TYPE,MEMBER,FREEFN) \
+ do { \
+ struct list_head *__p, *__pnext; \
+ \
+ list_for_each_safe (__p, __pnext, (LIST)) { \
+ TYPE *__elt = list_entry(__p, TYPE, MEMBER); \
+ list_del(__p); \
+ FREEFN(__elt); \
+ } \
+ } while (0)
+
+DIR *opendirf(const char *format, ...) __attribute__((format (printf, 1, 2)));
+
+/*
+ * column IDs
+ */
+enum {
+ COL_PID,
+ COL_FD,
+ COL_NAME,
+ COL_COMMAND,
+ COL_TYPE,
+};
+
+/*
+ * Process structure
+ */
+struct proc {
+ pid_t pid;
+ char *command;
+ struct list_head procs;
+ struct list_head files;
+};
+
+/*
+ * File classes
+ */
+struct file {
+ struct list_head files;
+ const struct file_class *class;
+ char *name;
+ struct stat stat;
+};
+
+struct fd_file {
+ struct file file;
+ int fd;
+};
+
+struct file_class {
+ const struct file_class *super;
+ size_t size;
+ bool (*fill_column)(struct proc *proc,
+ struct file *file,
+ struct libscols_line *ln,
+ int column_id,
+ size_t column_index);
+ void (*free_content)(struct file *file);
+};
+
+extern const struct file_class
+file_class, fd_file_class, regular_fd_file_class
+ ;
+
+struct file *make_file(const struct file_class *class,
+ struct stat *sb, const char *name);
+struct file *make_fd_file(const struct file_class *class,
+ struct stat *sb, const char *name, int fd);
+struct file *make_regular_fd_file(const struct file_class *class,
+ struct stat *sb, const char *name, int fd);
+
+#endif /* UTIL_LINUX_LSFD_H */