diff options
author | Robert Griebl <griebl@gmx.de> | 2002-05-14 23:42:08 +0000 |
---|---|---|
committer | Robert Griebl <griebl@gmx.de> | 2002-05-14 23:42:08 +0000 |
commit | 52e8d060a95877d3070c18e3bf05f3fe8854357f (patch) | |
tree | 96492d3e3eeb644c9df45220d16616c2fbc3325c /modutils/modprobe.c | |
parent | d77601178d9c9f5084e3842d0156dc4723592e44 (diff) | |
download | busybox-w32-52e8d060a95877d3070c18e3bf05f3fe8854357f.tar.gz busybox-w32-52e8d060a95877d3070c18e3bf05f3fe8854357f.tar.bz2 busybox-w32-52e8d060a95877d3070c18e3bf05f3fe8854357f.zip |
Complete rewrite to support stack loading/unloading with proper
handling of duplicates in the dependencies list.
Diffstat (limited to 'modutils/modprobe.c')
-rw-r--r-- | modutils/modprobe.c | 239 |
1 files changed, 145 insertions, 94 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 2f797ec4a..b13b9b04f 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -3,11 +3,12 @@ | |||
3 | * really dumb modprobe implementation for busybox | 3 | * really dumb modprobe implementation for busybox |
4 | * Copyright (C) 2001 Lineo, davidm@lineo.com | 4 | * Copyright (C) 2001 Lineo, davidm@lineo.com |
5 | * | 5 | * |
6 | * CONFIG_MODPROBE_DEPEND stuff was added and is | 6 | * dependency specific stuff completly rewritten and |
7 | * Copyright (C) 2002 Robert Griebl, griebl@gmx.de | 7 | * copyright (c) 2002 by Robert Griebl, griebl@gmx.de |
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <sys/utsname.h> | ||
11 | #include <stdio.h> | 12 | #include <stdio.h> |
12 | #include <getopt.h> | 13 | #include <getopt.h> |
13 | #include <stdlib.h> | 14 | #include <stdlib.h> |
@@ -17,22 +18,27 @@ | |||
17 | #include <ctype.h> | 18 | #include <ctype.h> |
18 | #include "busybox.h" | 19 | #include "busybox.h" |
19 | 20 | ||
20 | static char cmd[128]; | ||
21 | |||
22 | #define CONFIG_MODPROBE_DEPEND | ||
23 | 21 | ||
24 | #ifdef CONFIG_MODPROBE_DEPEND | ||
25 | |||
26 | #include <sys/utsname.h> | ||
27 | 22 | ||
28 | struct dep_t { | 23 | struct dep_t { |
29 | char * m_module; | 24 | char * m_module; |
25 | |||
30 | int m_depcnt; | 26 | int m_depcnt; |
31 | char ** m_deparr; | 27 | char ** m_deparr; |
32 | 28 | ||
33 | struct dep_t * m_next; | 29 | struct dep_t * m_next; |
34 | }; | 30 | }; |
35 | 31 | ||
32 | struct mod_list_t { | ||
33 | char * m_module; | ||
34 | |||
35 | struct mod_list_t * m_prev; | ||
36 | struct mod_list_t * m_next; | ||
37 | }; | ||
38 | |||
39 | |||
40 | static struct dep_t *depend = 0; | ||
41 | |||
36 | 42 | ||
37 | static struct dep_t *build_dep ( void ) | 43 | static struct dep_t *build_dep ( void ) |
38 | { | 44 | { |
@@ -99,7 +105,7 @@ static struct dep_t *build_dep ( void ) | |||
99 | current-> m_module = mod; | 105 | current-> m_module = mod; |
100 | current-> m_depcnt = 0; | 106 | current-> m_depcnt = 0; |
101 | current-> m_deparr = 0; | 107 | current-> m_deparr = 0; |
102 | current-> m_next = 0; | 108 | current-> m_next = 0; |
103 | 109 | ||
104 | //printf ( "%s:\n", mod ); | 110 | //printf ( "%s:\n", mod ); |
105 | 111 | ||
@@ -154,70 +160,142 @@ static struct dep_t *build_dep ( void ) | |||
154 | } | 160 | } |
155 | 161 | ||
156 | 162 | ||
157 | static struct dep_t *find_dep ( struct dep_t *dt, char *mod ) | 163 | static int mod_process ( struct mod_list_t *list, int do_insert, int autoclean, int quiet, int do_syslog, int show_only, int verbose ) |
158 | { | 164 | { |
159 | int lm = xstrlen ( mod ); | 165 | char lcmd [256]; |
160 | int extpos = 0; | 166 | int rc = 0; |
161 | 167 | ||
168 | if ( !list ) | ||
169 | return 1; | ||
170 | |||
171 | while ( list ) { | ||
172 | if ( do_insert ) | ||
173 | snprintf ( lcmd, sizeof( lcmd ) - 1, "insmod %s %s %s %s 2>/dev/null", do_syslog ? "-s" : "", autoclean ? "-k" : "", quiet ? "-q" : "", list-> m_module ); | ||
174 | else | ||
175 | snprintf ( lcmd, sizeof( lcmd ) - 1, "rmmod %s %s 2>/dev/null", do_syslog ? "-s" : "", list-> m_module ); | ||
176 | |||
177 | if ( verbose ) | ||
178 | printf ( "%s\n", lcmd ); | ||
179 | if ( !show_only ) | ||
180 | rc |= system ( lcmd ); | ||
181 | |||
182 | list = do_insert ? list-> m_prev : list-> m_next; | ||
183 | } | ||
184 | return rc; | ||
185 | } | ||
186 | |||
187 | static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail ) | ||
188 | { | ||
189 | struct mod_list_t *find; | ||
190 | struct dep_t *dt; | ||
191 | |||
192 | int lm; | ||
193 | |||
194 | // remove .o extension | ||
195 | lm = xstrlen ( mod ); | ||
162 | if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) | 196 | if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) |
163 | extpos = 2; | 197 | mod [lm-2] = 0; |
164 | 198 | ||
165 | if ( extpos > 0 ) | 199 | //printf ( "check_dep: %s\n", mod ); |
166 | mod [lm - extpos] = 0; | ||
167 | 200 | ||
168 | while ( dt ) { | 201 | // search for duplicates |
169 | if ( !strcmp ( dt-> m_module, mod )) | 202 | for ( find = *head; find; find = find-> m_next ) { |
170 | break; | 203 | if ( !strcmp ( mod, find-> m_module )) { |
204 | // found -> dequeue it | ||
205 | |||
206 | if ( find-> m_prev ) | ||
207 | find-> m_prev-> m_next = find-> m_next; | ||
208 | else | ||
209 | *head = find-> m_next; | ||
210 | |||
211 | if ( find-> m_next ) | ||
212 | find-> m_next-> m_prev = find-> m_prev; | ||
213 | else | ||
214 | *tail = find-> m_prev; | ||
215 | |||
216 | //printf ( "DUP\n" ); | ||
217 | |||
218 | break; // there can be only one duplicate | ||
219 | } | ||
220 | } | ||
171 | 221 | ||
172 | dt = dt-> m_next; | 222 | if ( !find ) { // did not find a duplicate |
223 | find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t)); | ||
224 | find-> m_module = mod; | ||
173 | } | 225 | } |
174 | if ( extpos > 0 ) | ||
175 | mod [lm - extpos] = '.'; | ||
176 | 226 | ||
177 | return dt; | 227 | // enqueue at tail |
228 | if ( *tail ) | ||
229 | (*tail)-> m_next = find; | ||
230 | find-> m_prev = *tail; | ||
231 | find-> m_next = 0; | ||
232 | |||
233 | if ( !*head ) | ||
234 | *head = find; | ||
235 | *tail = find; | ||
236 | |||
237 | // check dependencies | ||
238 | for ( dt = depend; dt; dt = dt-> m_next ) { | ||
239 | if ( !strcmp ( dt-> m_module, mod )) { | ||
240 | int i; | ||
241 | |||
242 | for ( i = 0; i < dt-> m_depcnt; i++ ) | ||
243 | check_dep ( dt-> m_deparr [i], head, tail ); | ||
244 | } | ||
245 | } | ||
178 | } | 246 | } |
179 | 247 | ||
180 | #define MODPROBE_EXECUTE 0x1 | ||
181 | #define MODPROBE_INSERT 0x2 | ||
182 | #define MODPROBE_REMOVE 0x4 | ||
183 | 248 | ||
184 | static void check_dep ( char *mod, int do_syslog, | 249 | |
185 | int show_only, int verbose, int flags ) | 250 | static int mod_insert ( char *mod, int argc, char **argv, int autoclean, int quiet, int do_syslog, int show_only, int verbose ) |
186 | { | 251 | { |
187 | static struct dep_t *depend = (struct dep_t *) -1; | 252 | struct mod_list_t *tail = 0; |
188 | struct dep_t *dt; | 253 | struct mod_list_t *head = 0; |
254 | int rc = 0; | ||
189 | 255 | ||
190 | if ( depend == (struct dep_t *) -1 ) | 256 | // get dep list for module mod |
191 | depend = build_dep ( ); | 257 | check_dep ( mod, &head, &tail ); |
192 | 258 | ||
193 | if (( dt = find_dep ( depend, mod ))) { | 259 | if ( head && tail ) { |
194 | int i; | 260 | int i; |
195 | 261 | ||
196 | for ( i = 0; i < dt-> m_depcnt; i++ ) | 262 | // append module args |
197 | check_dep ( dt-> m_deparr [i], do_syslog, | 263 | head-> m_module = xmalloc ( 256 ); |
198 | show_only, verbose, flags|MODPROBE_EXECUTE); | 264 | strcpy ( head-> m_module, mod ); |
199 | } | 265 | |
200 | if ( flags & MODPROBE_EXECUTE ) { | 266 | for ( i = 0; i < argc; i++ ) { |
201 | char lcmd [256]; | 267 | strcat ( head-> m_module, " " ); |
202 | if ( flags & MODPROBE_INSERT ) { | 268 | strcat ( head-> m_module, argv [i] ); |
203 | snprintf(lcmd, sizeof(lcmd)-1, "insmod %s -q -k %s 2>/dev/null", | ||
204 | do_syslog ? "-s" : "", mod ); | ||
205 | } | ||
206 | if ( flags & MODPROBE_REMOVE ) { | ||
207 | snprintf(lcmd, sizeof(lcmd)-1, "insmod %s -q -k %s 2>/dev/null", | ||
208 | do_syslog ? "-s" : "", mod ); | ||
209 | } | ||
210 | if ( flags & (MODPROBE_REMOVE|MODPROBE_INSERT) ) { | ||
211 | if (verbose) | ||
212 | printf("%s\n", lcmd); | ||
213 | if (!show_only) | ||
214 | system ( lcmd ); | ||
215 | } | 269 | } |
270 | |||
271 | // process tail ---> head | ||
272 | rc |= mod_process ( tail, 1, autoclean, quiet, do_syslog, show_only, verbose ); | ||
216 | } | 273 | } |
217 | } | 274 | else |
275 | rc = 1; | ||
276 | |||
277 | return rc; | ||
278 | } | ||
279 | |||
280 | static void mod_remove ( char *mod, int do_syslog, int show_only, int verbose ) | ||
281 | { | ||
282 | static struct mod_list_t rm_a_dummy = { "-a", 0, 0 }; | ||
283 | |||
284 | struct mod_list_t *head = 0; | ||
285 | struct mod_list_t *tail = 0; | ||
286 | |||
287 | if ( mod ) | ||
288 | check_dep ( mod, &head, &tail ); | ||
289 | else // autoclean | ||
290 | head = tail = &rm_a_dummy; | ||
291 | |||
292 | if ( head && tail ) { | ||
293 | // process head ---> tail | ||
294 | mod_process ( head, 0, 0, 0, do_syslog, show_only, verbose ); | ||
295 | } | ||
296 | } | ||
297 | |||
218 | 298 | ||
219 | #endif | ||
220 | |||
221 | 299 | ||
222 | extern int modprobe_main(int argc, char** argv) | 300 | extern int modprobe_main(int argc, char** argv) |
223 | { | 301 | { |
@@ -281,24 +359,18 @@ extern int modprobe_main(int argc, char** argv) | |||
281 | if (list) | 359 | if (list) |
282 | exit(EXIT_SUCCESS); | 360 | exit(EXIT_SUCCESS); |
283 | 361 | ||
362 | depend = build_dep ( ); | ||
363 | |||
364 | if ( !depend ) { | ||
365 | fprintf (stderr, "could not parse modules.dep\n" ); | ||
366 | exit (EXIT_FAILURE); | ||
367 | } | ||
368 | |||
284 | if (remove_opt) { | 369 | if (remove_opt) { |
285 | do { | 370 | do { |
286 | sprintf(cmd, "rmmod %s %s %s", | 371 | mod_remove ( optind < argc ? argv [optind] : 0, do_syslog, show_only, verbose ); |
287 | optind >= argc ? "-a" : "", | 372 | } while ( ++optind < argc ); |
288 | do_syslog ? "-s" : "", | 373 | |
289 | optind < argc ? argv[optind] : ""); | ||
290 | if (do_syslog) | ||
291 | syslog(LOG_INFO, "%s", cmd); | ||
292 | if (verbose) | ||
293 | printf("%s\n", cmd); | ||
294 | if (!show_only) | ||
295 | rc = system(cmd); | ||
296 | |||
297 | #ifdef CONFIG_MODPROBE_DEPEND | ||
298 | if ( optind < argc ) | ||
299 | check_dep ( argv [optind], do_syslog, show_only, verbose, MODPROBE_REMOVE); | ||
300 | #endif | ||
301 | } while (++optind < argc); | ||
302 | exit(EXIT_SUCCESS); | 374 | exit(EXIT_SUCCESS); |
303 | } | 375 | } |
304 | 376 | ||
@@ -306,29 +378,8 @@ extern int modprobe_main(int argc, char** argv) | |||
306 | fprintf(stderr, "No module or pattern provided\n"); | 378 | fprintf(stderr, "No module or pattern provided\n"); |
307 | exit(EXIT_FAILURE); | 379 | exit(EXIT_FAILURE); |
308 | } | 380 | } |
309 | 381 | ||
310 | sprintf(cmd, "insmod %s %s %s", | 382 | rc = mod_insert ( argv [optind], argc - optind - 1, argv + optind + 1, autoclean, quiet, do_syslog, show_only, verbose ); |
311 | do_syslog ? "-s" : "", | ||
312 | quiet ? "-q" : "", | ||
313 | autoclean ? "-k" : ""); | ||
314 | |||
315 | #ifdef CONFIG_MODPROBE_DEPEND | ||
316 | check_dep ( argv [optind], do_syslog, show_only, verbose, MODPROBE_INSERT); | ||
317 | #endif | ||
318 | |||
319 | while (optind < argc) { | ||
320 | strcat(cmd, " "); | ||
321 | strcat(cmd, argv[optind]); | ||
322 | optind++; | ||
323 | } | ||
324 | if (do_syslog) | ||
325 | syslog(LOG_INFO, "%s", cmd); | ||
326 | if (verbose) | ||
327 | printf("%s\n", cmd); | ||
328 | if (!show_only) | ||
329 | rc = system(cmd); | ||
330 | else | ||
331 | rc = 0; | ||
332 | 383 | ||
333 | exit(rc ? EXIT_FAILURE : EXIT_SUCCESS); | 384 | exit(rc ? EXIT_FAILURE : EXIT_SUCCESS); |
334 | } | 385 | } |