diff -u -r --new-file module-init-tools-0.8/Makefile.in module-init-tools-0.9.ajr/Makefile.in --- module-init-tools-0.8/Makefile.in 2002-11-13 18:09:56.000000000 -0800 +++ module-init-tools-0.9.ajr/Makefile.in 2002-11-21 05:55:06.000000000 -0800 @@ -5,8 +5,8 @@ default: insmod rmmod lsmod modprobe -insmod.o rmmod.o lsmod.o: backwards_compat.c -modprobe.o: backwards_compat.c mod32.c mod64.c mod_types.h +insmod.o rmmod.o lsmod.o: backwards_compat.c mod_types.h +modprobe.o: backwards_compat.c mod_types.h # Moving a link lsmod -> insmod requires two moves. %.old: diff -u -r --new-file module-init-tools-0.8/mod32.c module-init-tools-0.9.ajr/mod32.c --- module-init-tools-0.8/mod32.c 2002-11-13 18:15:24.000000000 -0800 +++ module-init-tools-0.9.ajr/mod32.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,158 +0,0 @@ -static void *load_section32(int fd, unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - const char *secname, - unsigned long *size) -{ - Elf32_Shdr sechdrs[num_secs]; - unsigned int i; - char *secnames; - - /* Grab headers. */ - lseek(fd, shdroff, SEEK_SET); - if (read(fd, sechdrs, sizeof(sechdrs)) != sizeof(sechdrs)) - return (void*)-1; - - /* Grab strings so we can tell who is who */ - secnames = malloc(sechdrs[secnamesec].sh_size); - lseek(fd, sechdrs[secnamesec].sh_offset, SEEK_SET); - if (read(fd, secnames, sechdrs[secnamesec].sh_size) - != sechdrs[secnamesec].sh_size) { - free(secnames); - return (void*)-1; - } - - - /* Find the section they want */ - for (i = 1; i < num_secs; i++) { - if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { - void *buf; - - free(secnames); - *size = sechdrs[i].sh_size; - buf = malloc(*size); - if (lseek(fd, sechdrs[i].sh_offset, SEEK_SET) == -1 - || read(fd, buf, *size) != *size) { - free(buf); - return (void *)-1; - } - return buf; - } - } - free(secnames); - return NULL; -} - -static void *map_exports32(int fd, - unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - const char *name, - unsigned int *num_exports) -{ - struct kernel_symbol32 *syms; - unsigned long size; - - syms = load_section32(fd, shdroff, num_secs, secnamesec, "__ksymtab", - &size); - *num_exports = 0; - if (syms == (void*)-1) { - warn("Error finding exports for module %s\n", name); - syms = NULL; - } else if (syms) - *num_exports = size / sizeof(struct kernel_symbol32); - return syms; -} - -static int export_name_cmp32(struct module *m, int index, const char *name) -{ - return strcmp(m->u.exports32[index].name, name); -} - -static struct module *add_module32(int fd, struct module *new, - struct module *last, - struct alias **aliases) -{ - Elf32_Ehdr hdr; - - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - warn("Error reading module %s\n", new->name); - free(new); - close(fd); - return last; - } - - /* Map the section table */ - new->u.ptr = mops->map_exports(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, new->name, - &new->num_exports); - - /* Add in any aliases */ - *aliases = add_aliases(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, new, *aliases); - - close(fd); - return new; -} - -/* Analyse this module to see if it needs others. */ -static int get_deps32(unsigned int order, - const char *dirname, - const char *modname, - struct module *modules, - int verbose) -{ - unsigned int i; - unsigned long size; - Elf32_Ehdr hdr; - int fd; - char *strings; - Elf32_Sym *syms; - int needed = 0; - char modpath[strlen(dirname) + strlen(modname) - + sizeof(MODULE_EXTENSION)]; - - sprintf(modpath, "%s%s%s", dirname, modname, MODULE_EXTENSION); - fd = open(modpath, O_RDONLY); - if (fd < 0) - fatal("Can't open module %s: %s\n", modpath, strerror(errno)); - - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - fatal("Error reading module %s\n", modpath); - - strings = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, ".strtab", &size); - syms = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, ".symtab", &size); - if (!strings || strings == (void *)-1 - || !syms || syms == (void *)-1) { - fatal("Could not load strings and symbol table from %s\n", - modpath); - } - - /* Now establish which modules we need */ - for (i = 0; i < size / sizeof(syms[0]); i++) { - if (syms[i].st_shndx == SHN_UNDEF) { - /* Look for symbol */ - const char *name = strings + syms[i].st_name; - - if (strcmp(name, "") == 0) - continue; - - /* Did this pull in a new module? */ - if (need_symbol(order, name, modules, - verbose ? modpath : NULL)) - needed = 1; - } - } - close(fd); - return needed; -} - -static struct mod_ops mod32_ops = { - .load_section = load_section32, - .map_exports = map_exports32, - .export_name_cmp = export_name_cmp32, - .add_module = add_module32, - .get_deps = get_deps32, -}; diff -u -r --new-file module-init-tools-0.8/mod64.c module-init-tools-0.9.ajr/mod64.c --- module-init-tools-0.8/mod64.c 2002-11-13 18:15:57.000000000 -0800 +++ module-init-tools-0.9.ajr/mod64.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,158 +0,0 @@ -static void *load_section64(int fd, unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - const char *secname, - unsigned long *size) -{ - Elf64_Shdr sechdrs[num_secs]; - unsigned int i; - char *secnames; - - /* Grab headers. */ - lseek(fd, shdroff, SEEK_SET); - if (read(fd, sechdrs, sizeof(sechdrs)) != sizeof(sechdrs)) - return (void*)-1; - - /* Grab strings so we can tell who is who */ - secnames = malloc(sechdrs[secnamesec].sh_size); - lseek(fd, sechdrs[secnamesec].sh_offset, SEEK_SET); - if (read(fd, secnames, sechdrs[secnamesec].sh_size) - != sechdrs[secnamesec].sh_size) { - free(secnames); - return (void*)-1; - } - - - /* Find the section they want */ - for (i = 1; i < num_secs; i++) { - if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { - void *buf; - - free(secnames); - *size = sechdrs[i].sh_size; - buf = malloc(*size); - if (lseek(fd, sechdrs[i].sh_offset, SEEK_SET) == -1 - || read(fd, buf, *size) != *size) { - free(buf); - return (void *)-1; - } - return buf; - } - } - free(secnames); - return NULL; -} - -static void *map_exports64(int fd, - unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - const char *name, - unsigned int *num_exports) -{ - struct kernel_symbol64 *syms; - unsigned long size; - - syms = load_section64(fd, shdroff, num_secs, secnamesec, "__ksymtab", - &size); - *num_exports = 0; - if (syms == (void*)-1) { - warn("Error finding exports for module %s\n", name); - syms = NULL; - } else if (syms) - *num_exports = size / sizeof(struct kernel_symbol64); - return syms; -} - -static int export_name_cmp64(struct module *m, int index, const char *name) -{ - return strcmp(m->u.exports64[index].name, name); -} - -static struct module *add_module64(int fd, struct module *new, - struct module *last, - struct alias **aliases) -{ - Elf64_Ehdr hdr; - - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - warn("Error reading module %s\n", new->name); - free(new); - close(fd); - return last; - } - - /* Map the section table */ - new->u.ptr = mops->map_exports(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, new->name, - &new->num_exports); - /* Add in any aliases */ - *aliases = add_aliases(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, new, *aliases); - - close(fd); - return new; -} - -/* Analyse this module to see if it needs others. */ -static int get_deps64(unsigned int order, - const char *dirname, - const char *modname, - struct module *modules, - int verbose) -{ - unsigned int i; - unsigned long size; - Elf64_Ehdr hdr; - int fd; - char *strings; - Elf64_Sym *syms; - int needed = 0; - char modpath[strlen(dirname) + strlen(modname) - + sizeof(MODULE_EXTENSION)]; - - sprintf(modpath, "%s%s%s", dirname, modname, MODULE_EXTENSION); - - fd = open(modpath, O_RDONLY); - if (fd < 0) - fatal("Can't open module %s: %s\n", modpath, strerror(errno)); - - if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - fatal("Error reading module %s\n", modpath); - - strings = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, ".strtab", &size); - syms = mops->load_section(fd, hdr.e_shoff, hdr.e_shnum, - hdr.e_shstrndx, ".symtab", &size); - if (!strings || strings == (void *)-1 - || !syms || syms == (void *)-1) { - fatal("Could not load strings and symbol table from %s\n", - modpath); - } - - /* Now establish which modules we need */ - for (i = 0; i < size / sizeof(syms[0]); i++) { - if (syms[i].st_shndx == SHN_UNDEF) { - /* Look for symbol */ - const char *name = strings + syms[i].st_name; - - if (strcmp(name, "") == 0) - continue; - - /* Did this pull in a new module? */ - if (need_symbol(order, name, modules, - verbose ? modpath : NULL)) - needed = 1; - } - } - close(fd); - return needed; -} - -static struct mod_ops mod64_ops = { - .load_section = load_section64, - .map_exports = map_exports64, - .export_name_cmp = export_name_cmp64, - .add_module = add_module64, - .get_deps = get_deps64, -}; diff -u -r --new-file module-init-tools-0.8/mod_types.h module-init-tools-0.9.ajr/mod_types.h --- module-init-tools-0.8/mod_types.h 2002-11-13 18:14:41.000000000 -0800 +++ module-init-tools-0.9.ajr/mod_types.h 2002-11-21 05:13:16.000000000 -0800 @@ -1,65 +1 @@ -struct kernel_symbol32 { - char value[4]; - char name[64 - 4]; -}; - -struct kernel_symbol64 { - char value[8]; - char name[64 - 8]; -}; - -/* All the modules kept in this list */ -struct module -{ - struct module *next; - - /* mmaped export symbols area */ - unsigned int num_exports; - union { - struct kernel_symbol32 *exports32; - struct kernel_symbol64 *exports64; - void *ptr; - } u; - - /* What order it has to be loaded (0 = never). */ - unsigned int order; - - /* full path name */ - char name[0]; -}; - -struct alias -{ - struct alias *next; - /* One of these two is set. */ - struct module *module; - struct alias *alias; - /* Line in config where this was defined */ - int config_line; - char name[0]; -}; - -struct mod_ops { - struct module *(*add_module)(int fd, struct module *new, - struct module *last, - struct alias **aliases); - void *(*load_section)(int fd, unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - const char *secname, - unsigned long *size); - void *(*map_exports)(int fd, - unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - const char *name, - unsigned int *num_exports); - int (*export_name_cmp)(struct module *m, int index, const char *name); - int (*get_deps)(unsigned int order, - const char *dirname, - const char *modname, - struct module *modules, - int verbose); -}; - #define MODULE_EXTENSION ".o" diff -u -r --new-file module-init-tools-0.8/modprobe.c module-init-tools-0.9.ajr/modprobe.c --- module-init-tools-0.8/modprobe.c 2002-11-20 14:30:32.000000000 -0800 +++ module-init-tools-0.9.ajr/modprobe.c 2002-11-21 05:37:16.000000000 -0800 @@ -39,11 +39,21 @@ #include "mod_types.h" -#define MODULE_DIR "/lib/modules/%s/kernel/" +struct module_list; -/* We decide when we hit the first module whether we are 32 or 64-bit, - and set this. */ -static struct mod_ops *mops; +struct module { + struct module *next; + struct module_list *dependencies; + enum { NOT_LOADED = 0, BEING_LOADED, LOADED } state; + char filename[0]; +}; + +struct module_list { + struct module *module; + struct module_list *next; +}; + +#define MODULE_DIR "/lib/modules" static void fatal(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2))); @@ -75,20 +85,16 @@ va_end(arglist); } -static struct alias *add_aliases(int fd, - unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - struct module *mod, - struct alias *last); - -static int need_symbol(unsigned int order, - const char *name, - struct module *modules, - const char *modname); +static void *do_nofail(void *ptr, const char *file, int line, const char *expr) +{ + if (!ptr) { + fatal("Memory allocation failure %s line %d: %s.\n", + file, line, expr); + } + return ptr; +} -#include "mod32.c" -#include "mod64.c" +#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr) static void print_usage(const char *progname) { @@ -98,185 +104,122 @@ exit(1); } -static int ends_in(const char *name, const char *ext) +static int fgetc_wrapped(FILE *file) { - unsigned int namelen, extlen, i; - - /* Grab lengths */ - namelen = strlen(name); - extlen = strlen(ext); - - if (namelen < extlen) return 0; - - /* Look backwards */ - for (i = 0; i < extlen; i++) - if (name[namelen - i] != ext[extlen - i]) return 0; - - return 1; + for (;;) { + int ch = fgetc(file); + if (ch != '\\') + return ch; + ch = fgetc(file); + if (ch != '\n') + return ch; + } } -/* FIXME: Loop detect. */ -static struct alias *find_alias(const char *name, struct alias *aliases) -{ - struct alias *i; - - for (i = aliases; i; i = i->next) - if (fnmatch(i->name, name, 0) == 0) { - /* Chase down alias to aliases */ - while (i->alias) - i = i->alias; - return i; +static char *getline_wrapped(FILE *file) +{ + int size = 1024; + int i = 0; + char *buf = NOFAIL(malloc(size)); + for(;;) { + int ch = fgetc_wrapped(file); + if (i == size) { + size *= 2; + buf = NOFAIL(realloc(buf, size)); } - - return NULL; + if (ch < 0 || ch == '\n') { + if (ch < 0 && i == 0) { + free(buf); + return NULL; + } + buf[i] = '\0'; + return NOFAIL(realloc(buf, i+1)); + } + buf[i++] = ch; + } } -static struct alias *add_alias(struct alias *last, - const char *aliasname, - struct module *mod, - struct alias *alias, - int linenum) -{ - struct alias *newalias; - - newalias = malloc(sizeof *newalias + strlen(aliasname) + 1); - strcpy(newalias->name, aliasname); - newalias->config_line = linenum; - newalias->module = mod; - newalias->alias = alias; +struct module *modules; /* = NULL */ - newalias->next = last; - return newalias; -} - -static struct alias *add_aliases(int fd, - unsigned long shdroff, - unsigned int num_secs, - unsigned int secnamesec, - struct module *mod, - struct alias *last) +struct module *get_module(char *filename, int namelen) { - char *aliases; - unsigned long size, i; - - aliases = mops->load_section(fd, shdroff, num_secs, secnamesec, - ".modalias", &size); - if (aliases == (void *)-1) { - warn("Error loading aliases from module %s\n", mod->name); - return last; + struct module *mod; + for (mod = modules; mod; mod = mod->next) { + if (strlen(mod->filename) == namelen && + memcmp(mod->filename, filename, namelen) == 0) + return mod; } - if (aliases) { - for (i = 0; i < size; i += strlen(aliases+i)+1) - last = add_alias(last, aliases+i, mod, NULL, 0); - free(aliases); - } - return last; + /* No match. Make a new module. */ + mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1)); + memset(mod, 0, sizeof(struct module)); + memcpy(mod->filename, filename, namelen); + mod->filename[namelen] = '\0'; + mod->next = modules; + modules = mod; + return mod; } -static struct module *add_module(const char *dirname, const char *entry, - struct module *last, struct alias **aliases) +static void add_modules_dep_line(char *line, const char *start_name, + struct module **start) { - int fd; - struct module *new; - char pathname[strlen(dirname) + strlen(entry) + 1]; + struct module_list *dep; + char *dep_start; + struct module *mod, *dep_mod; + char *ptr; + int len; + char *modname; - new = malloc(sizeof(*new) + strlen(entry) + 1); - strcpy(new->name, entry); - /* Truncate extension */ - new->name[strlen(new->name) - strlen(MODULE_EXTENSION)] = '\0'; - new->order = 0; - new->next = last; + ptr = index(line, ':'); + if (ptr == NULL || line[0] == '#') + return; - sprintf(pathname, "%s%s", dirname, entry); - fd = open(pathname, O_RDONLY); - if (fd < 0) { - warn("Can't read module %s: %s\n", pathname, strerror(errno)); - free(new); - return last; - } + mod = get_module(line, ptr - line); - /* First call initializes this. */ - if (!mops) { - /* "\177ELF" where byte = 001 for 32-bit, 002 for 64 */ - char ident[EI_NIDENT]; + modname = rindex(mod->filename, '/') + 1; + len = strlen(modname) - sizeof(MODULE_EXTENSION) + 1; - if (read(fd, ident, EI_NIDENT) != EI_NIDENT) { - warn("Can't read module %s elf identifier: %s\n", - pathname, strerror(errno)); - free(new); - return last; - } - switch (ident[EI_CLASS]) { - case ELFCLASS32: - mops = &mod32_ops; - break; - case ELFCLASS64: - mops = &mod64_ops; + if (len == strlen(start_name) && !strncmp(modname, start_name, len)) + *start = mod; + + ptr++; + for(;;) { + ptr += strspn(ptr, " \t"); + if (*ptr == '\0') break; - default: - warn("Module %s has elf unknown identifier %i\n", - pathname, ident[EI_CLASS]); - free(new); - return last; - } - lseek(fd, 0, SEEK_SET); + dep_start = ptr; + ptr += strcspn(ptr, " \t"); + dep_mod = get_module(dep_start, ptr - dep_start); + fflush(stdout); + dep = NOFAIL(malloc(sizeof(*dep))); + dep->module = dep_mod; + dep->next = mod->dependencies; + mod->dependencies = dep; } - - return mops->add_module(fd, new, last, aliases); } -static struct module *load_all_modules(const char *dirname, - struct alias **aliases) +static void load_all_modules(const char *dirname, + const char *start_name, + struct module **start) { - struct module *mods = NULL; - struct dirent *dirent; - DIR *dir; + char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1]; + char *line; + FILE *modules_dep; - dir = opendir(dirname); - if (dir) { - while ((dirent = readdir(dir)) != NULL) { - /* Is it a .o file? */ - if (ends_in(dirent->d_name, MODULE_EXTENSION)) - mods = add_module(dirname, dirent->d_name, - mods, aliases); - } - closedir(dir); + *start = NULL; + sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep"); + modules_dep = fopen(modules_dep_name, "r"); + if (!modules_dep) { + perror(modules_dep_name); + exit(1); } - return mods; -} -static int need_symbol(unsigned int order, - const char *name, - struct module *modules, - const char *modname) -{ - struct module *m; - struct module *found = NULL; - - for (m = modules; m; m = m->next) { - unsigned int i; - for (i = 0; i < m->num_exports; i++) { - if (mops->export_name_cmp(m, i, name) == 0) { - if (found) { - warn("%s supplied by %s and %s:" - " picking neither\n", - name, m->name, found->name); - /* Noone chosen */ - return 0; - } - if (modname) - printf("%s needs %s: found in %s\n", - modname, name, m->name); - found = m; - /* If we didn't need to load it - already, we do now. */ - found->order = order; - } - } + while((line = getline_wrapped(modules_dep)) != NULL) { + add_modules_dep_line(line, start_name, start); + free(line); } - if (found) return 1; - else return 0; + + fclose(modules_dep); } /* We use error numbers in a loose translation... */ @@ -292,308 +235,150 @@ } } +static int +module_in_kernel(const char *modname) +{ + FILE *proc_modules; + char *line; + const int modname_len = strlen(modname); + + proc_modules = fopen("/proc/modules", "r"); + if (proc_modules == NULL) + fatal("Error reading /proc/modules: %s\n", strerror(errno)); + + while ((line = getline_wrapped(proc_modules)) != NULL) { + if (strncmp(line, modname, modname_len) == 0 && + isspace(line[modname_len])) { + free(line); + fclose(proc_modules); + return 1; + } + free(line); + } + fclose(proc_modules); + return 0; +} + /* Actually do the insert. */ -static void insmod(const char *dirname, - const char *filename, - const char *options, - int dont_fail) +static void insmod(struct module *mod, const char *options, int dont_fail, + struct module_list *caller) { int fd, ret; struct stat st; unsigned long len; void *map; - char modpath[strlen(dirname) + strlen(filename) - + sizeof(MODULE_EXTENSION)]; + struct module_list *dep; + unsigned int i; + char modname[strlen(strrchr(mod->filename, '/'))]; + struct module_list call_history, *modlist; + + if (mod->state == LOADED) + return; + + call_history.next = caller; + call_history.module = mod; + + if (mod->state == BEING_LOADED) { + fprintf (stderr, "FATAL: recursive dependency loop:\n"); + modlist = &call_history; + do { + fprintf(stderr, "\t%s\n", modlist->module->filename); + modlist = modlist->next; + } while (modlist != NULL); + exit(1); + } - /* FIXME: Look in module for name. --RR */ - sprintf(modpath, "%s%s%s", dirname, filename, MODULE_EXTENSION); + mod->state = BEING_LOADED; + + for(dep = mod->dependencies; dep != NULL; dep = dep->next) + insmod(dep->module, options, 0, &call_history); + + /* If we fail to load after this piont, we abort the whole program. */ + mod->state = LOADED; /* Now, it may already be loaded: check /proc/modules */ - fd = open("/proc/modules", O_RDONLY); - if (fd < 0) { - warn("Cannot open /proc/modules:" - " assuming no modules loaded.\n"); - } else { - char *buf; - unsigned int fill, size = 1024; - - buf = malloc(size+1); - buf[0] = '\n'; - fill = 1; - while ((ret = read(fd, buf+fill, size - fill)) > 0) { - size *= 2; - buf = realloc(buf, size+1); - fill += ret; - } - if (ret < 0) - fatal("Error reading /proc/modules: %s\n", - strerror(errno)); - else { - char *ptr; - unsigned int i; - char name_with_ret[strlen(strrchr(modpath, '/')) + 2]; - - buf[fill+1] = '\0'; - /* Must appear at start of line. */ - name_with_ret[0] = '\n'; - strcpy(name_with_ret + 1, strrchr(modpath, '/') + 1); + strcpy(modname, strrchr(mod->filename, '/') + 1); - /* Convert to underscores */ - for (i = 0; name_with_ret[i]; i++) - if (name_with_ret[i] == '-') - name_with_ret[i] = '_'; - - for (ptr = buf; - (ptr = strstr(ptr, name_with_ret)) != NULL; - ptr++) { - if (!isspace(ptr[strlen(name_with_ret)])) - continue; - /* Found: don't try to load again */ - if (dont_fail) - fatal("Module %s already loaded\n", - name_with_ret+1); - close(fd); - free(buf); - return; - } - } - close(fd); - free(buf); - } - close(fd); + /* Convert to underscores */ + for (i = 0; modname[i]; i++) + if (modname[i] == '-') + modname[i] = '_'; + + modname[strlen(modname) - sizeof(MODULE_EXTENSION) + 1] = '\0'; + if (module_in_kernel(modname)) + return; - fd = open(modpath, O_RDONLY); + fd = open(mod->filename, O_RDONLY); if (fd < 0) - fatal("Could not open `%s': %s\n", modpath, strerror(errno)); + fatal("Could not open `%s': %s\n", mod->filename, strerror(errno)); fstat(fd, &st); len = st.st_size; map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) - fatal("Can't map `%s': %s\n", modpath, strerror(errno)); + fatal("Can't map `%s': %s\n", mod->filename, strerror(errno)); - ret = syscall(__NR_init_module, filename, map, len, options); + ret = syscall(__NR_init_module, modname, map, len, options); if (ret != 0) { if (dont_fail) - fatal("Error inserting %s: %s\n", - modpath, moderror(errno)); + fatal("Error inserting %s (%s): %s\n", + modname, mod->filename, moderror(errno)); else - warn("Error inserting %s: %s\n", - modpath, moderror(errno)); + warn("Error inserting %s (%s): %s\n", + modname, mod->filename, moderror(errno)); } close(fd); } -/* Read one line into the buffer */ -static char *read_line(FILE *f) -{ - int size = 80; - char *result = malloc(size); - - result[0] = '\0'; - while (fgets(result + strlen(result), size - strlen(result), f)) { - char *nl = strchr(result, '\n'); - if (nl) { - *nl = '\0'; - return result; - } - size *= 2; - result = realloc(result, size); - } - if (strlen(result)) { - warn("Unexpected error reading config file: %s\n", - strerror(errno)); - return result; - } - free(result); - return NULL; -} - -static struct module *find_module(const char *name, struct module *modules) -{ - struct module *m; - - for (m = modules; m; m = m->next) - if (strcmp(name, m->name) == 0) - return m; - return NULL; -} - -static char *get_word(const char **line) +static char *strsep_skipspace(char **string, char *delim) { - size_t len; - char *word = NULL; - - *line += strspn(*line, "\t "); - len = strcspn(*line, "\t "); - if (**line) { - word = strdup(*line); - word[len] = '\0'; - } - *line += len; - - return word; -} - -/* alias newname oldname */ -static struct alias *parse_alias(struct alias *last, const char *line, - int linenum, - struct module *modules) -{ - char *newname, *oldname; - struct alias *aliasto; - struct module *moduleto = NULL; - - newname = get_word(&line); - if (!newname) { - warn("Config line %i missing first arg\n", linenum); - return last; - } - oldname = get_word(&line); - if (!oldname) { - warn("Config line %i missing second arg\n", linenum); - free(newname); - return last; - } - - aliasto = find_alias(oldname, last); - if (aliasto || (moduleto = find_module(oldname, modules))) - last = add_alias(last, newname, moduleto, aliasto, linenum); - else - warn("Config line %i aliases to unknown module %s\n", - linenum, oldname); - - free(oldname); - free(newname); - return last; -} - -static int keyword(const char *line, const char *keyword) -{ - size_t len = strcspn(line, "\t "); - - if (len == strlen(keyword) - && memcmp(line, keyword, len) == 0) - return 1; - return 0; + *string += strspn(*string, delim); + return strsep(string, delim); } /* Simple format, ignore lines starting with #, one command per line */ -static void load_config_file(const char *filename, int mustload, - struct module *modules, - struct alias **aliases) +static char *get_alias(const char *filename, int mustload, char *name) { FILE *cfile; char *line; - int linenum = 1; + char *result = NULL; cfile = fopen(filename, "r"); if (!cfile) { if (mustload) fatal("Failed to open config file %s: %s\n", filename, strerror(errno)); - return; - } - - while ((line = read_line(cfile)) != NULL) { - size_t len; - len = strspn(line, "\t "); - /* Comment or blank? */ - if (line[len] == '#' || line[len] == '\0') - goto next; - else if (keyword(line+len, "alias")) - *aliases = parse_alias(*aliases, line+len+strlen("alias"), - linenum, modules); - else - fatal("Unknown line %s in config file\n", line); - next: - free(line); - linenum++; + return NOFAIL(strdup(name)); } -} -static char *resolve_alias(const char *name, - struct module *modules, - struct alias *aliases) -{ - struct module *m; - struct alias *a; + while ((line = getline_wrapped(cfile)) != NULL) { + char *ptr = line; + char *cmd = strsep_skipspace(&ptr, "\t "); - a = find_alias(name, aliases); - if (a) - return a->module->name; + if (cmd == NULL) + continue; - m = find_module(name, modules); - if (m) - return m->name; + if (strcmp(cmd, "alias") == 0) { + char *fakename = strsep_skipspace(&ptr, "\t "); + char *realname = strsep_skipspace(&ptr, "\t "); - fatal("Could not find a module or alias named %s\n", - name); -} - -static void load_symbol(const char *dirname, - const char *symname, - struct module *modules, - const char *options, - int verbose) -{ - struct module *i; - - if (!need_symbol(1, symname, modules, verbose?"symbol request":NULL)) - fatal("Could not find module with symbol %s\n", symname); - - for (i = modules; i; i = i->next) { - if (i->order) { - if (verbose) printf("Loading %s\n", i->name); - insmod(dirname, i->name, options, 1); - } - } -} - -static void load(const char *dirname, const char *modname, - struct module *modules, - struct alias *aliases, - const char *options, - int verbose) -{ - unsigned int order; - struct module *i; - char *realname; - - realname = resolve_alias(modname, modules, aliases); - - order = 1; - if (mops->get_deps(order, dirname, realname, modules, verbose)) { - /* We need some other modules. */ - int more_needed; - - do { - more_needed = 0; - for (i = modules; i; i = i->next) { - if (i->order == order) { - if (mops->get_deps(order + 1, dirname, - i->name, - modules, verbose)) - more_needed = 1; - } - } - order++; - } while (more_needed); - } - - /* Now, walk back through orders, loading */ - for (; order > 0; order--) { - for (i = modules; i; i = i->next) { - if (i->order == order) { - if (verbose) printf("Loading %s\n", i->name); - insmod(dirname, i->name, "", 0); + if (fakename && realname && !strcmp(fakename, name)) { + result = NOFAIL(strdup(realname)); + free(line); + break; } } + else if (strcmp(cmd, "include") == 0) { + filename = strsep(&ptr, "\t "); + result = get_alias(filename, 0, name); + if (result) + break; + } + free(line); } - if (verbose) - printf("Loading %s%s%s\n", dirname, realname,MODULE_EXTENSION); - insmod(dirname, realname, options, 1); + fclose(cfile); + return result; } static struct option options[] = { { "verbose", 0, NULL, 'v' }, @@ -608,10 +393,10 @@ struct utsname buf; int opt; int verbose = 0; - struct alias *aliases = NULL; - struct module *modules; const char *config = NULL; - char *dirname, *optstring = strdup(""); + char *dirname, *optstring = NOFAIL(strdup("")); + char *modname; + struct module *start; try_old_version("modprobe", argv); @@ -651,22 +436,23 @@ } uname(&buf); - dirname = malloc(strlen(buf.release) + sizeof(MODULE_DIR)); - sprintf(dirname, MODULE_DIR, buf.release); + dirname = malloc(strlen(buf.release) + sizeof(MODULE_DIR) + 1); + sprintf(dirname, "%s/%s", MODULE_DIR, buf.release); - /* Suck up the modules */ - modules = load_all_modules(dirname, &aliases); + modname = get_alias(config ?: DEFAULT_CONFIG, config ? 1 : 0, + argv[optind]); - /* No config file specified? Don't worry if it doesn't exist. */ - load_config_file(config ?: DEFAULT_CONFIG, config ? 1 : 0, - modules, &aliases); - - /* Special case for "symbol:" */ - if (strncmp(argv[optind], "symbol:", strlen("symbol:")) == 0) - load_symbol(dirname, argv[optind] + strlen("symbol:"), - modules, optstring, verbose); - else - load(dirname, argv[optind], modules, aliases, optstring, - verbose); - exit(0); + if (modname == NULL) + modname = argv[optind]; + + load_all_modules(dirname, modname, &start); + if (start == NULL) { + fprintf (stderr, "Module %s not found.\n", modname); + exit(1); + } + + insmod(start, optstring, 1, NULL); + + /* free(modname); -- Comment out. We're just going to exit. */ + return 0; }