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 tarball for details. 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