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/