1 /* vi: set sw=4 ts=4: */
3 * Modprobe written from scratch for BusyBox
5 * Copyright (c) 2008 Timo Teras <timo.teras@iki.fi>
6 * Copyright (c) 2008 Vladimir Dronnikov
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11 /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t),
12 * we expect the full dependency list to be specified in modules.dep. Older
13 * versions would only export the direct dependency list.
18 #include <sys/utsname.h>
21 //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
22 #define DBG(...) ((void)0)
24 #define MODULE_FLAG_LOADED 0x0001
25 #define MODULE_FLAG_NEED_DEPS 0x0002
26 /* "was seen in modules.dep": */
27 #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004
28 #define MODULE_FLAG_BLACKLISTED 0x0008
30 struct module_entry
{ /* I'll call it ME. */
32 char *modname
; /* stripped of /path/, .ext and s/-/_/g */
33 const char *probed_name
; /* verbatim as seen on cmdline */
34 char *options
; /* options from config files */
35 llist_t
*realnames
; /* strings. if this module is an alias, */
36 /* real module name is one of these. */
37 //Can there really be more than one? Example from real kernel?
38 llist_t
*deps
; /* strings. modules we depend on */
41 #define MODPROBE_OPTS "acdlnrt:VC:" USE_FEATURE_MODPROBE_BLACKLIST("b")
43 MODPROBE_OPT_INSERT_ALL
= (INSMOD_OPT_UNUSED
<< 0), /* a */
44 MODPROBE_OPT_DUMP_ONLY
= (INSMOD_OPT_UNUSED
<< 1), /* c */
45 MODPROBE_OPT_D
= (INSMOD_OPT_UNUSED
<< 2), /* d */
46 MODPROBE_OPT_LIST_ONLY
= (INSMOD_OPT_UNUSED
<< 3), /* l */
47 MODPROBE_OPT_SHOW_ONLY
= (INSMOD_OPT_UNUSED
<< 4), /* n */
48 MODPROBE_OPT_REMOVE
= (INSMOD_OPT_UNUSED
<< 5), /* r */
49 MODPROBE_OPT_RESTRICT
= (INSMOD_OPT_UNUSED
<< 6), /* t */
50 MODPROBE_OPT_VERONLY
= (INSMOD_OPT_UNUSED
<< 7), /* V */
51 MODPROBE_OPT_CONFIGFILE
= (INSMOD_OPT_UNUSED
<< 8), /* C */
52 MODPROBE_OPT_BLACKLIST
= (INSMOD_OPT_UNUSED
<< 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST
,
56 llist_t
*db
; /* MEs of all modules ever seen (caching for speed) */
57 llist_t
*probes
; /* MEs of module(s) requested on cmdline */
58 char *cmdline_mopts
; /* module options from cmdline */
59 int num_unresolved_deps
;
60 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
61 smallint need_symbols
;
63 #define G (*(struct globals*)&bb_common_bufsiz1)
64 #define INIT_G() do { } while (0)
67 static int read_config(const char *path
);
69 static char *gather_options_str(char *opts
, const char *append
)
71 /* Speed-optimized. We call gather_options_str many times. */
73 opts
= xstrdup(append
);
75 int optlen
= strlen(opts
);
76 opts
= xrealloc(opts
, optlen
+ strlen(append
) + 2);
77 sprintf(opts
+ optlen
, " %s", append
);
82 static struct module_entry
*helper_get_module(const char *module
, int create
)
84 char modname
[MODULE_NAME_LEN
];
85 struct module_entry
*e
;
88 filename2modname(module
, modname
);
89 for (l
= G
.db
; l
!= NULL
; l
= l
->link
) {
90 e
= (struct module_entry
*) l
->data
;
91 if (strcmp(e
->modname
, modname
) == 0)
97 e
= xzalloc(sizeof(*e
));
98 e
->modname
= xstrdup(modname
);
99 llist_add_to(&G
.db
, e
);
103 static struct module_entry
*get_or_add_modentry(const char *module
)
105 return helper_get_module(module
, 1);
107 static struct module_entry
*get_modentry(const char *module
)
109 return helper_get_module(module
, 0);
112 static void add_probe(const char *name
)
114 struct module_entry
*m
;
116 m
= get_or_add_modentry(name
);
117 if (!(option_mask32
& MODPROBE_OPT_REMOVE
)
118 && (m
->flags
& MODULE_FLAG_LOADED
)
120 DBG("skipping %s, it is already loaded", name
);
124 DBG("queuing %s", name
);
125 m
->probed_name
= name
;
126 m
->flags
|= MODULE_FLAG_NEED_DEPS
;
127 llist_add_to_end(&G
.probes
, m
);
128 G
.num_unresolved_deps
++;
129 if (ENABLE_FEATURE_MODUTILS_SYMBOLS
130 && strncmp(m
->modname
, "symbol:", 7) == 0
136 static int FAST_FUNC
config_file_action(const char *filename
,
137 struct stat
*statbuf UNUSED_PARAM
,
138 void *userdata UNUSED_PARAM
,
139 int depth UNUSED_PARAM
)
143 struct module_entry
*m
;
146 if (bb_basename(filename
)[0] == '.')
149 p
= config_open2(filename
, fopen_for_read
);
155 while (config_read(p
, tokens
, 3, 2, "# \t", PARSE_NORMAL
)) {
156 //Use index_in_strings?
157 if (strcmp(tokens
[0], "alias") == 0) {
158 /* alias <wildcard> <modulename> */
160 char wildcard
[MODULE_NAME_LEN
];
163 if (tokens
[2] == NULL
)
165 filename2modname(tokens
[1], wildcard
);
167 for (l
= G
.probes
; l
!= NULL
; l
= l
->link
) {
168 m
= (struct module_entry
*) l
->data
;
169 if (fnmatch(wildcard
, m
->modname
, 0) != 0)
171 rmod
= filename2modname(tokens
[2], NULL
);
172 llist_add_to(&m
->realnames
, rmod
);
174 if (m
->flags
& MODULE_FLAG_NEED_DEPS
) {
175 m
->flags
&= ~MODULE_FLAG_NEED_DEPS
;
176 G
.num_unresolved_deps
--;
179 m
= get_or_add_modentry(rmod
);
180 if (!(m
->flags
& MODULE_FLAG_NEED_DEPS
)) {
181 m
->flags
|= MODULE_FLAG_NEED_DEPS
;
182 G
.num_unresolved_deps
++;
185 } else if (strcmp(tokens
[0], "options") == 0) {
186 /* options <modulename> <option...> */
187 if (tokens
[2] == NULL
)
189 m
= get_or_add_modentry(tokens
[1]);
190 m
->options
= gather_options_str(m
->options
, tokens
[2]);
191 } else if (strcmp(tokens
[0], "include") == 0) {
192 /* include <filename> */
193 read_config(tokens
[1]);
194 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
195 && strcmp(tokens
[0], "blacklist") == 0
197 /* blacklist <modulename> */
198 get_or_add_modentry(tokens
[1])->flags
|= MODULE_FLAG_BLACKLISTED
;
206 static int read_config(const char *path
)
208 return recursive_action(path
, ACTION_RECURSE
| ACTION_QUIET
,
209 config_file_action
, NULL
, NULL
, 1);
212 static int do_modprobe(struct module_entry
*m
)
214 struct module_entry
*m2
= m2
; /* for compiler */
219 if (!(m
->flags
& MODULE_FLAG_FOUND_IN_MODDEP
)) {
220 DBG("skipping %s, not found in modules.dep", m
->modname
);
223 DBG("do_modprob'ing %s", m
->modname
);
225 if (!(option_mask32
& MODPROBE_OPT_REMOVE
))
226 m
->deps
= llist_rev(m
->deps
);
228 for (l
= m
->deps
; l
!= NULL
; l
= l
->link
)
229 DBG("dep: %s", l
->data
);
233 while (m
->deps
&& rc
== 0) {
234 fn
= llist_pop(&m
->deps
);
235 m2
= get_or_add_modentry(fn
);
236 if (option_mask32
& MODPROBE_OPT_REMOVE
) {
237 if (m2
->flags
& MODULE_FLAG_LOADED
) {
238 if (bb_delete_module(m2
->modname
, O_EXCL
) != 0) {
242 m2
->flags
&= ~MODULE_FLAG_LOADED
;
245 /* do not error out if *deps* fail to unload */
247 } else if (!(m2
->flags
& MODULE_FLAG_LOADED
)) {
248 options
= m2
->options
;
251 options
= gather_options_str(options
, G
.cmdline_mopts
);
252 rc
= bb_init_module(fn
, options
);
253 DBG("loaded %s '%s', rc:%d", fn
, options
, rc
);
255 m2
->flags
|= MODULE_FLAG_LOADED
;
258 DBG("%s is already loaded, skipping", fn
);
264 if (rc
&& !(option_mask32
& INSMOD_OPT_SILENT
)) {
265 bb_error_msg("failed to %sload module %s: %s",
266 (option_mask32
& MODPROBE_OPT_REMOVE
) ? "un" : "",
267 m2
->probed_name
? m2
->probed_name
: m2
->modname
,
275 static void load_modules_dep(void)
277 struct module_entry
*m
;
278 char *colon
, *tokens
[2];
281 /* Modprobe does not work at all without modprobe.dep,
282 * even if the full module name is given. Returning error here
283 * was making us later confuse user with this message:
284 * "module /full/path/to/existing/file/module.ko not found".
285 * It's better to die immediately, with good message.
286 * xfopen_for_read provides that. */
287 p
= config_open2(CONFIG_DEFAULT_DEPMOD_FILE
, xfopen_for_read
);
289 while (G
.num_unresolved_deps
290 && config_read(p
, tokens
, 2, 1, "# \t", PARSE_NORMAL
)
292 colon
= last_char_is(tokens
[0], ':');
297 m
= get_modentry(tokens
[0]);
301 /* Optimization... */
302 if ((m
->flags
& MODULE_FLAG_LOADED
)
303 && !(option_mask32
& MODPROBE_OPT_REMOVE
)
305 DBG("skip deps of %s, it's already loaded", tokens
[0]);
309 m
->flags
|= MODULE_FLAG_FOUND_IN_MODDEP
;
310 if ((m
->flags
& MODULE_FLAG_NEED_DEPS
) && (m
->deps
== NULL
)) {
311 G
.num_unresolved_deps
--;
312 llist_add_to(&m
->deps
, xstrdup(tokens
[0]));
314 string_to_llist(tokens
[1], &m
->deps
, " ");
316 DBG("skipping dep line");
321 int modprobe_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
322 int modprobe_main(int argc UNUSED_PARAM
, char **argv
)
327 struct module_entry
*me
;
329 opt_complementary
= "q-v:v-q";
330 opt
= getopt32(argv
, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS
, NULL
, NULL
);
333 if (opt
& (MODPROBE_OPT_DUMP_ONLY
| MODPROBE_OPT_LIST_ONLY
|
334 MODPROBE_OPT_SHOW_ONLY
))
335 bb_error_msg_and_die("not supported");
338 if (opt
& MODPROBE_OPT_REMOVE
) {
339 /* "modprobe -r" (w/o params).
340 * "If name is NULL, all unused modules marked
341 * autoclean will be removed".
343 if (bb_delete_module(NULL
, O_NONBLOCK
|O_EXCL
) != 0)
344 bb_perror_msg_and_die("rmmod");
349 /* Goto modules location */
350 xchdir(CONFIG_DEFAULT_MODULES_DIR
);
354 /* Retrieve module names of already loaded modules */
357 parser_t
*parser
= config_open2("/proc/modules", fopen_for_read
);
358 while (config_read(parser
, &s
, 1, 1, "# \t", PARSE_NORMAL
& ~PARSE_GREEDY
))
359 get_or_add_modentry(s
)->flags
|= MODULE_FLAG_LOADED
;
360 config_close(parser
);
363 if (opt
& (MODPROBE_OPT_INSERT_ALL
| MODPROBE_OPT_REMOVE
)) {
364 /* Each argument is a module name */
366 DBG("adding module %s", *argv
);
370 /* First argument is module name, rest are parameters */
371 DBG("probing just module %s", *argv
);
373 G
.cmdline_mopts
= parse_cmdline_module_options(argv
);
376 /* Happens if all requested modules are already loaded */
377 if (G
.probes
== NULL
)
380 read_config("/etc/modprobe.conf");
381 read_config("/etc/modprobe.d");
382 if (ENABLE_FEATURE_MODUTILS_SYMBOLS
&& G
.need_symbols
)
383 read_config("modules.symbols");
385 if (ENABLE_FEATURE_MODUTILS_ALIAS
&& G
.num_unresolved_deps
) {
386 read_config("modules.alias");
390 while ((me
= llist_pop(&G
.probes
)) != NULL
) {
391 if (me
->realnames
== NULL
) {
392 /* This is not an alias. Literal names are blacklisted
393 * only if '-b' is given.
395 if (!(opt
& MODPROBE_OPT_BLACKLIST
)
396 || !(me
->flags
& MODULE_FLAG_BLACKLISTED
)
398 rc
= do_modprobe(me
);
399 //FIXME: what if rc > 0?
400 if (rc
< 0 && !(opt
& INSMOD_OPT_SILENT
))
401 bb_error_msg("module %s not found",
405 /* Probe all realnames */
407 char *realname
= llist_pop(&me
->realnames
);
408 struct module_entry
*m2
;
410 DBG("probing %s by realname %s", me
->modname
, realname
);
411 m2
= get_or_add_modentry(realname
);
412 if (!(m2
->flags
& MODULE_FLAG_BLACKLISTED
))
414 //FIXME: error check?
416 } while (me
->realnames
!= NULL
);