Complete rewrite to support stack loading/unloading with proper handling of duplicates in the dependencies list.
No binary (build failed)
—
(log yok)
| @@ -3,11 +3,12 @@ | |
| * really dumb modprobe implementation for busybox | |
| * Copyright (C) 2001 Lineo, [email protected] | |
| * | |
| - | * CONFIG_MODPROBE_DEPEND stuff was added and is |
| - | * Copyright (C) 2002 Robert Griebl, [email protected] |
| + | * dependency specific stuff completly rewritten and |
| + | * copyright (c) 2002 by Robert Griebl, [email protected] |
| * | |
| */ | |
| + | #include <sys/utsname.h> |
| #include <stdio.h> | |
| #include <getopt.h> | |
| #include <stdlib.h> | |
| @@ -17,22 +18,27 @@ | |
| #include <ctype.h> | |
| #include "busybox.h" | |
| - | static char cmd[128]; |
| - | |
| - | #define CONFIG_MODPROBE_DEPEND |
| - | #ifdef CONFIG_MODPROBE_DEPEND |
| - | |
| - | #include <sys/utsname.h> |
| struct dep_t { | |
| char * m_module; | |
| + | |
| int m_depcnt; | |
| char ** m_deparr; | |
| struct dep_t * m_next; | |
| }; | |
| + | struct mod_list_t { |
| + | char * m_module; |
| + | |
| + | struct mod_list_t * m_prev; |
| + | struct mod_list_t * m_next; |
| + | }; |
| + | |
| + | |
| + | static struct dep_t *depend = 0; |
| + | |
| static struct dep_t *build_dep ( void ) | |
| { | |
| @@ -99,7 +105,7 @@ static struct dep_t *build_dep ( void ) | |
| current-> m_module = mod; | |
| current-> m_depcnt = 0; | |
| current-> m_deparr = 0; | |
| - | current-> m_next = 0; |
| + | current-> m_next = 0; |
| //printf ( "%s:\n", mod ); | |
| @@ -154,70 +160,142 @@ static struct dep_t *build_dep ( void ) | |
| } | |
| - | static struct dep_t *find_dep ( struct dep_t *dt, char *mod ) |
| + | static int mod_process ( struct mod_list_t *list, int do_insert, int autoclean, int quiet, int do_syslog, int show_only, int verbose ) |
| { | |
| - | int lm = xstrlen ( mod ); |
| - | int extpos = 0; |
| + | char lcmd [256]; |
| + | int rc = 0; |
| + | if ( !list ) |
| + | return 1; |
| + | |
| + | while ( list ) { |
| + | if ( do_insert ) |
| + | snprintf ( lcmd, sizeof( lcmd ) - 1, "insmod %s %s %s %s 2>/dev/null", do_syslog ? "-s" : "", autoclean ? "-k" : "", quiet ? "-q" : "", list-> m_module ); |
| + | else |
| + | snprintf ( lcmd, sizeof( lcmd ) - 1, "rmmod %s %s 2>/dev/null", do_syslog ? "-s" : "", list-> m_module ); |
| + | |
| + | if ( verbose ) |
| + | printf ( "%s\n", lcmd ); |
| + | if ( !show_only ) |
| + | rc |= system ( lcmd ); |
| + | |
| + | list = do_insert ? list-> m_prev : list-> m_next; |
| + | } |
| + | return rc; |
| + | } |
| + | |
| + | static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail ) |
| + | { |
| + | struct mod_list_t *find; |
| + | struct dep_t *dt; |
| + | |
| + | int lm; |
| + | |
| + | // remove .o extension |
| + | lm = xstrlen ( mod ); |
| if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) | |
| - | extpos = 2; |
| + | mod [lm-2] = 0; |
| - | if ( extpos > 0 ) |
| - | mod [lm - extpos] = 0; |
| + | //printf ( "check_dep: %s\n", mod ); |
| - | while ( dt ) { |
| - | if ( !strcmp ( dt-> m_module, mod )) |
| - | break; |
| + | // search for duplicates |
| + | for ( find = *head; find; find = find-> m_next ) { |
| + | if ( !strcmp ( mod, find-> m_module )) { |
| + | // found -> dequeue it |
| + | |
| + | if ( find-> m_prev ) |
| + | find-> m_prev-> m_next = find-> m_next; |
| + | else |
| + | *head = find-> m_next; |
| + | |
| + | if ( find-> m_next ) |
| + | find-> m_next-> m_prev = find-> m_prev; |
| + | else |
| + | *tail = find-> m_prev; |
| + | |
| + | //printf ( "DUP\n" ); |
| + | |
| + | break; // there can be only one duplicate |
| + | } |
| + | } |
| - | dt = dt-> m_next; |
| + | if ( !find ) { // did not find a duplicate |
| + | find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t)); |
| + | find-> m_module = mod; |
| } | |
| - | if ( extpos > 0 ) |
| - | mod [lm - extpos] = '.'; |
| - | return dt; |
| + | // enqueue at tail |
| + | if ( *tail ) |
| + | (*tail)-> m_next = find; |
| + | find-> m_prev = *tail; |
| + | find-> m_next = 0; |
| + | |
| + | if ( !*head ) |
| + | *head = find; |
| + | *tail = find; |
| + | |
| + | // check dependencies |
| + | for ( dt = depend; dt; dt = dt-> m_next ) { |
| + | if ( !strcmp ( dt-> m_module, mod )) { |
| + | int i; |
| + | |
| + | for ( i = 0; i < dt-> m_depcnt; i++ ) |
| + | check_dep ( dt-> m_deparr [i], head, tail ); |
| + | } |
| + | } |
| } | |
| - | #define MODPROBE_EXECUTE 0x1 |
| - | #define MODPROBE_INSERT 0x2 |
| - | #define MODPROBE_REMOVE 0x4 |
| - | static void check_dep ( char *mod, int do_syslog, |
| - | int show_only, int verbose, int flags ) |
| + | |
| + | static int mod_insert ( char *mod, int argc, char **argv, int autoclean, int quiet, int do_syslog, int show_only, int verbose ) |
| { | |
| - | static struct dep_t *depend = (struct dep_t *) -1; |
| - | struct dep_t *dt; |
| + | struct mod_list_t *tail = 0; |
| + | struct mod_list_t *head = 0; |
| + | int rc = 0; |
| - | if ( depend == (struct dep_t *) -1 ) |
| - | depend = build_dep ( ); |
| + | // get dep list for module mod |
| + | check_dep ( mod, &head, &tail ); |
| - | if (( dt = find_dep ( depend, mod ))) { |
| + | if ( head && tail ) { |
| int i; | |
| - | |
| - | for ( i = 0; i < dt-> m_depcnt; i++ ) |
| - | check_dep ( dt-> m_deparr [i], do_syslog, |
| - | show_only, verbose, flags|MODPROBE_EXECUTE); |
| - | } |
| - | if ( flags & MODPROBE_EXECUTE ) { |
| - | char lcmd [256]; |
| - | if ( flags & MODPROBE_INSERT ) { |
| - | snprintf(lcmd, sizeof(lcmd)-1, "insmod %s -q -k %s 2>/dev/null", |
| - | do_syslog ? "-s" : "", mod ); |
| - | } |
| - | if ( flags & MODPROBE_REMOVE ) { |
| - | snprintf(lcmd, sizeof(lcmd)-1, "insmod %s -q -k %s 2>/dev/null", |
| - | do_syslog ? "-s" : "", mod ); |
| - | } |
| - | if ( flags & (MODPROBE_REMOVE|MODPROBE_INSERT) ) { |
| - | if (verbose) |
| - | printf("%s\n", lcmd); |
| - | if (!show_only) |
| - | system ( lcmd ); |
| + | |
| + | // append module args |
| + | head-> m_module = xmalloc ( 256 ); |
| + | strcpy ( head-> m_module, mod ); |
| + | |
| + | for ( i = 0; i < argc; i++ ) { |
| + | strcat ( head-> m_module, " " ); |
| + | strcat ( head-> m_module, argv [i] ); |
| } | |
| + | |
| + | // process tail ---> head |
| + | rc |= mod_process ( tail, 1, autoclean, quiet, do_syslog, show_only, verbose ); |
| } | |
| - | } |
| + | else |
| + | rc = 1; |
| + | |
| + | return rc; |
| + | } |
| + | |
| + | static void mod_remove ( char *mod, int do_syslog, int show_only, int verbose ) |
| + | { |
| + | static struct mod_list_t rm_a_dummy = { "-a", 0, 0 }; |
| + | |
| + | struct mod_list_t *head = 0; |
| + | struct mod_list_t *tail = 0; |
| + | |
| + | if ( mod ) |
| + | check_dep ( mod, &head, &tail ); |
| + | else // autoclean |
| + | head = tail = &rm_a_dummy; |
| + | |
| + | if ( head && tail ) { |
| + | // process head ---> tail |
| + | mod_process ( head, 0, 0, 0, do_syslog, show_only, verbose ); |
| + | } |
| + | } |
| + | |
| - | #endif |
| - | |
| extern int modprobe_main(int argc, char** argv) | |
| { | |
| @@ -281,24 +359,18 @@ extern int modprobe_main(int argc, char** argv) | |
| if (list) | |
| exit(EXIT_SUCCESS); | |
| + | depend = build_dep ( ); |
| + | |
| + | if ( !depend ) { |
| + | fprintf (stderr, "could not parse modules.dep\n" ); |
| + | exit (EXIT_FAILURE); |
| + | } |
| + | |
| if (remove_opt) { | |
| do { | |
| - | sprintf(cmd, "rmmod %s %s %s", |
| - | optind >= argc ? "-a" : "", |
| - | do_syslog ? "-s" : "", |
| - | optind < argc ? argv[optind] : ""); |
| - | if (do_syslog) |
| - | syslog(LOG_INFO, "%s", cmd); |
| - | if (verbose) |
| - | printf("%s\n", cmd); |
| - | if (!show_only) |
| - | rc = system(cmd); |
| - | |
| - | #ifdef CONFIG_MODPROBE_DEPEND |
| - | if ( optind < argc ) |
| - | check_dep ( argv [optind], do_syslog, show_only, verbose, MODPROBE_REMOVE); |
| - | #endif |
| - | } while (++optind < argc); |
| + | mod_remove ( optind < argc ? argv [optind] : 0, do_syslog, show_only, verbose ); |
| + | } while ( ++optind < argc ); |
| + | |
| exit(EXIT_SUCCESS); | |
| } | |
| @@ -306,29 +378,8 @@ extern int modprobe_main(int argc, char** argv) | |
| fprintf(stderr, "No module or pattern provided\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| - | |
| - | sprintf(cmd, "insmod %s %s %s", |
| - | do_syslog ? "-s" : "", |
| - | quiet ? "-q" : "", |
| - | autoclean ? "-k" : ""); |
| - | |
| - | #ifdef CONFIG_MODPROBE_DEPEND |
| - | check_dep ( argv [optind], do_syslog, show_only, verbose, MODPROBE_INSERT); |
| - | #endif |
| - | |
| - | while (optind < argc) { |
| - | strcat(cmd, " "); |
| - | strcat(cmd, argv[optind]); |
| - | optind++; |
| - | } |
| - | if (do_syslog) |
| - | syslog(LOG_INFO, "%s", cmd); |
| - | if (verbose) |
| - | printf("%s\n", cmd); |
| - | if (!show_only) |
| - | rc = system(cmd); |
| - | else |
| - | rc = 0; |
| + | |
| + | rc = mod_insert ( argv [optind], argc - optind - 1, argv + optind + 1, autoclean, quiet, do_syslog, show_only, verbose ); |
| exit(rc ? EXIT_FAILURE : EXIT_SUCCESS); | |
| } | |