From: Masatake YAMATO Date: Wed, 27 Jul 2022 19:17:34 +0000 (+0900) Subject: lsfd: introduce a method table for supporting various anon inodes X-Git-Tag: v2.39-rc1~550^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9a9c96b70c66d544550ec17176de71786340359f;p=thirdparty%2Futil-linux.git lsfd: introduce a method table for supporting various anon inodes Signed-off-by: Masatake YAMATO --- diff --git a/misc-utils/lsfd-unkn.c b/misc-utils/lsfd-unkn.c index c7526818ed..34038e2b9a 100644 --- a/misc-utils/lsfd-unkn.c +++ b/misc-utils/lsfd-unkn.c @@ -25,6 +25,21 @@ #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, };