* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
+//applet:IF_DEPMOD(APPLET(depmod, BB_DIR_SBIN, BB_SUID_DROP))
+
#include "libbb.h"
#include "modutils.h"
#include <sys/utsname.h> /* uname() */
* 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);
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);
}
}
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;
start->dprev = m;
/* recurse */
- order_dep_list(modules, start, m->dependencies);
+ order_dep_list(modules, start, m->deps);
}
}
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.
* -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
* Print to stdout all the symbols each module depends on
* and the module's file name which provides that symbol.
* -r No-op
+ * -u No-op
+ * -q No-op
+ *
+ * So far we only support: [-n] [-b BASE] [VERSION] [MODFILES]...
+ * Accepted but ignored:
+ * -aAe
+ * -F System.map
+ * -C FILE/DIR
*
- * So far we only support: [-rn] [-b BASE] [VERSION] [MODFILES]...
- * -aAeF are accepted but ignored. -vC are not accepted.
+ * Not accepted: -v
*/
enum {
//OPT_a = (1 << 0), /* All modules, ignore mods in argv */
//OPT_e = (1 << 3), /* with -F, print unresolved symbols */
//OPT_F = (1 << 4), /* System.map that contains the symbols */
OPT_n = (1 << 5), /* dry-run, print to stdout only */
- OPT_r = (1 << 6) /* Compat dummy. Linux Makefile uses it */
+ OPT_r = (1 << 6), /* Compat dummy. Linux Makefile uses it */
+ OPT_u = (1 << 7), /* -u,--unresolved-error: ignored */
+ OPT_q = (1 << 8), /* -q,--quiet: ignored */
+ OPT_C = (1 << 9), /* -C,--config etc_modules_conf: ignored */
};
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:nr", &moddir_base, NULL);
+ getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL);
argv += optind;
/* goto modules location */
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);
#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;
}