diff options
-rw-r--r-- | modutils/modprobe.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 35feaeb..0b81142 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -2,6 +2,10 @@ /* * 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 + * */ #include <stdio.h> @@ -10,10 +14,189 @@ #include <unistd.h> #include <syslog.h> #include <string.h> +#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; +}; + + +static struct dep_t *build_dep ( ) +{ + struct utsname un; + FILE *f; + struct dep_t *first = 0; + struct dep_t *current = 0; + char buffer [4096]; + char *filename = buffer; + int continuation_line = 0; + + if ( uname ( &un )) + return 0; + strcpy ( filename, "/lib/modules/" ); + strcat ( filename, un. release ); + strcat ( filename, "/modules.dep" ); + + f = fopen ( filename, "r" ); + if ( !f ) + return 0; + + while ( fgets ( buffer, sizeof( buffer), f )) { + int l = strlen ( buffer ); + char *p = 0; + + if ( buffer [l-1] == '\n' ) { + buffer [l-1] = 0; + l--; + } + + if ( l == 0 ) { + continuation_line = 0; + continue; + } + + if ( !continuation_line ) { + char *col = strchr ( buffer, ':' ); + + if ( col ) { + char *mods; + char *mod; + + *col = 0; + mods = strrchr ( buffer, '/' ); + + if ( !mods ) + mods = buffer; + else + mods++; + + mod = (char *) malloc ( col - mods + 1 ); + strncpy ( mod, mods, col - mods ); + mod [col - mods] = 0; + + if ( !current ) { + first = current = (struct dep_t *) malloc ( sizeof ( struct dep_t )); + } + else { + current-> m_next = (struct dep_t *) malloc ( sizeof ( struct dep_t )); + current = current-> m_next; + } + current-> m_module = mod; + current-> m_depcnt = 0; + current-> m_deparr = 0; + current-> m_next = 0; + + /* printf ( "%s:\n", mod ); */ + + p = col + 1; + } + else + p = 0; + } + else + p = buffer; + + if ( p && *p ) { + char *end = &buffer [l-1]; + char *deps = strrchr ( end, '/' ); + char *dep; + + while ( isblank ( *end ) || ( *end == '\\' )) + end--; + + deps = strrchr ( p, '/' ); + + if ( !deps || ( deps < p )) { + deps = p; + + while ( isblank ( *deps )) + deps++; + } + else + deps++; + + dep = (char *) malloc ( end - deps + 2 ); + strncpy ( dep, deps, end - deps + 1 ); + dep [end - deps + 1] = 0; + + current-> m_depcnt++; + current-> m_deparr = (char **) realloc ( current-> m_deparr, sizeof ( char *) * current-> m_depcnt ); + current-> m_deparr [current-> m_depcnt - 1] = dep; + + /* printf ( " %d) %s\n", current-> m_depcnt, current-> m_deparr [current-> m_depcnt -1] ); */ + } + + if ( buffer [l-1] == '\\' ) + continuation_line = 1; + else + continuation_line = 0; + } + fclose ( f ); + + return first; +} + + +static struct dep_t *find_dep ( struct dep_t *dt, char *mod ) +{ + int lm = strlen ( mod ); + int hasext = 0; + + if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) + hasext = 1; + + while ( dt ) { + if ( hasext && !strcmp ( dt-> m_module, mod )) + break; + else if ( !hasext && !strncmp ( dt-> m_module, mod, strlen ( dt-> m_module ) - 2 )) + break; + + dt = dt-> m_next; + } + return dt; +} + + +static void check_dep ( char *mod, int loadit ) +{ + static struct dep_t *depend = (struct dep_t *) -1; + struct dep_t *dt; + + if ( depend == (struct dep_t *) -1 ) + depend = build_dep ( ); + + /* printf ( "CHECK: %s (%p)\n", mod, depend ); */ + + if (( dt = find_dep ( depend, mod ))) { + int i; + + for ( i = 0; i < dt-> m_depcnt; i++ ) + check_dep ( dt-> m_deparr [i], 1 ); + } + if ( loadit ) { + char lcmd [128]; + + sprintf ( lcmd, "insmod -k %s 2>/dev/null", mod ); + system ( lcmd ); + } +} + +#endif + + extern int modprobe_main(int argc, char** argv) { int ch, rc = 0; @@ -101,6 +284,11 @@ extern int modprobe_main(int argc, char** argv) do_syslog ? "-s" : "", quiet ? "-q" : "", autoclean ? "-k" : ""); + +#ifdef CONFIG_MODPROBE_DEPEND + check_dep ( argv [optind], 0 ); +#endif + while (optind < argc) { strcat(cmd, " "); strcat(cmd, argv[optind]); |