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