busybox/modutils/modinfo.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * modinfo - retrieve module info
   4 * Copyright (c) 2008 Pascal Bellard
   5 *
   6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   7 */
   8
   9//applet:IF_MODINFO(APPLET(modinfo, _BB_DIR_SBIN, _BB_SUID_DROP))
  10
  11//kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o
  12
  13//config:config MODINFO
  14//config:       bool "modinfo"
  15//config:       default y
  16//config:       help
  17//config:         Show information about a Linux Kernel module
  18
  19#include <fnmatch.h>
  20#include <sys/utsname.h> /* uname() */
  21#include "libbb.h"
  22#include "modutils.h"
  23
  24
  25enum {
  26        OPT_TAGS = (1 << 6) - 1,
  27        OPT_F = (1 << 6), /* field name */
  28        OPT_0 = (1 << 7),  /* \0 as separator */
  29};
  30
  31struct modinfo_env {
  32        char *field;
  33        int tags;
  34};
  35
  36static int display(const char *data, const char *pattern, int flag)
  37{
  38        if (flag) {
  39                int n = printf("%s:", pattern);
  40                while (n++ < 16)
  41                        bb_putchar(' ');
  42        }
  43        return printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');
  44}
  45
  46static void modinfo(const char *path, const char *version,
  47                        struct modinfo_env *env)
  48{
  49        static const char *const shortcuts[] = {
  50                "filename",
  51                "description",
  52                "author",
  53                "license",
  54                "vermagic",
  55                "parm",
  56        };
  57        size_t len;
  58        int j, length;
  59        char *ptr, *the_module;
  60        const char *field = env->field;
  61        int tags = env->tags;
  62
  63        if (tags & 1) { /* filename */
  64                display(path, shortcuts[0], 1 != tags);
  65        }
  66
  67        len = MAXINT(ssize_t);
  68        the_module = xmalloc_open_zipped_read_close(path, &len);
  69        if (!the_module) {
  70                if (path[0] == '/')
  71                        return;
  72                /* Newer depmod puts relative paths in modules.dep */
  73                path = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);
  74                the_module = xmalloc_open_zipped_read_close(path, &len);
  75                free((char*)path);
  76                if (!the_module)
  77                        return;
  78        }
  79
  80        if (field)
  81                tags |= OPT_F;
  82        for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) {
  83                const char *pattern = field;
  84                if ((1<<j) & OPT_TAGS)
  85                        pattern = shortcuts[j];
  86                if (!((1<<j) & tags))
  87                        continue;
  88                length = strlen(pattern);
  89                ptr = the_module;
  90                while (1) {
  91                        ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module));
  92                        if (ptr == NULL) /* no occurance left, done */
  93                                break;
  94                        if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') {
  95                                ptr += length + 1;
  96                                ptr += display(ptr, pattern, (1<<j) != tags);
  97                        }
  98                        ++ptr;
  99                }
 100        }
 101        free(the_module);
 102}
 103
 104//usage:#define modinfo_trivial_usage
 105//usage:       "[-adlp0] [-F keyword] MODULE"
 106//usage:#define modinfo_full_usage "\n\n"
 107//usage:       "Options:"
 108//usage:     "\n        -a              Shortcut for '-F author'"
 109//usage:     "\n        -d              Shortcut for '-F description'"
 110//usage:     "\n        -l              Shortcut for '-F license'"
 111//usage:     "\n        -p              Shortcut for '-F parm'"
 112//usage:     "\n        -F keyword      Keyword to look for"
 113//usage:     "\n        -0              Separate output with NULs"
 114//usage:#define modinfo_example_usage
 115//usage:       "$ modinfo -F vermagic loop\n"
 116
 117int modinfo_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 118int modinfo_main(int argc UNUSED_PARAM, char **argv)
 119{
 120        struct modinfo_env env;
 121        char name[MODULE_NAME_LEN];
 122        struct utsname uts;
 123        parser_t *parser;
 124        char *colon, *tokens[2];
 125        unsigned opts;
 126        unsigned i;
 127
 128        env.field = NULL;
 129        opt_complementary = "-1"; /* minimum one param */
 130        opts = getopt32(argv, "fdalvpF:0", &env.field);
 131        env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS;
 132        argv += optind;
 133
 134        uname(&uts);
 135        parser = config_open2(
 136                xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, uts.release, CONFIG_DEFAULT_DEPMOD_FILE),
 137                xfopen_for_read
 138        );
 139
 140        while (config_read(parser, tokens, 2, 1, "# \t", PARSE_NORMAL)) {
 141                colon = last_char_is(tokens[0], ':');
 142                if (colon == NULL)
 143                        continue;
 144                *colon = '\0';
 145                filename2modname(tokens[0], name);
 146                for (i = 0; argv[i]; i++) {
 147                        if (fnmatch(argv[i], name, 0) == 0) {
 148                                modinfo(tokens[0], uts.release, &env);
 149                                argv[i] = (char *) "";
 150                        }
 151                }
 152        }
 153        if (ENABLE_FEATURE_CLEAN_UP)
 154                config_close(parser);
 155
 156        for (i = 0; argv[i]; i++) {
 157                if (argv[i][0]) {
 158                        modinfo(argv[i], uts.release, &env);
 159                }
 160        }
 161
 162        return 0;
 163}
 164