Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/modutils/modprobe.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note:
See TracChangeset
for help on using the changeset viewer.