blob: 9faf9c302ecc09b571943fe6e2d2e1426daa093c [file] [log] [blame]
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +00001/* vi: set sw=4 ts=4: */
2/*
3 * depmod - generate modules.dep
4 * Copyright (c) 2008 Bernhard Fischer
5 *
6 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
7 */
8
9#undef _GNU_SOURCE
10#define _GNU_SOURCE
11#include <libbb.h>
12#include <sys/utsname.h> /* uname() */
13
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000014/*
15 * Theory of operation:
16 * - iterate over all modules and record their full path
17 * - iterate over all modules looking for "depends=" entries
18 * for each depends, look through our list of full paths and emit if found
19 */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000020struct globals {
21 llist_t *lst;
22};
23#define G (*(struct globals*)&bb_common_bufsiz1)
24/* We have to zero it out because of NOEXEC */
25#define INIT_G() memset(&G, 0, sizeof(G))
26
27static int fill_lst(const char *modulename, struct stat ATTRIBUTE_UNUSED *sb,
28 void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth)
29{
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +000030 llist_add_to(&G.lst, xstrdup(modulename));
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000031 return TRUE;
32}
33
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000034static int fileAction(const char *fname, struct stat *sb,
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000035 void *data, int ATTRIBUTE_UNUSED depth)
36{
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000037 size_t len = sb->st_size;
38 void *the_module, *ptr;
39 int fd;
40 char *depends, *deps;
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000041
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000042/*XXX: FIXME: does not handle compressed modules!
43 * There should be a function that looks at the extension and sets up
44 * open_transformer for us.
45 */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000046 if (last_char_is(fname, 'o') == NULL) /* not a module */
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000047 goto skip;
48
49 fd = xopen(fname, O_RDONLY);
50 the_module = mmap(NULL, len, PROT_READ, MAP_SHARED
51#if defined MAP_POPULATE
52 |MAP_POPULATE
53#endif
54 , fd, 0);
55 close(fd);
56 if (the_module == MAP_FAILED)
57 bb_perror_msg_and_die("mmap");
58
59 ptr = the_module;
60
Bernhard Reutner-Fischer423465c2008-05-26 12:19:35 +000061 fprintf((FILE*)data, "\n%s:", fname);
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000062//bb_info_msg("fname='%s'", fname);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000063 do {
64 /* search for a 'd' */
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000065 ptr = memchr(ptr, 'd', len);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000066 if (ptr == NULL) /* no d left, done */
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000067 goto done;
68 if (memcmp(ptr, "depends=", sizeof("depends=")-1) == 0)
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000069 break;
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000070 len -= ++ptr - the_module;
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000071 } while (1);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +000072 deps = depends = xstrdup (ptr + sizeof("depends=")-1);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000073//bb_info_msg(" depends='%s'", depends);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000074 while (*deps) {
75 llist_t * _lst = G.lst;
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000076 char *buf1;
77
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +000078 ptr = strchr(deps, ',');
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000079 if (ptr != NULL)
80 *(char*)ptr = '\0';
81 /* remember the length of the current dependency plus eventual 0 byte */
82 len = strlen(deps) + (ptr != NULL);
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000083 buf1 = xmalloc(len + 3);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000084 sprintf(buf1, "/%s.", deps); /* make sure we match the correct file */
85 while (_lst) {
86 ptr = strstr(_lst->data, buf1);
87 if (ptr != NULL)
88 break; /* found it */
89 _lst = _lst->link;
90 }
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000091 free(buf1);
92 if (_lst /*&& _lst->data*/) {
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000093//bb_info_msg("[%s] -> '%s'", deps, _lst->data);
Bernhard Reutner-Fischer423465c2008-05-26 12:19:35 +000094 fprintf((FILE*)data, " %s", _lst->data);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000095 deps += len;
96 }
97 }
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +000098 free(depends);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +000099done:
Bernhard Reutner-Fischercf180102008-05-26 15:12:01 +0000100 munmap(the_module, sb->st_size);
101skip:
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000102 return TRUE;
103}
104
105int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
106int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
107{
108 int retval = EXIT_SUCCESS;
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000109 char *moddir_base = NULL, *moddir, *system_map, *chp;
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000110 FILE *filedes = stdout;
111 enum {
112 ARG_a = (1<<0), /* All modules, ignore mods in argv */
113 ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */
114 ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */
115 ARG_e = (1<<3), /* with -F, print unresolved symbols */
116 ARG_F = (1<<4), /* System.map that contains the symbols */
117 ARG_n = (1<<5) /* dry-run, print to stdout only */
118 };
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000119
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000120 getopt32(argv, "aAb:eF:n", &moddir_base, &system_map);
121 argv += optind;
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000122 if (*argv) {/* got a version to use? */
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000123 chp = *argv++;
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000124// if (memchr(chp, '/', strlen(chp)) != NULL) /* XXX: drop this */
125// bb_show_usage();
126 } else {
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000127 struct utsname uts;
128 if (uname(&uts) < 0)
129 bb_simple_perror_msg_and_die("uname");
130 chp = xstrdup(uts.release);
131 }
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000132 /* if no modules are given on the command-line, -a is on per default */
133 option_mask32 |= *argv == NULL;
134
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +0000135 moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, chp);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000136// if (ENABLE_FEATURE_CLEAN_UP)
137// free(chp);
138 if (option_mask32 & ARG_b) {
139 char *old_moddir = moddir;
140 moddir = concat_path_file(moddir_base, moddir);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000141 if (ENABLE_FEATURE_CLEAN_UP)
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000142 free(old_moddir);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000143 }
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000144
145 if (!(option_mask32 & ARG_n)) { /* --dry-run */
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +0000146 chp = concat_path_file(moddir, CONFIG_DEFAULT_DEPMOD_FILE);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000147 filedes = xfopen(chp, "w");
148 if (ENABLE_FEATURE_CLEAN_UP)
149 free(chp);
150 }
151 /* have to do a full walk to collect all needed data */
152 if (!recursive_action(moddir,
153 ACTION_RECURSE, /* flags */
154 fill_lst, /* file action */
155 NULL, /* dir action */
156 NULL, /* user data */
157 0)) {
158 retval = EXIT_FAILURE;
159 } else
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000160 do {
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000161 chp = concat_path_file(option_mask32 & ARG_a ? moddir : moddir_base,
162 option_mask32 & ARG_a ? "" : *argv++);
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000163
164 if (!recursive_action(chp,
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000165 ACTION_RECURSE, /* flags */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000166 fileAction, /* file action */
167 NULL, /* dir action */
Bernhard Reutner-Fischer423465c2008-05-26 12:19:35 +0000168 (void*)filedes, /* user data */
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000169 0)) { /* depth */
170 retval = EXIT_FAILURE;
171 }
Bernhard Reutner-Fischer6bb55cf2008-05-26 17:04:01 +0000172 if (ENABLE_FEATURE_CLEAN_UP)
173 free(chp);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000174 } while (!(option_mask32 & ARG_a) && *argv);
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000175
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +0000176 if (ENABLE_FEATURE_CLEAN_UP) {
Bernhard Reutner-Fischer423465c2008-05-26 12:19:35 +0000177 fclose(filedes);
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +0000178 llist_free(G.lst, free);
Bernhard Reutner-Fischer1ea25682008-05-26 21:33:05 +0000179 free(moddir);
Bernhard Reutner-Fischerdc5d7fe2008-05-26 13:30:41 +0000180 }
Bernhard Reutner-Fischer55e547e2008-05-26 12:01:49 +0000181 return retval;
182}