Re: Patch: module-init-tools-0.6/modprobe.c - support subdirectories

From: Adam J. Richter (adam@yggdrasil.com)
Date: Mon Nov 18 2002 - 19:13:46 EST


        Here is an updated version of my patch to
module-init-tools-0.6/modprobe.c to allow it to recursively search
subdirectories so that we can have module directory tree again.
This version I have actually run and it seems to work.

        Unfortunately, about one out of four modules that I load
will get an error from the module loading system call (memory
allocation failure). I don't think that that is due to my
modprobe.c changes, but it could be.
        This version of the patch adds 39 lines, alas, but I think the
ability to have a module directory hierarchy if you want to is worth it
(e.g., it is a lot easier to select a class of drivers for inclusion in
a boot image).

Adam J. Richter __ ______________ 575 Oroville Road
adam@yggdrasil.com \ / Milpitas, California 95035
+1 408 309-6081 | g g d r a s i l United States of America
                         "Free Software For The Rest Of Us."

--- module-init-tools-0.6/modprobe.c 2002-10-30 20:03:06.000000000 -0800
+++ module-init-tools-0.6.ajr/modprobe.c 2002-11-18 12:23:08.000000000 -0800
@@ -36,7 +36,7 @@
 
 #include "backwards_compat.c"
 
-#define MODULE_DIR "/lib/modules/%s/kernel/"
+#define MODULE_DIR "/lib/modules"
 #define MODULE_EXTENSION ".o"
 
 #define MODULE_NAME_LEN (64 - ELF_TYPE / 8)
@@ -114,7 +114,7 @@
 
 static int ends_in(const char *name, const char *ext)
 {
- unsigned int namelen, extlen, i;
+ unsigned int namelen, extlen;
 
         /* Grab lengths */
         namelen = strlen(name);
@@ -122,11 +122,8 @@
 
         if (namelen < extlen) return 0;
 
- /* Look backwards */
- for (i = 0; i < extlen; i++)
- if (name[namelen - i] != ext[extlen - i]) return 0;
-
- return 1;
+ name += namelen - extlen;
+ return (strcmp(name, ext) == 0);
 }
 
 static void *load_section(int fd, unsigned long shdroff,
@@ -201,8 +198,8 @@
         Elf_Ehdr hdr;
         int fd;
 
- new = malloc(sizeof(*new) + strlen(dirname) + strlen(entry) + 1);
- sprintf(new->name, "%s%s", dirname, entry);
+ new = malloc(sizeof(*new) + strlen(dirname) + strlen(entry) + 2);
+ sprintf(new->name, "%s/%s", dirname, entry);
         new->next = last;
         new->order = 0;
         fd = open(new->name, O_RDONLY);
@@ -227,14 +224,46 @@
         return new;
 }
 
-static struct module *load_all_exports(const char *revision)
+static char *find_mod(const char *parent, const char *child,
+ const char *target)
+{
+ struct dirent *dirent;
+ DIR *dir;
+ char path[strlen(parent) + strlen(child) + 2];
+ struct stat statbuf;
+ char *result = NULL;
+
+ sprintf(path, "%s/%s", parent, child);
+
+ if (strcmp(child, target) == 0 &&
+ stat(path, &statbuf) == 0 &&
+ S_ISREG(statbuf.st_mode))
+ return strdup(path);
+
+ dir = opendir(path);
+ if (dir) {
+ while ((dirent = readdir(dir)) != NULL) {
+ if (!strcmp(dirent->d_name, "..") ||
+ !strcmp(dirent->d_name, "."))
+ continue;
+
+ result = find_mod(path, dirent->d_name, target);
+ if (result)
+ break;
+ }
+ closedir(dir);
+ }
+ return result;
+}
+
+static struct module *load_all_exports(const char *parent, const char *subdir,
+ struct module *mods)
 {
- struct module *mods = NULL;
         struct dirent *dirent;
         DIR *dir;
- char dirname[strlen(revision) + sizeof(MODULE_DIR)];
+ char dirname[strlen(parent) + strlen(subdir) + 2];
 
- sprintf(dirname, MODULE_DIR, revision);
+ sprintf(dirname, "%s/%s", parent, subdir);
         dir = opendir(dirname);
         if (dir) {
                 while ((dirent = readdir(dir)) != NULL) {
@@ -242,6 +271,10 @@
                         if (ends_in(dirent->d_name, MODULE_EXTENSION))
                                 mods = add_module(dirname, dirent->d_name,
                                                   mods);
+ else if (strcmp(dirent->d_name, "..") &&
+ strcmp(dirent->d_name, "."))
+ mods = load_all_exports(dirname,
+ dirent->d_name, mods);
                 }
                 closedir(dir);
         }
@@ -273,6 +306,7 @@
                                 found = m;
                                 /* If we didn't need to load it
                                    already, we do now. */
+
                                 found->order = order;
                         }
                 }
@@ -425,6 +459,7 @@
 
         ret = syscall(__NR_init_module, map, len, "");
         if (ret != 0) {
+ fprintf (stderr, "AJR init_module(map %p, len %d) failed, ret = %d.\n", map, len, ret);
                 if (dont_fail)
                         fatal("Error inserting %s: %s\n",name,moderror(errno));
                 else
@@ -439,13 +474,16 @@
         unsigned int order;
         struct module *modules;
         struct module *i;
- char pathname[strlen(revision) + sizeof(MODULE_DIR) + strlen(modname)
- + sizeof(MODULE_EXTENSION)];
+ char *pathname;
+ char modname_ext[strlen(modname) + sizeof(MODULE_EXTENSION)];
 
- /* Create path name */
- sprintf(pathname, MODULE_DIR "%s" MODULE_EXTENSION, revision, modname);
+ sprintf (modname_ext, "%s%s", modname, MODULE_EXTENSION);
+ pathname = find_mod(MODULE_DIR, revision, modname_ext);
+ if (!pathname)
+ fatal("No module %s in %s/%s or subdirectories.\n",
+ modname_ext, MODULE_DIR, revision);
 
- modules = load_all_exports(revision);
+ modules = load_all_exports(MODULE_DIR, revision, NULL);
         order = 1;
         if (get_deps(order, pathname, modules, verbose)) {
                 /* We need some other modules. */
@@ -475,6 +513,7 @@
         }
         if (verbose) printf("Loading %s\n", pathname);
         insmod(pathname, 1);
+ free(pathname);
 }
 
 static struct option options[] = { { "verbose", 0, NULL, 'v' },
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Nov 23 2002 - 22:00:25 EST