diff options
author | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2008-06-02 18:59:16 +0000 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2008-06-02 18:59:16 +0000 |
commit | c2741e1f72d77e8bd46c932d6d7b12286d5d338c (patch) | |
tree | 4401061001eca7d8991ff3fd0b8ec285e7cecfad | |
parent | ef729dd90c72d69523871b69ebb34fa367800a69 (diff) | |
download | busybox-w32-c2741e1f72d77e8bd46c932d6d7b12286d5d338c.tar.gz busybox-w32-c2741e1f72d77e8bd46c932d6d7b12286d5d338c.tar.bz2 busybox-w32-c2741e1f72d77e8bd46c932d6d7b12286d5d338c.zip |
- add alias support
-rw-r--r-- | modutils/Config.in | 10 | ||||
-rw-r--r-- | modutils/depmod.c | 190 |
2 files changed, 115 insertions, 85 deletions
diff --git a/modutils/Config.in b/modutils/Config.in index fb7fb2266..bf93c74a1 100644 --- a/modutils/Config.in +++ b/modutils/Config.in | |||
@@ -25,6 +25,16 @@ config FEATURE_DEPMOD_PRUNE_FANCY | |||
25 | 25 | ||
26 | If unsure, say N. | 26 | If unsure, say N. |
27 | 27 | ||
28 | config FEATURE_DEPMOD_ALIAS | ||
29 | bool "alias support" | ||
30 | default n | ||
31 | depends on DEPMOD | ||
32 | help | ||
33 | By default modules.dep does not contain alias information. | ||
34 | Enable this to emit aliases of the form: | ||
35 | |||
36 | alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs | ||
37 | |||
28 | config INSMOD | 38 | config INSMOD |
29 | bool "insmod" | 39 | bool "insmod" |
30 | default n | 40 | default n |
diff --git a/modutils/depmod.c b/modutils/depmod.c index b0b09c235..09d31f4c0 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c | |||
@@ -10,12 +10,6 @@ | |||
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 | #if ENABLE_DEBUG | ||
14 | #include <assert.h> | ||
15 | #define dbg_assert assert | ||
16 | #else | ||
17 | #define dbg_assert(stuff) do {} while (0) | ||
18 | #endif | ||
19 | /* | 13 | /* |
20 | * Theory of operation: | 14 | * Theory of operation: |
21 | * - iterate over all modules and record their full path | 15 | * - iterate over all modules and record their full path |
@@ -26,33 +20,33 @@ | |||
26 | typedef struct dep_lst_t { | 20 | typedef struct dep_lst_t { |
27 | char *name; | 21 | char *name; |
28 | llist_t *dependencies; | 22 | llist_t *dependencies; |
23 | llist_t *aliases; | ||
29 | struct dep_lst_t *next; | 24 | struct dep_lst_t *next; |
30 | } dep_lst_t; | 25 | } dep_lst_t; |
31 | 26 | ||
32 | struct globals { | 27 | struct globals { |
33 | dep_lst_t *lst; /* modules without their corresponding extension */ | 28 | dep_lst_t *lst; /* modules without their corresponding extension */ |
34 | size_t moddir_base_len; /* length of the "-b basedir" */ | ||
35 | }; | 29 | }; |
36 | #define G (*(struct globals*)&bb_common_bufsiz1) | 30 | #define G (*(struct globals*)&bb_common_bufsiz1) |
37 | /* We have to zero it out because of NOEXEC */ | 31 | /* We have to zero it out because of NOEXEC */ |
38 | #define INIT_G() memset(&G, 0, sizeof(G)) | 32 | #define INIT_G() memset(&G, 0, sizeof(G)) |
39 | 33 | ||
40 | static int fill_lst(const char *modulename, struct stat ATTRIBUTE_UNUSED *sb, | 34 | static char* find_keyword(void *the_module, size_t len, const char * const word) |
41 | void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth) | ||
42 | { | 35 | { |
43 | 36 | char *ptr = the_module; | |
44 | /* We get a file here. If the file does not have ".ko" but an | 37 | do { |
45 | * intermittent dentry has, it's just their fault. | 38 | /* search for the first char in word */ |
46 | */ | 39 | ptr = memchr(ptr, *word, len - (ptr - (char*)the_module)); |
47 | if (strrstr(modulename, ".ko") != NULL) { | 40 | if (ptr == NULL) /* no occurance left, done */ |
48 | dep_lst_t *new = xzalloc(sizeof(dep_lst_t)); | 41 | return NULL; |
49 | new->name = xstrdup(modulename + G.moddir_base_len); | 42 | if (!strncmp(ptr, word, strlen(word))) { |
50 | new->next = G.lst; | 43 | ptr += strlen(word); |
51 | G.lst = new; | 44 | break; |
52 | } | 45 | } |
53 | return TRUE; | 46 | ++ptr; |
47 | } while (1); | ||
48 | return ptr; | ||
54 | } | 49 | } |
55 | |||
56 | static int fileAction(const char *fname, struct stat *sb, | 50 | static int fileAction(const char *fname, struct stat *sb, |
57 | void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth) | 51 | void ATTRIBUTE_UNUSED *data, int ATTRIBUTE_UNUSED depth) |
58 | { | 52 | { |
@@ -79,45 +73,37 @@ static int fileAction(const char *fname, struct stat *sb, | |||
79 | close(fd); | 73 | close(fd); |
80 | if (the_module == MAP_FAILED) | 74 | if (the_module == MAP_FAILED) |
81 | bb_perror_msg_and_die("mmap"); | 75 | bb_perror_msg_and_die("mmap"); |
82 | ptr = the_module; | 76 | |
83 | this = G.lst; | 77 | this = xzalloc(sizeof(dep_lst_t)); |
84 | do { | 78 | this->name = xstrdup(fname); |
85 | if (!strcmp(fname + G.moddir_base_len, this->name)) | 79 | this->next = G.lst; |
86 | break; | 80 | G.lst = this; |
87 | this = this->next; | 81 | //bb_info_msg("fname='%s'", fname); |
88 | } while (this); | 82 | ptr = find_keyword(the_module, len, "depends="); |
89 | dbg_assert (this); | 83 | if (!*ptr) |
90 | //bb_info_msg("fname='%s'", fname + G.moddir_base_len); | 84 | goto d_none; |
91 | do { | 85 | deps = depends = xstrdup(ptr); |
92 | /* search for a 'd' */ | ||
93 | ptr = memchr(ptr, 'd', len - (ptr - (char*)the_module)); | ||
94 | if (ptr == NULL) /* no d left, done */ | ||
95 | goto none; | ||
96 | if (!strncmp(ptr, "depends=", sizeof("depends=")-1)) | ||
97 | break; | ||
98 | ++ptr; | ||
99 | } while (1); | ||
100 | deps = depends = xstrdup (ptr + sizeof("depends=")-1); | ||
101 | //bb_info_msg(" depends='%s'", depends); | 86 | //bb_info_msg(" depends='%s'", depends); |
102 | while (deps) { | 87 | while (deps) { |
103 | dep_lst_t *all = G.lst; | ||
104 | |||
105 | ptr = strsep(&deps, ","); | 88 | ptr = strsep(&deps, ","); |
106 | while (all) { | 89 | //bb_info_msg("[%s] -> '%s'", fname, (char*)ptr); |
107 | /* Compare the recorded filenames ignoring ".ko*" at the end. */ | 90 | llist_add_to_end(&this->dependencies, xstrdup(ptr)); |
108 | char *tmp = bb_get_last_path_component_nostrip(all->name); | ||
109 | if (!strncmp(ptr, tmp, MAX(strlen(ptr),strrstr(tmp, ".ko") - tmp))) | ||
110 | break; /* found it */ | ||
111 | all = all->next; | ||
112 | } | ||
113 | if (all) { | ||
114 | dbg_assert(all->name); /* this cannot be empty */ | ||
115 | //bb_info_msg("[%s] -> '%s'", (char*)ptr, all->name); | ||
116 | llist_add_to_end(&this->dependencies, all->name); | ||
117 | } | ||
118 | } | 91 | } |
119 | free(depends); | 92 | free(depends); |
120 | none: | 93 | d_none: |
94 | if (ENABLE_FEATURE_DEPMOD_ALIAS) | ||
95 | { | ||
96 | size_t pos = 0; | ||
97 | do { | ||
98 | ptr = find_keyword(the_module + pos, len - pos, "alias="); | ||
99 | if (ptr) { | ||
100 | //bb_info_msg("[%s] alias '%s'", fname, (char*)ptr); | ||
101 | llist_add_to_end(&this->aliases, xstrdup(ptr)); | ||
102 | } else | ||
103 | break; | ||
104 | pos = (ptr - (char*)the_module); | ||
105 | } while (1); | ||
106 | } | ||
121 | munmap(the_module, sb->st_size); | 107 | munmap(the_module, sb->st_size); |
122 | skip: | 108 | skip: |
123 | return TRUE; | 109 | return TRUE; |
@@ -127,6 +113,7 @@ int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
127 | int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) | 113 | int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) |
128 | { | 114 | { |
129 | int ret; | 115 | int ret; |
116 | size_t moddir_base_len = 0; /* length of the "-b basedir" */ | ||
130 | char *moddir_base = NULL, *moddir, *system_map, *chp; | 117 | char *moddir_base = NULL, *moddir, *system_map, *chp; |
131 | FILE *filedes = stdout; | 118 | FILE *filedes = stdout; |
132 | enum { | 119 | enum { |
@@ -157,13 +144,8 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) | |||
157 | option_mask32 |= *argv == NULL; | 144 | option_mask32 |= *argv == NULL; |
158 | 145 | ||
159 | if (option_mask32 & ARG_b) { | 146 | if (option_mask32 & ARG_b) { |
160 | G.moddir_base_len = strlen(moddir_base); | 147 | moddir_base_len = strlen(moddir_base) + 1; |
161 | if (ENABLE_FEATURE_CLEAN_UP) { | 148 | xchdir(moddir_base); |
162 | chp = moddir; | ||
163 | moddir = concat_path_file(moddir_base, moddir); | ||
164 | free (chp); | ||
165 | } else | ||
166 | moddir = concat_path_file(moddir_base, moddir); | ||
167 | } | 149 | } |
168 | 150 | ||
169 | if (!(option_mask32 & ARG_n)) { /* --dry-run */ | 151 | if (!(option_mask32 & ARG_n)) { /* --dry-run */ |
@@ -173,23 +155,8 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) | |||
173 | free(chp); | 155 | free(chp); |
174 | } | 156 | } |
175 | ret = EXIT_SUCCESS; | 157 | ret = EXIT_SUCCESS; |
176 | /* We have to do a full walk to collect all needed data. */ | ||
177 | if (!recursive_action(moddir, | ||
178 | ACTION_RECURSE, /* flags */ | ||
179 | fill_lst, /* file action */ | ||
180 | NULL, /* dir action */ | ||
181 | NULL, /* user data */ | ||
182 | 0)) { /* depth */ | ||
183 | if (ENABLE_FEATURE_CLEAN_UP) | ||
184 | ret = EXIT_FAILURE; | ||
185 | else | ||
186 | return EXIT_FAILURE; | ||
187 | } | ||
188 | #if ENABLE_FEATURE_CLEAN_UP | ||
189 | else | ||
190 | #endif | ||
191 | do { | 158 | do { |
192 | chp = option_mask32 & ARG_a ? moddir : *argv++; | 159 | chp = option_mask32 & ARG_a ? moddir : (*argv + moddir_base_len); |
193 | 160 | ||
194 | if (!recursive_action(chp, | 161 | if (!recursive_action(chp, |
195 | ACTION_RECURSE, /* flags */ | 162 | ACTION_RECURSE, /* flags */ |
@@ -199,8 +166,42 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) | |||
199 | 0)) { /* depth */ | 166 | 0)) { /* depth */ |
200 | ret = EXIT_FAILURE; | 167 | ret = EXIT_FAILURE; |
201 | } | 168 | } |
202 | } while (!(option_mask32 & ARG_a) && *argv); | 169 | } while (!(option_mask32 & ARG_a) && *++argv); |
170 | |||
171 | { | ||
172 | dep_lst_t *mods = G.lst; | ||
173 | |||
174 | /* Fixup the module names in the depends list */ | ||
175 | while (mods) { | ||
176 | llist_t *deps = NULL, *old_deps = mods->dependencies; | ||
177 | |||
178 | while (old_deps) { | ||
179 | dep_lst_t *all = G.lst; | ||
180 | char *longname = NULL; | ||
181 | char *shortname = llist_pop(&old_deps); | ||
203 | 182 | ||
183 | while (all) { | ||
184 | char *nam = | ||
185 | xstrdup(bb_get_last_path_component_nostrip(all->name)); | ||
186 | char *tmp = strrstr(nam, ".ko"); | ||
187 | |||
188 | *tmp = '\0'; | ||
189 | if (!strcmp(nam, shortname)) { | ||
190 | if (ENABLE_FEATURE_CLEAN_UP) | ||
191 | free(nam); | ||
192 | longname = all->name; | ||
193 | break; | ||
194 | } | ||
195 | free(nam); | ||
196 | all = all->next; | ||
197 | } | ||
198 | llist_add_to_end(&deps, longname); | ||
199 | } | ||
200 | mods->dependencies = deps; | ||
201 | mods = mods->next; | ||
202 | } | ||
203 | |||
204 | #if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY | ||
204 | /* modprobe allegedly wants dependencies without duplicates, i.e. | 205 | /* modprobe allegedly wants dependencies without duplicates, i.e. |
205 | * mod1: mod2 mod3 | 206 | * mod1: mod2 mod3 |
206 | * mod2: mod3 | 207 | * mod2: mod3 |
@@ -211,9 +212,7 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) | |||
211 | * mod2: mod3 | 212 | * mod2: mod3 |
212 | * mod3: | 213 | * mod3: |
213 | */ | 214 | */ |
214 | { | 215 | mods = G.lst; |
215 | dep_lst_t *mods = G.lst; | ||
216 | #if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY | ||
217 | while (mods) { | 216 | while (mods) { |
218 | llist_t *deps = mods->dependencies; | 217 | llist_t *deps = mods->dependencies; |
219 | while (deps) { | 218 | while (deps) { |
@@ -241,15 +240,36 @@ int depmod_main(int ATTRIBUTE_UNUSED argc, char **argv) | |||
241 | } | 240 | } |
242 | mods = mods->next; | 241 | mods = mods->next; |
243 | } | 242 | } |
243 | #endif | ||
244 | 244 | ||
245 | mods = G.lst; | 245 | mods = G.lst; |
246 | #endif | ||
247 | /* Finally print them. */ | 246 | /* Finally print them. */ |
248 | while (mods) { | 247 | while (mods) { |
249 | fprintf(filedes, "%s:", mods->name); | 248 | fprintf(filedes, "%s:", mods->name); |
250 | while (mods->dependencies) | 249 | /* If we did not resolve all modules, then it's likely that we just did |
251 | fprintf(filedes, " %s", (char*)llist_pop(&mods->dependencies)); | 250 | * not see the names of all prerequisites (which will be NULL in this |
251 | * case). */ | ||
252 | while (mods->dependencies) { | ||
253 | char *the_dep = llist_pop(&mods->dependencies); | ||
254 | if (the_dep) | ||
255 | fprintf(filedes, " %s", the_dep); | ||
256 | } | ||
252 | fprintf(filedes, "\n"); | 257 | fprintf(filedes, "\n"); |
258 | if (ENABLE_FEATURE_DEPMOD_ALIAS) | ||
259 | { | ||
260 | char *shortname = | ||
261 | xstrdup(bb_get_last_path_component_nostrip(mods->name)); | ||
262 | char *tmp = strrstr(shortname, ".ko"); | ||
263 | |||
264 | *tmp = '\0'; | ||
265 | |||
266 | while (mods->aliases) { | ||
267 | fprintf(filedes, "alias %s %s\n", | ||
268 | (char*)llist_pop(&mods->aliases), | ||
269 | shortname); | ||
270 | } | ||
271 | free(shortname); | ||
272 | } | ||
253 | mods = mods->next; | 273 | mods = mods->next; |
254 | } | 274 | } |
255 | } | 275 | } |