diff options
-rw-r--r-- | modutils/modprobe.c | 169 |
1 files changed, 106 insertions, 63 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 1a4f5d4d4..0c59e8ab3 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -48,6 +48,10 @@ struct mod_list_t { /* two-way list of modules to process */ | |||
48 | struct mod_list_t * m_next; | 48 | struct mod_list_t * m_next; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | struct include_conf_t { | ||
52 | struct dep_t *first; | ||
53 | struct dep_t *current; | ||
54 | }; | ||
51 | 55 | ||
52 | static struct dep_t *depend; | 56 | static struct dep_t *depend; |
53 | 57 | ||
@@ -242,21 +246,60 @@ static int is_conf_command(char *buffer, const char *command) | |||
242 | * This function reads aliases and default module options from a configuration file | 246 | * This function reads aliases and default module options from a configuration file |
243 | * (/etc/modprobe.conf syntax). It supports includes (only files, no directories). | 247 | * (/etc/modprobe.conf syntax). It supports includes (only files, no directories). |
244 | */ | 248 | */ |
245 | static void include_conf(struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd) | 249 | |
250 | static int FAST_FUNC include_conf_file_act(const char *filename, | ||
251 | struct stat *statbuf UNUSED_PARAM, | ||
252 | void *userdata, | ||
253 | int depth UNUSED_PARAM); | ||
254 | |||
255 | static int FAST_FUNC include_conf_dir_act(const char *filename UNUSED_PARAM, | ||
256 | struct stat *statbuf UNUSED_PARAM, | ||
257 | void *userdata UNUSED_PARAM, | ||
258 | int depth) | ||
259 | { | ||
260 | if (depth > 1) | ||
261 | return SKIP; | ||
262 | |||
263 | return TRUE; | ||
264 | } | ||
265 | |||
266 | static int inline include_conf_recursive(struct include_conf_t *conf, const char *filename) | ||
267 | { | ||
268 | return recursive_action(filename, ACTION_RECURSE, | ||
269 | include_conf_file_act, | ||
270 | include_conf_dir_act, | ||
271 | conf, 1); | ||
272 | } | ||
273 | |||
274 | static int FAST_FUNC include_conf_file_act(const char *filename, | ||
275 | struct stat *statbuf UNUSED_PARAM, | ||
276 | void *userdata, | ||
277 | int depth UNUSED_PARAM) | ||
246 | { | 278 | { |
279 | struct include_conf_t *conf = (struct include_conf_t *) userdata; | ||
280 | struct dep_t **first = &conf->first; | ||
281 | struct dep_t **current = &conf->current; | ||
247 | int continuation_line = 0; | 282 | int continuation_line = 0; |
283 | int fd; | ||
284 | |||
285 | if (bb_basename(filename)[0] == '.') | ||
286 | return TRUE; | ||
287 | |||
288 | fd = open(filename, O_RDONLY); | ||
289 | if (fd < 0) | ||
290 | return FALSE; | ||
248 | 291 | ||
249 | // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)! | 292 | // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)! |
250 | 293 | ||
251 | while (reads(fd, buffer, buflen)) { | 294 | while (reads(fd, line_buffer, sizeof(line_buffer))) { |
252 | int l; | 295 | int l; |
253 | 296 | ||
254 | *strchrnul(buffer, '#') = '\0'; | 297 | *strchrnul(line_buffer, '#') = '\0'; |
255 | 298 | ||
256 | l = strlen(buffer); | 299 | l = strlen(line_buffer); |
257 | 300 | ||
258 | while (l && isspace(buffer[l-1])) { | 301 | while (l && isspace(line_buffer[l-1])) { |
259 | buffer[l-1] = '\0'; | 302 | line_buffer[l-1] = '\0'; |
260 | l--; | 303 | l--; |
261 | } | 304 | } |
262 | 305 | ||
@@ -268,10 +311,10 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf | |||
268 | if (continuation_line) | 311 | if (continuation_line) |
269 | continue; | 312 | continue; |
270 | 313 | ||
271 | if (is_conf_command(buffer, "alias")) { | 314 | if (is_conf_command(line_buffer, "alias")) { |
272 | char *alias, *mod; | 315 | char *alias, *mod; |
273 | 316 | ||
274 | if (parse_tag_value(buffer + 6, &alias, &mod)) { | 317 | if (parse_tag_value(line_buffer + 6, &alias, &mod)) { |
275 | /* handle alias as a module dependent on the aliased module */ | 318 | /* handle alias as a module dependent on the aliased module */ |
276 | if (!*current) { | 319 | if (!*current) { |
277 | (*first) = (*current) = xzalloc(sizeof(struct dep_t)); | 320 | (*first) = (*current) = xzalloc(sizeof(struct dep_t)); |
@@ -292,11 +335,11 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf | |||
292 | } | 335 | } |
293 | /*(*current)->m_next = NULL; - done by xzalloc */ | 336 | /*(*current)->m_next = NULL; - done by xzalloc */ |
294 | } | 337 | } |
295 | } else if (is_conf_command(buffer, "options")) { | 338 | } else if (is_conf_command(line_buffer, "options")) { |
296 | char *mod, *opt; | 339 | char *mod, *opt; |
297 | 340 | ||
298 | /* split the line in the module/alias name, and options */ | 341 | /* split the line in the module/alias name, and options */ |
299 | if (parse_tag_value(buffer + 8, &mod, &opt)) { | 342 | if (parse_tag_value(line_buffer + 8, &mod, &opt)) { |
300 | struct dep_t *dt; | 343 | struct dep_t *dt; |
301 | 344 | ||
302 | /* find the corresponding module */ | 345 | /* find the corresponding module */ |
@@ -315,22 +358,17 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf | |||
315 | } | 358 | } |
316 | } | 359 | } |
317 | } | 360 | } |
318 | } else if (is_conf_command(buffer, "include")) { | 361 | } else if (is_conf_command(line_buffer, "include")) { |
319 | int fdi; | 362 | char *includefile; |
320 | char *filename; | 363 | |
321 | 364 | includefile = skip_whitespace(line_buffer + 8); | |
322 | filename = skip_whitespace(buffer + 8); | 365 | include_conf_recursive(conf, includefile); |
323 | fdi = open(filename, O_RDONLY); | ||
324 | if (fdi >= 0) { | ||
325 | include_conf(first, current, buffer, buflen, fdi); | ||
326 | close(fdi); | ||
327 | } | ||
328 | } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST && | 366 | } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST && |
329 | (is_conf_command(buffer, "blacklist"))) { | 367 | (is_conf_command(line_buffer, "blacklist"))) { |
330 | char *mod; | 368 | char *mod; |
331 | struct dep_t *dt; | 369 | struct dep_t *dt; |
332 | 370 | ||
333 | mod = skip_whitespace(buffer + 10); | 371 | mod = skip_whitespace(line_buffer + 10); |
334 | for (dt = *first; dt; dt = dt->m_next) { | 372 | for (dt = *first; dt; dt = dt->m_next) { |
335 | if (strcmp(dt->m_name, mod) == 0) | 373 | if (strcmp(dt->m_name, mod) == 0) |
336 | break; | 374 | break; |
@@ -339,6 +377,23 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf | |||
339 | dt->m_isblacklisted = 1; | 377 | dt->m_isblacklisted = 1; |
340 | } | 378 | } |
341 | } /* while (reads(...)) */ | 379 | } /* while (reads(...)) */ |
380 | |||
381 | close(fd); | ||
382 | return TRUE; | ||
383 | } | ||
384 | |||
385 | static int include_conf_file(struct include_conf_t *conf, | ||
386 | const char *filename) | ||
387 | { | ||
388 | return include_conf_file_act(filename, NULL, conf, 0); | ||
389 | } | ||
390 | |||
391 | static int include_conf_file2(struct include_conf_t *conf, | ||
392 | const char *filename, const char *oldname) | ||
393 | { | ||
394 | if (include_conf_file(conf, filename) == TRUE) | ||
395 | return TRUE; | ||
396 | return include_conf_file(conf, oldname); | ||
342 | } | 397 | } |
343 | 398 | ||
344 | /* | 399 | /* |
@@ -350,8 +405,7 @@ static struct dep_t *build_dep(void) | |||
350 | { | 405 | { |
351 | int fd; | 406 | int fd; |
352 | struct utsname un; | 407 | struct utsname un; |
353 | struct dep_t *first = NULL; | 408 | struct include_conf_t conf = { NULL, NULL }; |
354 | struct dep_t *current = NULL; | ||
355 | char *filename; | 409 | char *filename; |
356 | int continuation_line = 0; | 410 | int continuation_line = 0; |
357 | int k_version; | 411 | int k_version; |
@@ -421,14 +475,14 @@ static struct dep_t *build_dep(void) | |||
421 | mod = xstrndup(mods, dot - mods); | 475 | mod = xstrndup(mods, dot - mods); |
422 | 476 | ||
423 | /* enqueue new module */ | 477 | /* enqueue new module */ |
424 | if (!current) { | 478 | if (!conf.current) { |
425 | first = current = xzalloc(sizeof(struct dep_t)); | 479 | conf.first = conf.current = xzalloc(sizeof(struct dep_t)); |
426 | } else { | 480 | } else { |
427 | current->m_next = xzalloc(sizeof(struct dep_t)); | 481 | conf.current->m_next = xzalloc(sizeof(struct dep_t)); |
428 | current = current->m_next; | 482 | conf.current = conf.current->m_next; |
429 | } | 483 | } |
430 | current->m_name = mod; | 484 | conf.current->m_name = mod; |
431 | current->m_path = xstrdup(modpath); | 485 | conf.current->m_path = xstrdup(modpath); |
432 | /*current->m_options = NULL; - xzalloc did it*/ | 486 | /*current->m_options = NULL; - xzalloc did it*/ |
433 | /*current->m_isalias = 0;*/ | 487 | /*current->m_isalias = 0;*/ |
434 | /*current->m_depcnt = 0;*/ | 488 | /*current->m_depcnt = 0;*/ |
@@ -482,8 +536,8 @@ static struct dep_t *build_dep(void) | |||
482 | dep = xstrndup(deps, next - deps - ext + 1); | 536 | dep = xstrndup(deps, next - deps - ext + 1); |
483 | 537 | ||
484 | /* Add the new dependable module name */ | 538 | /* Add the new dependable module name */ |
485 | current->m_deparr = xrealloc_vector(current->m_deparr, 2, current->m_depcnt); | 539 | conf.current->m_deparr = xrealloc_vector(conf.current->m_deparr, 2, conf.current->m_depcnt); |
486 | current->m_deparr[current->m_depcnt++] = dep; | 540 | conf.current->m_deparr[conf.current->m_depcnt++] = dep; |
487 | 541 | ||
488 | p = next + 2; | 542 | p = next + 2; |
489 | } while (next < end); | 543 | } while (next < end); |
@@ -500,52 +554,41 @@ static struct dep_t *build_dep(void) | |||
500 | * >=2.6: we only care about modprobe.conf | 554 | * >=2.6: we only care about modprobe.conf |
501 | * <=2.4: we care about modules.conf and conf.modules | 555 | * <=2.4: we care about modules.conf and conf.modules |
502 | */ | 556 | */ |
503 | if (ENABLE_FEATURE_2_6_MODULES | 557 | { |
504 | && (fd = open("/etc/modprobe.conf", O_RDONLY)) < 0) | 558 | int r = FALSE; |
505 | if (ENABLE_FEATURE_2_4_MODULES | 559 | |
506 | && (fd = open("/etc/modules.conf", O_RDONLY)) < 0) | 560 | if (ENABLE_FEATURE_2_6_MODULES) { |
507 | if (ENABLE_FEATURE_2_4_MODULES) | 561 | if (include_conf_file(&conf, "/etc/modprobe.conf")) |
508 | fd = open("/etc/conf.modules", O_RDONLY); | 562 | r = TRUE; |
509 | 563 | if (include_conf_recursive(&conf, "/etc/modprobe.d")) | |
510 | if (fd >= 0) { | 564 | r = TRUE; |
511 | include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd); | 565 | } |
512 | close(fd); | 566 | if (ENABLE_FEATURE_2_4_MODULES && !r) |
567 | include_conf_file2(&conf, | ||
568 | "/etc/modules.conf", | ||
569 | "/etc/conf.modules"); | ||
513 | } | 570 | } |
514 | 571 | ||
515 | /* Only 2.6 has a modules.alias file */ | 572 | /* Only 2.6 has a modules.alias file */ |
516 | if (ENABLE_FEATURE_2_6_MODULES) { | 573 | if (ENABLE_FEATURE_2_6_MODULES) { |
517 | /* Parse kernel-declared module aliases */ | 574 | /* Parse kernel-declared module aliases */ |
518 | filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.alias", un.release); | 575 | filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.alias", un.release); |
519 | fd = open(filename, O_RDONLY); | 576 | include_conf_file2(&conf, |
520 | if (fd < 0) { | 577 | filename, |
521 | /* Ok, that didn't work. Fall back to looking in /lib/modules */ | 578 | CONFIG_DEFAULT_MODULES_DIR"/modules.alias"); |
522 | fd = open(CONFIG_DEFAULT_MODULES_DIR"/modules.alias", O_RDONLY); | ||
523 | } | ||
524 | if (ENABLE_FEATURE_CLEAN_UP) | 579 | if (ENABLE_FEATURE_CLEAN_UP) |
525 | free(filename); | 580 | free(filename); |
526 | 581 | ||
527 | if (fd >= 0) { | ||
528 | include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd); | ||
529 | close(fd); | ||
530 | } | ||
531 | |||
532 | /* Parse kernel-declared symbol aliases */ | 582 | /* Parse kernel-declared symbol aliases */ |
533 | filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.symbols", un.release); | 583 | filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.symbols", un.release); |
534 | fd = open(filename, O_RDONLY); | 584 | include_conf_file2(&conf, |
535 | if (fd < 0) { | 585 | filename, |
536 | /* Ok, that didn't work. Fall back to looking in /lib/modules */ | 586 | CONFIG_DEFAULT_MODULES_DIR"/modules.symbols"); |
537 | fd = open(CONFIG_DEFAULT_MODULES_DIR"/modules.symbols", O_RDONLY); | ||
538 | } | ||
539 | if (ENABLE_FEATURE_CLEAN_UP) | 587 | if (ENABLE_FEATURE_CLEAN_UP) |
540 | free(filename); | 588 | free(filename); |
541 | |||
542 | if (fd >= 0) { | ||
543 | include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd); | ||
544 | close(fd); | ||
545 | } | ||
546 | } | 589 | } |
547 | 590 | ||
548 | return first; | 591 | return conf.first; |
549 | } | 592 | } |
550 | 593 | ||
551 | /* return 1 = loaded, 0 = not loaded, -1 = can't tell */ | 594 | /* return 1 = loaded, 0 = not loaded, -1 = can't tell */ |