Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/modutils
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 10 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/modutils/Config.src
r3232 r3621 39 39 - depmod generates modules.dep.bb 40 40 41 As of 2008-07, this code is experimental. It is 14kb smaller42 than "non-small" modutils.43 44 41 config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 45 42 bool "Accept module options on modprobe command line" -
branches/3.3/mindi-busybox/modutils/depmod.c
r3232 r3621 22 22 */ 23 23 24 typedef struct module_info {25 struct module_info *next;26 char *name, *modname;27 llist_t *dependencies;28 llist_t *aliases;29 llist_t *symbols;30 struct module_info *dnext, *dprev;31 } module_info;32 33 24 static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, 34 25 void *data, int depth UNUSED_PARAM) 35 26 { 36 char modname[MODULE_NAME_LEN]; 37 module_info **first = (module_info **) data; 27 module_db *modules = data; 38 28 char *image, *ptr; 39 module_info *info; 29 module_entry *e; 30 40 31 /* Arbitrary. Was sb->st_size, but that breaks .gz etc */ 41 32 size_t len = (64*1024*1024 - 4096); … … 45 36 46 37 image = xmalloc_open_zipped_read_close(fname, &len); 47 info = xzalloc(sizeof(*info)); 48 49 info->next = *first; 50 *first = info; 51 52 info->dnext = info->dprev = info; 53 info->name = xstrdup(fname + 2); /* skip "./" */ 54 info->modname = xstrdup(filename2modname(fname, modname)); 38 39 e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname)); 40 e->name = xstrdup(fname + 2); /* skip "./" */ 41 55 42 for (ptr = image; ptr < image + len - 10; ptr++) { 56 if ( strncmp(ptr, "depends=", 8) == 0) {43 if (is_prefixed_with(ptr, "depends=")) { 57 44 char *u; 58 45 … … 61 48 if (*u == '-') 62 49 *u = '_'; 63 ptr += string_to_llist(ptr, & info->dependencies, ",");50 ptr += string_to_llist(ptr, &e->deps, ","); 64 51 } else if (ENABLE_FEATURE_MODUTILS_ALIAS 65 && strncmp(ptr, "alias=", 6) == 052 && is_prefixed_with(ptr, "alias=") 66 53 ) { 67 llist_add_to(& info->aliases, xstrdup(ptr + 6));54 llist_add_to(&e->aliases, xstrdup(ptr + 6)); 68 55 ptr += strlen(ptr); 69 56 } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS 70 && strncmp(ptr, "__ksymtab_", 10) == 057 && is_prefixed_with(ptr, "__ksymtab_") 71 58 ) { 72 59 ptr += 10; 73 if ( strncmp(ptr, "gpl", 3) == 060 if (is_prefixed_with(ptr, "gpl") 74 61 || strcmp(ptr, "strings") == 0 75 62 ) { 76 63 continue; 77 64 } 78 llist_add_to(& info->symbols, xstrdup(ptr));65 llist_add_to(&e->symbols, xstrdup(ptr)); 79 66 ptr += strlen(ptr); 80 67 } … … 85 72 } 86 73 87 static module_info *find_module(module_info *modules, const char *modname) 88 { 89 module_info *m; 90 91 for (m = modules; m != NULL; m = m->next) 92 if (strcmp(m->modname, modname) == 0) 93 return m; 94 return NULL; 95 } 96 97 static void order_dep_list(module_info *modules, module_info *start, 98 llist_t *add) 99 { 100 module_info *m; 74 static void order_dep_list(module_db *modules, module_entry *start, llist_t *add) 75 { 76 module_entry *m; 101 77 llist_t *n; 102 78 103 79 for (n = add; n != NULL; n = n->link) { 104 m = find_module(modules, n->data);80 m = moddb_get(modules, n->data); 105 81 if (m == NULL) 106 82 continue; … … 117 93 118 94 /* recurse */ 119 order_dep_list(modules, start, m->dep endencies);95 order_dep_list(modules, start, m->deps); 120 96 } 121 97 } … … 183 159 int depmod_main(int argc UNUSED_PARAM, char **argv) 184 160 { 185 module_info *modules, *m, *dep; 161 module_db modules; 162 module_entry *m, *dep; 186 163 const char *moddir_base = "/"; 187 164 char *moddir, *version; 188 165 struct utsname uts; 166 unsigned i; 189 167 int tmp; 190 168 … … 210 188 211 189 /* Scan modules */ 212 m odules = NULL;190 memset(&modules, 0, sizeof(modules)); 213 191 if (*argv) { 214 192 do { … … 223 201 if (!(option_mask32 & OPT_n)) 224 202 xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout); 225 for (m = modules; m != NULL; m = m->next) { 203 204 moddb_foreach_module(&modules, m, i) { 226 205 printf("%s:", m->name); 227 206 228 order_dep_list( modules, m, m->dependencies);207 order_dep_list(&modules, m, m->deps); 229 208 while (m->dnext != m) { 230 209 dep = m->dnext; … … 242 221 if (!(option_mask32 & OPT_n)) 243 222 xfreopen_write("modules.alias", stdout); 244 for (m = modules; m != NULL; m = m->next) { 245 const char *fname = bb_basename(m->name); 246 int fnlen = strchrnul(fname, '.') - fname; 223 moddb_foreach_module(&modules, m, i) { 247 224 while (m->aliases) { 248 /* Last word can well be m->modname instead, 249 * but depmod from module-init-tools 3.4 250 * uses module basename, i.e., no s/-/_/g. 251 * (pathname and .ko.* are still stripped) 252 * Mimicking that... */ 253 printf("alias %s %.*s\n", 225 /* 226 * Last word used to be a basename 227 * (filename with path and .ko.* stripped) 228 * at the time of module-init-tools 3.4. 229 * kmod v.12 uses module name, i.e., s/-/_/g. 230 */ 231 printf("alias %s %s\n", 254 232 (char*)llist_pop(&m->aliases), 255 fnlen, fname);233 m->modname); 256 234 } 257 235 } … … 260 238 if (!(option_mask32 & OPT_n)) 261 239 xfreopen_write("modules.symbols", stdout); 262 for (m = modules; m != NULL; m = m->next) { 263 const char *fname = bb_basename(m->name); 264 int fnlen = strchrnul(fname, '.') - fname; 240 moddb_foreach_module(&modules, m, i) { 265 241 while (m->symbols) { 266 printf("alias symbol:%s % .*s\n",242 printf("alias symbol:%s %s\n", 267 243 (char*)llist_pop(&m->symbols), 268 fnlen, fname);244 m->modname); 269 245 } 270 246 } 271 247 #endif 272 248 273 if (ENABLE_FEATURE_CLEAN_UP) { 274 while (modules) { 275 module_info *old = modules; 276 modules = modules->next; 277 free(old->name); 278 free(old->modname); 279 free(old); 280 } 281 } 249 if (ENABLE_FEATURE_CLEAN_UP) 250 moddb_free(&modules); 282 251 283 252 return EXIT_SUCCESS; -
branches/3.3/mindi-busybox/modutils/insmod.c
r3232 r3621 22 22 //usage: "[SYMBOL=VALUE]..." 23 23 //usage:#define insmod_full_usage "\n\n" 24 //usage: "Load the specified kernel modules into the kernel"24 //usage: "Load kernel module" 25 25 //usage: IF_FEATURE_2_4_MODULES( "\n" 26 26 //usage: "\n -f Force module to load into the wrong kernel version" -
branches/3.3/mindi-busybox/modutils/modinfo.c
r3232 r3621 6 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 7 */ 8 9 //applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP))10 11 //kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o12 13 8 //config:config MODINFO 14 9 //config: bool "modinfo" … … 18 13 //config: Show information about a Linux Kernel module 19 14 15 //applet:IF_MODINFO(APPLET(modinfo, BB_DIR_SBIN, BB_SUID_DROP)) 16 17 //kbuild:lib-$(CONFIG_MODINFO) += modinfo.o modutils.o 18 20 19 #include <fnmatch.h> 21 20 #include <sys/utsname.h> /* uname() */ … … 23 22 #include "modutils.h" 24 23 24 static const char *const shortcuts[] = { 25 "filename", // -n 26 "author", // -a 27 "description", // -d 28 "license", // -l 29 "parm", // -p 30 "version", // the rest has no shortcut options 31 "alias", 32 "srcversion", 33 "depends", 34 "uts_release", 35 "intree", 36 "vermagic", 37 "firmware", 38 }; 25 39 26 40 enum { 27 OPT_TAGS = (1 << 12) - 1, /* shortcut count */ 28 OPT_F = (1 << 12), /* field name */ 29 OPT_0 = (1 << 13), /* \0 as separator */ 41 OPT_0 = (1 << 0), /* \0 as separator */ 42 OPT_F = (1 << 1), /* field name */ 43 /* first bits are for -nadlp options, the rest are for 44 * fields not selectable with "shortcut" options 45 */ 46 OPT_n = (1 << 2), 47 OPT_TAGS = ((1 << ARRAY_SIZE(shortcuts)) - 1) << 2, 30 48 }; 31 49 32 struct modinfo_env { 33 char *field; 34 int tags; 35 }; 36 37 static int display(const char *data, const char *pattern, int flag) 50 static void display(const char *data, const char *pattern) 38 51 { 39 if (flag) { 52 int flag = option_mask32 >> 1; /* shift out -0 bit */ 53 if (flag & (flag-1)) { 54 /* more than one field to show: print "FIELD:" pfx */ 40 55 int n = printf("%s:", pattern); 41 56 while (n++ < 16) 42 57 bb_putchar(' '); 43 58 } 44 returnprintf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n');59 printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n'); 45 60 } 46 61 47 62 static void modinfo(const char *path, const char *version, 48 const struct modinfo_env *env)63 const char *field) 49 64 { 50 static const char *const shortcuts[] = {51 "filename",52 "license",53 "author",54 "description",55 "version",56 "alias",57 "srcversion",58 "depends",59 "uts_release",60 "vermagic",61 "parm",62 "firmware",63 };64 65 size_t len; 65 int j , length;66 int j; 66 67 char *ptr, *the_module; 67 c onst char *field = env->field;68 int tags = env->tags;68 char *allocated; 69 int tags = option_mask32; 69 70 70 if (tags & 1) { /* filename */ 71 display(path, shortcuts[0], 1 != tags); 72 } 73 71 allocated = NULL; 74 72 len = MAXINT(ssize_t); 75 73 the_module = xmalloc_open_zipped_read_close(path, &len); … … 78 76 return; 79 77 /* Newer depmod puts relative paths in modules.dep */ 80 path = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path);78 path = allocated = xasprintf("%s/%s/%s", CONFIG_DEFAULT_MODULES_DIR, version, path); 81 79 the_module = xmalloc_open_zipped_read_close(path, &len); 82 free((char*)path); 83 if (!the_module) 84 return; 80 if (!the_module) { 81 bb_error_msg("module '%s' not found", path); 82 goto ret; 83 } 85 84 } 86 85 87 if (field) 88 tags |= OPT_F; 89 for (j = 1; (1<<j) & (OPT_TAGS + OPT_F); j++) { 86 for (j = 1; (1<<j) & (OPT_TAGS|OPT_F); j++) { 90 87 const char *pattern; 91 88 92 89 if (!((1<<j) & tags)) 93 90 continue; 91 94 92 pattern = field; 95 93 if ((1<<j) & OPT_TAGS) 96 pattern = shortcuts[j]; 97 length = strlen(pattern); 94 pattern = shortcuts[j-2]; 95 96 if (strcmp(pattern, shortcuts[0]) == 0) { 97 /* "-n" or "-F filename" */ 98 display(path, shortcuts[0]); 99 continue; 100 } 101 98 102 ptr = the_module; 99 103 while (1) { 104 char *after_pattern; 105 100 106 ptr = memchr(ptr, *pattern, len - (ptr - (char*)the_module)); 101 107 if (ptr == NULL) /* no occurance left, done */ 102 108 break; 103 if (strncmp(ptr, pattern, length) == 0 && ptr[length] == '=') { 109 after_pattern = is_prefixed_with(ptr, pattern); 110 if (after_pattern && *after_pattern == '=') { 104 111 /* field prefixes are 0x80 or 0x00 */ 105 if ((ptr[-1] & 0x7F) == '\0') { 106 ptr += length + 1; 107 ptr += display(ptr, pattern, (1<<j) != tags); 112 if ((ptr[-1] & 0x7F) == 0x00) { 113 ptr = after_pattern + 1; 114 display(ptr, pattern); 115 ptr += strlen(ptr); 108 116 } 109 117 } … … 112 120 } 113 121 free(the_module); 122 ret: 123 free(allocated); 114 124 } 115 125 116 126 //usage:#define modinfo_trivial_usage 117 //usage: "[-adlp 0] [-F keyword] MODULE"127 //usage: "[-adlpn0] [-F keyword] MODULE" 118 128 //usage:#define modinfo_full_usage "\n\n" 119 129 //usage: " -a Shortcut for '-F author'" … … 121 131 //usage: "\n -l Shortcut for '-F license'" 122 132 //usage: "\n -p Shortcut for '-F parm'" 133 ////usage: "\n -n Shortcut for '-F filename'" 123 134 //usage: "\n -F keyword Keyword to look for" 124 135 //usage: "\n -0 Separate output with NULs" … … 129 140 int modinfo_main(int argc UNUSED_PARAM, char **argv) 130 141 { 131 struct modinfo_env env;142 const char *field; 132 143 char name[MODULE_NAME_LEN]; 133 144 struct utsname uts; … … 137 148 unsigned i; 138 149 139 env.field = NULL;150 field = NULL; 140 151 opt_complementary = "-1"; /* minimum one param */ 141 opts = getopt32(argv, "nladvAsDumpF:0", &env.field); 142 env.tags = opts & OPT_TAGS ? opts & OPT_TAGS : OPT_TAGS; 152 opts = getopt32(argv, "0F:nadlp", &field); 153 /* If no field selected, show all */ 154 if (!(opts & (OPT_TAGS|OPT_F))) 155 option_mask32 |= OPT_TAGS; 143 156 argv += optind; 144 157 … … 154 167 continue; 155 168 *colon = '\0'; 156 filename2modname( tokens[0], name);169 filename2modname(bb_basename(tokens[0]), name); 157 170 for (i = 0; argv[i]; i++) { 158 171 if (fnmatch(argv[i], name, 0) == 0) { 159 modinfo(tokens[0], uts.release, &env);172 modinfo(tokens[0], uts.release, field); 160 173 argv[i] = (char *) ""; 161 174 } … … 167 180 for (i = 0; argv[i]; i++) { 168 181 if (argv[i][0]) { 169 modinfo(argv[i], uts.release, &env);182 modinfo(argv[i], uts.release, field); 170 183 } 171 184 } -
branches/3.3/mindi-busybox/modutils/modprobe-small.c
r3232 r3621 10 10 11 11 //applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)) 12 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))13 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))14 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))15 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))12 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod)) 13 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod)) 14 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod)) 15 //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod)) 16 16 17 17 #include "libbb.h" … … 22 22 extern int init_module(void *module, unsigned long len, const char *options); 23 23 extern int delete_module(const char *module, unsigned flags); 24 extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); 24 /* linux/include/linux/module.h has limit of 64 chars on module names */ 25 #undef MODULE_NAME_LEN 26 #define MODULE_NAME_LEN 64 25 27 26 28 … … 44 46 char *aliases; 45 47 char *deps; 48 smallint open_read_failed; 46 49 } module_info; 47 50 … … 114 117 static char* find_keyword(char *ptr, size_t len, const char *word) 115 118 { 116 int wlen;117 118 119 if (!ptr) /* happens if xmalloc_open_zipped_read_close cannot read it */ 119 120 return NULL; 120 121 121 wlen = strlen(word); 122 len -= wlen - 1; 122 len -= strlen(word) - 1; 123 123 while ((ssize_t)len > 0) { 124 124 char *old = ptr; 125 char *after_word; 126 125 127 /* search for the first char in word */ 126 ptr = memchr(ptr, *word, len);128 ptr = memchr(ptr, word[0], len); 127 129 if (ptr == NULL) /* no occurance left, done */ 128 130 break; 129 if (strncmp(ptr, word, wlen) == 0) 130 return ptr + wlen; /* found, return ptr past it */ 131 after_word = is_prefixed_with(ptr, word); 132 if (after_word) 133 return after_word; /* found, return ptr past it */ 131 134 ++ptr; 132 135 len -= (ptr - old); … … 142 145 ++s; 143 146 } 147 } 148 149 static char *filename2modname(const char *filename, char *modname) 150 { 151 int i; 152 const char *from; 153 154 // Disabled since otherwise "modprobe dir/name" would work 155 // as if it is "modprobe name". It is unclear why 156 // 'basenamization' was here in the first place. 157 //from = bb_get_last_path_component_nostrip(filename); 158 from = filename; 159 for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) 160 modname[i] = (from[i] == '-') ? '_' : from[i]; 161 modname[i] = '\0'; 162 163 return modname; 164 } 165 166 static int pathname_matches_modname(const char *pathname, const char *modname) 167 { 168 int r; 169 char name[MODULE_NAME_LEN]; 170 filename2modname(bb_get_last_path_component_nostrip(pathname), name); 171 r = (strcmp(name, modname) == 0); 172 return r; 144 173 } 145 174 … … 195 224 } 196 225 197 static void parse_module(module_info *info, const char *pathname) 226 /* Returns !0 if open/read was unsuccessful */ 227 static int parse_module(module_info *info, const char *pathname) 198 228 { 199 229 char *module_image; … … 204 234 205 235 /* Read (possibly compressed) module */ 236 errno = 0; 206 237 len = 64 * 1024 * 1024; /* 64 Mb at most */ 207 238 module_image = xmalloc_open_zipped_read_close(pathname, &len); … … 213 244 pos = 0; 214 245 while (1) { 246 unsigned start = stringbuf_idx; 215 247 ptr = find_keyword(module_image + pos, len - pos, "alias="); 216 248 if (!ptr) { … … 229 261 append(ptr); 230 262 appendc(' '); 263 /* 264 * Don't add redundant aliases, such as: 265 * libcrc32c.ko symbol:crc32c symbol:crc32c 266 */ 267 if (start) { /* "if we aren't the first alias" */ 268 char *found, *last; 269 stringbuf[stringbuf_idx] = '\0'; 270 last = stringbuf + start; 271 /* 272 * String at last-1 is " symbol:crc32c " 273 * (with both leading and trailing spaces). 274 */ 275 if (strncmp(stringbuf, last, stringbuf_idx - start) == 0) 276 /* First alias matches us */ 277 found = stringbuf; 278 else 279 /* Does any other alias match? */ 280 found = strstr(stringbuf, last-1); 281 if (found < last-1) { 282 /* There is absolutely the same string before us */ 283 dbg2_error_msg("redundant:'%s'", last); 284 stringbuf_idx = start; 285 goto skip; 286 } 287 } 231 288 skip: 232 289 pos = (ptr - module_image); … … 245 302 append(ptr); 246 303 } 304 free(module_image); 247 305 info->deps = copy_stringbuf(); 248 306 249 free(module_image); 250 } 251 252 static int pathname_matches_modname(const char *pathname, const char *modname) 253 { 254 const char *fname = bb_get_last_path_component_nostrip(pathname); 255 const char *suffix = strrstr(fname, ".ko"); 256 //TODO: can do without malloc? 257 char *name = xstrndup(fname, suffix - fname); 258 int r; 259 replace(name, '-', '_'); 260 r = (strcmp(name, modname) == 0); 261 free(name); 262 return r; 307 info->open_read_failed = (module_image == NULL); 308 return info->open_read_failed; 263 309 } 264 310 … … 291 337 dbg1_error_msg("'%s' module name matches", pathname); 292 338 module_found_idx = cur; 293 parse_module(&modinfo[cur], pathname); 339 if (parse_module(&modinfo[cur], pathname) != 0) 340 return TRUE; /* failed to open/read it, no point in trying loading */ 294 341 295 342 if (!(option_mask32 & OPT_r)) { … … 422 469 } 423 470 424 static module_info* find_alias(const char *alias)471 static module_info** find_alias(const char *alias) 425 472 { 426 473 int i; 427 474 int dep_bb_fd; 428 module_info *result; 475 int infoidx; 476 module_info **infovec; 429 477 dbg1_error_msg("find_alias('%s')", alias); 430 478 … … 439 487 parse_module(&modinfo[i], modinfo[i].pathname); 440 488 } 441 return &modinfo[i]; 489 infovec = xzalloc(2 * sizeof(infovec[0])); 490 infovec[0] = &modinfo[i]; 491 return infovec; 442 492 } 443 493 i++; … … 452 502 /* Scan all module bodies, extract modinfo (it contains aliases) */ 453 503 i = 0; 454 result = NULL; 504 infoidx = 0; 505 infovec = NULL; 455 506 while (modinfo[i].pathname) { 456 507 char *desc, *s; 457 508 if (!modinfo[i].aliases) { 458 509 parse_module(&modinfo[i], modinfo[i].pathname); 459 }460 if (result) {461 i++;462 continue;463 510 } 464 511 /* "alias1 symbol:sym1 alias2 symbol:sym2" */ … … 473 520 dbg1_error_msg("found alias '%s' in module '%s'", 474 521 alias, modinfo[i].pathname); 475 result = &modinfo[i]; 522 infovec = xrealloc_vector(infovec, 1, infoidx); 523 infovec[infoidx++] = &modinfo[i]; 476 524 break; 477 525 } 478 526 } 479 527 free(desc); 480 if (result && dep_bb_fd < 0)481 return result;482 528 i++; 483 529 } … … 488 534 } 489 535 490 dbg1_error_msg("find_alias '%s' returns % p", alias, result);491 return result;536 dbg1_error_msg("find_alias '%s' returns %d results", alias, infoidx); 537 return infovec; 492 538 } 493 539 … … 496 542 static int already_loaded(const char *name) 497 543 { 498 int ret = 0; 499 char *s; 500 parser_t *parser = config_open2("/proc/modules", xfopen_for_read); 501 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) { 502 if (strcmp(s, name) == 0) { 503 ret = 1; 504 break; 505 } 506 } 507 config_close(parser); 508 return ret; 544 int ret; 545 char *line; 546 FILE *fp; 547 548 ret = 5 * 2; 549 again: 550 fp = fopen_for_read("/proc/modules"); 551 if (!fp) 552 return 0; 553 while ((line = xmalloc_fgetline(fp)) != NULL) { 554 char *live; 555 char *after_name; 556 557 // Examples from kernel 3.14.6: 558 //pcspkr 12718 0 - Live 0xffffffffa017e000 559 //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000 560 //i915 801405 2 - Live 0xffffffffa0096000 561 after_name = is_prefixed_with(line, name); 562 if (!after_name || *after_name != ' ') { 563 free(line); 564 continue; 565 } 566 live = strstr(line, " Live"); 567 free(line); 568 if (!live) { 569 /* State can be Unloading, Loading, or Live. 570 * modprobe must not return prematurely if we see "Loading": 571 * it can cause further programs to assume load completed, 572 * but it did not (yet)! 573 * Wait up to 5*20 ms for it to resolve. 574 */ 575 ret -= 2; 576 if (ret == 0) 577 break; /* huh? report as "not loaded" */ 578 fclose(fp); 579 usleep(20*1000); 580 goto again; 581 } 582 ret = 1; 583 break; 584 } 585 fclose(fp); 586 587 return ret & 1; 509 588 } 510 589 #else 511 #define already_loaded(name) is_rmmod590 #define already_loaded(name) 0 512 591 #endif 592 593 static int rmmod(const char *filename) 594 { 595 int r; 596 char modname[MODULE_NAME_LEN]; 597 598 filename2modname(filename, modname); 599 r = delete_module(modname, O_NONBLOCK | O_EXCL); 600 dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); 601 if (r != 0 && !(option_mask32 & OPT_q)) { 602 bb_perror_msg("remove '%s'", modname); 603 } 604 return r; 605 } 513 606 514 607 /* … … 522 615 #define cmdline_options "" 523 616 #endif 524 static voidprocess_module(char *name, const char *cmdline_options)617 static int process_module(char *name, const char *cmdline_options) 525 618 { 526 619 char *s, *deps, *options; 620 module_info **infovec; 527 621 module_info *info; 528 int is_rmmod = (option_mask32 & OPT_r) != 0; 622 int infoidx; 623 int is_remove = (option_mask32 & OPT_r) != 0; 624 int exitcode = EXIT_SUCCESS; 625 529 626 dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); 530 627 531 628 replace(name, '-', '_'); 532 629 533 dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod); 534 if (already_loaded(name) != is_rmmod) { 630 dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove); 631 632 if (applet_name[0] == 'r') { 633 /* rmmod. 634 * Does not remove dependencies, no need to scan, just remove. 635 * (compat note: this allows and strips .ko suffix) 636 */ 637 rmmod(name); 638 return EXIT_SUCCESS; 639 } 640 641 /* 642 * We used to have "is_remove != already_loaded(name)" check here, but 643 * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80 644 * won't unload modules (there are more than one) 645 * which have this alias. 646 */ 647 if (!is_remove && already_loaded(name)) { 535 648 dbg1_error_msg("nothing to do for '%s'", name); 536 return ;649 return EXIT_SUCCESS; 537 650 } 538 651 539 652 options = NULL; 540 if (!is_r mmod) {653 if (!is_remove) { 541 654 char *opt_filename = xasprintf("/etc/modules/%s", name); 542 655 options = xmalloc_open_read_close(opt_filename, NULL); … … 561 674 /* Scan module directory. This is done only once. 562 675 * It will attempt module load, and will exit(EXIT_SUCCESS) 563 * on success. */ 676 * on success. 677 */ 564 678 module_found_idx = -1; 565 679 recursive_action(".", … … 568 682 NULL, /* dir action */ 569 683 name, /* user data */ 570 0); /* depth */ 684 0 /* depth */ 685 ); 571 686 dbg1_error_msg("dirscan complete"); 572 /* Module was not found, or load failed, or is_r mmod*/687 /* Module was not found, or load failed, or is_remove */ 573 688 if (module_found_idx >= 0) { /* module was found */ 574 info = &modinfo[module_found_idx]; 689 infovec = xzalloc(2 * sizeof(infovec[0])); 690 infovec[0] = &modinfo[module_found_idx]; 575 691 } else { /* search for alias, not a plain module name */ 576 info = find_alias(name);692 infovec = find_alias(name); 577 693 } 578 694 } else { 579 info = find_alias(name); 580 } 581 582 // Problem here: there can be more than one module 583 // for the given alias. For example, 584 // "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches 585 // ata_piix because it has an alias "pci:v00008086d00007010sv*sd*bc*sc*i*" 586 // and ata_generic, it has an alias "alias=pci:v*d*sv*sd*bc01sc01i*" 587 // Standard modprobe would load them both. 588 // In this code, find_alias() returns only the first matching module. 589 590 /* rmmod? unload it by name */ 591 if (is_rmmod) { 592 if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) { 593 if (!(option_mask32 & OPT_q)) 594 bb_perror_msg("remove '%s'", name); 595 goto ret; 596 } 597 598 if (applet_name[0] == 'r') { 599 /* rmmod: do not remove dependencies, exit */ 600 goto ret; 601 } 602 695 infovec = find_alias(name); 696 } 697 698 if (!infovec) { 699 /* both dirscan and find_alias found nothing */ 700 if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ 701 bb_error_msg("module '%s' not found", name); 702 //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? 703 goto ret; 704 } 705 706 /* There can be more than one module for the given alias. For example, 707 * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches 708 * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*" 709 * and ata_generic, it has alias "pci:v*d*sv*sd*bc01sc01i*" 710 * Standard modprobe loads them both. We achieve it by returning 711 * a *list* of modinfo pointers from find_alias(). 712 */ 713 714 /* modprobe -r? unload module(s) */ 715 if (is_remove) { 716 infoidx = 0; 717 while ((info = infovec[infoidx++]) != NULL) { 718 int r = rmmod(bb_get_last_path_component_nostrip(info->pathname)); 719 if (r != 0) { 720 goto ret; /* error */ 721 } 722 } 603 723 /* modprobe -r: we do not stop here - 604 724 * continue to unload modules on which the module depends: … … 609 729 } 610 730 611 if (!info) { 612 /* both dirscan and find_alias found nothing */ 613 if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ 614 bb_error_msg("module '%s' not found", name); 615 //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? 616 goto ret; 617 } 618 619 /* Iterate thru dependencies, trying to (un)load them */ 620 deps = str_2_list(info->deps); 621 for (s = deps; *s; s += strlen(s) + 1) { 622 //if (strcmp(name, s) != 0) // N.B. do loops exist? 623 dbg1_error_msg("recurse on dep '%s'", s); 624 process_module(s, NULL); 625 dbg1_error_msg("recurse on dep '%s' done", s); 626 } 627 free(deps); 628 629 /* modprobe -> load it */ 630 if (!is_rmmod) { 631 if (!options || strstr(options, "blacklist") == NULL) { 632 errno = 0; 633 if (load_module(info->pathname, options) != 0) { 634 if (EEXIST != errno) { 635 bb_error_msg("'%s': %s", 636 info->pathname, 637 moderror(errno)); 638 } else { 639 dbg1_error_msg("'%s': %s", 640 info->pathname, 641 moderror(errno)); 642 } 731 infoidx = 0; 732 while ((info = infovec[infoidx++]) != NULL) { 733 /* Iterate thru dependencies, trying to (un)load them */ 734 deps = str_2_list(info->deps); 735 for (s = deps; *s; s += strlen(s) + 1) { 736 //if (strcmp(name, s) != 0) // N.B. do loops exist? 737 dbg1_error_msg("recurse on dep '%s'", s); 738 process_module(s, NULL); 739 dbg1_error_msg("recurse on dep '%s' done", s); 740 } 741 free(deps); 742 743 if (is_remove) 744 continue; 745 746 /* We are modprobe: load it */ 747 if (options && strstr(options, "blacklist")) { 748 dbg1_error_msg("'%s': blacklisted", info->pathname); 749 continue; 750 } 751 if (info->open_read_failed) { 752 /* We already tried it, didn't work. Don't try load again */ 753 exitcode = EXIT_FAILURE; 754 continue; 755 } 756 errno = 0; 757 if (load_module(info->pathname, options) != 0) { 758 if (EEXIST != errno) { 759 bb_error_msg("'%s': %s", 760 info->pathname, 761 moderror(errno)); 762 } else { 763 dbg1_error_msg("'%s': %s", 764 info->pathname, 765 moderror(errno)); 643 766 } 644 } else { 645 dbg1_error_msg("'%s': blacklisted", info->pathname); 767 exitcode = EXIT_FAILURE; 646 768 } 647 769 } 648 770 ret: 771 free(infovec); 649 772 free(options); 650 //TODO: return load attempt result from process_module. 651 //If dep didn't load ok, continuing makes little sense. 773 774 return exitcode; 652 775 } 653 776 #undef cmdline_options … … 704 827 //usage:#if ENABLE_MODPROBE_SMALL 705 828 706 //// Note: currently, help system shows modprobe --help text for all aliased cmds707 //// (see APPLET_ODDNAME macro definition).708 //// All other help texts defined below are not used. FIXME?709 710 829 //usage:#define depmod_trivial_usage NOUSAGE_STR 711 830 //usage:#define depmod_full_usage "" … … 721 840 //usage: "[SYMBOL=VALUE]..." 722 841 //usage:#define insmod_full_usage "\n\n" 723 //usage: "Load the specified kernel modules into the kernel"842 //usage: "Load kernel module" 724 843 //usage: IF_FEATURE_2_4_MODULES( "\n" 725 844 //usage: "\n -f Force module to load into the wrong kernel version" … … 746 865 747 866 //usage:#define modprobe_trivial_usage 748 //usage: "[-qfwrsv] MODULE [ symbol=value]..."867 //usage: "[-qfwrsv] MODULE [SYMBOL=VALUE]..." 749 868 //usage:#define modprobe_full_usage "\n\n" 750 869 //usage: " -r Remove MODULE (stacks) or do autoclean" … … 760 879 int modprobe_main(int argc UNUSED_PARAM, char **argv) 761 880 { 881 int exitcode; 762 882 struct utsname uts; 763 883 char applet0 = applet_name[0]; … … 831 951 832 952 #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE 833 /* If not rmmod , parse possible module options given on command line.953 /* If not rmmod/-r, parse possible module options given on command line. 834 954 * insmod/modprobe takes one module name, the rest are parameters. */ 835 955 options = NULL; 836 if ( 'r' != applet0) {956 if (!(option_mask32 & OPT_r)) { 837 957 char **arg = argv; 838 958 while (*++arg) { … … 845 965 } 846 966 #else 847 if ( 'r' != applet0)967 if (!(option_mask32 & OPT_r)) 848 968 argv[1] = NULL; 849 969 #endif … … 865 985 *argv, moderror(errno)); 866 986 } 867 return 0;987 return EXIT_SUCCESS; 868 988 } 869 989 870 990 /* Try to load modprobe.dep.bb */ 871 load_dep_bb(); 991 if ('r' != applet0) { /* not rmmod */ 992 load_dep_bb(); 993 } 872 994 873 995 /* Load/remove modules. 874 * Only rmmod loops here, modprobe has only argv[0] */ 996 * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ 997 exitcode = EXIT_SUCCESS; 875 998 do { 876 process_module(*argv, options);999 exitcode |= process_module(*argv, options); 877 1000 } while (*++argv); 878 1001 … … 880 1003 IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) 881 1004 } 882 return EXIT_SUCCESS;883 } 1005 return exitcode; 1006 } -
branches/3.3/mindi-busybox/modutils/modprobe.c
r3232 r3621 16 16 #include <fnmatch.h> 17 17 18 //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) 18 #if 1 19 19 #define DBG(...) ((void)0) 20 #else 21 #define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) 22 #endif 20 23 21 24 /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), … … 88 91 //usage:#define modprobe_trivial_usage 89 92 //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" 90 //usage: " MODULE [ symbol=value]..."93 //usage: " MODULE [SYMBOL=VALUE]..." 91 94 //usage:#define modprobe_full_usage "\n\n" 92 95 //usage: " -a Load multiple MODULEs" … … 148 151 #define MODULE_FLAG_BLACKLISTED 0x0008 149 152 150 struct module_entry { /* I'll call it ME. */151 unsigned flags;152 char *modname; /* stripped of /path/, .ext and s/-/_/g */153 const char *probed_name; /* verbatim as seen on cmdline */154 char *options; /* options from config files */155 llist_t *realnames; /* strings. if this module is an alias, */156 /* real module name is one of these. */157 //Can there really be more than one? Example from real kernel?158 llist_t *deps; /* strings. modules we depend on */159 };160 161 #define DB_HASH_SIZE 256162 163 153 struct globals { 164 154 llist_t *probes; /* MEs of module(s) requested on cmdline */ … … 168 158 smallint need_symbols; 169 159 struct utsname uts; 170 llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */160 module_db db; 171 161 } FIX_ALIASING; 172 162 #define G (*ptr_to_globals) 173 163 #define INIT_G() do { \ 174 164 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 175 165 } while (0) 176 166 … … 193 183 } 194 184 195 /* These three functions called many times, optimizing for speed. 196 * Users reported minute-long delays when they runn iptables repeatedly 197 * (iptables use modprobe to install needed kernel modules). 198 */ 199 static struct module_entry *helper_get_module(const char *module, int create) 200 { 201 char modname[MODULE_NAME_LEN]; 202 struct module_entry *e; 203 llist_t *l; 204 unsigned i; 205 unsigned hash; 206 207 filename2modname(module, modname); 208 209 hash = 0; 210 for (i = 0; modname[i]; i++) 211 hash = ((hash << 5) + hash) + modname[i]; 212 hash %= DB_HASH_SIZE; 213 214 for (l = G.db[hash]; l; l = l->link) { 215 e = (struct module_entry *) l->data; 216 if (strcmp(e->modname, modname) == 0) 217 return e; 218 } 219 if (!create) 220 return NULL; 221 222 e = xzalloc(sizeof(*e)); 223 e->modname = xstrdup(modname); 224 llist_add_to(&G.db[hash], e); 225 226 return e; 227 } 228 static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module) 229 { 230 return helper_get_module(module, 1); 231 } 232 static ALWAYS_INLINE struct module_entry *get_modentry(const char *module) 233 { 234 return helper_get_module(module, 0); 185 static struct module_entry *get_or_add_modentry(const char *module) 186 { 187 return moddb_get_or_create(&G.db, module); 235 188 } 236 189 … … 253 206 G.num_unresolved_deps++; 254 207 if (ENABLE_FEATURE_MODUTILS_SYMBOLS 255 && strncmp(m->modname, "symbol:", 7) == 0208 && is_prefixed_with(m->modname, "symbol:") 256 209 ) { 257 210 G.need_symbols = 1; … … 262 215 struct stat *statbuf UNUSED_PARAM, 263 216 void *userdata UNUSED_PARAM, 264 int depth UNUSED_PARAM)217 int depth) 265 218 { 266 219 char *tokens[3]; … … 268 221 struct module_entry *m; 269 222 int rc = TRUE; 270 271 if (bb_basename(filename)[0] == '.') 223 const char *base, *ext; 224 225 /* Skip files that begin with a "." */ 226 base = bb_basename(filename); 227 if (base[0] == '.') 272 228 goto error; 229 230 /* In dir recursion, skip files that do not end with a ".conf" 231 * depth==0: read_config("modules.{symbols,alias}") must work, 232 * "include FILE_NOT_ENDING_IN_CONF" must work too. 233 */ 234 if (depth != 0) { 235 ext = strrchr(base, '.'); 236 if (ext == NULL || strcmp(ext + 1, "conf")) 237 goto error; 238 } 273 239 274 240 p = config_open2(filename, fopen_for_read); … … 315 281 m->options = gather_options_str(m->options, tokens[2]); 316 282 } else if (strcmp(tokens[0], "include") == 0) { 317 /* include <filename> */283 /* include <filename>/<dirname> (yes, directories also must work) */ 318 284 read_config(tokens[1]); 319 285 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST … … 332 298 { 333 299 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET, 334 config_file_action, NULL, NULL, 1); 300 config_file_action, NULL, NULL, 301 /*depth:*/ 0); 335 302 } 336 303 … … 339 306 /* probed_name may be NULL. modname always exists. */ 340 307 return m->probed_name ? m->probed_name : m->modname; 308 } 309 310 /* Like strsep(&stringp, "\n\t ") but quoted text goes to single token 311 * even if it contains whitespace. 312 */ 313 static char *strsep_quotes(char **stringp) 314 { 315 char *s, *start = *stringp; 316 317 if (!start) 318 return NULL; 319 320 for (s = start; ; s++) { 321 switch (*s) { 322 case '"': 323 s = strchrnul(s + 1, '"'); /* find trailing quote */ 324 if (*s != '\0') 325 s++; /* skip trailing quote */ 326 /* fall through */ 327 case '\0': 328 case '\n': 329 case '\t': 330 case ' ': 331 if (*s != '\0') { 332 *s = '\0'; 333 *stringp = s + 1; 334 } else { 335 *stringp = NULL; 336 } 337 return start; 338 } 339 } 341 340 } 342 341 … … 346 345 char *kcmdline; 347 346 char *kptr; 348 int len;349 347 350 348 kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL); … … 353 351 354 352 kcmdline = kcmdline_buf; 355 len = strlen(modulename); 356 while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) { 357 if (strncmp(modulename, kptr, len) != 0) 358 continue; 359 kptr += len; 360 if (*kptr != '.') 353 while ((kptr = strsep_quotes(&kcmdline)) != NULL) { 354 char *after_modulename = is_prefixed_with(kptr, modulename); 355 if (!after_modulename || *after_modulename != '.') 361 356 continue; 362 357 /* It is "modulename.xxxx" */ 363 kptr ++;358 kptr = after_modulename + 1; 364 359 if (strchr(kptr, '=') != NULL) { 365 360 /* It is "modulename.opt=[val]" */ … … 418 413 rc = 0; 419 414 fn = llist_pop(&m->deps); /* we leak it */ 420 m2 = get_or_add_modentry( fn);415 m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn)); 421 416 422 417 if (option_mask32 & OPT_REMOVE) { … … 426 421 if (rc) { 427 422 if (first) { 428 bb_error_msg("can't unload module %s: %s", 429 humanly_readable_name(m2), 430 moderror(rc)); 423 bb_perror_msg("can't unload module '%s'", 424 humanly_readable_name(m2)); 431 425 break; 432 426 } … … 500 494 if (colon == NULL) 501 495 continue; 502 *colon = 0;503 504 m = get_modentry(tokens[0]);496 *colon = '\0'; 497 498 m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0])); 505 499 if (m == NULL) 506 500 continue; … … 547 541 if (opt & OPT_LIST_ONLY) { 548 542 int i; 549 char name[MODULE_NAME_LEN];550 543 char *colon, *tokens[2]; 551 544 parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); … … 559 552 continue; 560 553 *colon = '\0'; 561 filename2modname(tokens[0], name);562 554 if (!argv[0]) 563 555 puts(tokens[0]); 564 556 else { 557 char name[MODULE_NAME_LEN]; 558 filename2modname( 559 bb_get_last_path_component_nostrip(tokens[0]), 560 name 561 ); 565 562 for (i = 0; argv[i]; i++) { 566 563 if (fnmatch(argv[i], name, 0) == 0) { … … 584 581 */ 585 582 if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0) 586 bb_perror_ msg_and_die("rmmod");583 bb_perror_nomsg_and_die(); 587 584 } 588 585 return EXIT_SUCCESS; … … 660 657 } 661 658 659 if (ENABLE_FEATURE_CLEAN_UP) 660 moddb_free(&G.db); 661 662 662 return (rc != 0); 663 663 } -
branches/3.3/mindi-busybox/modutils/modutils-24.c
r3232 r3621 2256 2256 * their references. 2257 2257 */ 2258 if ( strncmp((char *)s->name, "GPLONLY_", 8) == 0) {2258 if (is_prefixed_with((char *)s->name, "GPLONLY_")) { 2259 2259 #if ENABLE_FEATURE_CHECK_TAINTED_MODULE 2260 2260 if (gpl) -
branches/3.3/mindi-busybox/modutils/modutils.c
r3232 r3621 17 17 #endif 18 18 19 static module_entry *helper_get_module(module_db *db, const char *module, int create) 20 { 21 char modname[MODULE_NAME_LEN]; 22 struct module_entry *e; 23 unsigned i, hash; 24 25 filename2modname(module, modname); 26 27 hash = 0; 28 for (i = 0; modname[i]; i++) 29 hash = ((hash << 5) + hash) + modname[i]; 30 hash %= MODULE_HASH_SIZE; 31 32 for (e = db->buckets[hash]; e; e = e->next) 33 if (strcmp(e->modname, modname) == 0) 34 return e; 35 if (!create) 36 return NULL; 37 38 e = xzalloc(sizeof(*e)); 39 e->modname = xstrdup(modname); 40 e->next = db->buckets[hash]; 41 db->buckets[hash] = e; 42 IF_DEPMOD(e->dnext = e->dprev = e;) 43 44 return e; 45 } 46 module_entry* FAST_FUNC moddb_get(module_db *db, const char *module) 47 { 48 return helper_get_module(db, module, 0); 49 } 50 module_entry* FAST_FUNC moddb_get_or_create(module_db *db, const char *module) 51 { 52 return helper_get_module(db, module, 1); 53 } 54 55 void FAST_FUNC moddb_free(module_db *db) 56 { 57 module_entry *e, *n; 58 unsigned i; 59 60 for (i = 0; i < MODULE_HASH_SIZE; i++) { 61 for (e = db->buckets[i]; e; e = n) { 62 n = e->next; 63 free(e->name); 64 free(e->modname); 65 free(e); 66 } 67 } 68 } 69 19 70 void FAST_FUNC replace(char *s, char what, char with) 20 71 { … … 48 99 char* FAST_FUNC filename2modname(const char *filename, char *modname) 49 100 { 101 char local_modname[MODULE_NAME_LEN]; 50 102 int i; 51 c har *from;103 const char *from; 52 104 53 105 if (filename == NULL) 54 106 return NULL; 55 107 if (modname == NULL) 56 modname = xmalloc(MODULE_NAME_LEN); 57 from = bb_get_last_path_component_nostrip(filename); 108 modname = local_modname; 109 // Disabled since otherwise "modprobe dir/name" would work 110 // as if it is "modprobe name". It is unclear why 111 // 'basenamization' was here in the first place. 112 //from = bb_get_last_path_component_nostrip(filename); 113 from = filename; 58 114 for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) 59 115 modname[i] = (from[i] == '-') ? '_' : from[i]; 60 116 modname[i] = '\0'; 117 118 if (modname == local_modname) 119 return xstrdup(modname); 61 120 62 121 return modname; … … 183 242 } 184 243 244 /* Note: not suitable for delete_module() errnos. 245 * For them, probably only EWOULDBLOCK needs explaining: 246 * "Other modules depend on us". So far we don't do such 247 * translation and don't use moderror() for removal errors. 248 */ 185 249 const char* FAST_FUNC moderror(int err) 186 250 { -
branches/3.3/mindi-busybox/modutils/modutils.h
r3232 r3621 17 17 * internally for the maximum alias name length, which can be quite long */ 18 18 #define MODULE_NAME_LEN 256 19 #define MODULE_HASH_SIZE 256 20 21 typedef struct module_entry { 22 struct module_entry *next; 23 char *name, *modname; 24 llist_t *deps; 25 IF_MODPROBE( 26 llist_t *realnames; 27 unsigned flags; 28 const char *probed_name; /* verbatim as seen on cmdline */ 29 char *options; /* options from config files */ 30 ) 31 IF_DEPMOD( 32 llist_t *aliases; 33 llist_t *symbols; 34 struct module_entry *dnext, *dprev; 35 ) 36 } module_entry; 37 38 typedef struct module_db { 39 module_entry *buckets[MODULE_HASH_SIZE]; 40 } module_db; 41 42 #define moddb_foreach_module(db, module, index) \ 43 for ((index) = 0; (index) < MODULE_HASH_SIZE; (index)++) \ 44 for (module = (db)->buckets[index]; module; module = module->next) 45 46 module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC; 47 module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC; 48 void moddb_free(module_db *db) FAST_FUNC; 19 49 20 50 void replace(char *s, char what, char with) FAST_FUNC; -
branches/3.3/mindi-busybox/modutils/rmmod.c
r3232 r3621 29 29 int rmmod_main(int argc UNUSED_PARAM, char **argv) 30 30 { 31 int n ;31 int n, err; 32 32 unsigned flags = O_NONBLOCK | O_EXCL; 33 33 … … 41 41 if (n & 4) { 42 42 /* Unload _all_ unused modules via NULL delete_module() call */ 43 if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT) 43 err = bb_delete_module(NULL, flags); 44 if (err && err != EFAULT) 44 45 bb_perror_msg_and_die("rmmod"); 45 46 return EXIT_SUCCESS; … … 59 60 else 60 61 filename2modname(bname, modname); 61 if (bb_delete_module(modname, flags)) 62 bb_error_msg_and_die("can't unload '%s': %s", 63 modname, moderror(errno)); 62 err = bb_delete_module(modname, flags); 63 if (err) 64 bb_perror_msg_and_die("can't unload module '%s'", 65 modname); 64 66 } 65 67
Note:
See TracChangeset
for help on using the changeset viewer.