diff options
author | Robert Griebl | 2002-05-14 23:42:08 +0000 |
---|---|---|
committer | Robert Griebl | 2002-05-14 23:42:08 +0000 |
commit | 52e8d060a95877d3070c18e3bf05f3fe8854357f (patch) | |
tree | 96492d3e3eeb644c9df45220d16616c2fbc3325c /modutils/modprobe.c | |
parent | d77601178d9c9f5084e3842d0156dc4723592e44 (diff) | |
download | busybox-52e8d060a95877d3070c18e3bf05f3fe8854357f.zip busybox-52e8d060a95877d3070c18e3bf05f3fe8854357f.tar.gz |
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 2f797ec..b13b9b0 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 <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); } |