modprobe-small: add depfile loading
authorDenis Vlasenko <vda.linux@googlemail.com>
Thu, 10 Jul 2008 14:14:20 +0000 (14:14 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Thu, 10 Jul 2008 14:14:20 +0000 (14:14 -0000)
modutils/modprobe-small.c

index 72209610a726bdc5bb24fa77b914822b8549d4df..1a9d98422f25dad2c2f346b921e7f8e637fa3372 100644 (file)
@@ -33,7 +33,8 @@ enum {
 
 typedef struct module_info {
        char *pathname;
-       char *desc;
+       char *aliases;
+       char *deps;
 } module_info;
 
 /*
@@ -209,7 +210,7 @@ static int load_module(const char *fname, const char *options)
 #endif
 }
 
-static char* parse_module(const char *pathname)
+static void parse_module(module_info *info, const char *pathname)
 {
        char *module_image;
        char *ptr;
@@ -220,11 +221,10 @@ static char* parse_module(const char *pathname)
        /* Read (possibly compressed) module */
        len = 64 * 1024 * 1024; /* 64 Mb at most */
        module_image = read_module(pathname, &len);
+//TODO: optimize redundant module body reads
 
+       /* "alias1 symbol:sym1 alias2 symbol:sym2" */
        reset_stringbuf();
-
-       /* First desc line's format is
-        * "alias1 symbol:sym1 alias2 symbol:sym2" */
        pos = 0;
        while (1) {
                ptr = find_keyword(module_image + pos, len - pos, "alias=");
@@ -247,8 +247,10 @@ static char* parse_module(const char *pathname)
        }
        bksp(); /* remove last ' ' */
        appendc('\0');
+       info->aliases = copy_stringbuf();
 
-       /* Second line: "dependency1 depandency2" */
+       /* "dependency1 depandency2" */
+       reset_stringbuf();
        ptr = find_keyword(module_image, len, "depends=");
        if (ptr && *ptr) {
                replace(ptr, ',', ' ');
@@ -257,9 +259,9 @@ static char* parse_module(const char *pathname)
                append(ptr);
        }
        appendc('\0');
+       info->deps = copy_stringbuf();
 
        free(module_image);
-       return copy_stringbuf();
 }
 
 static int pathname_matches_modname(const char *pathname, const char *modname)
@@ -294,9 +296,8 @@ static FAST_FUNC int fileAction(const char *pathname,
        modinfo = xrealloc_vector(modinfo, 12, cur);
 //TODO: use zeroing version of xrealloc_vector?
        modinfo[cur].pathname = xstrdup(pathname);
-       modinfo[cur].desc = NULL;
+       modinfo[cur].aliases = NULL;
        modinfo[cur+1].pathname = NULL;
-       modinfo[cur+1].desc = NULL;
 
        if (!pathname_matches_modname(fname, modname_to_match)) {
                dbg1_error_msg("'%s' module name doesn't match", pathname);
@@ -305,7 +306,7 @@ static FAST_FUNC int fileAction(const char *pathname,
 
        dbg1_error_msg("'%s' module name matches", pathname);
        module_found_idx = cur;
-       modinfo[cur].desc = parse_module(pathname);
+       parse_module(&modinfo[cur], pathname);
 
        if (!(option_mask32 & OPT_r)) {
                if (load_module(pathname, module_load_options) == 0) {
@@ -319,6 +320,43 @@ static FAST_FUNC int fileAction(const char *pathname,
        return TRUE;
 }
 
+static void load_dep_bb(void)
+{
+       char *line;
+       FILE *fp = fopen(DEPFILE_BB, "r");
+
+       if (!fp)
+               return;
+
+       while ((line = xmalloc_fgetline(fp)) != NULL) {
+               char* space;
+               int cur;
+
+               if (!line[0]) {
+                       free(line);
+                       continue;
+               }
+               space = strchrnul(line, ' ');
+               cur = module_count++;
+               modinfo = xrealloc_vector(modinfo, 12, cur);
+//TODO: use zeroing version of xrealloc_vector?
+               modinfo[cur+1].pathname = NULL;
+               modinfo[cur].pathname = line; /* we take ownership of malloced block here */
+               if (*space)
+                       *space++ = '\0';
+               modinfo[cur].aliases = space;
+               modinfo[cur].deps = xmalloc_fgetline(fp) ? : xzalloc(1);
+               if (modinfo[cur].deps[0]) {
+                       /* deps are not "", so next line must be empty */
+                       line = xmalloc_fgetline(fp);
+                       /* Refuse to work with damaged config file */
+                       if (line && line[0])
+                               bb_error_msg_and_die("error in %s at '%s'", DEPFILE_BB, line);
+                       free(line);
+               }
+       }
+}
+
 static module_info* find_alias(const char *alias)
 {
        int i;
@@ -330,8 +368,9 @@ static module_info* find_alias(const char *alias)
                if (pathname_matches_modname(modinfo[i].pathname, alias)) {
                        dbg1_error_msg("found '%s' in module '%s'",
                                        alias, modinfo[i].pathname);
-                       if (!modinfo[i].desc)
-                               modinfo[i].desc = parse_module(modinfo[i].pathname);
+                       if (!modinfo[i].aliases) {
+                               parse_module(&modinfo[i], modinfo[i].pathname);
+                       }
                        return &modinfo[i];
                }
                i++;
@@ -341,11 +380,11 @@ static module_info* find_alias(const char *alias)
        i = 0;
        while (modinfo[i].pathname) {
                char *desc, *s;
-               if (!modinfo[i].desc) {
-                       modinfo[i].desc = parse_module(modinfo[i].pathname);
+               if (!modinfo[i].aliases) {
+                       parse_module(&modinfo[i], modinfo[i].pathname);
                }
                /* "alias1 symbol:sym1 alias2 symbol:sym2" */
-               desc = str_2_list(modinfo[i].desc);
+               desc = str_2_list(modinfo[i].aliases);
                /* Does matching substring exist? */
                for (s = desc; *s; s += strlen(s) + 1) {
                        /* Aliases in module bodies can be defined with
@@ -475,10 +514,8 @@ static void process_module(char *name, const char *cmdline_options)
                goto ret;
        }
 
-       /* Second line of desc contains dependencies */
-       deps = str_2_list(info->desc + strlen(info->desc) + 1);
-
        /* Iterate thru dependencies, trying to (un)load them */
+       deps = str_2_list(info->deps);
        for (s = deps; *s; s += strlen(s) + 1) {
                //if (strcmp(name, s) != 0) // N.B. do loops exist?
                dbg1_error_msg("recurse on dep '%s'", s);
@@ -600,6 +637,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
                argv[1] = NULL;
 #endif
 
+       load_dep_bb();
+
        /* Load/remove modules.
         * Only rmmod loops here, insmod/modprobe has only argv[0] */
        do {