Parses files from /etc/depmod.alternatives which specify pairs of
(module directory, config file).

Signed-off-by: Keegan McAllister <[email protected]>
---
 depmod.c |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/depmod.c b/depmod.c
index d9652b3..14da871 100644
--- a/depmod.c
+++ b/depmod.c
@@ -1368,6 +1368,99 @@ struct config_alternative
        char *config_file;
 };
 
+static void parse_alternative(const char *filename,
+                              struct config_alternative **alts)
+{
+       char *line;
+       unsigned int linenum = 0;
+       FILE *cfile;
+       struct config_alternative *alt;
+       char *module_dir = NULL, *config_file = NULL;
+
+       cfile = fopen(filename, "r");
+       if (!cfile) {
+               if (errno != ENOENT)
+                       fatal("could not open '%s', reason: %s\n", filename,
+                             strerror(errno));
+               else if (verbose)
+                       warn("config file does not actually exist "
+                            "(broken symlink?): %s\n", filename);
+               return;
+       }
+
+       while ((line = getline_wrapped(cfile, &linenum)) != NULL) {
+               char *ptr = line;
+               char *cmd, *tmp;
+
+               cmd = strsep_skipspace(&ptr, "\t ");
+
+               if (cmd == NULL || cmd[0] == '#' || cmd[0] == '\0') {
+                       free(line);
+                       continue;
+               }
+
+               if (streq(cmd, "moduledir")) {
+                       tmp = strsep_skipspace(&ptr, "\t ");
+                       if (!tmp || module_dir)
+                               goto bad_file;
+                       module_dir = NOFAIL(strdup(tmp));
+               } else if (streq(cmd, "config")) {
+                       tmp = strsep_skipspace(&ptr, "\t ");
+                       if (!tmp || config_file)
+                               goto bad_file;
+                       config_file = NOFAIL(strdup(tmp));
+               } else {
+                       goto bad_file;
+               }
+
+               free(line);
+       }
+
+       fclose(cfile);
+
+       if (!module_dir)
+               goto bad_file;
+
+       alt = NOFAIL(malloc(sizeof(*alt)));
+       alt->module_dir = module_dir;
+       alt->config_file = config_file;
+
+       alt->next = *alts;
+       *alts = alt;
+       return;
+
+bad_file:
+       warn("%s line %u: malformed alternatives file\n", filename, linenum);
+       /* These may be NULL, but free(NULL) is fine. */
+       free(module_dir);
+       free(config_file);
+       free(line);
+}
+
+static void parse_alternatives_dir(const char *dirname,
+                                   struct config_alternative **alts)
+{
+       LIST_HEAD(files_list);
+       if (read_config_dir(dirname, &files_list)) {
+               struct file_entry *fe, *fe_tmp;
+
+               /* parse list of files */
+               list_for_each_entry_safe(fe, fe_tmp, &files_list, node) {
+                       char *cfgfile;
+
+                       nofail_asprintf(&cfgfile, "%s/%s", dirname, fe->name);
+                       parse_alternative(cfgfile, alts);
+                       free(cfgfile);
+                       list_del(&fe->node);
+                       free(fe);
+               }
+       } else {
+               if (verbose)
+                       warn("Failed to open alternatives directory "
+                            "%s: %s\n", dirname, strerror(errno));
+       }
+}
+
 static void do_alternative(struct config_alternative *alt,
                          const char *basedir, const char *version,
                          int argc, char *argv[])
@@ -1572,6 +1665,9 @@ int main(int argc, char *argv[])
        alts->module_dir = NOFAIL(strdup(MODULE_DIR));
        alts->config_file = config ? NOFAIL(strdup(config)) : NULL;
 
+       /* Read more alternatives from a directory, if present. */
+       parse_alternatives_dir("/etc/depmod.alternatives", &alts);
+
        /* Process each alternative */
        for (alt = alts; alt; alt = alt->next)
                do_alternative(alt, basedir, version, argc, argv);
-- 
1.7.2.3

--
To unsubscribe from this list: send the line "unsubscribe linux-modules" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to