summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modutils/modprobe.c188
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]);