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 @@ * really dumb modprobe implementation for busybox * Copyright (C) 2001 Lineo, davidm@lineo.com * - * CONFIG_MODPROBE_DEPEND stuff was added and is - * Copyright (C) 2002 Robert Griebl, griebl@gmx.de + * dependency specific stuff completly rewritten and + * copyright (c) 2002 by Robert Griebl, griebl@gmx.de * */ +#include #include #include #include @@ -17,22 +18,27 @@ #include #include "busybox.h" -static char cmd[128]; -#define CONFIG_MODPROBE_DEPEND - -#ifdef CONFIG_MODPROBE_DEPEND - -#include 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 (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) - extpos = 2; + if ( !list ) + return 1; - if ( extpos > 0 ) - mod [lm - extpos] = 0; - - while ( dt ) { - if ( !strcmp ( dt-> m_module, mod )) - break; - - dt = dt-> m_next; + 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; } - if ( extpos > 0 ) - mod [lm - extpos] = '.'; - - return dt; + return rc; } -#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 void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail ) { - static struct dep_t *depend = (struct dep_t *) -1; + struct mod_list_t *find; struct dep_t *dt; - - if ( depend == (struct dep_t *) -1 ) - depend = build_dep ( ); - - if (( dt = find_dep ( depend, mod ))) { - 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 ); - } - } -} -#endif + int lm; + + // remove .o extension + lm = xstrlen ( mod ); + if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) + mod [lm-2] = 0; + + //printf ( "check_dep: %s\n", mod ); + + // 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 + } + } + + if ( !find ) { // did not find a duplicate + find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t)); + find-> m_module = mod; + } + + // 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 ); + } + } +} + + + +static int mod_insert ( char *mod, int argc, char **argv, int autoclean, int quiet, int do_syslog, int show_only, int verbose ) +{ + struct mod_list_t *tail = 0; + struct mod_list_t *head = 0; + int rc = 0; + + // get dep list for module mod + check_dep ( mod, &head, &tail ); + + if ( head && tail ) { + int i; + + // 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 ); + } +} + + 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); }