Mercurial > hg > toybox
comparison toys/pending/modprobe.c @ 1384:4a7438307429 draft
minor cleanup: move a global variable into GLOBALS(), inline strchr_null(), some whitespace and bracket cleanups.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 06 Jul 2014 23:21:13 -0500 |
parents | b13728c24a58 |
children | 00c20f410c46 |
comparison
equal
deleted
inserted
replaced
1383:350655f8fe53 | 1384:4a7438307429 |
---|---|
32 struct arg_list *probes; | 32 struct arg_list *probes; |
33 struct arg_list *dbase[256]; | 33 struct arg_list *dbase[256]; |
34 char *cmdopts; | 34 char *cmdopts; |
35 int nudeps; | 35 int nudeps; |
36 uint8_t symreq; | 36 uint8_t symreq; |
37 void (*dbg)(char *format, ...); | |
37 ) | 38 ) |
38 | 39 |
39 /* Note: if "#define DBASE_SIZE" modified, | 40 /* Note: if "#define DBASE_SIZE" modified, |
40 * Please update GLOBALS dbase[256] accordingly. | 41 * Please update GLOBALS dbase[256] accordingly. |
41 */ | 42 */ |
46 #define MOD_ALOADED 0x0001 | 47 #define MOD_ALOADED 0x0001 |
47 #define MOD_BLACKLIST 0x0002 | 48 #define MOD_BLACKLIST 0x0002 |
48 #define MOD_FNDDEPMOD 0x0004 | 49 #define MOD_FNDDEPMOD 0x0004 |
49 #define MOD_NDDEPS 0x0008 | 50 #define MOD_NDDEPS 0x0008 |
50 | 51 |
51 static void (*dbg)(char *format, ...); | |
52 // dummy interface for debugging. | 52 // dummy interface for debugging. |
53 static void dummy(char *format, ...) | 53 static void dummy(char *format, ...) |
54 { | 54 { |
55 } | 55 } |
56 | 56 |
62 }; | 62 }; |
63 | 63 |
64 // Converts path name FILE to module name. | 64 // Converts path name FILE to module name. |
65 static char *path2mod(char *file, char *mod) | 65 static char *path2mod(char *file, char *mod) |
66 { | 66 { |
67 int i; | 67 int i; |
68 char *from, *lslash; | 68 char *from, *lslash; |
69 | 69 |
70 if (!file) return NULL; | 70 if (!file) return NULL; |
71 if (!mod) mod = xmalloc(MODNAME_LEN); | 71 if (!mod) mod = xmalloc(MODNAME_LEN); |
72 | 72 |
73 lslash = strrchr(file, '/'); | 73 lslash = strrchr(file, '/'); |
74 if (!lslash || (lslash == file && !lslash[1])) from = file; | 74 if (!lslash || (lslash == file && !lslash[1])) from = file; |
75 else from = lslash + 1; | 75 else from = lslash + 1; |
76 | 76 |
77 for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++) | 77 for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++) |
78 mod[i] = (from[i] == '-') ? '_' : from[i]; | 78 mod[i] = (from[i] == '-') ? '_' : from[i]; |
79 mod[i] = '\0'; | 79 mod[i] = '\0'; |
80 return mod; | 80 return mod; |
81 } | |
82 | |
83 // locate character in string. | |
84 static char *strchr_nul(char *s, int c) | |
85 { | |
86 while(*s != '\0' && *s != c) s++; | |
87 return (char*)s; | |
88 } | 81 } |
89 | 82 |
90 // Add options in opts from toadd. | 83 // Add options in opts from toadd. |
91 static char *add_opts(char *opts, char *toadd) | 84 static char *add_opts(char *opts, char *toadd) |
92 { | 85 { |
301 | 294 |
302 tmp = strchr(name, '.'); | 295 tmp = strchr(name, '.'); |
303 if (tmp) *tmp = '\0'; | 296 if (tmp) *tmp = '\0'; |
304 if (!cmdname || !fnmatch(cmdname, name, 0)) { | 297 if (!cmdname || !fnmatch(cmdname, name, 0)) { |
305 if (tmp) *tmp = '.'; | 298 if (tmp) *tmp = '.'; |
306 dbg("%s\n", line); | 299 TT.dbg("%s\n", line); |
307 ret = 0; | 300 ret = 0; |
308 } | 301 } |
309 } | 302 } |
310 free(line); | 303 free(line); |
311 } | 304 } |
349 } | 342 } |
350 | 343 |
351 // Remove a module from the Linux Kernel. if !modules does auto remove. | 344 // Remove a module from the Linux Kernel. if !modules does auto remove. |
352 static int rm_mod(char *modules, uint32_t flags) | 345 static int rm_mod(char *modules, uint32_t flags) |
353 { | 346 { |
354 errno = 0; | |
355 if (modules) { | 347 if (modules) { |
356 int len = strlen(modules); | 348 int len = strlen(modules); |
357 | 349 |
358 if (len > 3 && !strcmp(&modules[len-3], ".ko" )) modules[len-3] = 0; | 350 if (len > 3 && !strcmp(modules+len-3, ".ko" )) modules[len-3] = 0; |
359 } | 351 } |
360 if (!flags) flags = O_NONBLOCK|O_EXCL; | 352 |
361 syscall(__NR_delete_module, modules, flags); | 353 errno = 0; |
354 syscall(__NR_delete_module, modules, flags ? flags : O_NONBLOCK|O_EXCL); | |
355 | |
362 return errno; | 356 return errno; |
363 } | 357 } |
364 | 358 |
365 // Insert module same as insmod implementation. | 359 // Insert module same as insmod implementation. |
366 static int ins_mod(char *modules, char *flags) | 360 static int ins_mod(char *modules, char *flags) |
388 static void add_mod(char *name) | 382 static void add_mod(char *name) |
389 { | 383 { |
390 struct module_s *mod = get_mod(name, 1); | 384 struct module_s *mod = get_mod(name, 1); |
391 | 385 |
392 if (!(toys.optflags & (FLAG_r | FLAG_D)) && (mod->flags & MOD_ALOADED)) { | 386 if (!(toys.optflags & (FLAG_r | FLAG_D)) && (mod->flags & MOD_ALOADED)) { |
393 dbg("skipping %s, it is already loaded\n", name); | 387 TT.dbg("skipping %s, it is already loaded\n", name); |
394 return; | 388 return; |
395 } | 389 } |
396 dbg("queuing %s\n", name); | 390 TT.dbg("queuing %s\n", name); |
397 mod->cmdname = name; | 391 mod->cmdname = name; |
398 mod->flags |= MOD_NDDEPS; | 392 mod->flags |= MOD_NDDEPS; |
399 llist_add_tail(&TT.probes, mod); | 393 llist_add_tail(&TT.probes, mod); |
400 TT.nudeps++; | 394 TT.nudeps++; |
401 if (!strncmp(mod->name, "symbol:", 7)) TT.symreq = 1; | 395 if (!strncmp(mod->name, "symbol:", 7)) TT.symreq = 1; |
412 | 406 |
413 var = *argv; | 407 var = *argv; |
414 opt = xrealloc(opt, lopt + 2 + strlen(var) + 2); | 408 opt = xrealloc(opt, lopt + 2 + strlen(var) + 2); |
415 // check for key=val or key = val. | 409 // check for key=val or key = val. |
416 fmt = "%.*s%s "; | 410 fmt = "%.*s%s "; |
417 val = strchr_nul(var, '='); | 411 for (val = var; *val && *val != '='; val++); |
418 if (*val) { | 412 if (*val && strchr(++val, ' ')) fmt = "%.*s\"%s\" "; |
419 val++; | |
420 if (strchr(val, ' ')) fmt = "%.*s\"%s\" "; | |
421 } | |
422 lopt += sprintf(opt + lopt, fmt, (int) (val - var), var, val); | 413 lopt += sprintf(opt + lopt, fmt, (int) (val - var), var, val); |
423 } | 414 } |
424 return opt; | 415 return opt; |
425 } | 416 } |
426 | 417 |
432 if (!(m->flags & MOD_FNDDEPMOD)) { | 423 if (!(m->flags & MOD_FNDDEPMOD)) { |
433 if (!(toys.optflags & FLAG_s)) | 424 if (!(toys.optflags & FLAG_s)) |
434 error_msg("module %s not found in modules.dep", m->name); | 425 error_msg("module %s not found in modules.dep", m->name); |
435 return -ENOENT; | 426 return -ENOENT; |
436 } | 427 } |
437 dbg("go_prob'ing %s\n", m->name); | 428 TT.dbg("go_prob'ing %s\n", m->name); |
438 if (!(toys.optflags & FLAG_r)) m->dep = llist_rev(m->dep); | 429 if (!(toys.optflags & FLAG_r)) m->dep = llist_rev(m->dep); |
439 | 430 |
440 while (m->dep) { | 431 while (m->dep) { |
441 struct module_s *m2; | 432 struct module_s *m2; |
442 char *fn, *options; | 433 char *fn, *options; |
461 m2->opts = NULL; | 452 m2->opts = NULL; |
462 if (m == m2) options = add_opts(options, TT.cmdopts); | 453 if (m == m2) options = add_opts(options, TT.cmdopts); |
463 | 454 |
464 // are we only checking dependencies ? | 455 // are we only checking dependencies ? |
465 if (toys.optflags & FLAG_D) { | 456 if (toys.optflags & FLAG_D) { |
466 dbg(options ? "insmod %s %s\n" : "insmod %s\n", fn, options); | 457 TT.dbg(options ? "insmod %s %s\n" : "insmod %s\n", fn, options); |
467 if (options) free(options); | 458 if (options) free(options); |
468 continue; | 459 continue; |
469 } | 460 } |
470 if (m2->flags & MOD_ALOADED) { | 461 if (m2->flags & MOD_ALOADED) { |
471 dbg("%s is already loaded, skipping\n", fn); | 462 TT.dbg("%s is already loaded, skipping\n", fn); |
472 if (options) free(options); | 463 if (options) free(options); |
473 continue; | 464 continue; |
474 } | 465 } |
475 // none of above is true insert the module. | 466 // none of above is true insert the module. |
476 rc = ins_mod(fn, options); | 467 rc = ins_mod(fn, options); |
477 dbg("loaded %s '%s', rc:%d\n", fn, options, rc); | 468 TT.dbg("loaded %s '%s', rc:%d\n", fn, options, rc); |
478 if (rc == EEXIST) rc = 0; | 469 if (rc == EEXIST) rc = 0; |
479 if (options) free(options); | 470 if (options) free(options); |
480 if (rc) { | 471 if (rc) { |
481 perror_msg("can't load module %s (%s)", m2->name, fn); | 472 perror_msg("can't load module %s (%s)", m2->name, fn); |
482 break; | 473 break; |
492 char **argv = toys.optargs, *procline = NULL; | 483 char **argv = toys.optargs, *procline = NULL; |
493 FILE *fs; | 484 FILE *fs; |
494 struct module_s *module; | 485 struct module_s *module; |
495 unsigned flags = toys.optflags; | 486 unsigned flags = toys.optflags; |
496 | 487 |
497 dbg = dummy; | 488 TT.dbg = (flags & FLAG_v) ? xprintf : dummy; |
498 if (flags & FLAG_v) dbg = xprintf; | |
499 | 489 |
500 if ((toys.optc < 1) && (((flags & FLAG_r) && (flags & FLAG_l)) | 490 if ((toys.optc < 1) && (((flags & FLAG_r) && (flags & FLAG_l)) |
501 ||(!((flags & FLAG_r)||(flags & FLAG_l))))) { | 491 ||(!((flags & FLAG_r)||(flags & FLAG_l))))) |
492 { | |
502 toys.exithelp++; | 493 toys.exithelp++; |
503 error_exit("bad syntax"); | 494 error_exit("bad syntax"); |
504 } | 495 } |
505 // Check for -r flag without arg if yes then do auto remove. | 496 // Check for -r flag without arg if yes then do auto remove. |
506 if ((flags & FLAG_r) && (!toys.optc)) { | 497 if ((flags & FLAG_r) && !toys.optc) { |
507 if (rm_mod(NULL, O_NONBLOCK | O_EXCL) != 0) perror_exit("rmmod"); | 498 if (rm_mod(NULL, O_NONBLOCK | O_EXCL)) perror_exit("rmmod"); |
508 return; | 499 return; |
509 } | 500 } |
510 | 501 |
511 // change directory to /lib/modules/<release>/ | 502 // change directory to /lib/modules/<release>/ |
512 xchdir("/lib/modules"); | 503 xchdir("/lib/modules"); |
535 } else { | 526 } else { |
536 add_mod(argv[0]); | 527 add_mod(argv[0]); |
537 TT.cmdopts = add_cmdopt(argv); | 528 TT.cmdopts = add_cmdopt(argv); |
538 } | 529 } |
539 if (!TT.probes) { | 530 if (!TT.probes) { |
540 dbg("All modules loaded\n"); | 531 TT.dbg("All modules loaded\n"); |
541 return; | 532 return; |
542 } | 533 } |
543 dirtree_read("/etc/modprobe.conf", config_action); | 534 dirtree_read("/etc/modprobe.conf", config_action); |
544 dirtree_read("/etc/modprobe.d", config_action); | 535 dirtree_read("/etc/modprobe.d", config_action); |
545 if (TT.symreq) dirtree_read("modules.symbols", config_action); | 536 if (TT.symreq) dirtree_read("modules.symbols", config_action); |
546 if (TT.nudeps) dirtree_read("modules.alias", config_action); | 537 if (TT.nudeps) dirtree_read("modules.alias", config_action); |
547 find_dep(); | 538 find_dep(); |
548 while ((module = llist_popme(&TT.probes))) { | 539 while ((module = llist_popme(&TT.probes))) { |
549 if (!module->rnames) { | 540 if (!module->rnames) { |
550 dbg("probing by module name\n"); | 541 TT.dbg("probing by module name\n"); |
551 /* This is not an alias. Literal names are blacklisted | 542 /* This is not an alias. Literal names are blacklisted |
552 * only if '-b' is given. | 543 * only if '-b' is given. |
553 */ | 544 */ |
554 if (!(flags & FLAG_b) || !(module->flags & MOD_BLACKLIST)) | 545 if (!(flags & FLAG_b) || !(module->flags & MOD_BLACKLIST)) |
555 go_probe(module); | 546 go_probe(module); |
557 } | 548 } |
558 do { // Probe all real names for the alias. | 549 do { // Probe all real names for the alias. |
559 char *real = ((struct arg_list*)llist_pop(&module->rnames))->arg; | 550 char *real = ((struct arg_list*)llist_pop(&module->rnames))->arg; |
560 struct module_s *m2 = get_mod(real, 0); | 551 struct module_s *m2 = get_mod(real, 0); |
561 | 552 |
562 dbg("probing alias %s by realname %s\n", module->name, real); | 553 TT.dbg("probing alias %s by realname %s\n", module->name, real); |
563 if (!m2) continue; | 554 if (!m2) continue; |
564 if (!(m2->flags & MOD_BLACKLIST) | 555 if (!(m2->flags & MOD_BLACKLIST) |
565 && (!(m2->flags & MOD_ALOADED) || (flags & (FLAG_r | FLAG_D)))) | 556 && (!(m2->flags & MOD_ALOADED) || (flags & (FLAG_r | FLAG_D)))) |
566 go_probe(m2); | 557 go_probe(m2); |
567 free(real); | 558 free(real); |