service/fw example: do not ruin $if[], use different name
[oweals/busybox.git] / modutils / depmod.c
index 85b64a2295cf228cbbea0c1dcedb54fbcc981e96..e5f0e3d2b48e5d34fbe206003a90bdd27d9b2de6 100644 (file)
@@ -8,12 +8,7 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
-//applet:IF_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_DROP))
-
-//usage:#if !ENABLE_MODPROBE_SMALL
-//usage:#define depmod_trivial_usage NOUSAGE_STR
-//usage:#define depmod_full_usage ""
-//usage:#endif
+//applet:IF_DEPMOD(APPLET(depmod, BB_DIR_SBIN, BB_SUID_DROP))
 
 #include "libbb.h"
 #include "modutils.h"
  *   for each depends, look through our list of full paths and emit if found
  */
 
-typedef struct module_info {
-       struct module_info *next;
-       char *name, *modname;
-       llist_t *dependencies;
-       llist_t *aliases;
-       llist_t *symbols;
-       struct module_info *dnext, *dprev;
-} module_info;
-
 static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM,
-                                 void *data, int depth UNUSED_PARAM)
+                               void *data, int depth UNUSED_PARAM)
 {
-       char modname[MODULE_NAME_LEN];
-       module_info **first = (module_info **) data;
+       module_db *modules = data;
        char *image, *ptr;
-       module_info *info;
+       module_entry *e;
+
        /* Arbitrary. Was sb->st_size, but that breaks .gz etc */
        size_t len = (64*1024*1024 - 4096);
 
@@ -49,38 +35,34 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA
                return TRUE;
 
        image = xmalloc_open_zipped_read_close(fname, &len);
-       info = xzalloc(sizeof(*info));
 
-       info->next = *first;
-       *first = info;
+       e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname));
+       e->name = xstrdup(fname + 2); /* skip "./" */
 
-       info->dnext = info->dprev = info;
-       info->name = xstrdup(fname + 2); /* skip "./" */
-       info->modname = xstrdup(filename2modname(fname, modname));
        for (ptr = image; ptr < image + len - 10; ptr++) {
-               if (strncmp(ptr, "depends=", 8) == 0) {
+               if (is_prefixed_with(ptr, "depends=")) {
                        char *u;
 
                        ptr += 8;
                        for (u = ptr; *u; u++)
                                if (*u == '-')
                                        *u = '_';
-                       ptr += string_to_llist(ptr, &info->dependencies, ",");
+                       ptr += string_to_llist(ptr, &e->deps, ",");
                } else if (ENABLE_FEATURE_MODUTILS_ALIAS
-                && strncmp(ptr, "alias=", 6) == 0
+                && is_prefixed_with(ptr, "alias=")
                ) {
-                       llist_add_to(&info->aliases, xstrdup(ptr + 6));
+                       llist_add_to(&e->aliases, xstrdup(ptr + 6));
                        ptr += strlen(ptr);
                } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS
-                && strncmp(ptr, "__ksymtab_", 10) == 0
+                && is_prefixed_with(ptr, "__ksymtab_")
                ) {
                        ptr += 10;
-                       if (strncmp(ptr, "gpl", 3) == 0
+                       if (is_prefixed_with(ptr, "gpl")
                         || strcmp(ptr, "strings") == 0
                        ) {
                                continue;
                        }
-                       llist_add_to(&info->symbols, xstrdup(ptr));
+                       llist_add_to(&e->symbols, xstrdup(ptr));
                        ptr += strlen(ptr);
                }
        }
@@ -89,24 +71,13 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA
        return TRUE;
 }
 
-static module_info *find_module(module_info *modules, const char *modname)
-{
-       module_info *m;
-
-       for (m = modules; m != NULL; m = m->next)
-               if (strcmp(m->modname, modname) == 0)
-                       return m;
-       return NULL;
-}
-
-static void order_dep_list(module_info *modules, module_info *start,
-                          llist_t *add)
+static void order_dep_list(module_db *modules, module_entry *start, llist_t *add)
 {
-       module_info *m;
+       module_entry *m;
        llist_t *n;
 
        for (n = add; n != NULL; n = n->link) {
-               m = find_module(modules, n->data);
+               m = moddb_get(modules, n->data);
                if (m == NULL)
                        continue;
 
@@ -121,7 +92,7 @@ static void order_dep_list(module_info *modules, module_info *start,
                start->dprev = m;
 
                /* recurse */
-               order_dep_list(modules, start, m->dependencies);
+               order_dep_list(modules, start, m->deps);
        }
 }
 
@@ -131,7 +102,16 @@ static void xfreopen_write(const char *file, FILE *f)
                bb_perror_msg_and_die("can't open '%s'", file);
 }
 
-/* Usage:
+//usage:#if !ENABLE_MODPROBE_SMALL
+//usage:#define depmod_trivial_usage "[-n] [-b BASE] [VERSION] [MODFILES]..."
+//usage:#define depmod_full_usage "\n\n"
+//usage:       "Generate modules.dep, alias, and symbols files"
+//usage:     "\n"
+//usage:     "\n       -b BASE Use BASE/lib/modules/VERSION"
+//usage:     "\n       -n      Dry run: print files to stdout"
+//usage:#endif
+
+/* Upstream usage:
  * [-aAenv] [-C FILE or DIR] [-b BASE] [-F System.map] [VERSION] [MODFILES]...
  *     -a --all
  *             Probe all modules. Default if no MODFILES.
@@ -142,7 +122,7 @@ static void xfreopen_write(const char *file, FILE *f)
  *     -C --config FILE or DIR
  *             Path to /etc/depmod.conf or /etc/depmod.d/
  *     -e --errsyms
- *             When combined with the -F option, this reports any symbols which
+ *             When combined with the -F option, this reports any symbols
  *             which are not supplied by other modules or kernel.
  *     -F --filesyms System.map
  *     -n --dry-run
@@ -154,8 +134,13 @@ static void xfreopen_write(const char *file, FILE *f)
  *     -u      No-op
  *     -q      No-op
  *
- * So far we only support: [-rn] [-b BASE] [VERSION] [MODFILES]...
- * -aAeF are accepted but ignored. -vC are not accepted.
+ * So far we only support: [-n] [-b BASE] [VERSION] [MODFILES]...
+ * Accepted but ignored:
+ * -aAe
+ * -F System.map
+ * -C FILE/DIR
+ *
+ * Not accepted: -v
  */
 enum {
        //OPT_a = (1 << 0), /* All modules, ignore mods in argv */
@@ -173,10 +158,12 @@ enum {
 int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int depmod_main(int argc UNUSED_PARAM, char **argv)
 {
-       module_info *modules, *m, *dep;
+       module_db modules;
+       module_entry *m, *dep;
        const char *moddir_base = "/";
        char *moddir, *version;
        struct utsname uts;
+       unsigned i;
        int tmp;
 
        getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL);
@@ -200,23 +187,24 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
                free(moddir);
 
        /* Scan modules */
-       modules = NULL;
+       memset(&modules, 0, sizeof(modules));
        if (*argv) {
                do {
                        parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0);
                } while (*++argv);
        } else {
                recursive_action(".", ACTION_RECURSE,
-                                parse_module, NULL, &modules, 0);
+                               parse_module, NULL, &modules, 0);
        }
 
        /* Generate dependency and alias files */
        if (!(option_mask32 & OPT_n))
                xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout);
-       for (m = modules; m != NULL; m = m->next) {
+
+       moddb_foreach_module(&modules, m, i) {
                printf("%s:", m->name);
 
-               order_dep_list(modules, m, m->dependencies);
+               order_dep_list(&modules, m, m->deps);
                while (m->dnext != m) {
                        dep = m->dnext;
                        printf(" %s", dep->name);
@@ -232,44 +220,34 @@ int depmod_main(int argc UNUSED_PARAM, char **argv)
 #if ENABLE_FEATURE_MODUTILS_ALIAS
        if (!(option_mask32 & OPT_n))
                xfreopen_write("modules.alias", stdout);
-       for (m = modules; m != NULL; m = m->next) {
-               const char *fname = bb_basename(m->name);
-               int fnlen = strchrnul(fname, '.') - fname;
+       moddb_foreach_module(&modules, m, i) {
                while (m->aliases) {
-                       /* Last word can well be m->modname instead,
-                        * but depmod from module-init-tools 3.4
-                        * uses module basename, i.e., no s/-/_/g.
-                        * (pathname and .ko.* are still stripped)
-                        * Mimicking that... */
-                       printf("alias %s %.*s\n",
+                       /*
+                        * Last word used to be a basename
+                        * (filename with path and .ko.* stripped)
+                        * at the time of module-init-tools 3.4.
+                        * kmod v.12 uses module name, i.e., s/-/_/g.
+                        */
+                       printf("alias %s %s\n",
                                (char*)llist_pop(&m->aliases),
-                               fnlen, fname);
+                               m->modname);
                }
        }
 #endif
 #if ENABLE_FEATURE_MODUTILS_SYMBOLS
        if (!(option_mask32 & OPT_n))
                xfreopen_write("modules.symbols", stdout);
-       for (m = modules; m != NULL; m = m->next) {
-               const char *fname = bb_basename(m->name);
-               int fnlen = strchrnul(fname, '.') - fname;
+       moddb_foreach_module(&modules, m, i) {
                while (m->symbols) {
-                       printf("alias symbol:%s %.*s\n",
+                       printf("alias symbol:%s %s\n",
                                (char*)llist_pop(&m->symbols),
-                               fnlen, fname);
+                               m->modname);
                }
        }
 #endif
 
-       if (ENABLE_FEATURE_CLEAN_UP) {
-               while (modules) {
-                       module_info *old = modules;
-                       modules = modules->next;
-                       free(old->name);
-                       free(old->modname);
-                       free(old);
-               }
-       }
+       if (ENABLE_FEATURE_CLEAN_UP)
+               moddb_free(&modules);
 
        return EXIT_SUCCESS;
 }