diff -Naur busybox.orig/examples/depmod busybox/examples/depmod --- busybox.orig/examples/depmod 2008-05-28 21:53:36 +0000 +++ busybox/examples/depmod 2008-05-28 21:59:30 +0000 @@ -1,6 +1,6 @@ #!/bin/sh # -# Simple depmod, use to generate modprobe.conf +# Simple depmod, use to generate modules.dep # # Copyright (C) 2008 by Vladimir Dronnikov # diff -Naur busybox.orig/modutils/Config.in busybox/modutils/Config.in --- busybox.orig/modutils/Config.in 2008-05-27 22:37:51 +0000 +++ busybox/modutils/Config.in 2008-05-28 22:18:50 +0000 @@ -11,6 +11,14 @@ help depmod generates modules.dep (FIXME: elaborate) +config FEATURE_DEPMOD_DONT_APPEND_UNAME_R + bool "Do not append kernel version to modules directory" + default n + depends on DEPMOD + help + By default depmod looks modules at /lib/modules/ directory. + When this option is enabled is not appended, making depmod more configurable. + config INSMOD bool "insmod" default n diff -Naur busybox.orig/modutils/depmod.c busybox/modutils/depmod.c --- busybox.orig/modutils/depmod.c 2008-05-28 21:55:14 +0000 +++ busybox/modutils/depmod.c 2008-06-01 16:53:39 +0000 @@ -1,7 +1,9 @@ /* vi: set sw=4 ts=4: */ /* * depmod - generate modules.dep - * Copyright (c) 2008 Bernhard Fischer + * Copyright (c) 2008 Bernhard Fischer and Vladimir Dronnikov + * + * Dependencies resolution support by Vladimir Dronnikov . * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ @@ -11,43 +13,53 @@ #include #include /* uname() */ -/* - * Theory of operation: - * - iterate over all modules and record their full path - * - iterate over all modules looking for "depends=" entries - * for each depends, look through our list of full paths and emit if found - */ +struct module_dep { + struct module_dep *link; + char *path; + char *name; + llist_t *dep; +}; + struct globals { - llist_t *lst; /* modules without their corresponding extension */ - size_t moddir_base_len; /* length of the "-b basedir" */ + struct module_dep *deps; // modules dependencies }; #define G (*(struct globals*)&bb_common_bufsiz1) /* We have to zero it out because of NOEXEC */ #define INIT_G() memset(&G, 0, sizeof(G)) -static int fill_lst(const char *modulename, struct stat ATTRIBUTE_UNUSED *sb, - void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth) -{ - /* We get a file here. If the file does not have ".ko" but an - * intermittent dentry has, it's just their fault. - */ - if (strrstr(modulename, ".ko") != NULL) - llist_add_to(&G.lst, xstrdup(modulename + G.moddir_base_len)); - return TRUE; -} +/* + * Theory of operation: + * - iterate over all modules { + * record full path and basename + * collect "depends=" entries + * } + * - iterate over all modules { + * resolve implict dependencies: i.e. if A depends on B and B depends on C then A depends on C and B! + * } + * - iterate over all modules { + * dump full paths for dependencies + * } + */ static int fileAction(const char *fname, struct stat *sb, - void *data, int ATTRIBUTE_UNUSED depth) + void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth) { size_t len = sb->st_size; void *the_module; char *ptr; int fd; - char *depends, *deps; + struct module_dep *dep; if (strrstr(fname, ".ko") == NULL) /* not a module */ goto skip; + dep = xzalloc(sizeof(struct module_dep)); + dep->path = xstrdup(fname); + ptr = dep->name = (char *)basename(dep->path); + ptr[strlen(ptr)-sizeof(".ko")+1] = '\0'; + dep->link = G.deps; + G.deps = dep; + /*XXX: FIXME: does not handle compressed modules! * There should be a function that looks at the extension and sets up * open_transformer for us. @@ -63,52 +75,55 @@ bb_perror_msg_and_die("mmap"); ptr = the_module; - - fprintf((FILE*)data, "%s:", fname + G.moddir_base_len); -//bb_info_msg("fname='%s'", fname + G.moddir_base_len); do { /* search for a 'd' */ ptr = memchr(ptr, 'd', len - (ptr - (char*)the_module)); if (ptr == NULL) /* no d left, done */ - goto none; + break; if (strncmp(ptr, "depends=", sizeof("depends=")-1) == 0) break; ++ptr; } while (1); - deps = depends = xstrdup (ptr + sizeof("depends=")-1); -//bb_info_msg(" depends='%s'", depends); - while (deps) { - llist_t * _lst = G.lst; - - ptr = strsep(&deps, ","); - while (_lst) { - /* Compare the recorded filenames ignoring ".ko*" at the end. */ - char *tmp = bb_get_last_path_component_nostrip(_lst->data); - if (strncmp(ptr, tmp, strrstr(tmp, ".ko") - tmp) == 0) - break; /* found it */ - _lst = _lst->link; - } - if (_lst) { -//bb_info_msg("[%s] -> '%s'", (char*)ptr, _lst->data); - fprintf((FILE*)data, " %s", _lst->data); + // collect dependencies module names + if (ptr && ptr[sizeof("depends=")-1]) { + char *s = xstrdup(ptr + sizeof("depends=")-1); + while (s) { + ptr = strsep(&s, ","); + llist_add_to_end(&G.deps->dep, ptr); } - // DVV N.B. despite anything, get next dependency, plz. - deps += len; // DVV N.B. this line being within the above if(){} causes endless loop if dependency is not "verified". } - free(depends); - fprintf((FILE*)data, "\n"); - none: + munmap(the_module, sb->st_size); skip: return TRUE; } +static void print_deps(FILE *filedes, llist_t *d, llist_t **seen) +{ +#define D ((struct module_dep *)(d->data)) + while (d) { + llist_t *l; + print_deps(filedes, D->dep, seen); + for (l = *seen; l; l = l->link) { + if (0 == strcmp(l->data, D->name)) + break; + } + if (!l) { + llist_add_to(seen, (void *)(D->name)); + fprintf(filedes, " %s.%s", D->path, D->name + strlen(D->name) + 1); +// fprintf(filedes, " %s", D->name); + } + d = d->link; + } +} + int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) { int ret; - char *moddir_base = NULL, *moddir, *system_map, *chp; + char *moddir = (char *)CONFIG_DEFAULT_MODULES_DIR, *system_map; FILE *filedes = stdout; + struct module_dep *d; enum { ARG_a = (1<<0), /* All modules, ignore mods in argv */ ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */ @@ -118,66 +133,71 @@ ARG_n = (1<<5) /* dry-run, print to stdout only */ }; - getopt32(argv, "aAb:eF:n", &moddir_base, &system_map); + getopt32(argv, "aAb:eF:n", &moddir, &system_map); argv += optind; + // goto moddir + xchdir(moddir); + /* got a version to use? */ if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) { - moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++); - } else { + xchdir(*argv++); + } else if (!ENABLE_FEATURE_DEPMOD_DONT_APPEND_UNAME_R) { struct utsname uts; if (uname(&uts) < 0) bb_simple_perror_msg_and_die("uname"); - moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release); + xchdir(uts.release); } /* If no modules are given on the command-line, -a is on per default. */ option_mask32 |= *argv == NULL; - if (option_mask32 & ARG_b) { - G.moddir_base_len = strlen(moddir_base); - if (ENABLE_FEATURE_CLEAN_UP) { - chp = moddir; - moddir = concat_path_file(moddir_base, moddir); - free (chp); - } else - moddir = concat_path_file(moddir_base, moddir); - } - if (!(option_mask32 & ARG_n)) { /* --dry-run */ - chp = concat_path_file(moddir, CONFIG_DEFAULT_DEPMOD_FILE); - filedes = xfopen(chp, "w"); - if (ENABLE_FEATURE_CLEAN_UP) - free(chp); + filedes = xfopen(CONFIG_DEFAULT_DEPMOD_FILE, "w"); } + + // collect explicit dependencies ret = EXIT_SUCCESS; - /* We have to do a full walk to collect all needed data. */ - if (!recursive_action(moddir, - ACTION_RECURSE, /* flags */ - fill_lst, /* file action */ - NULL, /* dir action */ - NULL, /* user data */ - 0)) { /* depth */ - if (ENABLE_FEATURE_CLEAN_UP) - ret = EXIT_FAILURE; - else - return EXIT_FAILURE; - } do { - chp = option_mask32 & ARG_a ? moddir : *argv++; - if (!recursive_action(chp, + char *cwd = xrealloc_getcwd_or_warn(NULL); + if (!(option_mask32 & ARG_a)) + cwd = concat_path_file(cwd, *argv++); + if (!recursive_action(cwd, ACTION_RECURSE, /* flags */ fileAction, /* file action */ NULL, /* dir action */ - (void*)filedes, /* user data */ + NULL, /* user data */ 0)) { /* depth */ ret = EXIT_FAILURE; } } while (!(option_mask32 & ARG_a) && *argv); + // now we've collected all deps -> resolve implicit deps + for (d = G.deps; d; d = d->link) { + llist_t *m; + for (m = d->dep; m; m = m->link) { + struct module_dep *r; + for (r = G.deps; r; r = r->link) { + // find dep chain by name + if (0 == strcmp(r->name, m->data)) { + // found! replace name with chain + m->data = (void *)r; + break; + } + } + } + } + + // output dependencies in modules.dep format + for (d = G.deps; d; d = d->link) { + llist_t *seen = NULL; + fprintf(filedes, "%s.%s:", d->path, d->name + strlen(d->name) + 1); +// fprintf(filedes, "%s:", d->name); + print_deps(filedes, d->dep, &seen); + fprintf(filedes, "\n"); + } + if (ENABLE_FEATURE_CLEAN_UP) { fclose_if_not_stdin(filedes); - llist_free(G.lst, free); - free(moddir); } return ret; }