summaryrefslogtreecommitdiff
path: root/modutils/depmod.c
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2008-06-02 13:28:47 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2008-06-02 13:28:47 +0000
commitbeac1bd58e231f8b1664c767dc128a1d86b27fff (patch)
tree653087b8185b4418b44f2417ffe7871d5445b963 /modutils/depmod.c
parent9af7aba579184fb86f971302316f09210bf1de9d (diff)
downloadbusybox-w32-beac1bd58e231f8b1664c767dc128a1d86b27fff.tar.gz
busybox-w32-beac1bd58e231f8b1664c767dc128a1d86b27fff.tar.bz2
busybox-w32-beac1bd58e231f8b1664c767dc128a1d86b27fff.zip
- optional fancy pruning-mode for depmod
Diffstat (limited to 'modutils/depmod.c')
-rw-r--r--modutils/depmod.c128
1 files changed, 107 insertions, 21 deletions
diff --git a/modutils/depmod.c b/modutils/depmod.c
index e061501f6..b0b09c235 100644
--- a/modutils/depmod.c
+++ b/modutils/depmod.c
@@ -10,15 +10,27 @@
10#define _GNU_SOURCE 10#define _GNU_SOURCE
11#include <libbb.h> 11#include <libbb.h>
12#include <sys/utsname.h> /* uname() */ 12#include <sys/utsname.h> /* uname() */
13 13#if ENABLE_DEBUG
14#include <assert.h>
15#define dbg_assert assert
16#else
17#define dbg_assert(stuff) do {} while (0)
18#endif
14/* 19/*
15 * Theory of operation: 20 * Theory of operation:
16 * - iterate over all modules and record their full path 21 * - iterate over all modules and record their full path
17 * - iterate over all modules looking for "depends=" entries 22 * - iterate over all modules looking for "depends=" entries
18 * for each depends, look through our list of full paths and emit if found 23 * for each depends, look through our list of full paths and emit if found
19 */ 24 */
25
26typedef struct dep_lst_t {
27 char *name;
28 llist_t *dependencies;
29 struct dep_lst_t *next;
30} dep_lst_t;
31
20struct globals { 32struct globals {
21 llist_t *lst; /* modules without their corresponding extension */ 33 dep_lst_t *lst; /* modules without their corresponding extension */
22 size_t moddir_base_len; /* length of the "-b basedir" */ 34 size_t moddir_base_len; /* length of the "-b basedir" */
23}; 35};
24#define G (*(struct globals*)&bb_common_bufsiz1) 36#define G (*(struct globals*)&bb_common_bufsiz1)
@@ -28,22 +40,28 @@ struct globals {
28static int fill_lst(const char *modulename, struct stat ATTRIBUTE_UNUSED *sb, 40static int fill_lst(const char *modulename, struct stat ATTRIBUTE_UNUSED *sb,
29 void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth) 41 void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth)
30{ 42{
43
31 /* We get a file here. If the file does not have ".ko" but an 44 /* We get a file here. If the file does not have ".ko" but an
32 * intermittent dentry has, it's just their fault. 45 * intermittent dentry has, it's just their fault.
33 */ 46 */
34 if (strrstr(modulename, ".ko") != NULL) 47 if (strrstr(modulename, ".ko") != NULL) {
35 llist_add_to(&G.lst, xstrdup(modulename + G.moddir_base_len)); 48 dep_lst_t *new = xzalloc(sizeof(dep_lst_t));
49 new->name = xstrdup(modulename + G.moddir_base_len);
50 new->next = G.lst;
51 G.lst = new;
52 }
36 return TRUE; 53 return TRUE;
37} 54}
38 55
39static int fileAction(const char *fname, struct stat *sb, 56static int fileAction(const char *fname, struct stat *sb,
40 void *data, int ATTRIBUTE_UNUSED depth) 57 void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth)
41{ 58{
42 size_t len = sb->st_size; 59 size_t len = sb->st_size;
43 void *the_module; 60 void *the_module;
44 char *ptr; 61 char *ptr;
45 int fd; 62 int fd;
46 char *depends, *deps; 63 char *depends, *deps;
64 dep_lst_t *this;
47 65
48 if (strrstr(fname, ".ko") == NULL) /* not a module */ 66 if (strrstr(fname, ".ko") == NULL) /* not a module */
49 goto skip; 67 goto skip;
@@ -61,40 +79,44 @@ static int fileAction(const char *fname, struct stat *sb,
61 close(fd); 79 close(fd);
62 if (the_module == MAP_FAILED) 80 if (the_module == MAP_FAILED)
63 bb_perror_msg_and_die("mmap"); 81 bb_perror_msg_and_die("mmap");
64
65 ptr = the_module; 82 ptr = the_module;
66 83 this = G.lst;
67 fprintf((FILE*)data, "%s:", fname + G.moddir_base_len); 84 do {
85 if (!strcmp(fname + G.moddir_base_len, this->name))
86 break;
87 this = this->next;
88 } while (this);
89 dbg_assert (this);
68//bb_info_msg("fname='%s'", fname + G.moddir_base_len); 90//bb_info_msg("fname='%s'", fname + G.moddir_base_len);
69 do { 91 do {
70 /* search for a 'd' */ 92 /* search for a 'd' */
71 ptr = memchr(ptr, 'd', len - (ptr - (char*)the_module)); 93 ptr = memchr(ptr, 'd', len - (ptr - (char*)the_module));
72 if (ptr == NULL) /* no d left, done */ 94 if (ptr == NULL) /* no d left, done */
73 goto none; 95 goto none;
74 if (strncmp(ptr, "depends=", sizeof("depends=")-1) == 0) 96 if (!strncmp(ptr, "depends=", sizeof("depends=")-1))
75 break; 97 break;
76 ++ptr; 98 ++ptr;
77 } while (1); 99 } while (1);
78 deps = depends = xstrdup (ptr + sizeof("depends=")-1); 100 deps = depends = xstrdup (ptr + sizeof("depends=")-1);
79//bb_info_msg(" depends='%s'", depends); 101//bb_info_msg(" depends='%s'", depends);
80 while (deps) { 102 while (deps) {
81 llist_t * _lst = G.lst; 103 dep_lst_t *all = G.lst;
82 104
83 ptr = strsep(&deps, ","); 105 ptr = strsep(&deps, ",");
84 while (_lst) { 106 while (all) {
85 /* Compare the recorded filenames ignoring ".ko*" at the end. */ 107 /* Compare the recorded filenames ignoring ".ko*" at the end. */
86 char *tmp = bb_get_last_path_component_nostrip(_lst->data); 108 char *tmp = bb_get_last_path_component_nostrip(all->name);
87 if (strncmp(ptr, tmp, strrstr(tmp, ".ko") - tmp) == 0) 109 if (!strncmp(ptr, tmp, MAX(strlen(ptr),strrstr(tmp, ".ko") - tmp)))
88 break; /* found it */ 110 break; /* found it */
89 _lst = _lst->link; 111 all = all->next;
90 } 112 }
91 if (_lst) { 113 if (all) {
92//bb_info_msg("[%s] -> '%s'", (char*)ptr, _lst->data); 114 dbg_assert(all->name); /* this cannot be empty */
93 fprintf((FILE*)data, " %s", _lst->data); 115//bb_info_msg("[%s] -> '%s'", (char*)ptr, all->name);
116 llist_add_to_end(&this->dependencies, all->name);
94 } 117 }
95 } 118 }
96 free(depends); 119 free(depends);
97 fprintf((FILE*)data, "\n");
98 none: 120 none:
99 munmap(the_module, sb->st_size); 121 munmap(the_module, sb->st_size);
100 skip: 122 skip:
@@ -115,11 +137,14 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
115 ARG_F = (1<<4), /* System.map that contains the symbols */ 137 ARG_F = (1<<4), /* System.map that contains the symbols */
116 ARG_n = (1<<5) /* dry-run, print to stdout only */ 138 ARG_n = (1<<5) /* dry-run, print to stdout only */
117 }; 139 };
140 INIT_G();
118 141
119 getopt32(argv, "aAb:eF:n", &moddir_base, &system_map); 142 getopt32(argv, "aAb:eF:n", &moddir_base, &system_map);
120 argv += optind; 143 argv += optind;
121 144
122 /* got a version to use? */ 145 /* If a version is provided, then that kernel version’s module directory
146 * is used, rather than the current kernel version (as returned by
147 * "uname -r"). */
123 if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) { 148 if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) {
124 moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++); 149 moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++);
125 } else { 150 } else {
@@ -160,6 +185,9 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
160 else 185 else
161 return EXIT_FAILURE; 186 return EXIT_FAILURE;
162 } 187 }
188#if ENABLE_FEATURE_CLEAN_UP
189 else
190#endif
163 do { 191 do {
164 chp = option_mask32 & ARG_a ? moddir : *argv++; 192 chp = option_mask32 & ARG_a ? moddir : *argv++;
165 193
@@ -167,16 +195,74 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv)
167 ACTION_RECURSE, /* flags */ 195 ACTION_RECURSE, /* flags */
168 fileAction, /* file action */ 196 fileAction, /* file action */
169 NULL, /* dir action */ 197 NULL, /* dir action */
170 (void*)filedes, /* user data */ 198 NULL, /* user data */
171 0)) { /* depth */ 199 0)) { /* depth */
172 ret = EXIT_FAILURE; 200 ret = EXIT_FAILURE;
173 } 201 }
174 } while (!(option_mask32 & ARG_a) && *argv); 202 } while (!(option_mask32 & ARG_a) && *argv);
175 203
204 /* modprobe allegedly wants dependencies without duplicates, i.e.
205 * mod1: mod2 mod3
206 * mod2: mod3
207 * mod3:
208 * implies that mod1 directly depends on mod2 and _not_ mod3 as mod3 is
209 * already implicitely pulled in via mod2. This leaves us with:
210 * mod1: mod2
211 * mod2: mod3
212 * mod3:
213 */
214 {
215 dep_lst_t *mods = G.lst;
216#if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY
217 while (mods) {
218 llist_t *deps = mods->dependencies;
219 while (deps) {
220 dep_lst_t *all = G.lst;
221 while (all) {
222 if (!strcmp(all->name, deps->data)) {
223 llist_t *implied = all->dependencies;
224 while (implied) {
225 /* erm, nicer would be to just
226 * llist_unlink(&mods->dependencies, implied) */
227 llist_t *prune = mods->dependencies;
228 while (prune) {
229 if (!strcmp(implied->data, prune->data))
230 break;
231 prune = prune->link;
232 }
233//if (prune) bb_info_msg("[%s] '%s' implies '%s', removing", mods->name, all->name, implied->data);
234 llist_unlink(&mods->dependencies, prune);
235 implied = implied->link;
236 }
237 }
238 all = all->next;
239 }
240 deps = deps->link;
241 }
242 mods = mods->next;
243 }
244
245 mods = G.lst;
246#endif
247 /* Finally print them. */
248 while (mods) {
249 fprintf(filedes, "%s:", mods->name);
250 while (mods->dependencies)
251 fprintf(filedes, " %s", (char*)llist_pop(&mods->dependencies));
252 fprintf(filedes, "\n");
253 mods = mods->next;
254 }
255 }
256
176 if (ENABLE_FEATURE_CLEAN_UP) { 257 if (ENABLE_FEATURE_CLEAN_UP) {
177 fclose_if_not_stdin(filedes); 258 fclose_if_not_stdin(filedes);
178 llist_free(G.lst, free);
179 free(moddir); 259 free(moddir);
260 while (G.lst) {
261 dep_lst_t *old = G.lst;
262 G.lst = G.lst->next;
263 free(old->name);
264 free(old);
265 }
180 } 266 }
181 return ret; 267 return ret;
182} 268}