diff options
Diffstat (limited to 'modutils')
-rw-r--r-- | modutils/modprobe.c | 136 | ||||
-rw-r--r-- | modutils/rmmod.c | 4 |
2 files changed, 89 insertions, 51 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index a5cf4babf..73df39c6c 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -10,6 +10,20 @@ | |||
10 | 10 | ||
11 | //applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) | 11 | //applet:IF_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_DROP)) |
12 | 12 | ||
13 | #include "libbb.h" | ||
14 | #include "modutils.h" | ||
15 | #include <sys/utsname.h> | ||
16 | #include <fnmatch.h> | ||
17 | |||
18 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
19 | #define DBG(...) ((void)0) | ||
20 | |||
21 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | ||
22 | * we expect the full dependency list to be specified in modules.dep. | ||
23 | * Older versions would only export the direct dependency list. | ||
24 | */ | ||
25 | |||
26 | |||
13 | //usage:#if !ENABLE_MODPROBE_SMALL | 27 | //usage:#if !ENABLE_MODPROBE_SMALL |
14 | //usage:#define modprobe_notes_usage | 28 | //usage:#define modprobe_notes_usage |
15 | //usage: "modprobe can (un)load a stack of modules, passing each module options (when\n" | 29 | //usage: "modprobe can (un)load a stack of modules, passing each module options (when\n" |
@@ -72,9 +86,8 @@ | |||
72 | //usage: " from the command line\n" | 86 | //usage: " from the command line\n" |
73 | //usage: | 87 | //usage: |
74 | //usage:#define modprobe_trivial_usage | 88 | //usage:#define modprobe_trivial_usage |
75 | //usage: "[-alrqvs" | 89 | //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" |
76 | //usage: IF_FEATURE_MODPROBE_BLACKLIST("b") | 90 | //usage: " MODULE [symbol=value]..." |
77 | //usage: "] MODULE [symbol=value]..." | ||
78 | //usage:#define modprobe_full_usage "\n\n" | 91 | //usage:#define modprobe_full_usage "\n\n" |
79 | //usage: "Options:" | 92 | //usage: "Options:" |
80 | //usage: "\n -a Load multiple MODULEs" | 93 | //usage: "\n -a Load multiple MODULEs" |
@@ -83,43 +96,50 @@ | |||
83 | //usage: "\n -q Quiet" | 96 | //usage: "\n -q Quiet" |
84 | //usage: "\n -v Verbose" | 97 | //usage: "\n -v Verbose" |
85 | //usage: "\n -s Log to syslog" | 98 | //usage: "\n -s Log to syslog" |
99 | //usage: "\n -D Show dependencies" | ||
86 | //usage: IF_FEATURE_MODPROBE_BLACKLIST( | 100 | //usage: IF_FEATURE_MODPROBE_BLACKLIST( |
87 | //usage: "\n -b Apply blacklist to module names too" | 101 | //usage: "\n -b Apply blacklist to module names too" |
88 | //usage: ) | 102 | //usage: ) |
89 | //usage:#endif /* !ENABLE_MODPROBE_SMALL */ | 103 | //usage:#endif /* !ENABLE_MODPROBE_SMALL */ |
90 | 104 | ||
91 | #include "libbb.h" | ||
92 | #include "modutils.h" | ||
93 | #include <sys/utsname.h> | ||
94 | #include <fnmatch.h> | ||
95 | |||
96 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | ||
97 | #define DBG(...) ((void)0) | ||
98 | |||
99 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | ||
100 | * we expect the full dependency list to be specified in modules.dep. | ||
101 | * Older versions would only export the direct dependency list. | ||
102 | */ | ||
103 | |||
104 | /* Note that usage text doesn't document various 2.4 options | 105 | /* Note that usage text doesn't document various 2.4 options |
105 | * we pull in through INSMOD_OPTS define */ | 106 | * we pull in through INSMOD_OPTS define */ |
106 | 107 | #define MODPROBE_OPTS "alrD" IF_FEATURE_MODPROBE_BLACKLIST("b") | |
107 | #define MODPROBE_COMPLEMENTARY "q-v:v-q:l--ar:a--lr:r--al" | 108 | /* -a and -D _are_ in fact compatible */ |
108 | #define MODPROBE_OPTS "alr" IF_FEATURE_MODPROBE_BLACKLIST("b") | 109 | #define MODPROBE_COMPLEMENTARY ("q-v:v-q:l--arD:r--alD:a--lr:D--rl") |
109 | //#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--acr:a--lr:r--al" | ||
110 | //#define MODPROBE_OPTS "acd:lnrt:C:" IF_FEATURE_MODPROBE_BLACKLIST("b") | 110 | //#define MODPROBE_OPTS "acd:lnrt:C:" IF_FEATURE_MODPROBE_BLACKLIST("b") |
111 | //#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--acr:a--lr:r--al" | ||
111 | enum { | 112 | enum { |
112 | MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ | 113 | OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ |
113 | //MODPROBE_OPT_DUMP_ONLY= (INSMOD_OPT_UNUSED << x), /* c */ | 114 | //OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << x), /* c */ |
114 | //MODPROBE_OPT_DIRNAME = (INSMOD_OPT_UNUSED << x), /* d */ | 115 | //OPT_DIRNAME = (INSMOD_OPT_UNUSED << x), /* d */ |
115 | MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 1), /* l */ | 116 | OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 1), /* l */ |
116 | //MODPROBE_OPT_SHOW_ONLY= (INSMOD_OPT_UNUSED << x), /* n */ | 117 | //OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << x), /* n */ |
117 | MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 2), /* r */ | 118 | OPT_REMOVE = (INSMOD_OPT_UNUSED << 2), /* r */ |
118 | //MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */ | 119 | //OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */ |
119 | //MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << x), /* V */ | 120 | //OPT_VERONLY = (INSMOD_OPT_UNUSED << x), /* V */ |
120 | //MODPROBE_OPT_CONFIGFILE=(INSMOD_OPT_UNUSED << x), /* C */ | 121 | //OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << x), /* C */ |
121 | MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 3) * ENABLE_FEATURE_MODPROBE_BLACKLIST, | 122 | OPT_SHOW_DEPS = (INSMOD_OPT_UNUSED << 3), /* D */ |
123 | OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 4) * ENABLE_FEATURE_MODPROBE_BLACKLIST, | ||
122 | }; | 124 | }; |
125 | #if ENABLE_LONG_OPTS | ||
126 | static const char modprobe_longopts[] ALIGN1 = | ||
127 | /* nobody asked for long opts (yet) */ | ||
128 | // "all\0" No_argument "a" | ||
129 | // "list\0" No_argument "l" | ||
130 | // "remove\0" No_argument "r" | ||
131 | // "quiet\0" No_argument "q" | ||
132 | // "verbose\0" No_argument "v" | ||
133 | // "syslog\0" No_argument "s" | ||
134 | /* module-init-tools 3.11.1 has only long opt --show-depends | ||
135 | * but no short -D, we provide long opt for scripts which | ||
136 | * were written for 3.11.1: */ | ||
137 | "show-depends\0" No_argument "D" | ||
138 | // IF_FEATURE_MODPROBE_BLACKLIST( | ||
139 | // "use-blacklist\0" No_argument "b" | ||
140 | // ) | ||
141 | ; | ||
142 | #endif | ||
123 | 143 | ||
124 | #define MODULE_FLAG_LOADED 0x0001 | 144 | #define MODULE_FLAG_LOADED 0x0001 |
125 | #define MODULE_FLAG_NEED_DEPS 0x0002 | 145 | #define MODULE_FLAG_NEED_DEPS 0x0002 |
@@ -145,9 +165,13 @@ struct globals { | |||
145 | int num_unresolved_deps; | 165 | int num_unresolved_deps; |
146 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | 166 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ |
147 | smallint need_symbols; | 167 | smallint need_symbols; |
168 | struct utsname uts; | ||
148 | } FIX_ALIASING; | 169 | } FIX_ALIASING; |
149 | #define G (*(struct globals*)&bb_common_bufsiz1) | 170 | #define G (*(struct globals*)&bb_common_bufsiz1) |
150 | #define INIT_G() do { } while (0) | 171 | #define INIT_G() do { } while (0) |
172 | struct BUG_G_too_big { | ||
173 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | ||
174 | }; | ||
151 | 175 | ||
152 | 176 | ||
153 | static int read_config(const char *path); | 177 | static int read_config(const char *path); |
@@ -202,7 +226,7 @@ static void add_probe(const char *name) | |||
202 | struct module_entry *m; | 226 | struct module_entry *m; |
203 | 227 | ||
204 | m = get_or_add_modentry(name); | 228 | m = get_or_add_modentry(name); |
205 | if (!(option_mask32 & MODPROBE_OPT_REMOVE) | 229 | if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) |
206 | && (m->flags & MODULE_FLAG_LOADED) | 230 | && (m->flags & MODULE_FLAG_LOADED) |
207 | ) { | 231 | ) { |
208 | DBG("skipping %s, it is already loaded", name); | 232 | DBG("skipping %s, it is already loaded", name); |
@@ -353,8 +377,6 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo | |||
353 | */ | 377 | */ |
354 | static int do_modprobe(struct module_entry *m) | 378 | static int do_modprobe(struct module_entry *m) |
355 | { | 379 | { |
356 | struct module_entry *m2 = m2; /* for compiler */ | ||
357 | char *fn, *options; | ||
358 | int rc, first; | 380 | int rc, first; |
359 | llist_t *l; | 381 | llist_t *l; |
360 | 382 | ||
@@ -366,7 +388,7 @@ static int do_modprobe(struct module_entry *m) | |||
366 | } | 388 | } |
367 | DBG("do_modprob'ing %s", m->modname); | 389 | DBG("do_modprob'ing %s", m->modname); |
368 | 390 | ||
369 | if (!(option_mask32 & MODPROBE_OPT_REMOVE)) | 391 | if (!(option_mask32 & OPT_REMOVE)) |
370 | m->deps = llist_rev(m->deps); | 392 | m->deps = llist_rev(m->deps); |
371 | 393 | ||
372 | for (l = m->deps; l != NULL; l = l->link) | 394 | for (l = m->deps; l != NULL; l = l->link) |
@@ -375,11 +397,14 @@ static int do_modprobe(struct module_entry *m) | |||
375 | first = 1; | 397 | first = 1; |
376 | rc = 0; | 398 | rc = 0; |
377 | while (m->deps) { | 399 | while (m->deps) { |
400 | struct module_entry *m2; | ||
401 | char *fn, *options; | ||
402 | |||
378 | rc = 0; | 403 | rc = 0; |
379 | fn = llist_pop(&m->deps); /* we leak it */ | 404 | fn = llist_pop(&m->deps); /* we leak it */ |
380 | m2 = get_or_add_modentry(fn); | 405 | m2 = get_or_add_modentry(fn); |
381 | 406 | ||
382 | if (option_mask32 & MODPROBE_OPT_REMOVE) { | 407 | if (option_mask32 & OPT_REMOVE) { |
383 | /* modprobe -r */ | 408 | /* modprobe -r */ |
384 | if (m2->flags & MODULE_FLAG_LOADED) { | 409 | if (m2->flags & MODULE_FLAG_LOADED) { |
385 | rc = bb_delete_module(m2->modname, O_EXCL); | 410 | rc = bb_delete_module(m2->modname, O_EXCL); |
@@ -399,16 +424,27 @@ static int do_modprobe(struct module_entry *m) | |||
399 | continue; | 424 | continue; |
400 | } | 425 | } |
401 | 426 | ||
402 | if (m2->flags & MODULE_FLAG_LOADED) { | ||
403 | DBG("%s is already loaded, skipping", fn); | ||
404 | continue; | ||
405 | } | ||
406 | |||
407 | options = m2->options; | 427 | options = m2->options; |
408 | m2->options = NULL; | 428 | m2->options = NULL; |
409 | options = parse_and_add_kcmdline_module_options(options, m2->modname); | 429 | options = parse_and_add_kcmdline_module_options(options, m2->modname); |
410 | if (m == m2) | 430 | if (m == m2) |
411 | options = gather_options_str(options, G.cmdline_mopts); | 431 | options = gather_options_str(options, G.cmdline_mopts); |
432 | |||
433 | if (option_mask32 & OPT_SHOW_DEPS) { | ||
434 | printf(options ? "insmod %s/%s/%s %s\n" | ||
435 | : "insmod %s/%s/%s\n", | ||
436 | CONFIG_DEFAULT_MODULES_DIR, G.uts.release, fn, | ||
437 | options); | ||
438 | free(options); | ||
439 | continue; | ||
440 | } | ||
441 | |||
442 | if (m2->flags & MODULE_FLAG_LOADED) { | ||
443 | DBG("%s is already loaded, skipping", fn); | ||
444 | free(options); | ||
445 | continue; | ||
446 | } | ||
447 | |||
412 | rc = bb_init_module(fn, options); | 448 | rc = bb_init_module(fn, options); |
413 | DBG("loaded %s '%s', rc:%d", fn, options, rc); | 449 | DBG("loaded %s '%s', rc:%d", fn, options, rc); |
414 | if (rc == EEXIST) | 450 | if (rc == EEXIST) |
@@ -456,7 +492,7 @@ static void load_modules_dep(void) | |||
456 | 492 | ||
457 | /* Optimization... */ | 493 | /* Optimization... */ |
458 | if ((m->flags & MODULE_FLAG_LOADED) | 494 | if ((m->flags & MODULE_FLAG_LOADED) |
459 | && !(option_mask32 & MODPROBE_OPT_REMOVE) | 495 | && !(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) |
460 | ) { | 496 | ) { |
461 | DBG("skip deps of %s, it's already loaded", tokens[0]); | 497 | DBG("skip deps of %s, it's already loaded", tokens[0]); |
462 | continue; | 498 | continue; |
@@ -477,21 +513,23 @@ static void load_modules_dep(void) | |||
477 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 513 | int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
478 | int modprobe_main(int argc UNUSED_PARAM, char **argv) | 514 | int modprobe_main(int argc UNUSED_PARAM, char **argv) |
479 | { | 515 | { |
480 | struct utsname uts; | ||
481 | int rc; | 516 | int rc; |
482 | unsigned opt; | 517 | unsigned opt; |
483 | struct module_entry *me; | 518 | struct module_entry *me; |
484 | 519 | ||
520 | INIT_G(); | ||
521 | |||
522 | IF_LONG_OPTS(applet_long_options = modprobe_longopts;) | ||
485 | opt_complementary = MODPROBE_COMPLEMENTARY; | 523 | opt_complementary = MODPROBE_COMPLEMENTARY; |
486 | opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS); | 524 | opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS); |
487 | argv += optind; | 525 | argv += optind; |
488 | 526 | ||
489 | /* Goto modules location */ | 527 | /* Goto modules location */ |
490 | xchdir(CONFIG_DEFAULT_MODULES_DIR); | 528 | xchdir(CONFIG_DEFAULT_MODULES_DIR); |
491 | uname(&uts); | 529 | uname(&G.uts); |
492 | xchdir(uts.release); | 530 | xchdir(G.uts.release); |
493 | 531 | ||
494 | if (opt & MODPROBE_OPT_LIST_ONLY) { | 532 | if (opt & OPT_LIST_ONLY) { |
495 | char name[MODULE_NAME_LEN]; | 533 | char name[MODULE_NAME_LEN]; |
496 | char *colon, *tokens[2]; | 534 | char *colon, *tokens[2]; |
497 | parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); | 535 | parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); |
@@ -521,7 +559,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
521 | logmode = LOGMODE_SYSLOG; | 559 | logmode = LOGMODE_SYSLOG; |
522 | 560 | ||
523 | if (!argv[0]) { | 561 | if (!argv[0]) { |
524 | if (opt & MODPROBE_OPT_REMOVE) { | 562 | if (opt & OPT_REMOVE) { |
525 | /* "modprobe -r" (w/o params). | 563 | /* "modprobe -r" (w/o params). |
526 | * "If name is NULL, all unused modules marked | 564 | * "If name is NULL, all unused modules marked |
527 | * autoclean will be removed". | 565 | * autoclean will be removed". |
@@ -541,7 +579,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
541 | config_close(parser); | 579 | config_close(parser); |
542 | } | 580 | } |
543 | 581 | ||
544 | if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) { | 582 | if (opt & (OPT_INSERT_ALL | OPT_REMOVE)) { |
545 | /* Each argument is a module name */ | 583 | /* Each argument is a module name */ |
546 | do { | 584 | do { |
547 | DBG("adding module %s", *argv); | 585 | DBG("adding module %s", *argv); |
@@ -575,7 +613,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
575 | /* This is not an alias. Literal names are blacklisted | 613 | /* This is not an alias. Literal names are blacklisted |
576 | * only if '-b' is given. | 614 | * only if '-b' is given. |
577 | */ | 615 | */ |
578 | if (!(opt & MODPROBE_OPT_BLACKLIST) | 616 | if (!(opt & OPT_BLACKLIST) |
579 | || !(me->flags & MODULE_FLAG_BLACKLISTED) | 617 | || !(me->flags & MODULE_FLAG_BLACKLISTED) |
580 | ) { | 618 | ) { |
581 | rc |= do_modprobe(me); | 619 | rc |= do_modprobe(me); |
@@ -592,7 +630,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
592 | m2 = get_or_add_modentry(realname); | 630 | m2 = get_or_add_modentry(realname); |
593 | if (!(m2->flags & MODULE_FLAG_BLACKLISTED) | 631 | if (!(m2->flags & MODULE_FLAG_BLACKLISTED) |
594 | && (!(m2->flags & MODULE_FLAG_LOADED) | 632 | && (!(m2->flags & MODULE_FLAG_LOADED) |
595 | || (opt & MODPROBE_OPT_REMOVE)) | 633 | || (opt & (OPT_REMOVE | OPT_SHOW_DEPS))) |
596 | ) { | 634 | ) { |
597 | //TODO: we can pass "me" as 2nd param to do_modprobe, | 635 | //TODO: we can pass "me" as 2nd param to do_modprobe, |
598 | //and make do_modprobe emit more meaningful error messages | 636 | //and make do_modprobe emit more meaningful error messages |
diff --git a/modutils/rmmod.c b/modutils/rmmod.c index dde77731f..2486511d7 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c | |||
@@ -35,9 +35,9 @@ int rmmod_main(int argc UNUSED_PARAM, char **argv) | |||
35 | /* Parse command line. */ | 35 | /* Parse command line. */ |
36 | n = getopt32(argv, "wfas"); // -s ignored | 36 | n = getopt32(argv, "wfas"); // -s ignored |
37 | argv += optind; | 37 | argv += optind; |
38 | if (n & 1) // --wait | 38 | if (n & 1) // --wait |
39 | flags &= ~O_NONBLOCK; | 39 | flags &= ~O_NONBLOCK; |
40 | if (n & 2) // --force | 40 | if (n & 2) // --force |
41 | flags |= O_TRUNC; | 41 | flags |= O_TRUNC; |
42 | if (n & 4) { | 42 | if (n & 4) { |
43 | /* Unload _all_ unused modules via NULL delete_module() call */ | 43 | /* Unload _all_ unused modules via NULL delete_module() call */ |