aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-10 14:14:45 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-10 14:14:45 +0000
commit7f950a93ffd00cdeda83f06a447943c360005c34 (patch)
tree46351af3216642f9bbfce907205f28f47a622ee6
parent784369987f3014d5841e319fdef5211fc6b97236 (diff)
downloadbusybox-w32-7f950a93ffd00cdeda83f06a447943c360005c34.tar.gz
busybox-w32-7f950a93ffd00cdeda83f06a447943c360005c34.tar.bz2
busybox-w32-7f950a93ffd00cdeda83f06a447943c360005c34.zip
modprobe-small: add depfile creation
-rw-r--r--modutils/modprobe-small.c115
1 files changed, 108 insertions, 7 deletions
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index 1a9d98422..cf9be47a6 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -43,6 +43,7 @@ typedef struct module_info {
43struct globals { 43struct globals {
44 module_info *modinfo; 44 module_info *modinfo;
45 char *module_load_options; 45 char *module_load_options;
46 smallint dep_bb_seen;
46 int module_count; 47 int module_count;
47 int module_found_idx; 48 int module_found_idx;
48 int stringbuf_idx; 49 int stringbuf_idx;
@@ -51,6 +52,7 @@ struct globals {
51}; 52};
52#define G (*ptr_to_globals) 53#define G (*ptr_to_globals)
53#define modinfo (G.modinfo ) 54#define modinfo (G.modinfo )
55#define dep_bb_seen (G.dep_bb_seen )
54#define module_count (G.module_count ) 56#define module_count (G.module_count )
55#define module_found_idx (G.module_found_idx ) 57#define module_found_idx (G.module_found_idx )
56#define module_load_options (G.module_load_options) 58#define module_load_options (G.module_load_options)
@@ -320,13 +322,28 @@ static FAST_FUNC int fileAction(const char *pathname,
320 return TRUE; 322 return TRUE;
321} 323}
322 324
323static void load_dep_bb(void) 325static int load_dep_bb(void)
324{ 326{
325 char *line; 327 char *line;
326 FILE *fp = fopen(DEPFILE_BB, "r"); 328 FILE *fp = fopen(DEPFILE_BB, "r");
327 329
328 if (!fp) 330 if (!fp)
329 return; 331 return 0;
332
333 dep_bb_seen = 1;
334 dbg1_error_msg("loading "DEPFILE_BB);
335
336 /* Why? There is a rare scenario: we did not find modprobe.dep.bb,
337 * we scanned the dir and found no module by name, then we search
338 * for alias (full scan), and we decided to generate modprobe.dep.bb.
339 * But we see modprobe.dep.bb.new! Other modprobe is at work!
340 * We wait and other modprobe renames it to modprobe.dep.bb.
341 * Now we can use it.
342 * But we already have modinfo[] filled, and "module_count = 0"
343 * makes us start anew. Yes, we leak modinfo[].xxx pointers -
344 * there is not much of data there anyway. */
345 module_count = 0;
346 memset(&modinfo[0], 0, sizeof(modinfo[0]));
330 347
331 while ((line = xmalloc_fgetline(fp)) != NULL) { 348 while ((line = xmalloc_fgetline(fp)) != NULL) {
332 char* space; 349 char* space;
@@ -355,13 +372,74 @@ static void load_dep_bb(void)
355 free(line); 372 free(line);
356 } 373 }
357 } 374 }
375 return 1;
376}
377
378static int start_dep_bb_writeout(void)
379{
380 int fd;
381
382 fd = open(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
383 if (fd < 0) {
384 if (errno == EEXIST) {
385 int count = 5 * 20;
386 dbg1_error_msg(DEPFILE_BB".new exists, waiting for "DEPFILE_BB);
387 while (1) {
388 usleep(1000*1000 / 20);
389 if (load_dep_bb()) {
390 dbg1_error_msg(DEPFILE_BB" appeared");
391 return -2; /* magic number */
392 }
393 if (!--count)
394 break;
395 }
396 bb_error_msg("deleting stale %s", DEPFILE_BB".new");
397 fd = open_or_warn(DEPFILE_BB".new", O_WRONLY | O_CREAT | O_TRUNC);
398 }
399 }
400 dbg1_error_msg("opened "DEPFILE_BB".new:%d", fd);
401 return fd;
402}
403
404static void write_out_dep_bb(int fd)
405{
406 int i;
407 FILE *fp;
408
409 /* We want good error reporting. fdprintf is not good enough. */
410 fp = fdopen(fd, "w");
411 if (!fp) {
412 close(fd);
413 goto err;
414 }
415 i = 0;
416 while (modinfo[i].pathname) {
417 fprintf(fp, "%s%s%s\n" "%s%s\n",
418 modinfo[i].pathname, modinfo[i].aliases[0] ? " " : "", modinfo[i].aliases,
419 modinfo[i].deps, modinfo[i].deps[0] ? "\n" : "");
420 i++;
421 }
422 /* Badly formatted depfile is a no-no. Be paranoid. */
423 errno = 0;
424 if (ferror(fp) | fclose(fp))
425 goto err;
426 if (rename(DEPFILE_BB".new", DEPFILE_BB) != 0) {
427 err:
428 bb_perror_msg("can't create %s", DEPFILE_BB);
429 unlink(DEPFILE_BB".new");
430 } else {
431 dbg1_error_msg("created "DEPFILE_BB);
432 }
358} 433}
359 434
360static module_info* find_alias(const char *alias) 435static module_info* find_alias(const char *alias)
361{ 436{
362 int i; 437 int i;
438 int dep_bb_fd;
439 module_info *result;
363 dbg1_error_msg("find_alias('%s')", alias); 440 dbg1_error_msg("find_alias('%s')", alias);
364 441
442 try_again:
365 /* First try to find by name (cheaper) */ 443 /* First try to find by name (cheaper) */
366 i = 0; 444 i = 0;
367 while (modinfo[i].pathname) { 445 while (modinfo[i].pathname) {
@@ -376,13 +454,22 @@ static module_info* find_alias(const char *alias)
376 i++; 454 i++;
377 } 455 }
378 456
457 /* Ok, we definitely have to scan module bodies. This is a good
458 * moment to generate modprobe.dep.bb, if it does not exist yet */
459 dep_bb_fd = dep_bb_seen ? -1 : start_dep_bb_writeout();
460 if (dep_bb_fd == -2) /* modprobe.dep.bb appeared? */
461 goto try_again;
462
379 /* Scan all module bodies, extract modinfo (it contains aliases) */ 463 /* Scan all module bodies, extract modinfo (it contains aliases) */
380 i = 0; 464 i = 0;
465 result = NULL;
381 while (modinfo[i].pathname) { 466 while (modinfo[i].pathname) {
382 char *desc, *s; 467 char *desc, *s;
383 if (!modinfo[i].aliases) { 468 if (!modinfo[i].aliases) {
384 parse_module(&modinfo[i], modinfo[i].pathname); 469 parse_module(&modinfo[i], modinfo[i].pathname);
385 } 470 }
471 if (result)
472 continue;
386 /* "alias1 symbol:sym1 alias2 symbol:sym2" */ 473 /* "alias1 symbol:sym1 alias2 symbol:sym2" */
387 desc = str_2_list(modinfo[i].aliases); 474 desc = str_2_list(modinfo[i].aliases);
388 /* Does matching substring exist? */ 475 /* Does matching substring exist? */
@@ -392,17 +479,25 @@ static module_info* find_alias(const char *alias)
392 * "pci:v000010DEd000000D9sv*sd*bc*sc*i*". 479 * "pci:v000010DEd000000D9sv*sd*bc*sc*i*".
393 * Plain strcmp() won't catch that */ 480 * Plain strcmp() won't catch that */
394 if (fnmatch(s, alias, 0) == 0) { 481 if (fnmatch(s, alias, 0) == 0) {
395 free(desc);
396 dbg1_error_msg("found alias '%s' in module '%s'", 482 dbg1_error_msg("found alias '%s' in module '%s'",
397 alias, modinfo[i].pathname); 483 alias, modinfo[i].pathname);
398 return &modinfo[i]; 484 result = &modinfo[i];
485 break;
399 } 486 }
400 } 487 }
401 free(desc); 488 free(desc);
489 if (result && dep_bb_fd < 0)
490 return result;
402 i++; 491 i++;
403 } 492 }
404 dbg1_error_msg("find_alias '%s' returns NULL", alias); 493
405 return NULL; 494 /* Create module.dep.bb if needed */
495 if (dep_bb_fd >= 0) {
496 write_out_dep_bb(dep_bb_fd);
497 }
498
499 dbg1_error_msg("find_alias '%s' returns %p", alias, result);
500 return result;
406} 501}
407 502
408#if ENABLE_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED 503#if ENABLE_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
@@ -497,7 +592,7 @@ static void process_module(char *name, const char *cmdline_options)
497 592
498 /* rmmod? unload it by name */ 593 /* rmmod? unload it by name */
499 if (is_rmmod) { 594 if (is_rmmod) {
500 if (delete_module(name, O_NONBLOCK|O_EXCL) != 0 595 if (delete_module(name, O_NONBLOCK | O_EXCL) != 0
501 && !(option_mask32 & OPT_q) 596 && !(option_mask32 & OPT_q)
502 ) { 597 ) {
503 bb_perror_msg("remove '%s'", name); 598 bb_perror_msg("remove '%s'", name);
@@ -511,6 +606,8 @@ static void process_module(char *name, const char *cmdline_options)
511 } 606 }
512 607
513 if (!info) { /* both dirscan and find_alias found nothing */ 608 if (!info) { /* both dirscan and find_alias found nothing */
609 bb_error_msg("module '%s' not found", name);
610//TODO: _and_die()?
514 goto ret; 611 goto ret;
515 } 612 }
516 613
@@ -637,6 +734,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
637 argv[1] = NULL; 734 argv[1] = NULL;
638#endif 735#endif
639 736
737 /* Prevent ugly corner cases with no modules at all */
738 modinfo = xzalloc(sizeof(modinfo[0]));
739
740 /* Try to load modprobe.dep.bb */
640 load_dep_bb(); 741 load_dep_bb();
641 742
642 /* Load/remove modules. 743 /* Load/remove modules.