Reworked by Robert Griebl <griebl@gmx.de> to support proper
authorEric Andersen <andersen@codepoet.org>
Fri, 26 Apr 2002 06:04:01 +0000 (06:04 -0000)
committerEric Andersen <andersen@codepoet.org>
Fri, 26 Apr 2002 06:04:01 +0000 (06:04 -0000)
module dependancies.

modutils/modprobe.c

index 35feaebf7a28b681e7a036aebcc327b4b012fa95..0b81142d56581f6ccbcdb9d51b8a1e5abe0a6a5a 100644 (file)
@@ -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>
 #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]);