From: Masatake YAMATO Date: Fri, 7 May 2021 18:50:16 +0000 (+0900) Subject: lsfd: read character driver names from /proc/devices X-Git-Tag: v2.38-rc1~144^2~139 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=12951df22ea1a6ed720372c599deb170dd33624b;p=thirdparty%2Futil-linux.git lsfd: read character driver names from /proc/devices Signed-off-by: Masatake YAMATO --- diff --git a/misc-utils/lsfd-cdev.c b/misc-utils/lsfd-cdev.c index c31c3a8fad..21b8bde2b2 100644 --- a/misc-utils/lsfd-cdev.c +++ b/misc-utils/lsfd-cdev.c @@ -25,6 +25,14 @@ #include "lsfd.h" +static struct list_head chrdrvs; + +struct chrdrv { + struct list_head chrdrvs; + unsigned long major; + char *name; +}; + static bool cdev_fill_column(struct proc *proc __attribute__((__unused__)), struct file *file __attribute__((__unused__)), struct libscols_line *ln, @@ -60,9 +68,77 @@ struct file *make_cdev(const struct file_class *class, sb, name, fd); } +static struct chrdrv *make_chrdrv(unsigned long major, const char *name) +{ + struct chrdrv *chrdrv = xcalloc(1, sizeof(*chrdrv)); + + INIT_LIST_HEAD(&chrdrv->chrdrvs); + + chrdrv->major = major; + chrdrv->name = xstrdup(name); + + return chrdrv; +} + +static void free_chrdrv(struct chrdrv *chrdrv) +{ + free(chrdrv->name); + free(chrdrv); +} + +static void read_devices(struct list_head *chrdrvs_list, FILE *devices_fp) +{ + unsigned long major; + char line[256]; + char name[sizeof(line)]; + + while (fgets(line, sizeof(line), devices_fp)) { + struct chrdrv *chrdrv; + + if (line[0] == 'C') + continue; /* "Character devices:" */ + else if (line[0] == '\n') + break; + + if (sscanf(line, "%lu %s", &major, name) != 2) + continue; + chrdrv = make_chrdrv(major, name); + list_add_tail(&chrdrv->chrdrvs, chrdrvs_list); + } +} + +static void cdev_class_initialize(void) +{ + INIT_LIST_HEAD(&chrdrvs); + + FILE *devices_fp = fopen("/proc/devices", "r"); + if (devices_fp) { + read_devices(&chrdrvs, devices_fp); + fclose(devices_fp); + } +} + +static void cdev_class_finalize(void) +{ + list_free(&chrdrvs, struct chrdrv, chrdrvs, free_chrdrv); +} + +const char *get_chrdrv(unsigned long major) +{ + struct list_head *c; + list_for_each(c, &chrdrvs) { + struct chrdrv *chrdrv = list_entry(c, struct chrdrv, chrdrvs); + if (chrdrv->major == major) + return chrdrv->name; + } + return NULL; +} + const struct file_class cdev_class = { .super = &file_class, .size = sizeof(struct file), + .initialize_class = cdev_class_initialize, + .finalize_class = cdev_class_finalize, .fill_column = cdev_fill_column, .free_content = NULL, }; diff --git a/misc-utils/lsfd.h b/misc-utils/lsfd.h index b7dc585e41..03be082fc2 100644 --- a/misc-utils/lsfd.h +++ b/misc-utils/lsfd.h @@ -160,5 +160,6 @@ const char *get_name(struct name_manager *nm, unsigned long id); unsigned long add_name(struct name_manager *nm, const char *name); const char *get_partition(dev_t dev); +const char *get_chrdrv(unsigned long major); #endif /* UTIL_LINUX_LSFD_H */