Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/modutils/modprobe.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/modutils/modprobe.c
r1765 r2725 3 3 * Modprobe written from scratch for BusyBox 4 4 * 5 * Copyright (c) 2002 by Robert Griebl, griebl@gmx.de 6 * Copyright (c) 2003 by Andrew Dennison, andrew.dennison@motec.com.au 7 * Copyright (c) 2005 by Jim Bauer, jfbauer@nfr.com 5 * Copyright (c) 2008 Timo Teras <timo.teras@iki.fi> 6 * Copyright (c) 2008 Vladimir Dronnikov 8 7 * 9 * Portions Copyright (c) 2005 by Yann E. MORIN, yann.morin.1998@anciens.enib.fr 10 * 11 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 12 */ 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 //usage:#if !ENABLE_MODPROBE_SMALL 14 //usage:#define modprobe_notes_usage 15 //usage: "modprobe can (un)load a stack of modules, passing each module options (when\n" 16 //usage: "loading). modprobe uses a configuration file to determine what option(s) to\n" 17 //usage: "pass each module it loads.\n" 18 //usage: "\n" 19 //usage: "The configuration file is searched (in this order):\n" 20 //usage: "\n" 21 //usage: " /etc/modprobe.conf (2.6 only)\n" 22 //usage: " /etc/modules.conf\n" 23 //usage: " /etc/conf.modules (deprecated)\n" 24 //usage: "\n" 25 //usage: "They all have the same syntax (see below). If none is present, it is\n" 26 //usage: "_not_ an error; each loaded module is then expected to load without\n" 27 //usage: "options. Once a file is found, the others are tested for.\n" 28 //usage: "\n" 29 //usage: "/etc/modules.conf entry format:\n" 30 //usage: "\n" 31 //usage: " alias <alias_name> <mod_name>\n" 32 //usage: " Makes it possible to modprobe alias_name, when there is no such module.\n" 33 //usage: " It makes sense if your mod_name is long, or you want a more representative\n" 34 //usage: " name for that module (eg. 'scsi' in place of 'aha7xxx').\n" 35 //usage: " This makes it also possible to use a different set of options (below) for\n" 36 //usage: " the module and the alias.\n" 37 //usage: " A module can be aliased more than once.\n" 38 //usage: "\n" 39 //usage: " options <mod_name|alias_name> <symbol=value...>\n" 40 //usage: " When loading module mod_name (or the module aliased by alias_name), pass\n" 41 //usage: " the \"symbol=value\" pairs as option to that module.\n" 42 //usage: "\n" 43 //usage: "Sample /etc/modules.conf file:\n" 44 //usage: "\n" 45 //usage: " options tulip irq=3\n" 46 //usage: " alias tulip tulip2\n" 47 //usage: " options tulip2 irq=4 io=0x308\n" 48 //usage: "\n" 49 //usage: "Other functionality offered by 'classic' modprobe is not available in\n" 50 //usage: "this implementation.\n" 51 //usage: "\n" 52 //usage: "If module options are present both in the config file, and on the command line,\n" 53 //usage: "then the options from the command line will be passed to the module _after_\n" 54 //usage: "the options from the config file. That way, you can have defaults in the config\n" 55 //usage: "file, and override them for a specific usage from the command line.\n" 56 //usage:#define modprobe_example_usage 57 //usage: "(with the above /etc/modules.conf):\n\n" 58 //usage: "$ modprobe tulip\n" 59 //usage: " will load the module 'tulip' with default option 'irq=3'\n\n" 60 //usage: "$ modprobe tulip irq=5\n" 61 //usage: " will load the module 'tulip' with option 'irq=5', thus overriding the default\n\n" 62 //usage: "$ modprobe tulip2\n" 63 //usage: " will load the module 'tulip' with default options 'irq=4 io=0x308',\n" 64 //usage: " which are the default for alias 'tulip2'\n\n" 65 //usage: "$ modprobe tulip2 irq=8\n" 66 //usage: " will load the module 'tulip' with default options 'irq=4 io=0x308 irq=8',\n" 67 //usage: " which are the default for alias 'tulip2' overridden by the option 'irq=8'\n\n" 68 //usage: " from the command line\n\n" 69 //usage: "$ modprobe tulip2 irq=2 io=0x210\n" 70 //usage: " will load the module 'tulip' with default options 'irq=4 io=0x308 irq=4 io=0x210',\n" 71 //usage: " which are the default for alias 'tulip2' overridden by the options 'irq=2 io=0x210'\n\n" 72 //usage: " from the command line\n" 73 //usage: 74 //usage:#define modprobe_trivial_usage 75 //usage: "[-alrqvs" 76 //usage: IF_FEATURE_MODPROBE_BLACKLIST("b") 77 //usage: "] MODULE [symbol=value]..." 78 //usage:#define modprobe_full_usage "\n\n" 79 //usage: "Options:" 80 //usage: "\n -a Load multiple MODULEs" 81 //usage: "\n -l List (MODULE is a pattern)" 82 //usage: "\n -r Remove MODULE (stacks) or do autoclean" 83 //usage: "\n -q Quiet" 84 //usage: "\n -v Verbose" 85 //usage: "\n -s Log to syslog" 86 //usage: IF_FEATURE_MODPROBE_BLACKLIST( 87 //usage: "\n -b Apply blacklist to module names too" 88 //usage: ) 89 //usage:#endif /* !ENABLE_MODPROBE_SMALL */ 13 90 14 91 #include "libbb.h" 92 #include "modutils.h" 15 93 #include <sys/utsname.h> 16 94 #include <fnmatch.h> 17 95 18 struct mod_opt_t { /* one-way list of options to pass to a module */ 19 char * m_opt_val; 20 struct mod_opt_t * m_next; 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 * we pull in through INSMOD_OPTS define */ 106 107 #define MODPROBE_COMPLEMENTARY "q-v:v-q:l--ar:a--lr:r--al" 108 #define MODPROBE_OPTS "alr" IF_FEATURE_MODPROBE_BLACKLIST("b") 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") 111 enum { 112 MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ 113 //MODPROBE_OPT_DUMP_ONLY= (INSMOD_OPT_UNUSED << x), /* c */ 114 //MODPROBE_OPT_DIRNAME = (INSMOD_OPT_UNUSED << x), /* d */ 115 MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 1), /* l */ 116 //MODPROBE_OPT_SHOW_ONLY= (INSMOD_OPT_UNUSED << x), /* n */ 117 MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 2), /* r */ 118 //MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << x), /* t */ 119 //MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << x), /* V */ 120 //MODPROBE_OPT_CONFIGFILE=(INSMOD_OPT_UNUSED << x), /* C */ 121 MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 3) * ENABLE_FEATURE_MODPROBE_BLACKLIST, 21 122 }; 22 123 23 struct dep_t { /* one-way list of dependency rules */ 24 /* a dependency rule */ 25 char * m_name; /* the module name*/ 26 char * m_path; /* the module file path */ 27 struct mod_opt_t * m_options; /* the module options */ 28 29 int m_isalias : 1; /* the module is an alias */ 30 int m_reserved : 15; /* stuffin' */ 31 32 int m_depcnt : 16; /* the number of dependable module(s) */ 33 char ** m_deparr; /* the list of dependable module(s) */ 34 35 struct dep_t * m_next; /* the next dependency rule */ 124 #define MODULE_FLAG_LOADED 0x0001 125 #define MODULE_FLAG_NEED_DEPS 0x0002 126 /* "was seen in modules.dep": */ 127 #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 128 #define MODULE_FLAG_BLACKLISTED 0x0008 129 130 struct module_entry { /* I'll call it ME. */ 131 unsigned flags; 132 char *modname; /* stripped of /path/, .ext and s/-/_/g */ 133 const char *probed_name; /* verbatim as seen on cmdline */ 134 char *options; /* options from config files */ 135 llist_t *realnames; /* strings. if this module is an alias, */ 136 /* real module name is one of these. */ 137 //Can there really be more than one? Example from real kernel? 138 llist_t *deps; /* strings. modules we depend on */ 36 139 }; 37 140 38 struct mod_list_t { /* two-way list of modules to process */ 39 /* a module description */ 40 const char * m_name; 41 char * m_path; 42 struct mod_opt_t * m_options; 43 44 struct mod_list_t * m_prev; 45 struct mod_list_t * m_next; 46 }; 47 48 49 static struct dep_t *depend; 50 51 #define main_options "acdklnqrst:vVC:" 52 #define INSERT_ALL 1 /* a */ 53 #define DUMP_CONF_EXIT 2 /* c */ 54 #define D_OPT_IGNORED 4 /* d */ 55 #define AUTOCLEAN_FLG 8 /* k */ 56 #define LIST_ALL 16 /* l */ 57 #define SHOW_ONLY 32 /* n */ 58 #define QUIET 64 /* q */ 59 #define REMOVE_OPT 128 /* r */ 60 #define DO_SYSLOG 256 /* s */ 61 #define RESTRICT_DIR 512 /* t */ 62 #define VERBOSE 1024 /* v */ 63 #define VERSION_ONLY 2048 /* V */ 64 #define CONFIG_FILE 4096 /* C */ 65 66 #define autoclean (main_opts & AUTOCLEAN_FLG) 67 #define show_only (main_opts & SHOW_ONLY) 68 #define quiet (main_opts & QUIET) 69 #define remove_opt (main_opts & REMOVE_OPT) 70 #define do_syslog (main_opts & DO_SYSLOG) 71 #define verbose (main_opts & VERBOSE) 72 73 static int main_opts; 74 75 static int parse_tag_value(char *buffer, char **ptag, char **pvalue) 76 { 77 char *tag, *value; 78 79 buffer = skip_whitespace(buffer); 80 tag = value = buffer; 81 while (!isspace(*value)) 82 if (!*value) return 0; 83 else value++; 84 *value++ = 0; 85 value = skip_whitespace(value); 86 if (!*value) return 0; 87 88 *ptag = tag; 89 *pvalue = value; 90 91 return 1; 92 } 93 94 /* 95 * This function appends an option to a list 96 */ 97 static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt) 98 { 99 struct mod_opt_t *ol = opt_list; 100 101 if (ol) { 102 while (ol->m_next) { 103 ol = ol->m_next; 104 } 105 ol->m_next = xmalloc(sizeof(struct mod_opt_t)); 106 ol = ol->m_next; 107 } else { 108 ol = opt_list = xmalloc(sizeof(struct mod_opt_t)); 109 } 110 111 ol->m_opt_val = xstrdup(opt); 112 ol->m_next = NULL; 113 114 return opt_list; 115 } 116 117 #if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS 118 /* static char* parse_command_string(char* src, char **dst); 119 * src: pointer to string containing argument 120 * dst: pointer to where to store the parsed argument 121 * return value: the pointer to the first char after the parsed argument, 122 * NULL if there was no argument parsed (only trailing spaces). 123 * Note that memory is allocated with xstrdup when a new argument was 124 * parsed. Don't forget to free it! 125 */ 126 #define ARG_EMPTY 0x00 127 #define ARG_IN_DQUOTES 0x01 128 #define ARG_IN_SQUOTES 0x02 129 static char *parse_command_string(char *src, char **dst) 130 { 131 int opt_status = ARG_EMPTY; 132 char* tmp_str; 133 134 /* Dumb you, I have nothing to do... */ 135 if (src == NULL) return src; 136 137 /* Skip leading spaces */ 138 while (*src == ' ') { 139 src++; 140 } 141 /* Is the end of string reached? */ 142 if (*src == '\0') { 141 struct globals { 142 llist_t *db; /* MEs of all modules ever seen (caching for speed) */ 143 llist_t *probes; /* MEs of module(s) requested on cmdline */ 144 char *cmdline_mopts; /* module options from cmdline */ 145 int num_unresolved_deps; 146 /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ 147 smallint need_symbols; 148 } FIX_ALIASING; 149 #define G (*(struct globals*)&bb_common_bufsiz1) 150 #define INIT_G() do { } while (0) 151 152 153 static int read_config(const char *path); 154 155 static char *gather_options_str(char *opts, const char *append) 156 { 157 /* Speed-optimized. We call gather_options_str many times. */ 158 if (append) { 159 if (opts == NULL) { 160 opts = xstrdup(append); 161 } else { 162 int optlen = strlen(opts); 163 opts = xrealloc(opts, optlen + strlen(append) + 2); 164 sprintf(opts + optlen, " %s", append); 165 } 166 } 167 return opts; 168 } 169 170 static struct module_entry *helper_get_module(const char *module, int create) 171 { 172 char modname[MODULE_NAME_LEN]; 173 struct module_entry *e; 174 llist_t *l; 175 176 filename2modname(module, modname); 177 for (l = G.db; l != NULL; l = l->link) { 178 e = (struct module_entry *) l->data; 179 if (strcmp(e->modname, modname) == 0) 180 return e; 181 } 182 if (!create) 143 183 return NULL; 144 } 145 /* Reached the start of an argument 146 * By the way, we duplicate a little too much 147 * here but what is too much is freed later. */ 148 *dst = tmp_str = xstrdup(src); 149 /* Get to the end of that argument */ 150 while (*tmp_str != '\0' 151 && (*tmp_str != ' ' || (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES))) 184 185 e = xzalloc(sizeof(*e)); 186 e->modname = xstrdup(modname); 187 llist_add_to(&G.db, e); 188 189 return e; 190 } 191 static struct module_entry *get_or_add_modentry(const char *module) 192 { 193 return helper_get_module(module, 1); 194 } 195 static struct module_entry *get_modentry(const char *module) 196 { 197 return helper_get_module(module, 0); 198 } 199 200 static void add_probe(const char *name) 201 { 202 struct module_entry *m; 203 204 m = get_or_add_modentry(name); 205 if (!(option_mask32 & MODPROBE_OPT_REMOVE) 206 && (m->flags & MODULE_FLAG_LOADED) 152 207 ) { 153 switch (*tmp_str) { 154 case '\'': 155 if (opt_status & ARG_IN_DQUOTES) { 156 /* Already in double quotes, keep current char as is */ 157 } else { 158 /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ 159 memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); 160 /* mark me: we enter or leave single quotes */ 161 opt_status ^= ARG_IN_SQUOTES; 162 /* Back one char, as we need to re-scan the new char there. */ 163 tmp_str--; 164 } 165 break; 166 case '"': 167 if (opt_status & ARG_IN_SQUOTES) { 168 /* Already in single quotes, keep current char as is */ 169 } else { 170 /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ 171 memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); 172 /* mark me: we enter or leave double quotes */ 173 opt_status ^= ARG_IN_DQUOTES; 174 /* Back one char, as we need to re-scan the new char there. */ 175 tmp_str--; 176 } 177 break; 178 case '\\': 179 if (opt_status & ARG_IN_SQUOTES) { 180 /* Between single quotes: keep as is. */ 181 } else { 182 switch (*(tmp_str+1)) { 183 case 'a': 184 case 'b': 185 case 't': 186 case 'n': 187 case 'v': 188 case 'f': 189 case 'r': 190 case '0': 191 /* We escaped a special character. For now, keep 192 * both the back-slash and the following char. */ 193 tmp_str++; src++; 194 break; 195 default: 196 /* We escaped a space or a single or double quote, 197 * or a back-slash, or a non-escapable char. Remove 198 * the '\' and keep the new current char as is. */ 199 memmove(tmp_str, tmp_str + 1, strlen(tmp_str)); 200 break; 208 DBG("skipping %s, it is already loaded", name); 209 return; 210 } 211 212 DBG("queuing %s", name); 213 m->probed_name = name; 214 m->flags |= MODULE_FLAG_NEED_DEPS; 215 llist_add_to_end(&G.probes, m); 216 G.num_unresolved_deps++; 217 if (ENABLE_FEATURE_MODUTILS_SYMBOLS 218 && strncmp(m->modname, "symbol:", 7) == 0 219 ) { 220 G.need_symbols = 1; 221 } 222 } 223 224 static int FAST_FUNC config_file_action(const char *filename, 225 struct stat *statbuf UNUSED_PARAM, 226 void *userdata UNUSED_PARAM, 227 int depth UNUSED_PARAM) 228 { 229 char *tokens[3]; 230 parser_t *p; 231 struct module_entry *m; 232 int rc = TRUE; 233 234 if (bb_basename(filename)[0] == '.') 235 goto error; 236 237 p = config_open2(filename, fopen_for_read); 238 if (p == NULL) { 239 rc = FALSE; 240 goto error; 241 } 242 243 while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) { 244 //Use index_in_strings? 245 if (strcmp(tokens[0], "alias") == 0) { 246 /* alias <wildcard> <modulename> */ 247 llist_t *l; 248 char wildcard[MODULE_NAME_LEN]; 249 char *rmod; 250 251 if (tokens[2] == NULL) 252 continue; 253 filename2modname(tokens[1], wildcard); 254 255 for (l = G.probes; l != NULL; l = l->link) { 256 m = (struct module_entry *) l->data; 257 if (fnmatch(wildcard, m->modname, 0) != 0) 258 continue; 259 rmod = filename2modname(tokens[2], NULL); 260 llist_add_to(&m->realnames, rmod); 261 262 if (m->flags & MODULE_FLAG_NEED_DEPS) { 263 m->flags &= ~MODULE_FLAG_NEED_DEPS; 264 G.num_unresolved_deps--; 265 } 266 267 m = get_or_add_modentry(rmod); 268 if (!(m->flags & MODULE_FLAG_NEED_DEPS)) { 269 m->flags |= MODULE_FLAG_NEED_DEPS; 270 G.num_unresolved_deps++; 201 271 } 202 272 } 273 } else if (strcmp(tokens[0], "options") == 0) { 274 /* options <modulename> <option...> */ 275 if (tokens[2] == NULL) 276 continue; 277 m = get_or_add_modentry(tokens[1]); 278 m->options = gather_options_str(m->options, tokens[2]); 279 } else if (strcmp(tokens[0], "include") == 0) { 280 /* include <filename> */ 281 read_config(tokens[1]); 282 } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST 283 && strcmp(tokens[0], "blacklist") == 0 284 ) { 285 /* blacklist <modulename> */ 286 get_or_add_modentry(tokens[1])->flags |= MODULE_FLAG_BLACKLISTED; 287 } 288 } 289 config_close(p); 290 error: 291 return rc; 292 } 293 294 static int read_config(const char *path) 295 { 296 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET, 297 config_file_action, NULL, NULL, 1); 298 } 299 300 static const char *humanly_readable_name(struct module_entry *m) 301 { 302 /* probed_name may be NULL. modname always exists. */ 303 return m->probed_name ? m->probed_name : m->modname; 304 } 305 306 static char *parse_and_add_kcmdline_module_options(char *options, const char *modulename) 307 { 308 char *kcmdline_buf; 309 char *kcmdline; 310 char *kptr; 311 int len; 312 313 kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL); 314 if (!kcmdline_buf) 315 return options; 316 317 kcmdline = kcmdline_buf; 318 len = strlen(modulename); 319 while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) { 320 if (strncmp(modulename, kptr, len) != 0) 321 continue; 322 kptr += len; 323 if (*kptr != '.') 324 continue; 325 /* It is "modulename.xxxx" */ 326 kptr++; 327 if (strchr(kptr, '=') != NULL) { 328 /* It is "modulename.opt=[val]" */ 329 options = gather_options_str(options, kptr); 330 } 331 } 332 free(kcmdline_buf); 333 334 return options; 335 } 336 337 /* Return: similar to bb_init_module: 338 * 0 on success, 339 * -errno on open/read error, 340 * errno on init_module() error 341 */ 342 /* NB: INSMOD_OPT_SILENT bit suppresses ONLY non-existent modules, 343 * not deleted ones (those are still listed in modules.dep). 344 * module-init-tools version 3.4: 345 * # modprobe bogus 346 * FATAL: Module bogus not found. [exitcode 1] 347 * # modprobe -q bogus [silent, exitcode still 1] 348 * but: 349 * # rm kernel/drivers/net/dummy.ko 350 * # modprobe -q dummy 351 * FATAL: Could not open '/lib/modules/xxx/kernel/drivers/net/dummy.ko': No such file or directory 352 * [exitcode 1] 353 */ 354 static int do_modprobe(struct module_entry *m) 355 { 356 struct module_entry *m2 = m2; /* for compiler */ 357 char *fn, *options; 358 int rc, first; 359 llist_t *l; 360 361 if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { 362 if (!(option_mask32 & INSMOD_OPT_SILENT)) 363 bb_error_msg("module %s not found in modules.dep", 364 humanly_readable_name(m)); 365 return -ENOENT; 366 } 367 DBG("do_modprob'ing %s", m->modname); 368 369 if (!(option_mask32 & MODPROBE_OPT_REMOVE)) 370 m->deps = llist_rev(m->deps); 371 372 for (l = m->deps; l != NULL; l = l->link) 373 DBG("dep: %s", l->data); 374 375 first = 1; 376 rc = 0; 377 while (m->deps) { 378 rc = 0; 379 fn = llist_pop(&m->deps); /* we leak it */ 380 m2 = get_or_add_modentry(fn); 381 382 if (option_mask32 & MODPROBE_OPT_REMOVE) { 383 /* modprobe -r */ 384 if (m2->flags & MODULE_FLAG_LOADED) { 385 rc = bb_delete_module(m2->modname, O_EXCL); 386 if (rc) { 387 if (first) { 388 bb_error_msg("can't unload module %s: %s", 389 humanly_readable_name(m2), 390 moderror(rc)); 391 break; 392 } 393 } else { 394 m2->flags &= ~MODULE_FLAG_LOADED; 395 } 396 } 397 /* do not error out if *deps* fail to unload */ 398 first = 0; 399 continue; 400 } 401 402 if (m2->flags & MODULE_FLAG_LOADED) { 403 DBG("%s is already loaded, skipping", fn); 404 continue; 405 } 406 407 options = m2->options; 408 m2->options = NULL; 409 options = parse_and_add_kcmdline_module_options(options, m2->modname); 410 if (m == m2) 411 options = gather_options_str(options, G.cmdline_mopts); 412 rc = bb_init_module(fn, options); 413 DBG("loaded %s '%s', rc:%d", fn, options, rc); 414 if (rc == EEXIST) 415 rc = 0; 416 free(options); 417 if (rc) { 418 bb_error_msg("can't load module %s (%s): %s", 419 humanly_readable_name(m2), 420 fn, 421 moderror(rc) 422 ); 203 423 break; 204 /* Any other char that is special shall appear here. 205 * Example: $ starts a variable 206 case '$': 207 do_variable_expansion(); 208 break; 209 * */ 210 default: 211 /* any other char is kept as is. */ 212 break; 213 } 214 tmp_str++; /* Go to next char */ 215 src++; /* Go to next char to find the end of the argument. */ 216 } 217 /* End of string, but still no ending quote */ 218 if (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)) { 219 bb_error_msg_and_die("unterminated (single or double) quote in options list: %s", src); 220 } 221 *tmp_str++ = '\0'; 222 *dst = xrealloc(*dst, (tmp_str - *dst)); 223 return src; 224 } 225 #else 226 #define parse_command_string(src, dst) (0) 227 #endif /* ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS */ 228 229 /* 230 * This function reads aliases and default module options from a configuration file 231 * (/etc/modprobe.conf syntax). It supports includes (only files, no directories). 232 */ 233 static void include_conf(struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd) 234 { 235 int continuation_line = 0; 236 237 // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)! 238 239 while (reads(fd, buffer, buflen)) { 240 int l; 241 char *p; 242 243 p = strchr(buffer, '#'); 244 if (p) 245 *p = 0; 246 247 l = strlen(buffer); 248 249 while (l && isspace(buffer[l-1])) { 250 buffer[l-1] = 0; 251 l--; 252 } 253 254 if (l == 0) { 255 continuation_line = 0; 256 continue; 257 } 258 259 if (!continuation_line) { 260 if ((strncmp(buffer, "alias", 5) == 0) && isspace(buffer[5])) { 261 char *alias, *mod; 262 263 if (parse_tag_value(buffer + 6, &alias, &mod)) { 264 /* handle alias as a module dependent on the aliased module */ 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 274 if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) { 275 (*current)->m_depcnt = 0; 276 (*current)->m_deparr = 0; 277 } else { 278 (*current)->m_depcnt = 1; 279 (*current)->m_deparr = xmalloc(1 * sizeof(char *)); 280 (*current)->m_deparr[0] = xstrdup(mod); 281 } 282 (*current)->m_next = 0; 283 } 284 } else if ((strncmp(buffer, "options", 7) == 0) && isspace(buffer[7])) { 285 char *mod, *opt; 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 291 /* find the corresponding module */ 292 for (dt = *first; dt; dt = dt->m_next) { 293 if (strcmp(dt->m_name, mod) == 0) 294 break; 295 } 296 if (dt) { 297 if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) { 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 } 424 } 425 m2->flags |= MODULE_FLAG_LOADED; 426 } 427 428 return rc; 429 } 430 431 static void load_modules_dep(void) 432 { 433 struct module_entry *m; 434 char *colon, *tokens[2]; 435 parser_t *p; 436 437 /* Modprobe does not work at all without modules.dep, 438 * even if the full module name is given. Returning error here 439 * was making us later confuse user with this message: 440 * "module /full/path/to/existing/file/module.ko not found". 441 * It's better to die immediately, with good message. 442 * xfopen_for_read provides that. */ 443 p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); 444 445 while (G.num_unresolved_deps 446 && config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL) 447 ) { 448 colon = last_char_is(tokens[0], ':'); 449 if (colon == NULL) 450 continue; 451 *colon = 0; 452 453 m = get_modentry(tokens[0]); 454 if (m == NULL) 455 continue; 456 457 /* Optimization... */ 458 if ((m->flags & MODULE_FLAG_LOADED) 459 && !(option_mask32 & MODPROBE_OPT_REMOVE) 460 ) { 461 DBG("skip deps of %s, it's already loaded", tokens[0]); 462 continue; 463 } 464 465 m->flags |= MODULE_FLAG_FOUND_IN_MODDEP; 466 if ((m->flags & MODULE_FLAG_NEED_DEPS) && (m->deps == NULL)) { 467 G.num_unresolved_deps--; 468 llist_add_to(&m->deps, xstrdup(tokens[0])); 469 if (tokens[1]) 470 string_to_llist(tokens[1], &m->deps, " \t"); 471 } else 472 DBG("skipping dep line"); 473 } 474 config_close(p); 475 } 476 477 int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 478 int modprobe_main(int argc UNUSED_PARAM, char **argv) 479 { 480 struct utsname uts; 481 int rc; 482 unsigned opt; 483 struct module_entry *me; 484 485 opt_complementary = MODPROBE_COMPLEMENTARY; 486 opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS); 487 argv += optind; 488 489 /* Goto modules location */ 490 xchdir(CONFIG_DEFAULT_MODULES_DIR); 491 uname(&uts); 492 xchdir(uts.release); 493 494 if (opt & MODPROBE_OPT_LIST_ONLY) { 495 char name[MODULE_NAME_LEN]; 496 char *colon, *tokens[2]; 497 parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); 498 499 while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) { 500 colon = last_char_is(tokens[0], ':'); 501 if (!colon) 502 continue; 503 *colon = '\0'; 504 filename2modname(tokens[0], name); 505 if (!argv[0]) 506 puts(tokens[0]); 507 else { 508 int i; 509 for (i = 0; argv[i]; i++) { 510 if (fnmatch(argv[i], name, 0) == 0) { 511 puts(tokens[0]); 305 512 } 306 513 } 307 } else if ((strncmp(buffer, "include", 7) == 0) && isspace(buffer[7])) {308 int fdi; char *filename;309 310 filename = skip_whitespace(buffer + 8);311 312 if ((fdi = open(filename, O_RDONLY)) >= 0) {313 include_conf(first, current, buffer, buflen, fdi);314 close(fdi);315 }316 514 } 317 515 } 318 } 319 } 320 321 /* 322 * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep. 323 * It then fills every modules and aliases with their default options, found by parsing 324 * modprobe.conf (or modules.conf, or conf.modules). 325 */ 326 static struct dep_t *build_dep(void) 327 { 328 int fd; 329 struct utsname un; 330 struct dep_t *first = 0; 331 struct dep_t *current = 0; 332 char buffer[2048]; 333 char *filename; 334 int continuation_line = 0; 335 int k_version; 336 337 if (uname(&un)) 338 bb_error_msg_and_die("can't determine kernel version"); 339 340 k_version = 0; 341 if (un.release[0] == '2') { 342 k_version = un.release[2] - '0'; 343 } 344 345 filename = xasprintf("/lib/modules/%s/modules.dep", un.release); 346 fd = open(filename, O_RDONLY); 347 if (ENABLE_FEATURE_CLEAN_UP) 348 free(filename); 349 if (fd < 0) { 350 /* Ok, that didn't work. Fall back to looking in /lib/modules */ 351 fd = open("/lib/modules/modules.dep", O_RDONLY); 352 if (fd < 0) { 353 return 0; 354 } 355 } 356 357 while (reads(fd, buffer, sizeof(buffer))) { 358 int l = strlen(buffer); 359 char *p = 0; 360 361 while (l > 0 && isspace(buffer[l-1])) { 362 buffer[l-1] = 0; 363 l--; 364 } 365 366 if (l == 0) { 367 continuation_line = 0; 368 continue; 369 } 370 371 /* Is this a new module dep description? */ 372 if (!continuation_line) { 373 /* find the dep beginning */ 374 char *col = strchr(buffer, ':'); 375 char *dot = col; 376 377 if (col) { 378 /* This line is a dep description */ 379 const char *mods; 380 char *modpath; 381 char *mod; 382 383 /* Find the beginning of the module file name */ 384 *col = 0; 385 mods = bb_basename(buffer); 386 387 /* find the path of the module */ 388 modpath = strchr(buffer, '/'); /* ... and this is the path */ 389 if (!modpath) 390 modpath = buffer; /* module with no path */ 391 /* find the end of the module name in the file name */ 392 if (ENABLE_FEATURE_2_6_MODULES && 393 (k_version > 4) && (*(col-3) == '.') && 394 (*(col-2) == 'k') && (*(col-1) == 'o')) 395 dot = col - 3; 396 else 397 if ((*(col-2) == '.') && (*(col-1) == 'o')) 398 dot = col - 2; 399 400 mod = xstrndup(mods, dot - mods); 401 402 /* enqueue new module */ 403 if (!current) { 404 first = current = xmalloc(sizeof(struct dep_t)); 405 } else { 406 current->m_next = xmalloc(sizeof(struct dep_t)); 407 current = current->m_next; 408 } 409 current->m_name = mod; 410 current->m_path = xstrdup(modpath); 411 current->m_options = NULL; 412 current->m_isalias = 0; 413 current->m_depcnt = 0; 414 current->m_deparr = 0; 415 current->m_next = 0; 416 417 p = col + 1; 418 } else 419 /* this line is not a dep description */ 420 p = 0; 421 } else 422 /* It's a dep description continuation */ 423 p = buffer; 424 425 while (p && *p && isblank(*p)) 426 p++; 427 428 /* p points to the first dependable module; if NULL, no dependable module */ 429 if (p && *p) { 430 char *end = &buffer[l-1]; 431 const char *deps; 432 char *dep; 433 char *next; 434 int ext = 0; 435 436 while (isblank(*end) || (*end == '\\')) 437 end--; 438 439 do { 440 /* search the end of the dependency */ 441 next = strchr(p, ' '); 442 if (next) { 443 *next = 0; 444 next--; 445 } else 446 next = end; 447 448 /* find the beginning of the module file name */ 449 deps = bb_basename(p); 450 if (deps == p) { 451 while (isblank(*deps)) 452 deps++; 453 } 454 455 /* find the end of the module name in the file name */ 456 if (ENABLE_FEATURE_2_6_MODULES 457 && (k_version > 4) && (*(next-2) == '.') 458 && (*(next-1) == 'k') && (*next == 'o')) 459 ext = 3; 460 else 461 if ((*(next-1) == '.') && (*next == 'o')) 462 ext = 2; 463 464 /* Cope with blank lines */ 465 if ((next-deps-ext+1) <= 0) 466 continue; 467 dep = xstrndup(deps, next - deps - ext + 1); 468 469 /* Add the new dependable module name */ 470 current->m_depcnt++; 471 current->m_deparr = xrealloc(current->m_deparr, 472 sizeof(char *) * current->m_depcnt); 473 current->m_deparr[current->m_depcnt - 1] = dep; 474 475 p = next + 2; 476 } while (next < end); 477 } 478 479 /* is there other dependable module(s) ? */ 480 if (buffer[l-1] == '\\') 481 continuation_line = 1; 482 else 483 continuation_line = 0; 484 } 485 close(fd); 486 487 /* 488 * First parse system-specific options and aliases 489 * as they take precedence over the kernel ones. 490 * >=2.6: we only care about modprobe.conf 491 * <=2.4: we care about modules.conf and conf.modules 492 */ 493 if (ENABLE_FEATURE_2_6_MODULES 494 && (fd = open("/etc/modprobe.conf", O_RDONLY)) < 0) 495 if (ENABLE_FEATURE_2_4_MODULES 496 && (fd = open("/etc/modules.conf", O_RDONLY)) < 0) 497 if (ENABLE_FEATURE_2_4_MODULES) 498 fd = open("/etc/conf.modules", O_RDONLY); 499 500 if (fd >= 0) { 501 include_conf(&first, ¤t, buffer, sizeof(buffer), fd); 502 close(fd); 503 } 504 505 /* Only 2.6 has a modules.alias file */ 506 if (ENABLE_FEATURE_2_6_MODULES) { 507 /* Parse kernel-declared module aliases */ 508 filename = xasprintf("/lib/modules/%s/modules.alias", un.release); 509 fd = open(filename, O_RDONLY); 510 if (fd < 0) { 511 /* Ok, that didn't work. Fall back to looking in /lib/modules */ 512 fd = open("/lib/modules/modules.alias", O_RDONLY); 513 } 514 if (ENABLE_FEATURE_CLEAN_UP) 515 free(filename); 516 517 if (fd >= 0) { 518 include_conf(&first, ¤t, buffer, sizeof(buffer), fd); 519 close(fd); 520 } 521 522 /* Parse kernel-declared symbol aliases */ 523 filename = xasprintf("/lib/modules/%s/modules.symbols", un.release); 524 fd = open(filename, O_RDONLY); 525 if (fd < 0) { 526 /* Ok, that didn't work. Fall back to looking in /lib/modules */ 527 fd = open("/lib/modules/modules.symbols", O_RDONLY); 528 } 529 if (ENABLE_FEATURE_CLEAN_UP) 530 free(filename); 531 532 if (fd >= 0) { 533 include_conf(&first, ¤t, buffer, sizeof(buffer), fd); 534 close(fd); 535 } 536 } 537 538 return first; 539 } 540 541 /* return 1 = loaded, 0 = not loaded, -1 = can't tell */ 542 static int already_loaded(const char *name) 543 { 544 int fd, ret = 0; 545 char buffer[4096]; 546 547 fd = open("/proc/modules", O_RDONLY); 548 if (fd < 0) 549 return -1; 550 551 while (reads(fd, buffer, sizeof(buffer))) { 552 char *p; 553 554 p = strchr (buffer, ' '); 555 if (p) { 556 const char *n; 557 558 // Truncate buffer at first space and check for matches, with 559 // the idiosyncrasy that _ and - are interchangeable because the 560 // 2.6 kernel does weird things. 561 562 *p = 0; 563 for (p = buffer, n = name; ; p++, n++) { 564 if (*p != *n) { 565 if ((*p == '_' || *p == '-') && (*n == '_' || *n == '-')) 566 continue; 567 break; 568 } 569 // If we made it to the end, that's a match. 570 if (!*p) { 571 ret = 1; 572 goto done; 573 } 516 return EXIT_SUCCESS; 517 } 518 519 /* Yes, for some reason -l ignores -s... */ 520 if (opt & INSMOD_OPT_SYSLOG) 521 logmode = LOGMODE_SYSLOG; 522 523 if (!argv[0]) { 524 if (opt & MODPROBE_OPT_REMOVE) { 525 /* "modprobe -r" (w/o params). 526 * "If name is NULL, all unused modules marked 527 * autoclean will be removed". 528 */ 529 if (bb_delete_module(NULL, O_NONBLOCK | O_EXCL) != 0) 530 bb_perror_msg_and_die("rmmod"); 531 } 532 return EXIT_SUCCESS; 533 } 534 535 /* Retrieve module names of already loaded modules */ 536 { 537 char *s; 538 parser_t *parser = config_open2("/proc/modules", fopen_for_read); 539 while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) 540 get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED; 541 config_close(parser); 542 } 543 544 if (opt & (MODPROBE_OPT_INSERT_ALL | MODPROBE_OPT_REMOVE)) { 545 /* Each argument is a module name */ 546 do { 547 DBG("adding module %s", *argv); 548 add_probe(*argv++); 549 } while (*argv); 550 } else { 551 /* First argument is module name, rest are parameters */ 552 DBG("probing just module %s", *argv); 553 add_probe(argv[0]); 554 G.cmdline_mopts = parse_cmdline_module_options(argv); 555 } 556 557 /* Happens if all requested modules are already loaded */ 558 if (G.probes == NULL) 559 return EXIT_SUCCESS; 560 561 read_config("/etc/modprobe.conf"); 562 read_config("/etc/modprobe.d"); 563 if (ENABLE_FEATURE_MODUTILS_SYMBOLS && G.need_symbols) 564 read_config("modules.symbols"); 565 load_modules_dep(); 566 if (ENABLE_FEATURE_MODUTILS_ALIAS && G.num_unresolved_deps) { 567 read_config("modules.alias"); 568 load_modules_dep(); 569 } 570 571 rc = 0; 572 while ((me = llist_pop(&G.probes)) != NULL) { 573 if (me->realnames == NULL) { 574 DBG("probing by module name"); 575 /* This is not an alias. Literal names are blacklisted 576 * only if '-b' is given. 577 */ 578 if (!(opt & MODPROBE_OPT_BLACKLIST) 579 || !(me->flags & MODULE_FLAG_BLACKLISTED) 580 ) { 581 rc |= do_modprobe(me); 574 582 } 575 } 576 } 577 done: 578 close (fd); 579 return ret; 580 } 581 582 static int mod_process(const struct mod_list_t *list, int do_insert) 583 { 584 int rc = 0; 585 char **argv = NULL; 586 struct mod_opt_t *opts; 587 int argc_malloc; /* never used when CONFIG_FEATURE_CLEAN_UP not defined */ 588 int argc; 589 590 while (list) { 591 argc = 0; 592 if (ENABLE_FEATURE_CLEAN_UP) 593 argc_malloc = 0; 594 /* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory 595 * each time we allocate memory for argv. 596 * But it is (quite) small amounts of memory that leak each 597 * time a module is loaded, and it is reclaimed when modprobe 598 * exits anyway (even when standalone shell?). 599 * This could become a problem when loading a module with LOTS of 600 * dependencies, with LOTS of options for each dependencies, with 601 * very little memory on the target... But in that case, the module 602 * would not load because there is no more memory, so there's no 603 * problem. */ 604 /* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */ 605 argv = xmalloc(6 * sizeof(char*)); 606 if (do_insert) { 607 if (already_loaded(list->m_name) != 1) { 608 argv[argc++] = (char*)"insmod"; 609 if (ENABLE_FEATURE_2_4_MODULES) { 610 if (do_syslog) 611 argv[argc++] = (char*)"-s"; 612 if (autoclean) 613 argv[argc++] = (char*)"-k"; 614 if (quiet) 615 argv[argc++] = (char*)"-q"; 616 else if (verbose) /* verbose and quiet are mutually exclusive */ 617 argv[argc++] = (char*)"-v"; 618 } 619 argv[argc++] = list->m_path; 620 if (ENABLE_FEATURE_CLEAN_UP) 621 argc_malloc = argc; 622 opts = list->m_options; 623 while (opts) { 624 /* Add one more option */ 625 argc++; 626 argv = xrealloc(argv,(argc + 1)* sizeof(char*)); 627 argv[argc-1] = opts->m_opt_val; 628 opts = opts->m_next; 629 } 583 continue; 584 } 585 586 /* Probe all real names for the alias */ 587 do { 588 char *realname = llist_pop(&me->realnames); 589 struct module_entry *m2; 590 591 DBG("probing alias %s by realname %s", me->modname, realname); 592 m2 = get_or_add_modentry(realname); 593 if (!(m2->flags & MODULE_FLAG_BLACKLISTED) 594 && (!(m2->flags & MODULE_FLAG_LOADED) 595 || (opt & MODPROBE_OPT_REMOVE)) 596 ) { 597 //TODO: we can pass "me" as 2nd param to do_modprobe, 598 //and make do_modprobe emit more meaningful error messages 599 //with alias name included, not just module name alias resolves to. 600 rc |= do_modprobe(m2); 630 601 } 631 } else { 632 /* modutils uses short name for removal */ 633 if (already_loaded(list->m_name) != 0) { 634 argv[argc++] = (char*)"rmmod"; 635 if (do_syslog) 636 argv[argc++] = (char*)"-s"; 637 argv[argc++] = (char*)list->m_name; 638 if (ENABLE_FEATURE_CLEAN_UP) 639 argc_malloc = argc; 640 } 641 } 642 argv[argc] = NULL; 643 644 if (argc) { 645 if (verbose) { 646 printf("%s module %s\n", do_insert?"Loading":"Unloading", list->m_name); 647 } 648 if (!show_only) { 649 int rc2 = wait4pid(spawn(argv)); 650 651 if (do_insert) { 652 rc = rc2; /* only last module matters */ 653 } else if (!rc2) { 654 rc = 0; /* success if remove any mod */ 655 } 656 } 657 if (ENABLE_FEATURE_CLEAN_UP) { 658 /* the last value in the array has index == argc, but 659 * it is the terminating NULL, so we must not free it. */ 660 while (argc_malloc < argc) { 661 free(argv[argc_malloc++]); 662 } 663 } 664 } 665 if (ENABLE_FEATURE_CLEAN_UP) { 666 free(argv); 667 argv = NULL; 668 } 669 list = do_insert ? list->m_prev : list->m_next; 670 } 671 return (show_only) ? 0 : rc; 672 } 673 674 /* 675 * Check the matching between a pattern and a module name. 676 * We need this as *_* is equivalent to *-*, even in pattern matching. 677 */ 678 static int check_pattern(const char* pat_src, const char* mod_src) 679 { 680 int ret; 681 682 if (ENABLE_FEATURE_MODPROBE_FANCY_ALIAS) { 683 char* pat; 684 char* mod; 685 char* p; 686 687 pat = xstrdup(pat_src); 688 mod = xstrdup(mod_src); 689 690 for (p = pat; (p = strchr(p, '-')); *p++ = '_'); 691 for (p = mod; (p = strchr(p, '-')); *p++ = '_'); 692 693 ret = fnmatch(pat, mod, 0); 694 695 if (ENABLE_FEATURE_CLEAN_UP) { 696 free(pat); 697 free(mod); 698 } 699 700 return ret; 701 } else { 702 return fnmatch(pat_src, mod_src, 0); 703 } 704 } 705 706 /* 707 * Builds the dependency list (aka stack) of a module. 708 * head: the highest module in the stack (last to insmod, first to rmmod) 709 * tail: the lowest module in the stack (first to insmod, last to rmmod) 710 */ 711 static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **tail) 712 { 713 struct mod_list_t *find; 714 struct dep_t *dt; 715 struct mod_opt_t *opt = 0; 716 char *path = 0; 717 718 /* Search for the given module name amongst all dependency rules. 719 * The module name in a dependency rule can be a shell pattern, 720 * so try to match the given module name against such a pattern. 721 * Of course if the name in the dependency rule is a plain string, 722 * then we consider it a pattern, and matching will still work. */ 723 for (dt = depend; dt; dt = dt->m_next) { 724 if (check_pattern(dt->m_name, mod) == 0) { 725 break; 726 } 727 } 728 729 if (!dt) { 730 bb_error_msg("module %s not found", mod); 731 return; 732 } 733 734 // resolve alias names 735 while (dt->m_isalias) { 736 if (dt->m_depcnt == 1) { 737 struct dep_t *adt; 738 739 for (adt = depend; adt; adt = adt->m_next) { 740 if (check_pattern(adt->m_name, dt->m_deparr[0]) == 0) 741 break; 742 } 743 if (adt) { 744 /* This is the module we are aliased to */ 745 struct mod_opt_t *opts = dt->m_options; 746 /* Option of the alias are appended to the options of the module */ 747 while (opts) { 748 adt->m_options = append_option(adt->m_options, opts->m_opt_val); 749 opts = opts->m_next; 750 } 751 dt = adt; 752 } else { 753 bb_error_msg("module %s not found", mod); 754 return; 755 } 756 } else { 757 bb_error_msg("bad alias %s", dt->m_name); 758 return; 759 } 760 } 761 762 mod = dt->m_name; 763 path = dt->m_path; 764 opt = dt->m_options; 765 766 // search for duplicates 767 for (find = *head; find; find = find->m_next) { 768 if (!strcmp(mod, find->m_name)) { 769 // found ->dequeue it 770 771 if (find->m_prev) 772 find->m_prev->m_next = find->m_next; 773 else 774 *head = find->m_next; 775 776 if (find->m_next) 777 find->m_next->m_prev = find->m_prev; 778 else 779 *tail = find->m_prev; 780 781 break; // there can be only one duplicate 782 } 783 } 784 785 if (!find) { // did not find a duplicate 786 find = xmalloc(sizeof(struct mod_list_t)); 787 find->m_name = mod; 788 find->m_path = path; 789 find->m_options = opt; 790 } 791 792 // enqueue at tail 793 if (*tail) 794 (*tail)->m_next = find; 795 find->m_prev = *tail; 796 find->m_next = 0; 797 798 if (!*head) 799 *head = find; 800 *tail = find; 801 802 if (dt) { 803 int i; 804 805 /* Add all dependable module for that new module */ 806 for (i = 0; i < dt->m_depcnt; i++) 807 check_dep(dt->m_deparr[i], head, tail); 808 } 809 } 810 811 static int mod_insert(char *mod, int argc, char **argv) 812 { 813 struct mod_list_t *tail = NULL; 814 struct mod_list_t *head = NULL; 815 int rc; 816 817 // get dep list for module mod 818 check_dep(mod, &head, &tail); 819 820 rc = 1; 821 if (head && tail) { 822 if (argc) { 823 int i; 824 // append module args 825 for (i = 0; i < argc; i++) 826 head->m_options = append_option(head->m_options, argv[i]); 827 } 828 829 // process tail ---> head 830 rc = mod_process(tail, 1); 831 if (rc) { 832 /* 833 * In case of using udev, multiple instances of modprobe can be 834 * spawned to load the same module (think of two same usb devices, 835 * for example; or cold-plugging at boot time). Thus we shouldn't 836 * fail if the module was loaded, and not by us. 837 */ 838 if (already_loaded(mod)) 839 rc = 0; 840 } 841 } 842 return rc; 843 } 844 845 static int mod_remove(char *mod) 846 { 847 int rc; 848 static const struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL }; 849 850 struct mod_list_t *head = NULL; 851 struct mod_list_t *tail = NULL; 852 853 if (mod) 854 check_dep(mod, &head, &tail); 855 else // autoclean 856 head = tail = (struct mod_list_t*) &rm_a_dummy; 857 858 rc = 1; 859 if (head && tail) 860 rc = mod_process(head, 0); // process head ---> tail 861 return rc; 862 } 863 864 int modprobe_main(int argc, char** argv); 865 int modprobe_main(int argc, char** argv) 866 { 867 int rc = EXIT_SUCCESS; 868 char *unused; 869 870 opt_complementary = "?V-:q-v:v-q"; 871 main_opts = getopt32(argv, "acdklnqrst:vVC:", 872 &unused, &unused); 873 if (main_opts & (DUMP_CONF_EXIT | LIST_ALL)) 874 return EXIT_SUCCESS; 875 if (main_opts & (RESTRICT_DIR | CONFIG_FILE)) 876 bb_error_msg_and_die("-t and -C not supported"); 877 878 depend = build_dep(); 879 880 if (!depend) 881 bb_error_msg_and_die("cannot parse modules.dep"); 882 883 if (remove_opt) { 884 do { 885 if (mod_remove(optind < argc ? 886 argv[optind] : NULL)) { 887 bb_error_msg("failed to remove module %s", 888 argv[optind]); 889 rc = EXIT_FAILURE; 890 } 891 } while (++optind < argc); 892 } else { 893 if (optind >= argc) 894 bb_error_msg_and_die("no module or pattern provided"); 895 896 if (mod_insert(argv[optind], argc - optind - 1, argv + optind + 1)) 897 bb_error_msg_and_die("failed to load module %s", argv[optind]); 898 } 899 900 /* Here would be a good place to free up memory allocated during the dependencies build. */ 901 902 return rc; 903 } 602 free(realname); 603 } while (me->realnames != NULL); 604 } 605 606 return (rc != 0); 607 }
Note:
See TracChangeset
for help on using the changeset viewer.