aboutsummaryrefslogtreecommitdiff
path: root/modutils
diff options
context:
space:
mode:
Diffstat (limited to 'modutils')
-rw-r--r--modutils/modprobe.c136
-rw-r--r--modutils/rmmod.c4
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"
111enum { 112enum {
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
126static 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)
172struct BUG_G_too_big {
173 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
174};
151 175
152 176
153static int read_config(const char *path); 177static 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 */
354static int do_modprobe(struct module_entry *m) 378static 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)
477int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 513int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
478int modprobe_main(int argc UNUSED_PARAM, char **argv) 514int 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 */