Complete rewrite to support stack loading/unloading with proper
authorRobert Griebl <griebl@gmx.de>
Tue, 14 May 2002 23:42:08 +0000 (23:42 -0000)
committerRobert Griebl <griebl@gmx.de>
Tue, 14 May 2002 23:42:08 +0000 (23:42 -0000)
handling of duplicates in the dependencies list.

modutils/modprobe.c

index 2f797ec4a064ac4d9b281577f26482877e0d37cf..b13b9b04fd6b4aa3b18785c28c72938c0ac4fa78 100644 (file)
@@ -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>
 #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);
 }