diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2010-02-26 15:59:22 +0000 |
---|---|---|
committer | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2010-03-02 09:25:15 +0000 |
commit | 49fb4faf3c8b03218d012e90e53a951129893ea9 (patch) | |
tree | 3ae898c519ea52a649712aa597cefcb41cec1053 | |
parent | eb1e17254348d2c9b209439826306327663e1c14 (diff) | |
download | module-init-tools-49fb4faf3c8b03218d012e90e53a951129893ea9.tar.gz |
modprobe: complete the separation of config parsing and alias resolution
The parser now records all the aliases from the config file, deferring
alias resolution to do_modprobe(). This will allow the config data to
be re-used across multiple invocations of do_modprobe().
-rw-r--r-- | modprobe.c | 139 |
1 files changed, 96 insertions, 43 deletions
@@ -385,6 +385,7 @@ struct module_command struct module_alias { struct module_alias *next; + char *aliasname; char *module; }; @@ -449,16 +450,34 @@ add_command(const char *modname, /* Link in a new alias line from the config file. */ static struct module_alias * -add_alias(const char *modname, struct module_alias *aliases) +add_alias(const char *aliasname, const char *modname, struct module_alias *aliases) { struct module_alias *new; new = NOFAIL(malloc(sizeof(*new))); + new->aliasname = NOFAIL(strdup(aliasname)); new->module = NOFAIL(strdup(modname)); new->next = aliases; return new; } + +/* Return a list of matching aliases */ +static struct module_alias * +find_aliases(const struct module_alias *aliases, + const char *name) +{ + struct module_alias *result = NULL; + while (aliases) { + char *aliasname = aliases->aliasname; + char *modname = aliases->module; + if (fnmatch(aliasname, name, 0) == 0) + result = add_alias(aliasname, modname, result); + aliases = aliases->next; + } + return result; +} + static void free_aliases(struct module_alias *alias_list) { while (alias_list) { @@ -467,6 +486,7 @@ static void free_aliases(struct module_alias *alias_list) alias = alias_list; alias_list = alias_list->next; + free(alias->aliasname); free(alias->module); free(alias); } @@ -485,7 +505,7 @@ add_blacklist(const char *modname, struct module_blacklist *blacklist) } /* Find blacklist commands if any. */ -static int +static int find_blacklist(const char *modname, const struct module_blacklist *blacklist) { while (blacklist) { @@ -496,19 +516,21 @@ find_blacklist(const char *modname, const struct module_blacklist *blacklist) return 0; } -/* return a new alias list, with backlisted elems filtered out */ -static struct module_alias * -apply_blacklist(const struct module_alias *aliases, +/* delete backlisted elems from a list of aliases */ +static void +apply_blacklist(struct module_alias **aliases, const struct module_blacklist *blacklist) { struct module_alias *result = NULL; - while (aliases) { - char *modname = aliases->module; + struct module_alias *alias = *aliases; + while (alias) { + char *modname = alias->module; if (!find_blacklist(modname, blacklist)) - result = add_alias(modname, result); - aliases = aliases->next; + result = add_alias(alias->aliasname, modname, result); + alias = alias->next; } - return result; + free_aliases(*aliases); + *aliases = result; } /* Find install commands if any. */ @@ -743,13 +765,11 @@ static char *strsep_skipspace(char **string, char *delim) } static int parse_config_scan(const char *filename, - const char *name, struct modprobe_conf *conf, int dump_only, int removing); static int parse_config_file(const char *filename, - const char *name, struct modprobe_conf *conf, int dump_only, int removing) @@ -785,8 +805,9 @@ static int parse_config_file(const char *filename, char *realname = strsep_skipspace(&ptr, "\t "); if (!wildcard || !realname) goto syntax_error; - if (fnmatch(underscores(wildcard),name,0) == 0) - *aliases = add_alias(underscores(realname), *aliases); + *aliases = add_alias(underscores(wildcard), + underscores(realname), + *aliases); } else if (streq(cmd, "include")) { struct modprobe_conf newconf = *conf; newconf.aliases = NULL; @@ -801,7 +822,7 @@ static int parse_config_file(const char *filename, warn("\"include /etc/modprobe.d\" is " "the default, ignored\n"); } else { - if (!parse_config_scan(newfilename, name, + if (!parse_config_scan(newfilename, &newconf, dump_only, removing)) warn("Failed to open included" @@ -935,7 +956,7 @@ static int read_aliases_file(const char *filename, realnames = index_searchwild(index, name); for (realname = realnames; realname; realname = realname->next) - *aliases = add_alias(realname->value, *aliases); + *aliases = add_alias("*", realname->value, *aliases); index_values_free(realnames); free(binfile); @@ -949,20 +970,52 @@ static int read_aliases(const char *filename, int dump_only, struct module_alias **aliases) { - struct modprobe_conf conf = { .aliases = *aliases }; - int ret; + char *line; + unsigned int linenum = 0; + FILE *cfile; if (use_binary_indexes) if (read_aliases_file(filename, name, dump_only, aliases)) return 1; - ret = parse_config_file(filename, name, &conf, dump_only, 0); - *aliases = conf.aliases; - return ret; + cfile = fopen(filename, "r"); + if (!cfile) + return 0; + + while ((line = getline_wrapped(cfile, &linenum)) != NULL) { + char *ptr = line; + char *cmd; + + if (dump_only) + printf("%s\n", line); + + cmd = strsep_skipspace(&ptr, "\t "); + if (cmd == NULL || cmd[0] == '#' || cmd[0] == '\0') { + free(line); + continue; + } + + if (streq(cmd, "alias")) { + char *wildcard = strsep_skipspace(&ptr, "\t "); + char *realname = strsep_skipspace(&ptr, "\t "); + if (!wildcard || !realname) + goto syntax_error; + if (fnmatch(underscores(wildcard),name,0) == 0) + *aliases = add_alias(wildcard, + underscores(realname), + *aliases); + } else { +syntax_error: + grammar(cmd, filename, linenum); + } + + free(line); + } + fclose(cfile); + return 1; } static int parse_config_scan(const char *filename, - const char *name, struct modprobe_conf *conf, int dump_only, int removing) @@ -1012,7 +1065,7 @@ static int parse_config_scan(const char *filename, char *cfgfile; nofail_asprintf(&cfgfile, "%s/%s", filename, fe->name); - if (!parse_config_file(cfgfile, name, conf, + if (!parse_config_file(cfgfile, conf, dump_only, removing)) warn("Failed to open config file " "%s: %s\n", fe->name, strerror(errno)); @@ -1023,33 +1076,32 @@ static int parse_config_scan(const char *filename, ret = 1; } else { - if (parse_config_file(filename, name, conf, dump_only, removing)) + if (parse_config_file(filename, conf, dump_only, removing)) ret = 1; } return ret; } static void parse_toplevel_config(const char *filename, - const char *name, struct modprobe_conf *conf, int dump_only, int removing) { if (filename) { - if (!parse_config_scan(filename, name, conf, dump_only, removing)) + if (!parse_config_scan(filename, conf, dump_only, removing)) fatal("Failed to open config file %s: %s\n", filename, strerror(errno)); return; } /* deprecated config file */ - if (parse_config_file("/etc/modprobe.conf", name, conf, + if (parse_config_file("/etc/modprobe.conf", conf, dump_only, removing) > 0) warn("Deprecated config file /etc/modprobe.conf, " "all config files belong into /etc/modprobe.d/.\n"); /* default config */ - parse_config_scan("/etc/modprobe.d", name, conf, dump_only, removing); + parse_config_scan("/etc/modprobe.d", conf, dump_only, removing); } /* Read possible module arguments from the kernel command line. */ @@ -1525,28 +1577,30 @@ int do_modprobe(const char *modulename, { char *modname; struct modprobe_conf conf = {}; - struct module_alias *filtered_aliases; + struct module_alias *matching_aliases; LIST_HEAD(list); int failed = 0; /* Convert name we are looking for */ modname = underscores(NOFAIL(strdup(modulename))); - /* Returns the resolved alias, options */ - parse_toplevel_config(configname, modname, &conf, 0, flags & mit_remove); + /* Read aliases, options etc. */ + parse_toplevel_config(configname, &conf, 0, flags & mit_remove); /* Read module options from kernel command line */ parse_kcmdline(0, &conf.options); + matching_aliases = find_aliases(conf.aliases, modname); + /* No luck? Try symbol names, if starts with symbol:. */ - if (!conf.aliases && strstarts(modname, "symbol:")) { + if (!matching_aliases && strstarts(modname, "symbol:")) { char *symfilename; nofail_asprintf(&symfilename, "%s/modules.symbols", dirname); - read_aliases(symfilename, modname, 0, &conf.aliases); + read_aliases(symfilename, modname, 0, &matching_aliases); free(symfilename); } - if (!conf.aliases) { + if (!matching_aliases) { if(!strchr(modname, ':')) read_depends(dirname, modname, &list); @@ -1557,14 +1611,13 @@ int do_modprobe(const char *modulename, { char *aliasfilename; - nofail_asprintf(&aliasfilename, "%s/modules.alias", dirname); read_aliases(aliasfilename, modname, 0, - &conf.aliases); + &matching_aliases); free(aliasfilename); /* builtin module? */ - if (!conf.aliases && module_builtin(dirname, modname) > 0) { + if (!matching_aliases && module_builtin(dirname, modname) > 0) { failed |= handle_builtin_module(modname, error, flags); goto out; @@ -1572,17 +1625,17 @@ int do_modprobe(const char *modulename, } } - filtered_aliases = apply_blacklist(conf.aliases, conf.blacklist); + apply_blacklist(&matching_aliases, conf.blacklist); if(flags & mit_resolve_alias) { - struct module_alias *aliases = filtered_aliases; + struct module_alias *aliases = matching_aliases; for(; aliases; aliases=aliases->next) printf("%s\n", aliases->module); goto out; } - if (filtered_aliases) { + if (matching_aliases) { errfn_t err = error; - struct module_alias *aliases = filtered_aliases; + struct module_alias *aliases = matching_aliases; /* More than one alias? Don't bail out on failure. */ if (aliases->next) @@ -1612,7 +1665,7 @@ int do_modprobe(const char *modulename, } out: free(modname); - free_aliases(filtered_aliases); + free_aliases(matching_aliases); return failed; } @@ -1784,7 +1837,7 @@ int main(int argc, char *argv[]) nofail_asprintf(&aliasfilename, "%s/modules.alias", dirname); nofail_asprintf(&symfilename, "%s/modules.symbols", dirname); - parse_toplevel_config(configname, "", &conf, 1, 0); + parse_toplevel_config(configname, &conf, 1, 0); /* Read module options from kernel command line */ parse_kcmdline(1, &conf.options); read_aliases(aliasfilename, "", 1, &conf.aliases); |