diff options
-rw-r--r-- | include/applets.h | 1 | ||||
-rw-r--r-- | include/usage.h | 6 | ||||
-rw-r--r-- | modutils/Config.in | 6 | ||||
-rw-r--r-- | modutils/Kbuild | 1 | ||||
-rw-r--r-- | modutils/depmod.c | 116 |
5 files changed, 130 insertions, 0 deletions
diff --git a/include/applets.h b/include/applets.h index 4797e1dd5..17113dfe7 100644 --- a/include/applets.h +++ b/include/applets.h @@ -115,6 +115,7 @@ USE_DD(APPLET_NOEXEC(dd, dd, _BB_DIR_BIN, _BB_SUID_NEVER, dd)) USE_DEALLOCVT(APPLET(deallocvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_NEVER, delgroup)) USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER)) +USE_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER)) USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) diff --git a/include/usage.h b/include/usage.h index a4fe6a7e0..e9943d539 100644 --- a/include/usage.h +++ b/include/usage.h @@ -692,6 +692,12 @@ #define deluser_full_usage "\n\n" \ "Delete user USER from the system" +#define depmod_trivial_usage \ + "" +#define depmod_full_usage \ + "\n" \ + "\n" + #define devfsd_trivial_usage \ "mntpnt [-v]" USE_DEVFSD_FG_NP("[-fg][-np]") #define devfsd_full_usage "\n\n" \ diff --git a/modutils/Config.in b/modutils/Config.in index c5e596d1d..bffb521c4 100644 --- a/modutils/Config.in +++ b/modutils/Config.in @@ -5,6 +5,12 @@ menu "Linux Module Utilities" +config DEPMOD + bool "depmod" + default n + help + depmod generates modules.dep (FIXME: elaborate) + config INSMOD bool "insmod" default n diff --git a/modutils/Kbuild b/modutils/Kbuild index cff02b4f2..40ea0efbe 100644 --- a/modutils/Kbuild +++ b/modutils/Kbuild @@ -5,6 +5,7 @@ # Licensed under the GPL v2, see the file LICENSE in this tarball. lib-y:= +lib-$(CONFIG_DEPMOD) += depmod.o lib-$(CONFIG_INSMOD) += insmod.o lib-$(CONFIG_LSMOD) += lsmod.o lib-$(CONFIG_MODPROBE) += modprobe.o diff --git a/modutils/depmod.c b/modutils/depmod.c new file mode 100644 index 000000000..9131dc1ab --- /dev/null +++ b/modutils/depmod.c @@ -0,0 +1,116 @@ +/* vi: set sw=4 ts=4: */ +/* + * depmod - generate modules.dep + * Copyright (c) 2008 Bernhard Fischer + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ + +#undef _GNU_SOURCE +#define _GNU_SOURCE +#include <libbb.h> +#include <sys/utsname.h> /* uname() */ + +struct globals { + llist_t *lst; +}; +#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) +{ + llist_add_to_end(&G.lst, strdup(modulename)); + return TRUE; +} + +static int fileAction(const char *fname, struct stat ATTRIBUTE_UNUSED *sb, + void *data, int ATTRIBUTE_UNUSED depth) +{ + size_t seen = 0; + size_t len = MAXINT(ssize_t); + void *the_module = xmalloc_open_read_close(fname, &len), *ptr = the_module; + const char *deps; + RESERVE_CONFIG_BUFFER(depends, 512); + RESERVE_CONFIG_BUFFER(buf1, 512); + + memset(buf1, 0, sizeof(buf1)); + memset(depends, 0, sizeof(depends)); + sprintf(buf1, "\n%s:", fname); + + if (last_char_is(fname, 'o') == NULL) /* not a module */ + goto done; + write((int)data, buf1, strlen(buf1)); +//bb_info_msg("[%d] fname='%s'", (int)data, fname); + do { + /* search for a 'd' */ + ptr = memchr(ptr, 'd', len - seen); + if (ptr == NULL) /* no d left, done */ + break; + if (sscanf(ptr, "depends=%s", depends) == 1) + break; + seen = ++ptr - the_module; + } while (1); +//bb_info_msg(" depends='%s'", depends); + deps = depends; + while (*deps) { + llist_t * _lst = G.lst; + ptr = memchr(deps, ',', strlen(deps)); + if (ptr != NULL) + *(char*)ptr = '\0'; + /* remember the length of the current dependency plus eventual 0 byte */ + len = strlen(deps) + (ptr != NULL); + sprintf(buf1, "/%s.", deps); /* make sure we match the correct file */ + while (_lst) { + ptr = strstr(_lst->data, buf1); + if (ptr != NULL) + break; /* found it */ + _lst = _lst->link; + } + if (_lst && _lst->data) { + const char separator = ' '; +//bb_info_msg("[%s] -> '%s'", deps, _lst->data); + write((int)data, &separator, 1); + write((int)data, _lst->data, strlen(_lst->data)); + + deps += len; + } + } +done: + RELEASE_CONFIG_BUFFER(depends); + RELEASE_CONFIG_BUFFER(buf1); + free(the_module); + return TRUE; +} + +int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) +{ + int retval = EXIT_SUCCESS; +// static const char moddir_base[] ALIGN1 = "/lib/modules/%s"; + + int fd = xopen3("/tmp/modules.dep", O_CREAT|O_WRONLY|O_TRUNC, + S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); + argv++; + do { + if (!recursive_action(*argv, + ACTION_RECURSE, /* flags */ + fill_lst, /* file action */ + NULL, /* dir action */ + NULL, /* user data */ + 0) || /* depth */ + !recursive_action(*argv, + ACTION_RECURSE, /* flags */ + fileAction, /* file action */ + NULL, /* dir action */ + (void*)fd, /* user data */ + 0)) { /* depth */ + retval = EXIT_FAILURE; + } + } while (*++argv); + + if (ENABLE_FEATURE_CLEAN_UP) + close(fd); + return retval; +} |