| @@ -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; |
| + | } |