diff options
-rw-r--r-- | libbb/xreadlink.c | 3 | ||||
-rw-r--r-- | modutils/insmod.c | 411 | ||||
-rw-r--r-- | modutils/lsmod.c | 10 | ||||
-rw-r--r-- | modutils/modprobe.c | 270 |
4 files changed, 313 insertions, 381 deletions
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 4d87b944d..98b795f56 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c | |||
@@ -18,7 +18,8 @@ char *xmalloc_readlink(const char *path) | |||
18 | int bufsize = 0, readsize = 0; | 18 | int bufsize = 0, readsize = 0; |
19 | 19 | ||
20 | do { | 20 | do { |
21 | buf = xrealloc(buf, bufsize += GROWBY); | 21 | bufsize += GROWBY; |
22 | buf = xrealloc(buf, bufsize); | ||
22 | readsize = readlink(path, buf, bufsize); | 23 | readsize = readlink(path, buf, bufsize); |
23 | if (readsize == -1) { | 24 | if (readsize == -1) { |
24 | free(buf); | 25 | free(buf); |
diff --git a/modutils/insmod.c b/modutils/insmod.c index 6f3b7d0f4..df75abbfa 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -67,25 +67,21 @@ | |||
67 | #define ENABLE_FEATURE_2_4_MODULES 1 | 67 | #define ENABLE_FEATURE_2_4_MODULES 1 |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #if !ENABLE_FEATURE_2_4_MODULES | 70 | /* |
71 | #define insmod_ng_main insmod_main | 71 | * Big piece of 2.4-specific code |
72 | #endif | 72 | */ |
73 | #if ENABLE_FEATURE_2_4_MODULES | ||
73 | 74 | ||
74 | #if ENABLE_FEATURE_2_6_MODULES | 75 | #if ENABLE_FEATURE_2_6_MODULES |
75 | extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 76 | static int insmod_ng_main(int argc, char **argv); |
76 | #endif | 77 | #endif |
77 | 78 | ||
78 | |||
79 | #if ENABLE_FEATURE_2_4_MODULES | ||
80 | |||
81 | |||
82 | #if ENABLE_FEATURE_INSMOD_LOADINKMEM | 79 | #if ENABLE_FEATURE_INSMOD_LOADINKMEM |
83 | #define LOADBITS 0 | 80 | #define LOADBITS 0 |
84 | #else | 81 | #else |
85 | #define LOADBITS 1 | 82 | #define LOADBITS 1 |
86 | #endif | 83 | #endif |
87 | 84 | ||
88 | |||
89 | /* Alpha */ | 85 | /* Alpha */ |
90 | #if defined(__alpha__) | 86 | #if defined(__alpha__) |
91 | #define MATCH_MACHINE(x) (x == EM_ALPHA) | 87 | #define MATCH_MACHINE(x) (x == EM_ALPHA) |
@@ -627,13 +623,13 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, | |||
627 | 623 | ||
628 | static void *obj_extend_section(struct obj_section *sec, unsigned long more); | 624 | static void *obj_extend_section(struct obj_section *sec, unsigned long more); |
629 | 625 | ||
630 | static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 626 | static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
631 | const char *string); | 627 | const char *string); |
632 | 628 | ||
633 | static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 629 | static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
634 | struct obj_symbol *sym); | 630 | struct obj_symbol *sym); |
635 | 631 | ||
636 | static int obj_check_undefineds(struct obj_file *f); | 632 | static void obj_check_undefineds(struct obj_file *f); |
637 | 633 | ||
638 | static void obj_allocate_commons(struct obj_file *f); | 634 | static void obj_allocate_commons(struct obj_file *f); |
639 | 635 | ||
@@ -788,7 +784,6 @@ static size_t nksyms; | |||
788 | static struct external_module *ext_modules; | 784 | static struct external_module *ext_modules; |
789 | static int n_ext_modules; | 785 | static int n_ext_modules; |
790 | static int n_ext_modules_used; | 786 | static int n_ext_modules_used; |
791 | extern int delete_module(const char *); | ||
792 | 787 | ||
793 | static char *m_filename; | 788 | static char *m_filename; |
794 | static char *m_fullName; | 789 | static char *m_fullName; |
@@ -801,19 +796,16 @@ static int check_module_name_match(const char *filename, struct stat *statbuf, | |||
801 | void *userdata, int depth) | 796 | void *userdata, int depth) |
802 | { | 797 | { |
803 | char *fullname = (char *) userdata; | 798 | char *fullname = (char *) userdata; |
799 | char *tmp; | ||
804 | 800 | ||
805 | if (fullname[0] == '\0') | 801 | if (fullname[0] == '\0') |
806 | return FALSE; | 802 | return FALSE; |
807 | else { | 803 | |
808 | char *tmp, *tmp1 = xstrdup(filename); | 804 | tmp = bb_get_last_path_component_nostrip(filename); |
809 | tmp = bb_get_last_path_component_nostrip(tmp1); | 805 | if (strcmp(tmp, fullname) == 0) { |
810 | if (strcmp(tmp, fullname) == 0) { | 806 | /* Stop searching if we find a match */ |
811 | free(tmp1); | 807 | m_filename = xstrdup(filename); |
812 | /* Stop searching if we find a match */ | 808 | return FALSE; |
813 | m_filename = xstrdup(filename); | ||
814 | return FALSE; | ||
815 | } | ||
816 | free(tmp1); | ||
817 | } | 809 | } |
818 | return TRUE; | 810 | return TRUE; |
819 | } | 811 | } |
@@ -824,25 +816,19 @@ static int check_module_name_match(const char *filename, struct stat *statbuf, | |||
824 | static struct obj_file *arch_new_file(void) | 816 | static struct obj_file *arch_new_file(void) |
825 | { | 817 | { |
826 | struct arch_file *f; | 818 | struct arch_file *f; |
827 | f = xmalloc(sizeof(*f)); | 819 | f = xzalloc(sizeof(*f)); |
828 | 820 | return &f->root; /* it's a first member */ | |
829 | memset(f, 0, sizeof(*f)); | ||
830 | |||
831 | return &f->root; | ||
832 | } | 821 | } |
833 | 822 | ||
834 | static struct obj_section *arch_new_section(void) | 823 | static struct obj_section *arch_new_section(void) |
835 | { | 824 | { |
836 | return xmalloc(sizeof(struct obj_section)); | 825 | return xzalloc(sizeof(struct obj_section)); |
837 | } | 826 | } |
838 | 827 | ||
839 | static struct obj_symbol *arch_new_symbol(void) | 828 | static struct obj_symbol *arch_new_symbol(void) |
840 | { | 829 | { |
841 | struct arch_symbol *sym; | 830 | struct arch_symbol *sym; |
842 | sym = xmalloc(sizeof(*sym)); | 831 | sym = xzalloc(sizeof(*sym)); |
843 | |||
844 | memset(sym, 0, sizeof(*sym)); | ||
845 | |||
846 | return &sym->root; | 832 | return &sym->root; |
847 | } | 833 | } |
848 | 834 | ||
@@ -2210,7 +2196,6 @@ static struct obj_section *obj_create_alloced_section(struct obj_file *f, | |||
2210 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); | 2196 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); |
2211 | f->sections[newidx] = sec = arch_new_section(); | 2197 | f->sections[newidx] = sec = arch_new_section(); |
2212 | 2198 | ||
2213 | memset(sec, 0, sizeof(*sec)); | ||
2214 | sec->header.sh_type = SHT_PROGBITS; | 2199 | sec->header.sh_type = SHT_PROGBITS; |
2215 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; | 2200 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; |
2216 | sec->header.sh_size = size; | 2201 | sec->header.sh_size = size; |
@@ -2236,7 +2221,6 @@ static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, | |||
2236 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); | 2221 | f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); |
2237 | f->sections[newidx] = sec = arch_new_section(); | 2222 | f->sections[newidx] = sec = arch_new_section(); |
2238 | 2223 | ||
2239 | memset(sec, 0, sizeof(*sec)); | ||
2240 | sec->header.sh_type = SHT_PROGBITS; | 2224 | sec->header.sh_type = SHT_PROGBITS; |
2241 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; | 2225 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; |
2242 | sec->header.sh_size = size; | 2226 | sec->header.sh_size = size; |
@@ -2398,7 +2382,7 @@ static char *get_modinfo_value(struct obj_file *f, const char *key) | |||
2398 | /*======================================================================*/ | 2382 | /*======================================================================*/ |
2399 | /* Functions relating to module loading after 2.1.18. */ | 2383 | /* Functions relating to module loading after 2.1.18. */ |
2400 | 2384 | ||
2401 | static int | 2385 | static void |
2402 | new_process_module_arguments(struct obj_file *f, int argc, char **argv) | 2386 | new_process_module_arguments(struct obj_file *f, int argc, char **argv) |
2403 | { | 2387 | { |
2404 | while (argc > 0) { | 2388 | while (argc > 0) { |
@@ -2408,7 +2392,8 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2408 | int min, max, n; | 2392 | int min, max, n; |
2409 | 2393 | ||
2410 | p = *argv; | 2394 | p = *argv; |
2411 | if ((q = strchr(p, '=')) == NULL) { | 2395 | q = strchr(p, '='); |
2396 | if (q == NULL) { | ||
2412 | argc--; | 2397 | argc--; |
2413 | continue; | 2398 | continue; |
2414 | } | 2399 | } |
@@ -2421,8 +2406,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2421 | p = get_modinfo_value(f, key); | 2406 | p = get_modinfo_value(f, key); |
2422 | key += 5; | 2407 | key += 5; |
2423 | if (p == NULL) { | 2408 | if (p == NULL) { |
2424 | bb_error_msg("invalid parameter %s", key); | 2409 | bb_error_msg_and_die("invalid parameter %s", key); |
2425 | return 0; | ||
2426 | } | 2410 | } |
2427 | 2411 | ||
2428 | #ifdef SYMBOL_PREFIX | 2412 | #ifdef SYMBOL_PREFIX |
@@ -2436,8 +2420,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2436 | 2420 | ||
2437 | /* Also check that the parameter was not resolved from the kernel. */ | 2421 | /* Also check that the parameter was not resolved from the kernel. */ |
2438 | if (sym == NULL || sym->secidx > SHN_HIRESERVE) { | 2422 | if (sym == NULL || sym->secidx > SHN_HIRESERVE) { |
2439 | bb_error_msg("symbol for parameter %s not found", key); | 2423 | bb_error_msg_and_die("symbol for parameter %s not found", key); |
2440 | return 0; | ||
2441 | } | 2424 | } |
2442 | 2425 | ||
2443 | if (isdigit(*p)) { | 2426 | if (isdigit(*p)) { |
@@ -2463,11 +2446,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2463 | 2446 | ||
2464 | str = alloca(strlen(q)); | 2447 | str = alloca(strlen(q)); |
2465 | for (r = str, q++; *q != '"'; ++q, ++r) { | 2448 | for (r = str, q++; *q != '"'; ++q, ++r) { |
2466 | if (*q == '\0') { | 2449 | if (*q == '\0') |
2467 | bb_error_msg("improperly terminated string argument for %s", | 2450 | bb_error_msg_and_die("improperly terminated string argument for %s", |
2468 | key); | 2451 | key); |
2469 | return 0; | 2452 | if (*q == '\\') |
2470 | } else if (*q == '\\') | ||
2471 | switch (*++q) { | 2453 | switch (*++q) { |
2472 | case 'a': | 2454 | case 'a': |
2473 | *r = '\a'; | 2455 | *r = '\a'; |
@@ -2513,8 +2495,9 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2513 | default: | 2495 | default: |
2514 | *r = *q; | 2496 | *r = *q; |
2515 | break; | 2497 | break; |
2516 | } else | 2498 | } |
2517 | *r = *q; | 2499 | else |
2500 | *r = *q; | ||
2518 | } | 2501 | } |
2519 | *r = '\0'; | 2502 | *r = '\0'; |
2520 | ++q; | 2503 | ++q; |
@@ -2558,17 +2541,15 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2558 | /* Get the size of each member */ | 2541 | /* Get the size of each member */ |
2559 | /* Probably we should do that outside the loop ? */ | 2542 | /* Probably we should do that outside the loop ? */ |
2560 | if (!isdigit(*(p + 1))) { | 2543 | if (!isdigit(*(p + 1))) { |
2561 | bb_error_msg("parameter type 'c' for %s must be followed by" | 2544 | bb_error_msg_and_die("parameter type 'c' for %s must be followed by" |
2562 | " the maximum size", key); | 2545 | " the maximum size", key); |
2563 | return 0; | ||
2564 | } | 2546 | } |
2565 | charssize = strtoul(p + 1, (char **) NULL, 10); | 2547 | charssize = strtoul(p + 1, (char **) NULL, 10); |
2566 | 2548 | ||
2567 | /* Check length */ | 2549 | /* Check length */ |
2568 | if (strlen(str) >= charssize) { | 2550 | if (strlen(str) >= charssize) { |
2569 | bb_error_msg("string too long for %s (max %ld)", key, | 2551 | bb_error_msg_and_die("string too long for %s (max %ld)", key, |
2570 | charssize - 1); | 2552 | charssize - 1); |
2571 | return 0; | ||
2572 | } | 2553 | } |
2573 | 2554 | ||
2574 | /* Copy to location */ | 2555 | /* Copy to location */ |
@@ -2595,12 +2576,10 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) | |||
2595 | break; | 2576 | break; |
2596 | 2577 | ||
2597 | default: | 2578 | default: |
2598 | bb_error_msg("unknown parameter type '%c' for %s", *p, key); | 2579 | bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key); |
2599 | return 0; | ||
2600 | } | 2580 | } |
2601 | } | 2581 | } |
2602 | 2582 | retry_end_of_value: | |
2603 | retry_end_of_value: | ||
2604 | switch (*q) { | 2583 | switch (*q) { |
2605 | case '\0': | 2584 | case '\0': |
2606 | goto end_of_arg; | 2585 | goto end_of_arg; |
@@ -2614,28 +2593,23 @@ retry_end_of_value: | |||
2614 | 2593 | ||
2615 | case ',': | 2594 | case ',': |
2616 | if (++n > max) { | 2595 | if (++n > max) { |
2617 | bb_error_msg("too many values for %s (max %d)", key, max); | 2596 | bb_error_msg_and_die("too many values for %s (max %d)", key, max); |
2618 | return 0; | ||
2619 | } | 2597 | } |
2620 | ++q; | 2598 | ++q; |
2621 | break; | 2599 | break; |
2622 | 2600 | ||
2623 | default: | 2601 | default: |
2624 | bb_error_msg("invalid argument syntax for %s", key); | 2602 | bb_error_msg_and_die("invalid argument syntax for %s", key); |
2625 | return 0; | ||
2626 | } | 2603 | } |
2627 | } | 2604 | } |
2628 | 2605 | end_of_arg: | |
2629 | end_of_arg: | ||
2630 | if (n < min) { | 2606 | if (n < min) { |
2631 | bb_error_msg("too few values for %s (min %d)", key, min); | 2607 | bb_error_msg_and_die("too few values for %s (min %d)", key, min); |
2632 | return 0; | ||
2633 | } | 2608 | } |
2634 | 2609 | ||
2635 | argc--, argv++; | 2610 | argc--; |
2611 | argv++; | ||
2636 | } | 2612 | } |
2637 | |||
2638 | return 1; | ||
2639 | } | 2613 | } |
2640 | 2614 | ||
2641 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING | 2615 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING |
@@ -2644,8 +2618,7 @@ static int new_is_module_checksummed(struct obj_file *f) | |||
2644 | const char *p = get_modinfo_value(f, "using_checksums"); | 2618 | const char *p = get_modinfo_value(f, "using_checksums"); |
2645 | if (p) | 2619 | if (p) |
2646 | return xatoi(p); | 2620 | return xatoi(p); |
2647 | else | 2621 | return 0; |
2648 | return 0; | ||
2649 | } | 2622 | } |
2650 | 2623 | ||
2651 | /* Get the module's kernel version in the canonical integer form. */ | 2624 | /* Get the module's kernel version in the canonical integer form. */ |
@@ -2679,7 +2652,7 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) | |||
2679 | 2652 | ||
2680 | /* Fetch the loaded modules, and all currently exported symbols. */ | 2653 | /* Fetch the loaded modules, and all currently exported symbols. */ |
2681 | 2654 | ||
2682 | static int new_get_kernel_symbols(void) | 2655 | static void new_get_kernel_symbols(void) |
2683 | { | 2656 | { |
2684 | char *module_names, *mn; | 2657 | char *module_names, *mn; |
2685 | struct external_module *modules, *m; | 2658 | struct external_module *modules, *m; |
@@ -2688,15 +2661,17 @@ static int new_get_kernel_symbols(void) | |||
2688 | 2661 | ||
2689 | /* Collect the loaded modules. */ | 2662 | /* Collect the loaded modules. */ |
2690 | 2663 | ||
2691 | module_names = xmalloc(bufsize = 256); | 2664 | bufsize = 256; |
2692 | retry_modules_load: | 2665 | module_names = xmalloc(bufsize); |
2666 | |||
2667 | retry_modules_load: | ||
2693 | if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { | 2668 | if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { |
2694 | if (errno == ENOSPC && bufsize < ret) { | 2669 | if (errno == ENOSPC && bufsize < ret) { |
2695 | module_names = xrealloc(module_names, bufsize = ret); | 2670 | bufsize = ret; |
2671 | module_names = xrealloc(module_names, bufsize); | ||
2696 | goto retry_modules_load; | 2672 | goto retry_modules_load; |
2697 | } | 2673 | } |
2698 | bb_perror_msg("QM_MODULES"); | 2674 | bb_perror_msg_and_die("QM_MODULES"); |
2699 | return 0; | ||
2700 | } | 2675 | } |
2701 | 2676 | ||
2702 | n_ext_modules = nmod = ret; | 2677 | n_ext_modules = nmod = ret; |
@@ -2715,23 +2690,23 @@ retry_modules_load: | |||
2715 | /* The module was removed out from underneath us. */ | 2690 | /* The module was removed out from underneath us. */ |
2716 | continue; | 2691 | continue; |
2717 | } | 2692 | } |
2718 | bb_perror_msg("query_module: QM_INFO: %s", mn); | 2693 | bb_perror_msg_and_die("query_module: QM_INFO: %s", mn); |
2719 | return 0; | ||
2720 | } | 2694 | } |
2721 | 2695 | ||
2722 | syms = xmalloc(bufsize = 1024); | 2696 | bufsize = 1024; |
2723 | retry_mod_sym_load: | 2697 | syms = xmalloc(bufsize); |
2698 | retry_mod_sym_load: | ||
2724 | if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { | 2699 | if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { |
2725 | switch (errno) { | 2700 | switch (errno) { |
2726 | case ENOSPC: | 2701 | case ENOSPC: |
2727 | syms = xrealloc(syms, bufsize = ret); | 2702 | bufsize = ret; |
2703 | syms = xrealloc(syms, bufsize); | ||
2728 | goto retry_mod_sym_load; | 2704 | goto retry_mod_sym_load; |
2729 | case ENOENT: | 2705 | case ENOENT: |
2730 | /* The module was removed out from underneath us. */ | 2706 | /* The module was removed out from underneath us. */ |
2731 | continue; | 2707 | continue; |
2732 | default: | 2708 | default: |
2733 | bb_perror_msg("query_module: QM_SYMBOLS: %s", mn); | 2709 | bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn); |
2734 | return 0; | ||
2735 | } | 2710 | } |
2736 | } | 2711 | } |
2737 | nsyms = ret; | 2712 | nsyms = ret; |
@@ -2750,14 +2725,13 @@ retry_mod_sym_load: | |||
2750 | /* Collect the kernel's symbols. */ | 2725 | /* Collect the kernel's symbols. */ |
2751 | 2726 | ||
2752 | syms = xmalloc(bufsize = 16 * 1024); | 2727 | syms = xmalloc(bufsize = 16 * 1024); |
2753 | retry_kern_sym_load: | 2728 | retry_kern_sym_load: |
2754 | if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { | 2729 | if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { |
2755 | if (errno == ENOSPC && bufsize < ret) { | 2730 | if (errno == ENOSPC && bufsize < ret) { |
2756 | syms = xrealloc(syms, bufsize = ret); | 2731 | syms = xrealloc(syms, bufsize = ret); |
2757 | goto retry_kern_sym_load; | 2732 | goto retry_kern_sym_load; |
2758 | } | 2733 | } |
2759 | bb_perror_msg("kernel: QM_SYMBOLS"); | 2734 | bb_perror_msg_and_die("kernel: QM_SYMBOLS"); |
2760 | return 0; | ||
2761 | } | 2735 | } |
2762 | nksyms = nsyms = ret; | 2736 | nksyms = nsyms = ret; |
2763 | ksyms = syms; | 2737 | ksyms = syms; |
@@ -2765,7 +2739,6 @@ retry_kern_sym_load: | |||
2765 | for (j = 0, s = syms; j < nsyms; ++j, ++s) { | 2739 | for (j = 0, s = syms; j < nsyms; ++j, ++s) { |
2766 | s->name += (unsigned long) syms; | 2740 | s->name += (unsigned long) syms; |
2767 | } | 2741 | } |
2768 | return 1; | ||
2769 | } | 2742 | } |
2770 | 2743 | ||
2771 | 2744 | ||
@@ -2786,7 +2759,7 @@ static int new_is_kernel_checksummed(void) | |||
2786 | } | 2759 | } |
2787 | 2760 | ||
2788 | 2761 | ||
2789 | static int new_create_this_module(struct obj_file *f, const char *m_name) | 2762 | static void new_create_this_module(struct obj_file *f, const char *m_name) |
2790 | { | 2763 | { |
2791 | struct obj_section *sec; | 2764 | struct obj_section *sec; |
2792 | 2765 | ||
@@ -2800,8 +2773,6 @@ static int new_create_this_module(struct obj_file *f, const char *m_name) | |||
2800 | 2773 | ||
2801 | obj_string_patch(f, sec->idx, offsetof(struct new_module, name), | 2774 | obj_string_patch(f, sec->idx, offsetof(struct new_module, name), |
2802 | m_name); | 2775 | m_name); |
2803 | |||
2804 | return 1; | ||
2805 | } | 2776 | } |
2806 | 2777 | ||
2807 | #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS | 2778 | #if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS |
@@ -2985,7 +2956,7 @@ new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size) | |||
2985 | 2956 | ||
2986 | /*======================================================================*/ | 2957 | /*======================================================================*/ |
2987 | 2958 | ||
2988 | static int | 2959 | static void |
2989 | obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 2960 | obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
2990 | const char *string) | 2961 | const char *string) |
2991 | { | 2962 | { |
@@ -3010,11 +2981,9 @@ obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | |||
3010 | loc = obj_extend_section(strsec, len); | 2981 | loc = obj_extend_section(strsec, len); |
3011 | } | 2982 | } |
3012 | memcpy(loc, string, len); | 2983 | memcpy(loc, string, len); |
3013 | |||
3014 | return 1; | ||
3015 | } | 2984 | } |
3016 | 2985 | ||
3017 | static int | 2986 | static void |
3018 | obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | 2987 | obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, |
3019 | struct obj_symbol *sym) | 2988 | struct obj_symbol *sym) |
3020 | { | 2989 | { |
@@ -3026,14 +2995,11 @@ obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, | |||
3026 | p->reloc_offset = offset; | 2995 | p->reloc_offset = offset; |
3027 | p->sym = sym; | 2996 | p->sym = sym; |
3028 | f->symbol_patches = p; | 2997 | f->symbol_patches = p; |
3029 | |||
3030 | return 1; | ||
3031 | } | 2998 | } |
3032 | 2999 | ||
3033 | static int obj_check_undefineds(struct obj_file *f) | 3000 | static void obj_check_undefineds(struct obj_file *f) |
3034 | { | 3001 | { |
3035 | unsigned long i; | 3002 | unsigned i; |
3036 | int ret = 1; | ||
3037 | 3003 | ||
3038 | for (i = 0; i < HASH_BUCKETS; ++i) { | 3004 | for (i = 0; i < HASH_BUCKETS; ++i) { |
3039 | struct obj_symbol *sym; | 3005 | struct obj_symbol *sym; |
@@ -3043,15 +3009,11 @@ static int obj_check_undefineds(struct obj_file *f) | |||
3043 | sym->secidx = SHN_ABS; | 3009 | sym->secidx = SHN_ABS; |
3044 | sym->value = 0; | 3010 | sym->value = 0; |
3045 | } else { | 3011 | } else { |
3046 | if (!flag_quiet) { | 3012 | if (!flag_quiet) |
3047 | bb_error_msg("unresolved symbol %s", sym->name); | 3013 | bb_error_msg_and_die("unresolved symbol %s", sym->name); |
3048 | } | ||
3049 | ret = 0; | ||
3050 | } | 3014 | } |
3051 | } | 3015 | } |
3052 | } | 3016 | } |
3053 | |||
3054 | return ret; | ||
3055 | } | 3017 | } |
3056 | 3018 | ||
3057 | static void obj_allocate_commons(struct obj_file *f) | 3019 | static void obj_allocate_commons(struct obj_file *f) |
@@ -3114,7 +3076,6 @@ static void obj_allocate_commons(struct obj_file *f) | |||
3114 | f->sections[i] = sec = arch_new_section(); | 3076 | f->sections[i] = sec = arch_new_section(); |
3115 | f->header.e_shnum = i + 1; | 3077 | f->header.e_shnum = i + 1; |
3116 | 3078 | ||
3117 | memset(sec, 0, sizeof(*sec)); | ||
3118 | sec->header.sh_type = SHT_PROGBITS; | 3079 | sec->header.sh_type = SHT_PROGBITS; |
3119 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; | 3080 | sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; |
3120 | sec->name = ".bss"; | 3081 | sec->name = ".bss"; |
@@ -3347,44 +3308,38 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3347 | /* Read the file header. */ | 3308 | /* Read the file header. */ |
3348 | 3309 | ||
3349 | f = arch_new_file(); | 3310 | f = arch_new_file(); |
3350 | memset(f, 0, sizeof(*f)); | ||
3351 | f->symbol_cmp = strcmp; | 3311 | f->symbol_cmp = strcmp; |
3352 | f->symbol_hash = obj_elf_hash; | 3312 | f->symbol_hash = obj_elf_hash; |
3353 | f->load_order_search_start = &f->load_order; | 3313 | f->load_order_search_start = &f->load_order; |
3354 | 3314 | ||
3355 | fseek(fp, 0, SEEK_SET); | 3315 | fseek(fp, 0, SEEK_SET); |
3356 | if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { | 3316 | if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { |
3357 | bb_perror_msg("error reading ELF header"); | 3317 | bb_perror_msg_and_die("error reading ELF header"); |
3358 | return NULL; | ||
3359 | } | 3318 | } |
3360 | 3319 | ||
3361 | if (f->header.e_ident[EI_MAG0] != ELFMAG0 | 3320 | if (f->header.e_ident[EI_MAG0] != ELFMAG0 |
3362 | || f->header.e_ident[EI_MAG1] != ELFMAG1 | 3321 | || f->header.e_ident[EI_MAG1] != ELFMAG1 |
3363 | || f->header.e_ident[EI_MAG2] != ELFMAG2 | 3322 | || f->header.e_ident[EI_MAG2] != ELFMAG2 |
3364 | || f->header.e_ident[EI_MAG3] != ELFMAG3) { | 3323 | || f->header.e_ident[EI_MAG3] != ELFMAG3) { |
3365 | bb_error_msg("not an ELF file"); | 3324 | bb_error_msg_and_die("not an ELF file"); |
3366 | return NULL; | ||
3367 | } | 3325 | } |
3368 | if (f->header.e_ident[EI_CLASS] != ELFCLASSM | 3326 | if (f->header.e_ident[EI_CLASS] != ELFCLASSM |
3369 | || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN | 3327 | || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN |
3370 | ? ELFDATA2MSB : ELFDATA2LSB) | 3328 | ? ELFDATA2MSB : ELFDATA2LSB) |
3371 | || f->header.e_ident[EI_VERSION] != EV_CURRENT | 3329 | || f->header.e_ident[EI_VERSION] != EV_CURRENT |
3372 | || !MATCH_MACHINE(f->header.e_machine)) { | 3330 | || !MATCH_MACHINE(f->header.e_machine)) { |
3373 | bb_error_msg("ELF file not for this architecture"); | 3331 | bb_error_msg_and_die("ELF file not for this architecture"); |
3374 | return NULL; | ||
3375 | } | 3332 | } |
3376 | if (f->header.e_type != ET_REL) { | 3333 | if (f->header.e_type != ET_REL) { |
3377 | bb_error_msg("ELF file not a relocatable object"); | 3334 | bb_error_msg_and_die("ELF file not a relocatable object"); |
3378 | return NULL; | ||
3379 | } | 3335 | } |
3380 | 3336 | ||
3381 | /* Read the section headers. */ | 3337 | /* Read the section headers. */ |
3382 | 3338 | ||
3383 | if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { | 3339 | if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { |
3384 | bb_error_msg("section header size mismatch: %lu != %lu", | 3340 | bb_error_msg_and_die("section header size mismatch: %lu != %lu", |
3385 | (unsigned long) f->header.e_shentsize, | 3341 | (unsigned long) f->header.e_shentsize, |
3386 | (unsigned long) sizeof(ElfW(Shdr))); | 3342 | (unsigned long) sizeof(ElfW(Shdr))); |
3387 | return NULL; | ||
3388 | } | 3343 | } |
3389 | 3344 | ||
3390 | shnum = f->header.e_shnum; | 3345 | shnum = f->header.e_shnum; |
@@ -3394,8 +3349,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3394 | section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); | 3349 | section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); |
3395 | fseek(fp, f->header.e_shoff, SEEK_SET); | 3350 | fseek(fp, f->header.e_shoff, SEEK_SET); |
3396 | if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { | 3351 | if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { |
3397 | bb_perror_msg("error reading ELF section headers"); | 3352 | bb_perror_msg_and_die("error reading ELF section headers"); |
3398 | return NULL; | ||
3399 | } | 3353 | } |
3400 | 3354 | ||
3401 | /* Read the section data. */ | 3355 | /* Read the section data. */ |
@@ -3404,7 +3358,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3404 | struct obj_section *sec; | 3358 | struct obj_section *sec; |
3405 | 3359 | ||
3406 | f->sections[i] = sec = arch_new_section(); | 3360 | f->sections[i] = sec = arch_new_section(); |
3407 | memset(sec, 0, sizeof(*sec)); | ||
3408 | 3361 | ||
3409 | sec->header = section_headers[i]; | 3362 | sec->header = section_headers[i]; |
3410 | sec->idx = i; | 3363 | sec->idx = i; |
@@ -3431,8 +3384,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3431 | sec->contents = xmalloc(sec->header.sh_size); | 3384 | sec->contents = xmalloc(sec->header.sh_size); |
3432 | fseek(fp, sec->header.sh_offset, SEEK_SET); | 3385 | fseek(fp, sec->header.sh_offset, SEEK_SET); |
3433 | if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { | 3386 | if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { |
3434 | bb_perror_msg("error reading ELF section data"); | 3387 | bb_perror_msg_and_die("error reading ELF section data"); |
3435 | return NULL; | ||
3436 | } | 3388 | } |
3437 | } else { | 3389 | } else { |
3438 | sec->contents = NULL; | 3390 | sec->contents = NULL; |
@@ -3441,14 +3393,11 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3441 | 3393 | ||
3442 | #if SHT_RELM == SHT_REL | 3394 | #if SHT_RELM == SHT_REL |
3443 | case SHT_RELA: | 3395 | case SHT_RELA: |
3444 | bb_error_msg("RELA relocations not supported on this architecture"); | 3396 | bb_error_msg_and_die("RELA relocations not supported on this architecture"); |
3445 | return NULL; | ||
3446 | #else | 3397 | #else |
3447 | case SHT_REL: | 3398 | case SHT_REL: |
3448 | bb_error_msg("REL relocations not supported on this architecture"); | 3399 | bb_error_msg_and_die("REL relocations not supported on this architecture"); |
3449 | return NULL; | ||
3450 | #endif | 3400 | #endif |
3451 | |||
3452 | default: | 3401 | default: |
3453 | if (sec->header.sh_type >= SHT_LOPROC) { | 3402 | if (sec->header.sh_type >= SHT_LOPROC) { |
3454 | /* Assume processor specific section types are debug | 3403 | /* Assume processor specific section types are debug |
@@ -3458,9 +3407,8 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3458 | break; | 3407 | break; |
3459 | } | 3408 | } |
3460 | 3409 | ||
3461 | bb_error_msg("can't handle sections of type %ld", | 3410 | bb_error_msg_and_die("can't handle sections of type %ld", |
3462 | (long) sec->header.sh_type); | 3411 | (long) sec->header.sh_type); |
3463 | return NULL; | ||
3464 | } | 3412 | } |
3465 | } | 3413 | } |
3466 | } | 3414 | } |
@@ -3494,10 +3442,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3494 | ElfW(Sym) * sym; | 3442 | ElfW(Sym) * sym; |
3495 | 3443 | ||
3496 | if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { | 3444 | if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { |
3497 | bb_error_msg("symbol size mismatch: %lu != %lu", | 3445 | bb_error_msg_and_die("symbol size mismatch: %lu != %lu", |
3498 | (unsigned long) sec->header.sh_entsize, | 3446 | (unsigned long) sec->header.sh_entsize, |
3499 | (unsigned long) sizeof(ElfW(Sym))); | 3447 | (unsigned long) sizeof(ElfW(Sym))); |
3500 | return NULL; | ||
3501 | } | 3448 | } |
3502 | 3449 | ||
3503 | nsym = sec->header.sh_size / sizeof(ElfW(Sym)); | 3450 | nsym = sec->header.sh_size / sizeof(ElfW(Sym)); |
@@ -3528,7 +3475,6 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3528 | */ | 3475 | */ |
3529 | val |= sym->st_other & 4; | 3476 | val |= sym->st_other & 4; |
3530 | #endif | 3477 | #endif |
3531 | |||
3532 | obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, | 3478 | obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, |
3533 | val, sym->st_size); | 3479 | val, sym->st_size); |
3534 | } | 3480 | } |
@@ -3537,10 +3483,9 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) | |||
3537 | 3483 | ||
3538 | case SHT_RELM: | 3484 | case SHT_RELM: |
3539 | if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { | 3485 | if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { |
3540 | bb_error_msg("relocation entry size mismatch: %lu != %lu", | 3486 | bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu", |
3541 | (unsigned long) sec->header.sh_entsize, | 3487 | (unsigned long) sec->header.sh_entsize, |
3542 | (unsigned long) sizeof(ElfW(RelM))); | 3488 | (unsigned long) sizeof(ElfW(RelM))); |
3543 | return NULL; | ||
3544 | } | 3489 | } |
3545 | break; | 3490 | break; |
3546 | /* XXX Relocation code from modutils-2.3.19 is not here. | 3491 | /* XXX Relocation code from modutils-2.3.19 is not here. |
@@ -3638,8 +3583,9 @@ static int obj_gpl_license(struct obj_file *f, const char **license) | |||
3638 | } | 3583 | } |
3639 | return 2; | 3584 | return 2; |
3640 | } | 3585 | } |
3641 | if (strchr(ptr, '\0')) | 3586 | ptr = strchr(ptr, '\0'); |
3642 | ptr = strchr(ptr, '\0') + 1; | 3587 | if (ptr) |
3588 | ptr++; | ||
3643 | else | 3589 | else |
3644 | ptr = endptr; | 3590 | ptr = endptr; |
3645 | } | 3591 | } |
@@ -3648,12 +3594,12 @@ static int obj_gpl_license(struct obj_file *f, const char **license) | |||
3648 | } | 3594 | } |
3649 | 3595 | ||
3650 | #define TAINT_FILENAME "/proc/sys/kernel/tainted" | 3596 | #define TAINT_FILENAME "/proc/sys/kernel/tainted" |
3651 | #define TAINT_PROPRIETORY_MODULE (1<<0) | 3597 | #define TAINT_PROPRIETORY_MODULE (1 << 0) |
3652 | #define TAINT_FORCED_MODULE (1<<1) | 3598 | #define TAINT_FORCED_MODULE (1 << 1) |
3653 | #define TAINT_UNSAFE_SMP (1<<2) | 3599 | #define TAINT_UNSAFE_SMP (1 << 2) |
3654 | #define TAINT_URL "http://www.tux.org/lkml/#export-tainted" | 3600 | #define TAINT_URL "http://www.tux.org/lkml/#export-tainted" |
3655 | 3601 | ||
3656 | static void set_tainted(struct obj_file *f, int fd, char *m_name, | 3602 | static void set_tainted(int fd, char *m_name, |
3657 | int kernel_has_tainted, int taint, const char *text1, const char *text2) | 3603 | int kernel_has_tainted, int taint, const char *text1, const char *text2) |
3658 | { | 3604 | { |
3659 | static smallint printed_info; | 3605 | static smallint printed_info; |
@@ -3703,22 +3649,22 @@ static void check_tainted_module(struct obj_file *f, char *m_name) | |||
3703 | case 0: | 3649 | case 0: |
3704 | break; | 3650 | break; |
3705 | case 1: | 3651 | case 1: |
3706 | set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); | 3652 | set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", ""); |
3707 | break; | 3653 | break; |
3708 | case 2: | 3654 | case 2: |
3709 | /* The module has a non-GPL license so we pretend that the | 3655 | /* The module has a non-GPL license so we pretend that the |
3710 | * kernel always has a taint flag to get a warning even on | 3656 | * kernel always has a taint flag to get a warning even on |
3711 | * kernels without the proc flag. | 3657 | * kernels without the proc flag. |
3712 | */ | 3658 | */ |
3713 | set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); | 3659 | set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr); |
3714 | break; | 3660 | break; |
3715 | default: | 3661 | default: |
3716 | set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); | 3662 | set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", ""); |
3717 | break; | 3663 | break; |
3718 | } | 3664 | } |
3719 | 3665 | ||
3720 | if (flag_force_load) | 3666 | if (flag_force_load) |
3721 | set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); | 3667 | set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", ""); |
3722 | 3668 | ||
3723 | if (fd >= 0) | 3669 | if (fd >= 0) |
3724 | close(fd); | 3670 | close(fd); |
@@ -3752,15 +3698,7 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3752 | const char *m_name) | 3698 | const char *m_name) |
3753 | { | 3699 | { |
3754 | static const char symprefix[] ALIGN1 = "__insmod_"; | 3700 | static const char symprefix[] ALIGN1 = "__insmod_"; |
3755 | 3701 | static const char section_names[][8] = { | |
3756 | struct obj_section *sec; | ||
3757 | struct obj_symbol *sym; | ||
3758 | char *name, *absolute_filename; | ||
3759 | char str[STRVERSIONLEN], real[PATH_MAX]; | ||
3760 | int i, l, lm_name, lfilename, use_ksymtab, version; | ||
3761 | struct stat statbuf; | ||
3762 | |||
3763 | static const char *section_names[] = { | ||
3764 | ".text", | 3702 | ".text", |
3765 | ".rodata", | 3703 | ".rodata", |
3766 | ".data", | 3704 | ".data", |
@@ -3768,12 +3706,18 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3768 | ".sbss" | 3706 | ".sbss" |
3769 | }; | 3707 | }; |
3770 | 3708 | ||
3771 | if (realpath(filename, real)) { | 3709 | struct obj_section *sec; |
3772 | absolute_filename = xstrdup(real); | 3710 | struct obj_symbol *sym; |
3773 | } else { | 3711 | char *name, *absolute_filename; |
3774 | bb_perror_msg("cannot get realpath for %s", filename); | 3712 | char str[STRVERSIONLEN]; |
3713 | int i, l, lm_name, lfilename, use_ksymtab, version; | ||
3714 | struct stat statbuf; | ||
3715 | |||
3716 | /* WARNING: was using realpath, but replaced by readlink to stop using | ||
3717 | * lots of stack. But here it seems to be able to cause problems? */ | ||
3718 | absolute_filename = xmalloc_readlink(filename); | ||
3719 | if (!absolute_filename) | ||
3775 | absolute_filename = xstrdup(filename); | 3720 | absolute_filename = xstrdup(filename); |
3776 | } | ||
3777 | 3721 | ||
3778 | lm_name = strlen(m_name); | 3722 | lm_name = strlen(m_name); |
3779 | lfilename = strlen(absolute_filename); | 3723 | lfilename = strlen(absolute_filename); |
@@ -3791,22 +3735,22 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3791 | * is 0xffffff, decimal 16777215. putting all three fields in | 3735 | * is 0xffffff, decimal 16777215. putting all three fields in |
3792 | * one symbol is less readable but saves kernel space. | 3736 | * one symbol is less readable but saves kernel space. |
3793 | */ | 3737 | */ |
3794 | l = sizeof(symprefix)+ /* "__insmod_" */ | 3738 | l = sizeof(symprefix) + /* "__insmod_" */ |
3795 | lm_name+ /* module name */ | 3739 | lm_name + /* module name */ |
3796 | 2+ /* "_O" */ | 3740 | 2 + /* "_O" */ |
3797 | lfilename+ /* object filename */ | 3741 | lfilename + /* object filename */ |
3798 | 2+ /* "_M" */ | 3742 | 2 + /* "_M" */ |
3799 | 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */ | 3743 | 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */ |
3800 | 2+ /* "_V" */ | 3744 | 2 + /* "_V" */ |
3801 | 8+ /* version in dec */ | 3745 | 8 + /* version in dec */ |
3802 | 1; /* nul */ | 3746 | 1; /* nul */ |
3803 | name = xmalloc(l); | 3747 | name = xmalloc(l); |
3804 | if (stat(absolute_filename, &statbuf) != 0) | 3748 | if (stat(absolute_filename, &statbuf) != 0) |
3805 | statbuf.st_mtime = 0; | 3749 | statbuf.st_mtime = 0; |
3806 | version = get_module_version(f, str); /* -1 if not found */ | 3750 | version = get_module_version(f, str); /* -1 if not found */ |
3807 | snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", | 3751 | snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", |
3808 | symprefix, m_name, absolute_filename, | 3752 | symprefix, m_name, absolute_filename, |
3809 | (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime, | 3753 | (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime, |
3810 | version); | 3754 | version); |
3811 | sym = obj_add_symbol(f, name, -1, | 3755 | sym = obj_add_symbol(f, name, -1, |
3812 | ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), | 3756 | ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), |
@@ -3819,11 +3763,11 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3819 | /* record where the persistent data is going, same address as previous symbol */ | 3763 | /* record where the persistent data is going, same address as previous symbol */ |
3820 | 3764 | ||
3821 | if (f->persist) { | 3765 | if (f->persist) { |
3822 | l = sizeof(symprefix)+ /* "__insmod_" */ | 3766 | l = sizeof(symprefix) + /* "__insmod_" */ |
3823 | lm_name+ /* module name */ | 3767 | lm_name + /* module name */ |
3824 | 2+ /* "_P" */ | 3768 | 2 + /* "_P" */ |
3825 | strlen(f->persist)+ /* data store */ | 3769 | strlen(f->persist) + /* data store */ |
3826 | 1; /* nul */ | 3770 | 1; /* nul */ |
3827 | name = xmalloc(l); | 3771 | name = xmalloc(l); |
3828 | snprintf(name, l, "%s%s_P%s", | 3772 | snprintf(name, l, "%s%s_P%s", |
3829 | symprefix, m_name, f->persist); | 3773 | symprefix, m_name, f->persist); |
@@ -3838,13 +3782,13 @@ add_ksymoops_symbols(struct obj_file *f, const char *filename, | |||
3838 | for (i = 0; i < ARRAY_SIZE(section_names); ++i) { | 3782 | for (i = 0; i < ARRAY_SIZE(section_names); ++i) { |
3839 | sec = obj_find_section(f, section_names[i]); | 3783 | sec = obj_find_section(f, section_names[i]); |
3840 | if (sec && sec->header.sh_size) { | 3784 | if (sec && sec->header.sh_size) { |
3841 | l = sizeof(symprefix)+ /* "__insmod_" */ | 3785 | l = sizeof(symprefix) + /* "__insmod_" */ |
3842 | lm_name+ /* module name */ | 3786 | lm_name + /* module name */ |
3843 | 2+ /* "_S" */ | 3787 | 2 + /* "_S" */ |
3844 | strlen(sec->name)+ /* section name */ | 3788 | strlen(sec->name) + /* section name */ |
3845 | 2+ /* "_L" */ | 3789 | 2 + /* "_L" */ |
3846 | 8+ /* length in dec */ | 3790 | 8 + /* length in dec */ |
3847 | 1; /* nul */ | 3791 | 1; /* nul */ |
3848 | name = xmalloc(l); | 3792 | name = xmalloc(l); |
3849 | snprintf(name, l, "%s%s_S%s_L%ld", | 3793 | snprintf(name, l, "%s%s_S%s_L%ld", |
3850 | symprefix, m_name, sec->name, | 3794 | symprefix, m_name, sec->name, |
@@ -3891,9 +3835,10 @@ static void print_load_map(struct obj_file *f) | |||
3891 | #if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL | 3835 | #if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL |
3892 | /* Quick reference which section indicies are loaded. */ | 3836 | /* Quick reference which section indicies are loaded. */ |
3893 | 3837 | ||
3894 | loaded = alloca(sizeof(int) * (i = f->header.e_shnum)); | 3838 | i = f->header.e_shnum; |
3839 | loaded = alloca(sizeof(int) * i); | ||
3895 | while (--i >= 0) | 3840 | while (--i >= 0) |
3896 | loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0; | 3841 | loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0); |
3897 | 3842 | ||
3898 | /* Collect the symbols we'll be listing. */ | 3843 | /* Collect the symbols we'll be listing. */ |
3899 | 3844 | ||
@@ -3963,7 +3908,7 @@ int insmod_main(int argc, char **argv) | |||
3963 | ElfW(Addr) m_addr; | 3908 | ElfW(Addr) m_addr; |
3964 | struct obj_file *f; | 3909 | struct obj_file *f; |
3965 | struct stat st; | 3910 | struct stat st; |
3966 | char *m_name = 0; | 3911 | char *m_name = NULL; |
3967 | int exit_status = EXIT_FAILURE; | 3912 | int exit_status = EXIT_FAILURE; |
3968 | int m_has_modinfo; | 3913 | int m_has_modinfo; |
3969 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING | 3914 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING |
@@ -4027,7 +3972,7 @@ int insmod_main(int argc, char **argv) | |||
4027 | m_name = tmp; | 3972 | m_name = tmp; |
4028 | } else { | 3973 | } else { |
4029 | free(tmp1); | 3974 | free(tmp1); |
4030 | tmp1 = 0; /* flag for free(m_name) before exit() */ | 3975 | tmp1 = NULL; /* flag for free(m_name) before exit() */ |
4031 | } | 3976 | } |
4032 | 3977 | ||
4033 | /* Get a filedesc for the module. Check that we have a complete path */ | 3978 | /* Get a filedesc for the module. Check that we have a complete path */ |
@@ -4039,7 +3984,6 @@ int insmod_main(int argc, char **argv) | |||
4039 | if (k_version) { /* uname succeedd */ | 3984 | if (k_version) { /* uname succeedd */ |
4040 | char *module_dir; | 3985 | char *module_dir; |
4041 | char *tmdn; | 3986 | char *tmdn; |
4042 | char real_module_dir[FILENAME_MAX]; | ||
4043 | 3987 | ||
4044 | tmdn = concat_path_file(_PATH_MODULES, myuname.release); | 3988 | tmdn = concat_path_file(_PATH_MODULES, myuname.release); |
4045 | /* Jump through hoops in case /lib/modules/`uname -r` | 3989 | /* Jump through hoops in case /lib/modules/`uname -r` |
@@ -4047,36 +3991,37 @@ int insmod_main(int argc, char **argv) | |||
4047 | * follow symlinks, but we do want to follow the | 3991 | * follow symlinks, but we do want to follow the |
4048 | * /lib/modules/`uname -r` dir, So resolve it ourselves | 3992 | * /lib/modules/`uname -r` dir, So resolve it ourselves |
4049 | * if it is a link... */ | 3993 | * if it is a link... */ |
4050 | if (realpath(tmdn, real_module_dir) == NULL) | 3994 | module_dir = xmalloc_readlink(tmdn); |
4051 | module_dir = tmdn; | 3995 | if (!module_dir) |
4052 | else | 3996 | module_dir = xstrdup(tmdn); |
4053 | module_dir = real_module_dir; | ||
4054 | recursive_action(module_dir, ACTION_RECURSE, | 3997 | recursive_action(module_dir, ACTION_RECURSE, |
4055 | check_module_name_match, 0, m_fullName, 0); | 3998 | check_module_name_match, NULL, m_fullName, 0); |
3999 | free(module_dir); | ||
4056 | free(tmdn); | 4000 | free(tmdn); |
4057 | } | 4001 | } |
4058 | 4002 | ||
4059 | /* Check if we have found anything yet */ | 4003 | /* Check if we have found anything yet */ |
4060 | if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) { | 4004 | if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) { |
4061 | char module_dir[FILENAME_MAX]; | 4005 | int r; |
4006 | char *module_dir; | ||
4062 | 4007 | ||
4063 | free(m_filename); | 4008 | free(m_filename); |
4064 | m_filename = NULL; | 4009 | m_filename = NULL; |
4065 | if (realpath(_PATH_MODULES, module_dir) == NULL) | 4010 | module_dir = xmalloc_readlink(_PATH_MODULES); |
4066 | strcpy(module_dir, _PATH_MODULES); | 4011 | if (!module_dir) |
4012 | module_dir = xstrdup(_PATH_MODULES); | ||
4067 | /* No module found under /lib/modules/`uname -r`, this | 4013 | /* No module found under /lib/modules/`uname -r`, this |
4068 | * time cast the net a bit wider. Search /lib/modules/ */ | 4014 | * time cast the net a bit wider. Search /lib/modules/ */ |
4069 | if (!recursive_action(module_dir, ACTION_RECURSE, | 4015 | r = recursive_action(module_dir, ACTION_RECURSE, |
4070 | check_module_name_match, 0, m_fullName, 0) | 4016 | check_module_name_match, NULL, m_fullName, 0); |
4017 | if (r) | ||
4018 | bb_error_msg_and_die("%s: module not found", m_fullName); | ||
4019 | free(module_dir); | ||
4020 | if (m_filename == NULL | ||
4021 | || ((fp = fopen(m_filename, "r")) == NULL) | ||
4071 | ) { | 4022 | ) { |
4072 | if (m_filename == 0 | ||
4073 | || ((fp = fopen(m_filename, "r")) == NULL) | ||
4074 | ) { | ||
4075 | bb_error_msg("%s: module not found", m_fullName); | ||
4076 | goto out; | ||
4077 | } | ||
4078 | } else | ||
4079 | bb_error_msg_and_die("%s: module not found", m_fullName); | 4023 | bb_error_msg_and_die("%s: module not found", m_fullName); |
4024 | } | ||
4080 | } | 4025 | } |
4081 | } else | 4026 | } else |
4082 | m_filename = xstrdup(arg1); | 4027 | m_filename = xstrdup(arg1); |
@@ -4093,8 +4038,6 @@ int insmod_main(int argc, char **argv) | |||
4093 | #endif | 4038 | #endif |
4094 | 4039 | ||
4095 | f = obj_load(fp, LOADBITS); | 4040 | f = obj_load(fp, LOADBITS); |
4096 | if (f == NULL) | ||
4097 | bb_perror_msg_and_die("cannot load the module"); | ||
4098 | 4041 | ||
4099 | if (get_modinfo_value(f, "kernel_version") == NULL) | 4042 | if (get_modinfo_value(f, "kernel_version") == NULL) |
4100 | m_has_modinfo = 0; | 4043 | m_has_modinfo = 0; |
@@ -4109,9 +4052,8 @@ int insmod_main(int argc, char **argv) | |||
4109 | if (m_has_modinfo) { | 4052 | if (m_has_modinfo) { |
4110 | m_version = new_get_module_version(f, m_strversion); | 4053 | m_version = new_get_module_version(f, m_strversion); |
4111 | if (m_version == -1) { | 4054 | if (m_version == -1) { |
4112 | bb_error_msg("cannot find the kernel version the module was " | 4055 | bb_error_msg_and_die("cannot find the kernel version the module was " |
4113 | "compiled for"); | 4056 | "compiled for"); |
4114 | goto out; | ||
4115 | } | 4057 | } |
4116 | } | 4058 | } |
4117 | 4059 | ||
@@ -4128,14 +4070,10 @@ int insmod_main(int argc, char **argv) | |||
4128 | k_crcs = 0; | 4070 | k_crcs = 0; |
4129 | #endif /* FEATURE_INSMOD_VERSION_CHECKING */ | 4071 | #endif /* FEATURE_INSMOD_VERSION_CHECKING */ |
4130 | 4072 | ||
4131 | if (!query_module(NULL, 0, NULL, 0, NULL)) { | 4073 | if (query_module(NULL, 0, NULL, 0, NULL)) |
4132 | if (!new_get_kernel_symbols()) | 4074 | bb_error_msg_and_die("not configured to support old kernels"); |
4133 | goto out; | 4075 | new_get_kernel_symbols(); |
4134 | k_crcs = new_is_kernel_checksummed(); | 4076 | k_crcs = new_is_kernel_checksummed(); |
4135 | } else { | ||
4136 | bb_error_msg("not configured to support old kernels"); | ||
4137 | goto out; | ||
4138 | } | ||
4139 | 4077 | ||
4140 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING | 4078 | #if ENABLE_FEATURE_INSMOD_VERSION_CHECKING |
4141 | m_crcs = 0; | 4079 | m_crcs = 0; |
@@ -4151,22 +4089,15 @@ int insmod_main(int argc, char **argv) | |||
4151 | 4089 | ||
4152 | /* Allocate common symbols, symbol tables, and string tables. */ | 4090 | /* Allocate common symbols, symbol tables, and string tables. */ |
4153 | 4091 | ||
4154 | if (!new_create_this_module(f, m_name)) { | 4092 | new_create_this_module(f, m_name); |
4155 | goto out; | 4093 | obj_check_undefineds(f); |
4156 | } | ||
4157 | |||
4158 | if (!obj_check_undefineds(f)) { | ||
4159 | goto out; | ||
4160 | } | ||
4161 | obj_allocate_commons(f); | 4094 | obj_allocate_commons(f); |
4162 | check_tainted_module(f, m_name); | 4095 | check_tainted_module(f, m_name); |
4163 | 4096 | ||
4164 | /* done with the module name, on to the optional var=value arguments */ | 4097 | /* done with the module name, on to the optional var=value arguments */ |
4165 | ++optind; | 4098 | ++optind; |
4166 | if (optind < argc) { | 4099 | if (optind < argc) { |
4167 | if (!new_process_module_arguments(f, argc - optind, argv + optind)) { | 4100 | new_process_module_arguments(f, argc - optind, argv + optind); |
4168 | goto out; | ||
4169 | } | ||
4170 | } | 4101 | } |
4171 | 4102 | ||
4172 | arch_create_got(f); | 4103 | arch_create_got(f); |
@@ -4181,22 +4112,18 @@ int insmod_main(int argc, char **argv) | |||
4181 | /* Find current size of the module */ | 4112 | /* Find current size of the module */ |
4182 | m_size = obj_load_size(f); | 4113 | m_size = obj_load_size(f); |
4183 | 4114 | ||
4184 | |||
4185 | m_addr = create_module(m_name, m_size); | 4115 | m_addr = create_module(m_name, m_size); |
4186 | if (m_addr == -1) switch (errno) { | 4116 | if (m_addr == -1) switch (errno) { |
4187 | case EEXIST: | 4117 | case EEXIST: |
4188 | bb_error_msg("a module named %s already exists", m_name); | 4118 | bb_error_msg_and_die("a module named %s already exists", m_name); |
4189 | goto out; | ||
4190 | case ENOMEM: | 4119 | case ENOMEM: |
4191 | bb_error_msg("can't allocate kernel memory for module; needed %lu bytes", | 4120 | bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes", |
4192 | m_size); | 4121 | m_size); |
4193 | goto out; | ||
4194 | default: | 4122 | default: |
4195 | bb_perror_msg("create_module: %s", m_name); | 4123 | bb_perror_msg_and_die("create_module: %s", m_name); |
4196 | goto out; | ||
4197 | } | 4124 | } |
4198 | 4125 | ||
4199 | #if !LOADBITS | 4126 | #if !LOADBITS |
4200 | /* | 4127 | /* |
4201 | * the PROGBITS section was not loaded by the obj_load | 4128 | * the PROGBITS section was not loaded by the obj_load |
4202 | * now we can load them directly into the kernel memory | 4129 | * now we can load them directly into the kernel memory |
@@ -4222,7 +4149,7 @@ int insmod_main(int argc, char **argv) | |||
4222 | 4149 | ||
4223 | exit_status = EXIT_SUCCESS; | 4150 | exit_status = EXIT_SUCCESS; |
4224 | 4151 | ||
4225 | out: | 4152 | out: |
4226 | #if ENABLE_FEATURE_CLEAN_UP | 4153 | #if ENABLE_FEATURE_CLEAN_UP |
4227 | if (fp) | 4154 | if (fp) |
4228 | fclose(fp); | 4155 | fclose(fp); |
@@ -4234,8 +4161,10 @@ out: | |||
4234 | return exit_status; | 4161 | return exit_status; |
4235 | } | 4162 | } |
4236 | 4163 | ||
4237 | 4164 | #endif /* ENABLE_FEATURE_2_4_MODULES */ | |
4238 | #endif | 4165 | /* |
4166 | * End of big piece of 2.4-specific code | ||
4167 | */ | ||
4239 | 4168 | ||
4240 | 4169 | ||
4241 | #if ENABLE_FEATURE_2_6_MODULES | 4170 | #if ENABLE_FEATURE_2_6_MODULES |
@@ -4249,20 +4178,24 @@ static const char *moderror(int err) | |||
4249 | { | 4178 | { |
4250 | switch (err) { | 4179 | switch (err) { |
4251 | case ENOEXEC: | 4180 | case ENOEXEC: |
4252 | return "Invalid module format"; | 4181 | return "invalid module format"; |
4253 | case ENOENT: | 4182 | case ENOENT: |
4254 | return "Unknown symbol in module"; | 4183 | return "unknown symbol in module"; |
4255 | case ESRCH: | 4184 | case ESRCH: |
4256 | return "Module has wrong symbol version"; | 4185 | return "module has wrong symbol version"; |
4257 | case EINVAL: | 4186 | case EINVAL: |
4258 | return "Invalid parameters"; | 4187 | return "invalid parameters"; |
4259 | default: | 4188 | default: |
4260 | return strerror(err); | 4189 | return strerror(err); |
4261 | } | 4190 | } |
4262 | } | 4191 | } |
4263 | 4192 | ||
4264 | int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 4193 | #if !ENABLE_FEATURE_2_4_MODULES |
4265 | int insmod_ng_main(int argc, char **argv) | 4194 | int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
4195 | int insmod_main(int argc, char **argv) | ||
4196 | #else | ||
4197 | static int insmod_ng_main(int argc, char **argv) | ||
4198 | #endif | ||
4266 | { | 4199 | { |
4267 | long ret; | 4200 | long ret; |
4268 | size_t len; | 4201 | size_t len; |
diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 70146814c..f1f78ff9f 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c | |||
@@ -28,17 +28,17 @@ static void check_tainted(void) | |||
28 | FILE *f; | 28 | FILE *f; |
29 | 29 | ||
30 | tainted = 0; | 30 | tainted = 0; |
31 | if ((f = fopen(TAINT_FILENAME, "r"))) { | 31 | f = fopen(TAINT_FILENAME, "r"); |
32 | if (f) { | ||
32 | fscanf(f, "%d", &tainted); | 33 | fscanf(f, "%d", &tainted); |
33 | fclose(f); | 34 | fclose(f); |
34 | } | 35 | } |
35 | if (f && tainted) { | 36 | if (tainted) { |
36 | printf(" Tainted: %c%c%c\n", | 37 | printf(" Tainted: %c%c%c\n", |
37 | tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G', | 38 | tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G', |
38 | tainted & TAINT_FORCED_MODULE ? 'F' : ' ', | 39 | tainted & TAINT_FORCED_MODULE ? 'F' : ' ', |
39 | tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); | 40 | tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); |
40 | } | 41 | } else { |
41 | else { | ||
42 | printf(" Not tainted\n"); | 42 | printf(" Not tainted\n"); |
43 | } | 43 | } |
44 | } | 44 | } |
@@ -147,7 +147,7 @@ int lsmod_main(int argc, char **argv) | |||
147 | 147 | ||
148 | printf("Module Size Used by"); | 148 | printf("Module Size Used by"); |
149 | check_tainted(); | 149 | check_tainted(); |
150 | #if defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT) | 150 | #if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT |
151 | { | 151 | { |
152 | char *line; | 152 | char *line; |
153 | while ((line = xmalloc_fgets(file)) != NULL) { | 153 | while ((line = xmalloc_fgets(file)) != NULL) { |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index a67ddea9b..f7d193a05 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <sys/utsname.h> | 15 | #include <sys/utsname.h> |
16 | #include <fnmatch.h> | 16 | #include <fnmatch.h> |
17 | 17 | ||
18 | #define line_buffer bb_common_bufsiz1 | ||
19 | |||
18 | struct mod_opt_t { /* one-way list of options to pass to a module */ | 20 | struct mod_opt_t { /* one-way list of options to pass to a module */ |
19 | char * m_opt_val; | 21 | char * m_opt_val; |
20 | struct mod_opt_t * m_next; | 22 | struct mod_opt_t * m_next; |
@@ -48,7 +50,7 @@ struct mod_list_t { /* two-way list of modules to process */ | |||
48 | 50 | ||
49 | static struct dep_t *depend; | 51 | static struct dep_t *depend; |
50 | 52 | ||
51 | #define main_options "acdklnqrst:vVC:" | 53 | #define MAIN_OPT_STR "acdklnqrst:vVC:" |
52 | #define INSERT_ALL 1 /* a */ | 54 | #define INSERT_ALL 1 /* a */ |
53 | #define DUMP_CONF_EXIT 2 /* c */ | 55 | #define DUMP_CONF_EXIT 2 /* c */ |
54 | #define D_OPT_IGNORED 4 /* d */ | 56 | #define D_OPT_IGNORED 4 /* d */ |
@@ -63,14 +65,12 @@ static struct dep_t *depend; | |||
63 | #define VERSION_ONLY 2048 /* V */ | 65 | #define VERSION_ONLY 2048 /* V */ |
64 | #define CONFIG_FILE 4096 /* C */ | 66 | #define CONFIG_FILE 4096 /* C */ |
65 | 67 | ||
66 | #define autoclean (main_opts & AUTOCLEAN_FLG) | 68 | #define autoclean (option_mask32 & AUTOCLEAN_FLG) |
67 | #define show_only (main_opts & SHOW_ONLY) | 69 | #define show_only (option_mask32 & SHOW_ONLY) |
68 | #define quiet (main_opts & QUIET) | 70 | #define quiet (option_mask32 & QUIET) |
69 | #define remove_opt (main_opts & REMOVE_OPT) | 71 | #define remove_opt (option_mask32 & REMOVE_OPT) |
70 | #define do_syslog (main_opts & DO_SYSLOG) | 72 | #define do_syslog (option_mask32 & DO_SYSLOG) |
71 | #define verbose (main_opts & VERBOSE) | 73 | #define verbose (option_mask32 & VERBOSE) |
72 | |||
73 | static int main_opts; | ||
74 | 74 | ||
75 | static int parse_tag_value(char *buffer, char **ptag, char **pvalue) | 75 | static int parse_tag_value(char *buffer, char **ptag, char **pvalue) |
76 | { | 76 | { |
@@ -78,12 +78,15 @@ static int parse_tag_value(char *buffer, char **ptag, char **pvalue) | |||
78 | 78 | ||
79 | buffer = skip_whitespace(buffer); | 79 | buffer = skip_whitespace(buffer); |
80 | tag = value = buffer; | 80 | tag = value = buffer; |
81 | while (!isspace(*value)) | 81 | while (!isspace(*value)) { |
82 | if (!*value) return 0; | 82 | if (!*value) |
83 | else value++; | 83 | return 0; |
84 | *value++ = 0; | 84 | value++; |
85 | } | ||
86 | *value++ = '\0'; | ||
85 | value = skip_whitespace(value); | 87 | value = skip_whitespace(value); |
86 | if (!*value) return 0; | 88 | if (!*value) |
89 | return 0; | ||
87 | 90 | ||
88 | *ptag = tag; | 91 | *ptag = tag; |
89 | *pvalue = value; | 92 | *pvalue = value; |
@@ -102,14 +105,14 @@ static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt) | |||
102 | while (ol->m_next) { | 105 | while (ol->m_next) { |
103 | ol = ol->m_next; | 106 | ol = ol->m_next; |
104 | } | 107 | } |
105 | ol->m_next = xmalloc(sizeof(struct mod_opt_t)); | 108 | ol->m_next = xzalloc(sizeof(struct mod_opt_t)); |
106 | ol = ol->m_next; | 109 | ol = ol->m_next; |
107 | } else { | 110 | } else { |
108 | ol = opt_list = xmalloc(sizeof(struct mod_opt_t)); | 111 | ol = opt_list = xzalloc(sizeof(struct mod_opt_t)); |
109 | } | 112 | } |
110 | 113 | ||
111 | ol->m_opt_val = xstrdup(opt); | 114 | ol->m_opt_val = xstrdup(opt); |
112 | ol->m_next = NULL; | 115 | /*ol->m_next = NULL; - done by xzalloc*/ |
113 | 116 | ||
114 | return opt_list; | 117 | return opt_list; |
115 | } | 118 | } |
@@ -190,7 +193,8 @@ static char *parse_command_string(char *src, char **dst) | |||
190 | case '0': | 193 | case '0': |
191 | /* We escaped a special character. For now, keep | 194 | /* We escaped a special character. For now, keep |
192 | * both the back-slash and the following char. */ | 195 | * both the back-slash and the following char. */ |
193 | tmp_str++; src++; | 196 | tmp_str++; |
197 | src++; | ||
194 | break; | 198 | break; |
195 | default: | 199 | default: |
196 | /* We escaped a space or a single or double quote, | 200 | /* We escaped a space or a single or double quote, |
@@ -242,12 +246,12 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf | |||
242 | 246 | ||
243 | p = strchr(buffer, '#'); | 247 | p = strchr(buffer, '#'); |
244 | if (p) | 248 | if (p) |
245 | *p = 0; | 249 | *p = '\0'; |
246 | 250 | ||
247 | l = strlen(buffer); | 251 | l = strlen(buffer); |
248 | 252 | ||
249 | while (l && isspace(buffer[l-1])) { | 253 | while (l && isspace(buffer[l-1])) { |
250 | buffer[l-1] = 0; | 254 | buffer[l-1] = '\0'; |
251 | l--; | 255 | l--; |
252 | } | 256 | } |
253 | 257 | ||
@@ -256,66 +260,68 @@ static void include_conf(struct dep_t **first, struct dep_t **current, char *buf | |||
256 | continue; | 260 | continue; |
257 | } | 261 | } |
258 | 262 | ||
259 | if (!continuation_line) { | 263 | if (continuation_line) |
260 | if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) { | 264 | continue; |
261 | char *alias, *mod; | ||
262 | 265 | ||
263 | if (parse_tag_value(buffer + 6, &alias, &mod)) { | 266 | if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) { |
264 | /* handle alias as a module dependent on the aliased module */ | 267 | char *alias, *mod; |
265 | if (!*current) { | ||
266 | (*first) = (*current) = xzalloc(sizeof(struct dep_t)); | ||
267 | } else { | ||
268 | (*current)->m_next = xzalloc(sizeof(struct dep_t)); | ||
269 | (*current) = (*current)->m_next; | ||
270 | } | ||
271 | (*current)->m_name = xstrdup(alias); | ||
272 | (*current)->m_isalias = 1; | ||
273 | 268 | ||
274 | if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) { | 269 | if (parse_tag_value(buffer + 6, &alias, &mod)) { |
275 | (*current)->m_depcnt = 0; | 270 | /* handle alias as a module dependent on the aliased module */ |
276 | (*current)->m_deparr = 0; | 271 | if (!*current) { |
277 | } else { | 272 | (*first) = (*current) = xzalloc(sizeof(struct dep_t)); |
278 | (*current)->m_depcnt = 1; | 273 | } else { |
279 | (*current)->m_deparr = xmalloc(1 * sizeof(char *)); | 274 | (*current)->m_next = xzalloc(sizeof(struct dep_t)); |
280 | (*current)->m_deparr[0] = xstrdup(mod); | 275 | (*current) = (*current)->m_next; |
281 | } | ||
282 | (*current)->m_next = 0; | ||
283 | } | 276 | } |
284 | } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) { | 277 | (*current)->m_name = xstrdup(alias); |
285 | char *mod, *opt; | 278 | (*current)->m_isalias = 1; |
286 | |||
287 | /* split the line in the module/alias name, and options */ | ||
288 | if (parse_tag_value(buffer + 8, &mod, &opt)) { | ||
289 | struct dep_t *dt; | ||
290 | 279 | ||
291 | /* find the corresponding module */ | 280 | if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) { |
292 | for (dt = *first; dt; dt = dt->m_next) { | 281 | /*(*current)->m_depcnt = 0; - done by xzalloc */ |
293 | if (strcmp(dt->m_name, mod) == 0) | 282 | /*(*current)->m_deparr = 0;*/ |
294 | break; | 283 | } else { |
295 | } | 284 | (*current)->m_depcnt = 1; |
296 | if (dt) { | 285 | (*current)->m_deparr = xmalloc(sizeof(char *)); |
297 | if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) { | 286 | (*current)->m_deparr[0] = xstrdup(mod); |
298 | char* new_opt = NULL; | ||
299 | while ((opt = parse_command_string(opt, &new_opt))) { | ||
300 | dt->m_options = append_option(dt->m_options, new_opt); | ||
301 | } | ||
302 | } else { | ||
303 | dt->m_options = append_option(dt->m_options, opt); | ||
304 | } | ||
305 | } | ||
306 | } | 287 | } |
307 | } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) { | 288 | /*(*current)->m_next = NULL; - done by xzalloc */ |
308 | int fdi; char *filename; | 289 | } |
290 | } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) { | ||
291 | char *mod, *opt; | ||
309 | 292 | ||
310 | filename = skip_whitespace(buffer + 8); | 293 | /* split the line in the module/alias name, and options */ |
294 | if (parse_tag_value(buffer + 8, &mod, &opt)) { | ||
295 | struct dep_t *dt; | ||
311 | 296 | ||
312 | if ((fdi = open(filename, O_RDONLY)) >= 0) { | 297 | /* find the corresponding module */ |
313 | include_conf(first, current, buffer, buflen, fdi); | 298 | for (dt = *first; dt; dt = dt->m_next) { |
314 | close(fdi); | 299 | if (strcmp(dt->m_name, mod) == 0) |
300 | break; | ||
315 | } | 301 | } |
302 | if (dt) { | ||
303 | if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) { | ||
304 | char* new_opt = NULL; | ||
305 | while ((opt = parse_command_string(opt, &new_opt))) { | ||
306 | dt->m_options = append_option(dt->m_options, new_opt); | ||
307 | } | ||
308 | } else { | ||
309 | dt->m_options = append_option(dt->m_options, opt); | ||
310 | } | ||
311 | } | ||
312 | } | ||
313 | } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) { | ||
314 | int fdi; | ||
315 | char *filename; | ||
316 | |||
317 | filename = skip_whitespace(buffer + 8); | ||
318 | fdi = open(filename, O_RDONLY); | ||
319 | if (fdi >= 0) { | ||
320 | include_conf(first, current, buffer, buflen, fdi); | ||
321 | close(fdi); | ||
316 | } | 322 | } |
317 | } | 323 | } |
318 | } | 324 | } /* while (reads(...)) */ |
319 | } | 325 | } |
320 | 326 | ||
321 | /* | 327 | /* |
@@ -327,9 +333,8 @@ static struct dep_t *build_dep(void) | |||
327 | { | 333 | { |
328 | int fd; | 334 | int fd; |
329 | struct utsname un; | 335 | struct utsname un; |
330 | struct dep_t *first = 0; | 336 | struct dep_t *first = NULL; |
331 | struct dep_t *current = 0; | 337 | struct dep_t *current = NULL; |
332 | char buffer[2048]; | ||
333 | char *filename; | 338 | char *filename; |
334 | int continuation_line = 0; | 339 | int continuation_line = 0; |
335 | int k_version; | 340 | int k_version; |
@@ -350,16 +355,16 @@ static struct dep_t *build_dep(void) | |||
350 | /* Ok, that didn't work. Fall back to looking in /lib/modules */ | 355 | /* Ok, that didn't work. Fall back to looking in /lib/modules */ |
351 | fd = open("/lib/modules/modules.dep", O_RDONLY); | 356 | fd = open("/lib/modules/modules.dep", O_RDONLY); |
352 | if (fd < 0) { | 357 | if (fd < 0) { |
353 | return 0; | 358 | bb_error_msg_and_die("cannot parse modules.dep"); |
354 | } | 359 | } |
355 | } | 360 | } |
356 | 361 | ||
357 | while (reads(fd, buffer, sizeof(buffer))) { | 362 | while (reads(fd, line_buffer, sizeof(line_buffer))) { |
358 | int l = strlen(buffer); | 363 | int l = strlen(line_buffer); |
359 | char *p = 0; | 364 | char *p = 0; |
360 | 365 | ||
361 | while (l > 0 && isspace(buffer[l-1])) { | 366 | while (l > 0 && isspace(line_buffer[l-1])) { |
362 | buffer[l-1] = 0; | 367 | line_buffer[l-1] = '\0'; |
363 | l--; | 368 | l--; |
364 | } | 369 | } |
365 | 370 | ||
@@ -371,7 +376,7 @@ static struct dep_t *build_dep(void) | |||
371 | /* Is this a new module dep description? */ | 376 | /* Is this a new module dep description? */ |
372 | if (!continuation_line) { | 377 | if (!continuation_line) { |
373 | /* find the dep beginning */ | 378 | /* find the dep beginning */ |
374 | char *col = strchr(buffer, ':'); | 379 | char *col = strchr(line_buffer, ':'); |
375 | char *dot = col; | 380 | char *dot = col; |
376 | 381 | ||
377 | if (col) { | 382 | if (col) { |
@@ -381,53 +386,52 @@ static struct dep_t *build_dep(void) | |||
381 | char *mod; | 386 | char *mod; |
382 | 387 | ||
383 | /* Find the beginning of the module file name */ | 388 | /* Find the beginning of the module file name */ |
384 | *col = 0; | 389 | *col = '\0'; |
385 | mods = bb_basename(buffer); | 390 | mods = bb_basename(line_buffer); |
386 | 391 | ||
387 | /* find the path of the module */ | 392 | /* find the path of the module */ |
388 | modpath = strchr(buffer, '/'); /* ... and this is the path */ | 393 | modpath = strchr(line_buffer, '/'); /* ... and this is the path */ |
389 | if (!modpath) | 394 | if (!modpath) |
390 | modpath = buffer; /* module with no path */ | 395 | modpath = line_buffer; /* module with no path */ |
391 | /* find the end of the module name in the file name */ | 396 | /* find the end of the module name in the file name */ |
392 | if (ENABLE_FEATURE_2_6_MODULES && | 397 | if (ENABLE_FEATURE_2_6_MODULES && |
393 | (k_version > 4) && (*(col-3) == '.') && | 398 | (k_version > 4) && (col[-3] == '.') && |
394 | (*(col-2) == 'k') && (*(col-1) == 'o')) | 399 | (col[-2] == 'k') && (col[-1] == 'o')) |
395 | dot = col - 3; | 400 | dot = col - 3; |
396 | else | 401 | else if ((col[-2] == '.') && (col[-1] == 'o')) |
397 | if ((*(col-2) == '.') && (*(col-1) == 'o')) | 402 | dot = col - 2; |
398 | dot = col - 2; | ||
399 | 403 | ||
400 | mod = xstrndup(mods, dot - mods); | 404 | mod = xstrndup(mods, dot - mods); |
401 | 405 | ||
402 | /* enqueue new module */ | 406 | /* enqueue new module */ |
403 | if (!current) { | 407 | if (!current) { |
404 | first = current = xmalloc(sizeof(struct dep_t)); | 408 | first = current = xzalloc(sizeof(struct dep_t)); |
405 | } else { | 409 | } else { |
406 | current->m_next = xmalloc(sizeof(struct dep_t)); | 410 | current->m_next = xzalloc(sizeof(struct dep_t)); |
407 | current = current->m_next; | 411 | current = current->m_next; |
408 | } | 412 | } |
409 | current->m_name = mod; | 413 | current->m_name = mod; |
410 | current->m_path = xstrdup(modpath); | 414 | current->m_path = xstrdup(modpath); |
411 | current->m_options = NULL; | 415 | /*current->m_options = NULL; - xzalloc did it*/ |
412 | current->m_isalias = 0; | 416 | /*current->m_isalias = 0;*/ |
413 | current->m_depcnt = 0; | 417 | /*current->m_depcnt = 0;*/ |
414 | current->m_deparr = 0; | 418 | /*current->m_deparr = 0;*/ |
415 | current->m_next = 0; | 419 | /*current->m_next = 0;*/ |
416 | 420 | ||
417 | p = col + 1; | 421 | p = col + 1; |
418 | } else | 422 | } else |
419 | /* this line is not a dep description */ | 423 | /* this line is not a dep description */ |
420 | p = 0; | 424 | p = NULL; |
421 | } else | 425 | } else |
422 | /* It's a dep description continuation */ | 426 | /* It's a dep description continuation */ |
423 | p = buffer; | 427 | p = line_buffer; |
424 | 428 | ||
425 | while (p && *p && isblank(*p)) | 429 | while (p && *p && isblank(*p)) |
426 | p++; | 430 | p++; |
427 | 431 | ||
428 | /* p points to the first dependable module; if NULL, no dependable module */ | 432 | /* p points to the first dependable module; if NULL, no dependable module */ |
429 | if (p && *p) { | 433 | if (p && *p) { |
430 | char *end = &buffer[l-1]; | 434 | char *end = &line_buffer[l-1]; |
431 | const char *deps; | 435 | const char *deps; |
432 | char *dep; | 436 | char *dep; |
433 | char *next; | 437 | char *next; |
@@ -440,7 +444,7 @@ static struct dep_t *build_dep(void) | |||
440 | /* search the end of the dependency */ | 444 | /* search the end of the dependency */ |
441 | next = strchr(p, ' '); | 445 | next = strchr(p, ' '); |
442 | if (next) { | 446 | if (next) { |
443 | *next = 0; | 447 | *next = '\0'; |
444 | next--; | 448 | next--; |
445 | } else | 449 | } else |
446 | next = end; | 450 | next = end; |
@@ -454,12 +458,11 @@ static struct dep_t *build_dep(void) | |||
454 | 458 | ||
455 | /* find the end of the module name in the file name */ | 459 | /* find the end of the module name in the file name */ |
456 | if (ENABLE_FEATURE_2_6_MODULES | 460 | if (ENABLE_FEATURE_2_6_MODULES |
457 | && (k_version > 4) && (*(next-2) == '.') | 461 | && (k_version > 4) && (next[-2] == '.') |
458 | && (*(next-1) == 'k') && (*next == 'o')) | 462 | && (next[-1] == 'k') && (next[0] == 'o')) |
459 | ext = 3; | 463 | ext = 3; |
460 | else | 464 | else if ((next[-1] == '.') && (next[0] == 'o')) |
461 | if ((*(next-1) == '.') && (*next == 'o')) | 465 | ext = 2; |
462 | ext = 2; | ||
463 | 466 | ||
464 | /* Cope with blank lines */ | 467 | /* Cope with blank lines */ |
465 | if ((next-deps-ext+1) <= 0) | 468 | if ((next-deps-ext+1) <= 0) |
@@ -477,11 +480,8 @@ static struct dep_t *build_dep(void) | |||
477 | } | 480 | } |
478 | 481 | ||
479 | /* is there other dependable module(s) ? */ | 482 | /* is there other dependable module(s) ? */ |
480 | if (buffer[l-1] == '\\') | 483 | continuation_line = (line_buffer[l-1] == '\\'); |
481 | continuation_line = 1; | 484 | } /* while (reads(...)) */ |
482 | else | ||
483 | continuation_line = 0; | ||
484 | } | ||
485 | close(fd); | 485 | close(fd); |
486 | 486 | ||
487 | /* | 487 | /* |
@@ -498,7 +498,7 @@ static struct dep_t *build_dep(void) | |||
498 | fd = open("/etc/conf.modules", O_RDONLY); | 498 | fd = open("/etc/conf.modules", O_RDONLY); |
499 | 499 | ||
500 | if (fd >= 0) { | 500 | if (fd >= 0) { |
501 | include_conf(&first, ¤t, buffer, sizeof(buffer), fd); | 501 | include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd); |
502 | close(fd); | 502 | close(fd); |
503 | } | 503 | } |
504 | 504 | ||
@@ -515,7 +515,7 @@ static struct dep_t *build_dep(void) | |||
515 | free(filename); | 515 | free(filename); |
516 | 516 | ||
517 | if (fd >= 0) { | 517 | if (fd >= 0) { |
518 | include_conf(&first, ¤t, buffer, sizeof(buffer), fd); | 518 | include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd); |
519 | close(fd); | 519 | close(fd); |
520 | } | 520 | } |
521 | 521 | ||
@@ -530,7 +530,7 @@ static struct dep_t *build_dep(void) | |||
530 | free(filename); | 530 | free(filename); |
531 | 531 | ||
532 | if (fd >= 0) { | 532 | if (fd >= 0) { |
533 | include_conf(&first, ¤t, buffer, sizeof(buffer), fd); | 533 | include_conf(&first, ¤t, line_buffer, sizeof(line_buffer), fd); |
534 | close(fd); | 534 | close(fd); |
535 | } | 535 | } |
536 | } | 536 | } |
@@ -542,16 +542,15 @@ static struct dep_t *build_dep(void) | |||
542 | static int already_loaded(const char *name) | 542 | static int already_loaded(const char *name) |
543 | { | 543 | { |
544 | int fd, ret = 0; | 544 | int fd, ret = 0; |
545 | char buffer[4096]; | ||
546 | 545 | ||
547 | fd = open("/proc/modules", O_RDONLY); | 546 | fd = open("/proc/modules", O_RDONLY); |
548 | if (fd < 0) | 547 | if (fd < 0) |
549 | return -1; | 548 | return -1; |
550 | 549 | ||
551 | while (reads(fd, buffer, sizeof(buffer))) { | 550 | while (reads(fd, line_buffer, sizeof(line_buffer))) { |
552 | char *p; | 551 | char *p; |
553 | 552 | ||
554 | p = strchr (buffer, ' '); | 553 | p = strchr(line_buffer, ' '); |
555 | if (p) { | 554 | if (p) { |
556 | const char *n; | 555 | const char *n; |
557 | 556 | ||
@@ -559,8 +558,8 @@ static int already_loaded(const char *name) | |||
559 | // the idiosyncrasy that _ and - are interchangeable because the | 558 | // the idiosyncrasy that _ and - are interchangeable because the |
560 | // 2.6 kernel does weird things. | 559 | // 2.6 kernel does weird things. |
561 | 560 | ||
562 | *p = 0; | 561 | *p = '\0'; |
563 | for (p = buffer, n = name; ; p++, n++) { | 562 | for (p = line_buffer, n = name; ; p++, n++) { |
564 | if (*p != *n) { | 563 | if (*p != *n) { |
565 | if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-')) | 564 | if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-')) |
566 | continue; | 565 | continue; |
@@ -574,8 +573,8 @@ static int already_loaded(const char *name) | |||
574 | } | 573 | } |
575 | } | 574 | } |
576 | } | 575 | } |
577 | done: | 576 | done: |
578 | close (fd); | 577 | close(fd); |
579 | return ret; | 578 | return ret; |
580 | } | 579 | } |
581 | 580 | ||
@@ -623,7 +622,7 @@ static int mod_process(const struct mod_list_t *list, int do_insert) | |||
623 | while (opts) { | 622 | while (opts) { |
624 | /* Add one more option */ | 623 | /* Add one more option */ |
625 | argc++; | 624 | argc++; |
626 | argv = xrealloc(argv,(argc + 1)* sizeof(char*)); | 625 | argv = xrealloc(argv, (argc + 1) * sizeof(char*)); |
627 | argv[argc-1] = opts->m_opt_val; | 626 | argv[argc-1] = opts->m_opt_val; |
628 | opts = opts->m_next; | 627 | opts = opts->m_next; |
629 | } | 628 | } |
@@ -698,9 +697,8 @@ static int check_pattern(const char* pat_src, const char* mod_src) | |||
698 | } | 697 | } |
699 | 698 | ||
700 | return ret; | 699 | return ret; |
701 | } else { | ||
702 | return fnmatch(pat_src, mod_src, 0); | ||
703 | } | 700 | } |
701 | return fnmatch(pat_src, mod_src, 0); | ||
704 | } | 702 | } |
705 | 703 | ||
706 | /* | 704 | /* |
@@ -712,8 +710,8 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t | |||
712 | { | 710 | { |
713 | struct mod_list_t *find; | 711 | struct mod_list_t *find; |
714 | struct dep_t *dt; | 712 | struct dep_t *dt; |
715 | struct mod_opt_t *opt = 0; | 713 | struct mod_opt_t *opt = NULL; |
716 | char *path = 0; | 714 | char *path = NULL; |
717 | 715 | ||
718 | /* Search for the given module name amongst all dependency rules. | 716 | /* Search for the given module name amongst all dependency rules. |
719 | * The module name in a dependency rule can be a shell pattern, | 717 | * The module name in a dependency rule can be a shell pattern, |
@@ -765,8 +763,8 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t | |||
765 | 763 | ||
766 | // search for duplicates | 764 | // search for duplicates |
767 | for (find = *head; find; find = find->m_next) { | 765 | for (find = *head; find; find = find->m_next) { |
768 | if (!strcmp(mod, find->m_name)) { | 766 | if (strcmp(mod, find->m_name) == 0) { |
769 | // found ->dequeue it | 767 | // found -> dequeue it |
770 | 768 | ||
771 | if (find->m_prev) | 769 | if (find->m_prev) |
772 | find->m_prev->m_next = find->m_next; | 770 | find->m_prev->m_next = find->m_next; |
@@ -783,7 +781,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t | |||
783 | } | 781 | } |
784 | 782 | ||
785 | if (!find) { // did not find a duplicate | 783 | if (!find) { // did not find a duplicate |
786 | find = xmalloc(sizeof(struct mod_list_t)); | 784 | find = xzalloc(sizeof(struct mod_list_t)); |
787 | find->m_name = mod; | 785 | find->m_name = mod; |
788 | find->m_path = path; | 786 | find->m_path = path; |
789 | find->m_options = opt; | 787 | find->m_options = opt; |
@@ -793,7 +791,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t | |||
793 | if (*tail) | 791 | if (*tail) |
794 | (*tail)->m_next = find; | 792 | (*tail)->m_next = find; |
795 | find->m_prev = *tail; | 793 | find->m_prev = *tail; |
796 | find->m_next = 0; | 794 | /*find->m_next = NULL; - xzalloc did it */ |
797 | 795 | ||
798 | if (!*head) | 796 | if (!*head) |
799 | *head = find; | 797 | *head = find; |
@@ -868,11 +866,11 @@ int modprobe_main(int argc, char **argv) | |||
868 | char *unused; | 866 | char *unused; |
869 | 867 | ||
870 | opt_complementary = "?V-:q-v:v-q"; | 868 | opt_complementary = "?V-:q-v:v-q"; |
871 | main_opts = getopt32(argv, "acdklnqrst:vVC:", | 869 | getopt32(argv, MAIN_OPT_STR, &unused, &unused); |
872 | &unused, &unused); | 870 | |
873 | if (main_opts & (DUMP_CONF_EXIT | LIST_ALL)) | 871 | if (option_mask32 & (DUMP_CONF_EXIT | LIST_ALL)) |
874 | return EXIT_SUCCESS; | 872 | return EXIT_SUCCESS; |
875 | if (main_opts & (RESTRICT_DIR | CONFIG_FILE)) | 873 | if (option_mask32 & (RESTRICT_DIR | CONFIG_FILE)) |
876 | bb_error_msg_and_die("-t and -C not supported"); | 874 | bb_error_msg_and_die("-t and -C not supported"); |
877 | 875 | ||
878 | depend = build_dep(); | 876 | depend = build_dep(); |
@@ -882,8 +880,8 @@ int modprobe_main(int argc, char **argv) | |||
882 | 880 | ||
883 | if (remove_opt) { | 881 | if (remove_opt) { |
884 | do { | 882 | do { |
885 | if (mod_remove(optind < argc ? | 883 | /* argv[optind] can be NULL here */ |
886 | argv[optind] : NULL)) { | 884 | if (mod_remove(argv[optind])) { |
887 | bb_error_msg("failed to remove module %s", | 885 | bb_error_msg("failed to remove module %s", |
888 | argv[optind]); | 886 | argv[optind]); |
889 | rc = EXIT_FAILURE; | 887 | rc = EXIT_FAILURE; |