source: MondoRescue/branches/3.3/mindi-busybox/modutils/modprobe.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 18.9 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Modprobe written from scratch for BusyBox
4 *
5 * Copyright (c) 2008 Timo Teras <timo.teras@iki.fi>
6 * Copyright (c) 2008 Vladimir Dronnikov
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */
10
11//applet:IF_MODPROBE(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))
12
13#include "libbb.h"
14#include "modutils.h"
15#include <sys/utsname.h>
16#include <fnmatch.h>
17
18#if 1
19#define DBG(...) ((void)0)
20#else
21#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
22#endif
23
24/* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t),
25 * we expect the full dependency list to be specified in modules.dep.
26 * Older versions would only export the direct dependency list.
27 */
28
29
30//usage:#if !ENABLE_MODPROBE_SMALL
31//usage:#define modprobe_notes_usage
32//usage: "modprobe can (un)load a stack of modules, passing each module options (when\n"
33//usage: "loading). modprobe uses a configuration file to determine what option(s) to\n"
34//usage: "pass each module it loads.\n"
35//usage: "\n"
36//usage: "The configuration file is searched (in this order):\n"
37//usage: "\n"
38//usage: " /etc/modprobe.conf (2.6 only)\n"
39//usage: " /etc/modules.conf\n"
40//usage: " /etc/conf.modules (deprecated)\n"
41//usage: "\n"
42//usage: "They all have the same syntax (see below). If none is present, it is\n"
43//usage: "_not_ an error; each loaded module is then expected to load without\n"
44//usage: "options. Once a file is found, the others are tested for.\n"
45//usage: "\n"
46//usage: "/etc/modules.conf entry format:\n"
47//usage: "\n"
48//usage: " alias <alias_name> <mod_name>\n"
49//usage: " Makes it possible to modprobe alias_name, when there is no such module.\n"
50//usage: " It makes sense if your mod_name is long, or you want a more representative\n"
51//usage: " name for that module (eg. 'scsi' in place of 'aha7xxx').\n"
52//usage: " This makes it also possible to use a different set of options (below) for\n"
53//usage: " the module and the alias.\n"
54//usage: " A module can be aliased more than once.\n"
55//usage: "\n"
56//usage: " options <mod_name|alias_name> <symbol=value...>\n"
57//usage: " When loading module mod_name (or the module aliased by alias_name), pass\n"
58//usage: " the \"symbol=value\" pairs as option to that module.\n"
59//usage: "\n"
60//usage: "Sample /etc/modules.conf file:\n"
61//usage: "\n"
62//usage: " options tulip irq=3\n"
63//usage: " alias tulip tulip2\n"
64//usage: " options tulip2 irq=4 io=0x308\n"
65//usage: "\n"
66//usage: "Other functionality offered by 'classic' modprobe is not available in\n"
67//usage: "this implementation.\n"
68//usage: "\n"
69//usage: "If module options are present both in the config file, and on the command line,\n"
70//usage: "then the options from the command line will be passed to the module _after_\n"
71//usage: "the options from the config file. That way, you can have defaults in the config\n"
72//usage: "file, and override them for a specific usage from the command line.\n"
73//usage:#define modprobe_example_usage
74//usage: "(with the above /etc/modules.conf):\n\n"
75//usage: "$ modprobe tulip\n"
76//usage: " will load the module 'tulip' with default option 'irq=3'\n\n"
77//usage: "$ modprobe tulip irq=5\n"
78//usage: " will load the module 'tulip' with option 'irq=5', thus overriding the default\n\n"
79//usage: "$ modprobe tulip2\n"
80//usage: " will load the module 'tulip' with default options 'irq=4 io=0x308',\n"
81//usage: " which are the default for alias 'tulip2'\n\n"
82//usage: "$ modprobe tulip2 irq=8\n"
83//usage: " will load the module 'tulip' with default options 'irq=4 io=0x308 irq=8',\n"
84//usage: " which are the default for alias 'tulip2' overridden by the option 'irq=8'\n\n"
85//usage: " from the command line\n\n"
86//usage: "$ modprobe tulip2 irq=2 io=0x210\n"
87//usage: " will load the module 'tulip' with default options 'irq=4 io=0x308 irq=4 io=0x210',\n"
88//usage: " which are the default for alias 'tulip2' overridden by the options 'irq=2 io=0x210'\n\n"
89//usage: " from the command line\n"
90//usage:
91//usage:#define modprobe_trivial_usage
92//usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]"
93//usage: " MODULE [SYMBOL=VALUE]..."
94//usage:#define modprobe_full_usage "\n\n"
95//usage: " -a Load multiple MODULEs"
96//usage: "\n -l List (MODULE is a pattern)"
97//usage: "\n -r Remove MODULE (stacks) or do autoclean"
98//usage: "\n -q Quiet"
99//usage: "\n -v Verbose"
100//usage: "\n -s Log to syslog"
101//usage: "\n -D Show dependencies"
102//usage: IF_FEATURE_MODPROBE_BLACKLIST(
103//usage: "\n -b Apply blacklist to module names too"
104//usage: )
105//usage:#endif /* !ENABLE_MODPROBE_SMALL */
106
107/* Note: usage text doesn't document various 2.4 options
108 * we pull in through INSMOD_OPTS define
109 * Note2: -b is always accepted, but if !FEATURE_MODPROBE_BLACKLIST,
110 * it is a no-op.
111 */
112#define MODPROBE_OPTS "alrDb"
113/* -a and -D _are_ in fact compatible */
114#define MODPROBE_COMPLEMENTARY ("q-v:v-q:l--arD:r--alD:a--lr:D--rl")
115//#define MODPROBE_OPTS "acd:lnrt:C:b"
116//#define MODPROBE_COMPLEMENTARY "q-v:v-q:l--acr:a--lr:r--al"
117enum {
118 OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */
119 //OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << x), /* c */
120 //OPT_DIRNAME = (INSMOD_OPT_UNUSED << x), /* d */
121 OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 1), /* l */
122 //OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << x), /* n */
123 OPT_REMOVE = (INSMOD_OPT_UNUSED << 2), /* r */
124 //OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */
125 //OPT_VERONLY = (INSMOD_OPT_UNUSED << x), /* V */
126 //OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << x), /* C */
127 OPT_SHOW_DEPS = (INSMOD_OPT_UNUSED << 3), /* D */
128 OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 4) * ENABLE_FEATURE_MODPROBE_BLACKLIST,
129};
130#if ENABLE_LONG_OPTS
131static const char modprobe_longopts[] ALIGN1 =
132 /* nobody asked for long opts (yet) */
133 // "all\0" No_argument "a"
134 // "list\0" No_argument "l"
135 // "remove\0" No_argument "r"
136 // "quiet\0" No_argument "q"
137 // "verbose\0" No_argument "v"
138 // "syslog\0" No_argument "s"
139 /* module-init-tools 3.11.1 has only long opt --show-depends
140 * but no short -D, we provide long opt for scripts which
141 * were written for 3.11.1: */
142 "show-depends\0" No_argument "D"
143 // "use-blacklist\0" No_argument "b"
144 ;
145#endif
146
147#define MODULE_FLAG_LOADED 0x0001
148#define MODULE_FLAG_NEED_DEPS 0x0002
149/* "was seen in modules.dep": */
150#define MODULE_FLAG_FOUND_IN_MODDEP 0x0004
151#define MODULE_FLAG_BLACKLISTED 0x0008
152
153struct globals {
154 llist_t *probes; /* MEs of module(s) requested on cmdline */
155 char *cmdline_mopts; /* module options from cmdline */
156 int num_unresolved_deps;
157 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
158 smallint need_symbols;
159 struct utsname uts;
160 module_db db;
161} FIX_ALIASING;
162#define G (*ptr_to_globals)
163#define INIT_G() do { \
164 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
165} while (0)
166
167
168static int read_config(const char *path);
169
170static char *gather_options_str(char *opts, const char *append)
171{
172 /* Speed-optimized. We call gather_options_str many times. */
173 if (append) {
174 if (opts == NULL) {
175 opts = xstrdup(append);
176 } else {
177 int optlen = strlen(opts);
178 opts = xrealloc(opts, optlen + strlen(append) + 2);
179 sprintf(opts + optlen, " %s", append);
180 }
181 }
182 return opts;
183}
184
185static struct module_entry *get_or_add_modentry(const char *module)
186{
187 return moddb_get_or_create(&G.db, module);
188}
189
190static void add_probe(const char *name)
191{
192 struct module_entry *m;
193
194 m = get_or_add_modentry(name);
195 if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
196 && (m->flags & MODULE_FLAG_LOADED)
197 ) {
198 DBG("skipping %s, it is already loaded", name);
199 return;
200 }
201
202 DBG("queuing %s", name);
203 m->probed_name = name;
204 m->flags |= MODULE_FLAG_NEED_DEPS;
205 llist_add_to_end(&G.probes, m);
206 G.num_unresolved_deps++;
207 if (ENABLE_FEATURE_MODUTILS_SYMBOLS
208 && is_prefixed_with(m->modname, "symbol:")
209 ) {
210 G.need_symbols = 1;
211 }
212}
213
214static int FAST_FUNC config_file_action(const char *filename,
215 struct stat *statbuf UNUSED_PARAM,
216 void *userdata UNUSED_PARAM,
217 int depth)
218{
219 char *tokens[3];
220 parser_t *p;
221 struct module_entry *m;
222 int rc = TRUE;
223 const char *base, *ext;
224
225 /* Skip files that begin with a "." */
226 base = bb_basename(filename);
227 if (base[0] == '.')
228 goto error;
229
230 /* In dir recursion, skip files that do not end with a ".conf"
231 * depth==0: read_config("modules.{symbols,alias}") must work,
232 * "include FILE_NOT_ENDING_IN_CONF" must work too.
233 */
234 if (depth != 0) {
235 ext = strrchr(base, '.');
236 if (ext == NULL || strcmp(ext + 1, "conf"))
237 goto error;
238 }
239
240 p = config_open2(filename, fopen_for_read);
241 if (p == NULL) {
242 rc = FALSE;
243 goto error;
244 }
245
246 while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) {
247//Use index_in_strings?
248 if (strcmp(tokens[0], "alias") == 0) {
249 /* alias <wildcard> <modulename> */
250 llist_t *l;
251 char wildcard[MODULE_NAME_LEN];
252 char *rmod;
253
254 if (tokens[2] == NULL)
255 continue;
256 filename2modname(tokens[1], wildcard);
257
258 for (l = G.probes; l; l = l->link) {
259 m = (struct module_entry *) l->data;
260 if (fnmatch(wildcard, m->modname, 0) != 0)
261 continue;
262 rmod = filename2modname(tokens[2], NULL);
263 llist_add_to(&m->realnames, rmod);
264
265 if (m->flags & MODULE_FLAG_NEED_DEPS) {
266 m->flags &= ~MODULE_FLAG_NEED_DEPS;
267 G.num_unresolved_deps--;
268 }
269
270 m = get_or_add_modentry(rmod);
271 if (!(m->flags & MODULE_FLAG_NEED_DEPS)) {
272 m->flags |= MODULE_FLAG_NEED_DEPS;
273 G.num_unresolved_deps++;
274 }
275 }
276 } else if (strcmp(tokens[0], "options") == 0) {
277 /* options <modulename> <option...> */
278 if (tokens[2] == NULL)
279 continue;
280 m = get_or_add_modentry(tokens[1]);
281 m->options = gather_options_str(m->options, tokens[2]);
282 } else if (strcmp(tokens[0], "include") == 0) {
283 /* include <filename>/<dirname> (yes, directories also must work) */
284 read_config(tokens[1]);
285 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
286 && strcmp(tokens[0], "blacklist") == 0
287 ) {
288 /* blacklist <modulename> */
289 get_or_add_modentry(tokens[1])->flags |= MODULE_FLAG_BLACKLISTED;
290 }
291 }
292 config_close(p);
293 error:
294 return rc;
295}
296
297static int read_config(const char *path)
298{
299 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
300 config_file_action, NULL, NULL,
301 /*depth:*/ 0);
302}
303
304static const char *humanly_readable_name(struct module_entry *m)
305{
306 /* probed_name may be NULL. modname always exists. */
307 return m->probed_name ? m->probed_name : m->modname;
308}
309
310/* Like strsep(&stringp, "\n\t ") but quoted text goes to single token
311 * even if it contains whitespace.
312 */
313static char *strsep_quotes(char **stringp)
314{
315 char *s, *start = *stringp;
316
317 if (!start)
318 return NULL;
319
320 for (s = start; ; s++) {
321 switch (*s) {
322 case '"':
323 s = strchrnul(s + 1, '"'); /* find trailing quote */
324 if (*s != '\0')
325 s++; /* skip trailing quote */
326 /* fall through */
327 case '\0':
328 case '\n':
329 case '\t':
330 case ' ':
331 if (*s != '\0') {
332 *s = '\0';
333 *stringp = s + 1;
334 } else {
335 *stringp = NULL;
336 }
337 return start;
338 }
339 }
340}
341
342static char *parse_and_add_kcmdline_module_options(char *options, const char *modulename)
343{
344 char *kcmdline_buf;
345 char *kcmdline;
346 char *kptr;
347
348 kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL);
349 if (!kcmdline_buf)
350 return options;
351
352 kcmdline = kcmdline_buf;
353 while ((kptr = strsep_quotes(&kcmdline)) != NULL) {
354 char *after_modulename = is_prefixed_with(kptr, modulename);
355 if (!after_modulename || *after_modulename != '.')
356 continue;
357 /* It is "modulename.xxxx" */
358 kptr = after_modulename + 1;
359 if (strchr(kptr, '=') != NULL) {
360 /* It is "modulename.opt=[val]" */
361 options = gather_options_str(options, kptr);
362 }
363 }
364 free(kcmdline_buf);
365
366 return options;
367}
368
369/* Return: similar to bb_init_module:
370 * 0 on success,
371 * -errno on open/read error,
372 * errno on init_module() error
373 */
374/* NB: INSMOD_OPT_SILENT bit suppresses ONLY non-existent modules,
375 * not deleted ones (those are still listed in modules.dep).
376 * module-init-tools version 3.4:
377 * # modprobe bogus
378 * FATAL: Module bogus not found. [exitcode 1]
379 * # modprobe -q bogus [silent, exitcode still 1]
380 * but:
381 * # rm kernel/drivers/net/dummy.ko
382 * # modprobe -q dummy
383 * FATAL: Could not open '/lib/modules/xxx/kernel/drivers/net/dummy.ko': No such file or directory
384 * [exitcode 1]
385 */
386static int do_modprobe(struct module_entry *m)
387{
388 int rc, first;
389
390 if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) {
391 if (!(option_mask32 & INSMOD_OPT_SILENT))
392 bb_error_msg("module %s not found in modules.dep",
393 humanly_readable_name(m));
394 return -ENOENT;
395 }
396 DBG("do_modprob'ing %s", m->modname);
397
398 if (!(option_mask32 & OPT_REMOVE))
399 m->deps = llist_rev(m->deps);
400
401 if (0) {
402 llist_t *l;
403 for (l = m->deps; l; l = l->link)
404 DBG("dep: %s", l->data);
405 }
406
407 first = 1;
408 rc = 0;
409 while (m->deps) {
410 struct module_entry *m2;
411 char *fn, *options;
412
413 rc = 0;
414 fn = llist_pop(&m->deps); /* we leak it */
415 m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn));
416
417 if (option_mask32 & OPT_REMOVE) {
418 /* modprobe -r */
419 if (m2->flags & MODULE_FLAG_LOADED) {
420 rc = bb_delete_module(m2->modname, O_EXCL);
421 if (rc) {
422 if (first) {
423 bb_perror_msg("can't unload module '%s'",
424 humanly_readable_name(m2));
425 break;
426 }
427 } else {
428 m2->flags &= ~MODULE_FLAG_LOADED;
429 }
430 }
431 /* do not error out if *deps* fail to unload */
432 first = 0;
433 continue;
434 }
435
436 options = m2->options;
437 m2->options = NULL;
438 options = parse_and_add_kcmdline_module_options(options, m2->modname);
439 if (m == m2)
440 options = gather_options_str(options, G.cmdline_mopts);
441
442 if (option_mask32 & OPT_SHOW_DEPS) {
443 printf(options ? "insmod %s/%s/%s %s\n"
444 : "insmod %s/%s/%s\n",
445 CONFIG_DEFAULT_MODULES_DIR, G.uts.release, fn,
446 options);
447 free(options);
448 continue;
449 }
450
451 if (m2->flags & MODULE_FLAG_LOADED) {
452 DBG("%s is already loaded, skipping", fn);
453 free(options);
454 continue;
455 }
456
457 rc = bb_init_module(fn, options);
458 DBG("loaded %s '%s', rc:%d", fn, options, rc);
459 if (rc == EEXIST)
460 rc = 0;
461 free(options);
462 if (rc) {
463 bb_error_msg("can't load module %s (%s): %s",
464 humanly_readable_name(m2),
465 fn,
466 moderror(rc)
467 );
468 break;
469 }
470 m2->flags |= MODULE_FLAG_LOADED;
471 }
472
473 return rc;
474}
475
476static void load_modules_dep(void)
477{
478 struct module_entry *m;
479 char *colon, *tokens[2];
480 parser_t *p;
481
482 /* Modprobe does not work at all without modules.dep,
483 * even if the full module name is given. Returning error here
484 * was making us later confuse user with this message:
485 * "module /full/path/to/existing/file/module.ko not found".
486 * It's better to die immediately, with good message.
487 * xfopen_for_read provides that. */
488 p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
489
490 while (G.num_unresolved_deps
491 && config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)
492 ) {
493 colon = last_char_is(tokens[0], ':');
494 if (colon == NULL)
495 continue;
496 *colon = '\0';
497
498 m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0]));
499 if (m == NULL)
500 continue;
501
502 /* Optimization... */
503 if ((m->flags & MODULE_FLAG_LOADED)
504 && !(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS))
505 ) {
506 DBG("skip deps of %s, it's already loaded", tokens[0]);
507 continue;
508 }
509
510 m->flags |= MODULE_FLAG_FOUND_IN_MODDEP;
511 if ((m->flags & MODULE_FLAG_NEED_DEPS) && (m->deps == NULL)) {
512 G.num_unresolved_deps--;
513 llist_add_to(&m->deps, xstrdup(tokens[0]));
514 if (tokens[1])
515 string_to_llist(tokens[1], &m->deps, " \t");
516 } else
517 DBG("skipping dep line");
518 }
519 config_close(p);
520}
521
522int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
523int modprobe_main(int argc UNUSED_PARAM, char **argv)
524{
525 int rc;
526 unsigned opt;
527 struct module_entry *me;
528
529 INIT_G();
530
531 IF_LONG_OPTS(applet_long_options = modprobe_longopts;)
532 opt_complementary = MODPROBE_COMPLEMENTARY;
533 opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS);
534 argv += optind;
535
536 /* Goto modules location */
537 xchdir(CONFIG_DEFAULT_MODULES_DIR);
538 uname(&G.uts);
539 xchdir(G.uts.release);
540
541 if (opt & OPT_LIST_ONLY) {
542 int i;
543 char *colon, *tokens[2];
544 parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
545
546 for (i = 0; argv[i]; i++)
547 replace(argv[i], '-', '_');
548
549 while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) {
550 colon = last_char_is(tokens[0], ':');
551 if (!colon)
552 continue;
553 *colon = '\0';
554 if (!argv[0])
555 puts(tokens[0]);
556 else {
557 char name[MODULE_NAME_LEN];
558 filename2modname(
559 bb_get_last_path_component_nostrip(tokens[0]),
560 name
561 );
562 for (i = 0; argv[i]; i++) {
563 if (fnmatch(argv[i], name, 0) == 0) {
564 puts(tokens[0]);
565 }
566 }
567 }
568 }
569 return EXIT_SUCCESS;
570 }
571
572 /* Yes, for some reason -l ignores -s... */
573 if (opt & INSMOD_OPT_SYSLOG)
574 logmode = LOGMODE_SYSLOG;
575
576 if (!argv[0]) {
577 if (opt & OPT_REMOVE) {
578 /* "modprobe -r" (w/o params).
579 * "If name is NULL, all unused modules marked
580 * autoclean will be removed".
581 */
582 if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0)
583 bb_perror_nomsg_and_die();
584 }
585 return EXIT_SUCCESS;
586 }
587
588 /* Retrieve module names of already loaded modules */
589 {
590 char *s;
591 parser_t *parser = config_open2("/proc/modules", fopen_for_read);
592 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
593 get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED;
594 config_close(parser);
595 }
596
597 if (opt & (OPT_INSERT_ALL | OPT_REMOVE)) {
598 /* Each argument is a module name */
599 do {
600 DBG("adding module %s", *argv);
601 add_probe(*argv++);
602 } while (*argv);
603 } else {
604 /* First argument is module name, rest are parameters */
605 DBG("probing just module %s", *argv);
606 add_probe(argv[0]);
607 G.cmdline_mopts = parse_cmdline_module_options(argv, /*quote_spaces:*/ 1);
608 }
609
610 /* Happens if all requested modules are already loaded */
611 if (G.probes == NULL)
612 return EXIT_SUCCESS;
613
614 read_config("/etc/modprobe.conf");
615 read_config("/etc/modprobe.d");
616 if (ENABLE_FEATURE_MODUTILS_SYMBOLS && G.need_symbols)
617 read_config("modules.symbols");
618 load_modules_dep();
619 if (ENABLE_FEATURE_MODUTILS_ALIAS && G.num_unresolved_deps) {
620 read_config("modules.alias");
621 load_modules_dep();
622 }
623
624 rc = 0;
625 while ((me = llist_pop(&G.probes)) != NULL) {
626 if (me->realnames == NULL) {
627 DBG("probing by module name");
628 /* This is not an alias. Literal names are blacklisted
629 * only if '-b' is given.
630 */
631 if (!(opt & OPT_BLACKLIST)
632 || !(me->flags & MODULE_FLAG_BLACKLISTED)
633 ) {
634 rc |= do_modprobe(me);
635 }
636 continue;
637 }
638
639 /* Probe all real names for the alias */
640 do {
641 char *realname = llist_pop(&me->realnames);
642 struct module_entry *m2;
643
644 DBG("probing alias %s by realname %s", me->modname, realname);
645 m2 = get_or_add_modentry(realname);
646 if (!(m2->flags & MODULE_FLAG_BLACKLISTED)
647 && (!(m2->flags & MODULE_FLAG_LOADED)
648 || (opt & (OPT_REMOVE | OPT_SHOW_DEPS)))
649 ) {
650//TODO: we can pass "me" as 2nd param to do_modprobe,
651//and make do_modprobe emit more meaningful error messages
652//with alias name included, not just module name alias resolves to.
653 rc |= do_modprobe(m2);
654 }
655 free(realname);
656 } while (me->realnames != NULL);
657 }
658
659 if (ENABLE_FEATURE_CLEAN_UP)
660 moddb_free(&G.db);
661
662 return (rc != 0);
663}
Note: See TracBrowser for help on using the repository browser.