]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: introduce a method table for supporting various anon inodes
authorMasatake YAMATO <yamato@redhat.com>
Wed, 27 Jul 2022 19:17:34 +0000 (04:17 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Mon, 8 Aug 2022 20:51:50 +0000 (05:51 +0900)
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
misc-utils/lsfd-unkn.c

index c7526818edf93a97524c68bc294a7cb2a1a910dd..34038e2b9a941c9d9165bfc9761052a09243267b 100644 (file)
 
 #include "lsfd.h"
 
+struct unkn {
+       struct file file;
+       struct anon_ops *anon_ops;
+       void *anon_data;
+};
+
+struct anon_ops {
+       char * (*get_name)(struct unkn *);
+       void (*init)(struct unkn *);
+       void (*free)(struct unkn *);
+       int (*handle_fdinfo)(struct unkn *, const char *, const char *);
+};
+
+static struct anon_ops anon_generic_ops;
+
 static bool unkn_fill_column(struct proc *proc __attribute__((__unused__)),
                             struct file *file,
                             struct libscols_line *ln,
@@ -32,15 +47,22 @@ static bool unkn_fill_column(struct proc *proc __attribute__((__unused__)),
                             size_t column_index)
 {
        char *str = NULL;
+       struct unkn *unkn = (struct unkn *)file;
 
        switch(column_id) {
+       case COL_NAME:
+               if (unkn->anon_ops && unkn->anon_ops->get_name) {
+                       str = unkn->anon_ops->get_name(unkn);
+                       if (str)
+                               break;
+               }
+               return false;
        case COL_TYPE:
                if (scols_line_set_data(ln, column_index, "UNKN"))
                        err(EXIT_FAILURE, _("failed to add output data"));
                return true;
        case COL_SOURCE:
-               if (major(file->stat.st_dev) == 0
-                   && strncmp(file->name, "anon_inode:", 11) == 0) {
+               if (unkn->anon_ops) {
                        str = strdup("anon_inodefs");
                        break;
                }
@@ -56,8 +78,56 @@ static bool unkn_fill_column(struct proc *proc __attribute__((__unused__)),
        return true;
 }
 
+static void unkn_init_content(struct file *file)
+{
+       struct unkn *unkn = (struct unkn *)file;
+
+       assert(file);
+       unkn->anon_ops = NULL;
+       unkn->anon_data = NULL;
+
+       if (major(file->stat.st_dev) == 0
+           && strncmp(file->name, "anon_inode:", 11) == 0) {
+               unkn->anon_ops = &anon_generic_ops;
+               if (unkn->anon_ops->init)
+                       unkn->anon_ops->init(unkn);
+       }
+}
+
+static void unkn_content_free(struct file *file)
+{
+       struct unkn *unkn = (struct unkn *)file;
+
+       assert(file);
+       if (unkn->anon_ops && unkn->anon_ops->free)
+               unkn->anon_ops->free((struct unkn *)file);
+}
+
+static int unkn_handle_fdinfo(struct file *file, const char *key, const char *value)
+{
+       struct unkn *unkn = (struct unkn *)file;
+
+       assert(file);
+       if (unkn->anon_ops && unkn->anon_ops->handle_fdinfo)
+               return unkn->anon_ops->handle_fdinfo(unkn, key, value);
+       return 0;               /* Should be handled in parents */
+}
+
+/*
+ * generic (fallback implementation)
+ */
+static struct anon_ops anon_generic_ops = {
+       .get_name = NULL,
+       .init = NULL,
+       .free = NULL,
+       .handle_fdinfo = NULL,
+};
+
 const struct file_class unkn_class = {
        .super = &file_class,
-       .size = sizeof(struct file),
+       .size = sizeof(struct unkn),
        .fill_column = unkn_fill_column,
+       .initialize_content = unkn_init_content,
+       .free_content = unkn_content_free,
+       .handle_fdinfo = unkn_handle_fdinfo,
 };