Read config files from the following directories: /run/modprobe.d config files generated at runtime, useful e.g. for compatibility with non-standard config files (such as /etc/rc.conf in Arch) /etc/modprobe.d config files manually created by the administrator /lib/modprobe.d config files installed by third-party packages /usr/local/lib/modprobe.d config files during development of third-party packages This scheme is the same as the one employed by udev, systemd and possibly others. A follow-up patch lets files in one directory override files in others, as done elsewhere. Cc: Jon Masters <jcm@xxxxxxxxxxxxxx> Cc: Kay Sievers <kay.sievers@xxxxxxxx> Cc: Aaron Griffin <aaron@xxxxxxxxxxxxx> Cc: Thomas BÃchler <thomas@xxxxxxxxxxxxx> Signed-off-by: Tom Gundersen <teg@xxxxxxx> --- modprobe.c | 137 ++++++++++++++++++++++++++++++++---------------------------- 1 files changed, 73 insertions(+), 64 deletions(-) diff --git a/modprobe.c b/modprobe.c index 65de11a..9c8ba37 100644 --- a/modprobe.c +++ b/modprobe.c @@ -789,10 +789,9 @@ static char *strsep_skipspace(char **string, char *delim) return strsep(string, delim); } -static int parse_config_scan(const char *filename, - struct modprobe_conf *conf, +static int parse_config_scan(struct modprobe_conf *conf, int dump_only, - int removing); + int removing, ...); static int parse_config_file(const char *filename, struct modprobe_conf *conf, @@ -847,9 +846,9 @@ static int parse_config_file(const char *filename, warn("\"include /etc/modprobe.d\" is " "the default, ignored\n"); } else { - if (!parse_config_scan(newfilename, - &newconf, dump_only, - removing)) + if (!parse_config_scan(&newconf, dump_only, + removing, newfilename, + NULL)) warn("Failed to open included" " config file %s: %s\n", newfilename, strerror(errno)); @@ -1044,70 +1043,77 @@ syntax_error: return 1; } -static int parse_config_scan(const char *filename, - struct modprobe_conf *conf, +static int parse_config_scan(struct modprobe_conf *conf, int dump_only, - int removing) + int removing, ...) { + va_list filelist; + char *filename; DIR *dir; int ret = 0; - dir = opendir(filename); - if (dir) { - struct file_entry { - struct list_head node; - char name[]; - }; - LIST_HEAD(files_list); - struct file_entry *fe, *fe_tmp; - struct dirent *i; - - /* sort files from directory into list */ - while ((i = readdir(dir)) != NULL) { - size_t len; - - if (i->d_name[0] == '.') - continue; - if (!config_filter(i->d_name)) - continue; - - len = strlen(i->d_name); - if (len < 6 || - (strcmp(&i->d_name[len-5], ".conf") != 0 && - strcmp(&i->d_name[len-6], ".alias") != 0)) - warn("All config files need .conf: %s/%s, " - "it will be ignored in a future release.\n", - filename, i->d_name); - fe = malloc(sizeof(struct file_entry) + len + 1); - if (fe == NULL) - continue; - strcpy(fe->name, i->d_name); - list_for_each_entry(fe_tmp, &files_list, node) - if (strcmp(fe_tmp->name, fe->name) >= 0) - break; - list_add_tail(&fe->node, &fe_tmp->node); - } - closedir(dir); - - /* parse list of files */ - list_for_each_entry_safe(fe, fe_tmp, &files_list, node) { - char *cfgfile; - - nofail_asprintf(&cfgfile, "%s/%s", filename, fe->name); - if (!parse_config_file(cfgfile, conf, - dump_only, removing)) - warn("Failed to open config file " - "%s: %s\n", fe->name, strerror(errno)); - free(cfgfile); - list_del(&fe->node); - free(fe); - } + va_start(filelist, removing); + + while ((filename = va_arg(filelist, char*))) { + dir = opendir(filename); + if (dir) { + struct file_entry { + struct list_head node; + char name[]; + }; + LIST_HEAD(files_list); + struct file_entry *fe, *fe_tmp; + struct dirent *i; + + /* sort files from directory into list */ + while ((i = readdir(dir)) != NULL) { + size_t len; + + if (i->d_name[0] == '.') + continue; + if (!config_filter(i->d_name)) + continue; + + len = strlen(i->d_name); + if (len < 6 || + (strcmp(&i->d_name[len-5], ".conf") != 0 && + strcmp(&i->d_name[len-6], ".alias") != 0)) + warn("All config files need .conf: %s/%s, " + "it will be ignored in a future release.\n", + filename, i->d_name); + fe = malloc(sizeof(struct file_entry) + len + 1); + if (fe == NULL) + continue; + strcpy(fe->name, i->d_name); + list_for_each_entry(fe_tmp, &files_list, node) + if (strcmp(fe_tmp->name, fe->name) >= 0) + break; + list_add_tail(&fe->node, &fe_tmp->node); + } + closedir(dir); + + /* parse list of files */ + list_for_each_entry_safe(fe, fe_tmp, &files_list, node) { + char *cfgfile; + + nofail_asprintf(&cfgfile, "%s/%s", filename, fe->name); + if (!parse_config_file(cfgfile, conf, + dump_only, removing)) + warn("Failed to open config file " + "%s: %s\n", fe->name, strerror(errno)); + free(cfgfile); + list_del(&fe->node); + free(fe); + } - ret = 1; - } else { - if (parse_config_file(filename, conf, dump_only, removing)) ret = 1; + } else { + if (parse_config_file(filename, conf, dump_only, removing)) + ret = 1; + } } + + va_end(filelist); return ret; } @@ -1117,7 +1123,8 @@ static void parse_toplevel_config(const char *filename, int removing) { if (filename) { - if (!parse_config_scan(filename, conf, dump_only, removing)) + if (!parse_config_scan(conf, dump_only, removing, filename, + NULL)) fatal("Failed to open config file %s: %s\n", filename, strerror(errno)); return; @@ -1130,7 +1137,9 @@ static void parse_toplevel_config(const char *filename, "all config files belong into /etc/modprobe.d/.\n"); /* default config */ - parse_config_scan("/etc/modprobe.d", conf, dump_only, removing); + parse_config_scan(conf, dump_only, removing, "/run/modprobe.d", + "/etc/modprobe.d", "/usr/local/lib/modprobe.d", + "/lib/modprobe.d", NULL); } /* Read possible module arguments from the kernel command line. */ -- 1.7.5.2 -- To unsubscribe from this list: send the line "unsubscribe linux-modules" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html