Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 204087 Details for
Bug 284957
sys-libs/klibc-1.5.15: savedconfig and extra functionality
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
dev-libs/klibc/files/oe/klibc-1.5.15/modprobe.patch
modprobe.patch (text/plain), 50.24 KB, created by
Christopher Friedt
on 2009-09-14 16:41:50 UTC
(
hide
)
Description:
dev-libs/klibc/files/oe/klibc-1.5.15/modprobe.patch
Filename:
MIME Type:
Creator:
Christopher Friedt
Created:
2009-09-14 16:41:50 UTC
Size:
50.24 KB
patch
obsolete
>Index: klibc-1.5/usr/utils/Kbuild >=================================================================== >--- klibc-1.5.15/usr/utils/Kbuild_orig 2009-09-05 17:35:26.000000000 -0400 >+++ klibc-1.5.15/usr/utils/Kbuild 2009-09-05 17:35:06.000000000 -0400 >@@ -4,7 +4,7 @@ > > progs := chroot dd mkdir mkfifo mknod mount pivot_root umount > progs += true false sleep ln nuke minips cat >-progs += uname halt kill readlink cpio sync dmesg losetup wc >+progs += uname halt kill readlink cpio sync dmesg losetup wc modprobe > > static-y := $(addprefix static/, $(progs)) > shared-y := $(addprefix shared/, $(progs)) >@@ -58,6 +58,8 @@ > shared/losetup-y := losetup.o > static/wc-y := wc.o > shared/wc-y := wc.o >+static/modprobe-y := modprobe.o >+shared/modprobe-y := modprobe.o > > # Additionally linked targets > always := static/reboot static/poweroff shared/reboot shared/poweroff > >Index: klibc-1.5/usr/utils/list.h >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ klibc-1.5/usr/utils/list.h 2008-03-07 22:33:22.287688586 +0100 >@@ -0,0 +1,238 @@ >+/* Stolen from Linux Kernel Source's list.h -- GPL. */ >+#ifndef _MODINITTOOLS_LIST_H >+#define _MODINITTOOLS_LIST_H >+ >+#undef offsetof >+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) >+ >+/** >+ * container_of - cast a member of a structure out to the containing structure >+ * >+ * @ptr: the pointer to the member. >+ * @type: the type of the container struct this is embedded in. >+ * @member: the name of the member within the struct. >+ * >+ */ >+#define container_of(ptr, type, member) ({ \ >+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ >+ (type *)( (char *)__mptr - offsetof(type,member) );}) >+ >+/* >+ * Simple doubly linked list implementation. >+ * >+ * Some of the internal functions ("__xxx") are useful when >+ * manipulating whole lists rather than single entries, as >+ * sometimes we already know the next/prev entries and we can >+ * generate better code by using them directly rather than >+ * using the generic single-entry routines. >+ */ >+ >+struct list_head { >+ struct list_head *next, *prev; >+}; >+ >+#define LIST_HEAD_INIT(name) { &(name), &(name) } >+ >+#define LIST_HEAD(name) \ >+ struct list_head name = LIST_HEAD_INIT(name) >+ >+#define INIT_LIST_HEAD(ptr) do { \ >+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ >+} while (0) >+ >+/* >+ * Insert a new entry between two known consecutive entries. >+ * >+ * This is only for internal list manipulation where we know >+ * the prev/next entries already! >+ */ >+static inline void __list_add(struct list_head *new, >+ struct list_head *prev, >+ struct list_head *next) >+{ >+ next->prev = new; >+ new->next = next; >+ new->prev = prev; >+ prev->next = new; >+} >+ >+/** >+ * list_add - add a new entry >+ * @new: new entry to be added >+ * @head: list head to add it after >+ * >+ * Insert a new entry after the specified head. >+ * This is good for implementing stacks. >+ */ >+static inline void list_add(struct list_head *new, struct list_head *head) >+{ >+ __list_add(new, head, head->next); >+} >+ >+/** >+ * list_add_tail - add a new entry >+ * @new: new entry to be added >+ * @head: list head to add it before >+ * >+ * Insert a new entry before the specified head. >+ * This is useful for implementing queues. >+ */ >+static inline void list_add_tail(struct list_head *new, struct list_head *head) >+{ >+ __list_add(new, head->prev, head); >+} >+ >+/* >+ * Delete a list entry by making the prev/next entries >+ * point to each other. >+ * >+ * This is only for internal list manipulation where we know >+ * the prev/next entries already! >+ */ >+static inline void __list_del(struct list_head * prev, struct list_head * next) >+{ >+ next->prev = prev; >+ prev->next = next; >+} >+ >+/** >+ * list_del - deletes entry from list. >+ * @entry: the element to delete from the list. >+ * Note: list_empty on entry does not return true after this, the entry is >+ * in an undefined state. >+ */ >+static inline void list_del(struct list_head *entry) >+{ >+ __list_del(entry->prev, entry->next); >+} >+ >+/** >+ * list_del_init - deletes entry from list and reinitialize it. >+ * @entry: the element to delete from the list. >+ */ >+static inline void list_del_init(struct list_head *entry) >+{ >+ __list_del(entry->prev, entry->next); >+ INIT_LIST_HEAD(entry); >+} >+ >+/** >+ * list_move - delete from one list and add as another's head >+ * @list: the entry to move >+ * @head: the head that will precede our entry >+ */ >+static inline void list_move(struct list_head *list, struct list_head *head) >+{ >+ __list_del(list->prev, list->next); >+ list_add(list, head); >+} >+ >+/** >+ * list_move_tail - delete from one list and add as another's tail >+ * @list: the entry to move >+ * @head: the head that will follow our entry >+ */ >+static inline void list_move_tail(struct list_head *list, >+ struct list_head *head) >+{ >+ __list_del(list->prev, list->next); >+ list_add_tail(list, head); >+} >+ >+/** >+ * list_empty - tests whether a list is empty >+ * @head: the list to test. >+ */ >+static inline int list_empty(struct list_head *head) >+{ >+ return head->next == head; >+} >+ >+static inline void __list_splice(struct list_head *list, >+ struct list_head *head) >+{ >+ struct list_head *first = list->next; >+ struct list_head *last = list->prev; >+ struct list_head *at = head->next; >+ >+ first->prev = head; >+ head->next = first; >+ >+ last->next = at; >+ at->prev = last; >+} >+ >+/** >+ * list_splice - join two lists >+ * @list: the new list to add. >+ * @head: the place to add it in the first list. >+ */ >+static inline void list_splice(struct list_head *list, struct list_head *head) >+{ >+ if (!list_empty(list)) >+ __list_splice(list, head); >+} >+ >+/** >+ * list_splice_init - join two lists and reinitialise the emptied list. >+ * @list: the new list to add. >+ * @head: the place to add it in the first list. >+ * >+ * The list at @list is reinitialised >+ */ >+static inline void list_splice_init(struct list_head *list, >+ struct list_head *head) >+{ >+ if (!list_empty(list)) { >+ __list_splice(list, head); >+ INIT_LIST_HEAD(list); >+ } >+} >+ >+/** >+ * list_entry - get the struct for this entry >+ * @ptr: the &struct list_head pointer. >+ * @type: the type of the struct this is embedded in. >+ * @member: the name of the list_struct within the struct. >+ */ >+#define list_entry(ptr, type, member) \ >+ container_of(ptr, type, member) >+ >+/** >+ * list_for_each - iterate over a list >+ * @pos: the &struct list_head to use as a loop counter. >+ * @head: the head for your list. >+ */ >+#define list_for_each(pos, head) \ >+ for (pos = (head)->next; pos != (head); pos = pos->next) >+ >+/** >+ * list_for_each_prev - iterate over a list backwards >+ * @pos: the &struct list_head to use as a loop counter. >+ * @head: the head for your list. >+ */ >+#define list_for_each_prev(pos, head) \ >+ for (pos = (head)->prev; pos != (head); pos = pos->prev) >+ >+/** >+ * list_for_each_safe - iterate over a list safe against removal of list entry >+ * @pos: the &struct list_head to use as a loop counter. >+ * @n: another &struct list_head to use as temporary storage >+ * @head: the head for your list. >+ */ >+#define list_for_each_safe(pos, n, head) \ >+ for (pos = (head)->next, n = pos->next; pos != (head); \ >+ pos = n, n = pos->next) >+ >+/** >+ * list_for_each_entry - iterate over list of given type >+ * @pos: the type * to use as a loop counter. >+ * @head: the head for your list. >+ * @member: the name of the list_struct within the struct. >+ */ >+#define list_for_each_entry(pos, head, member) \ >+ for (pos = list_entry((head)->next, typeof(*pos), member); \ >+ &pos->member != (head); \ >+ pos = list_entry(pos->member.next, typeof(*pos), member)) >+ >+#endif >Index: klibc-1.5/usr/utils/modprobe.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ klibc-1.5/usr/utils/modprobe.c 2008-03-08 03:05:51.847688952 +0100 >@@ -0,0 +1,1710 @@ >+/* modprobe.c: insert a module into the kernel, intelligently. >+ Copyright (C) 2001 Rusty Russell. >+ Copyright (C) 2002, 2003 Rusty Russell, IBM Corporation. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+*/ >+#define _GNU_SOURCE /* asprintf */ >+ >+#include <sys/utsname.h> >+#include <sys/types.h> >+#include <sys/stat.h> >+#include <sys/mman.h> >+#include <fcntl.h> >+#include <stdarg.h> >+#include <stdio.h> >+#include <stdlib.h> >+#include <ctype.h> >+#include <string.h> >+#include <errno.h> >+#include <unistd.h> >+#include <dirent.h> >+#include <limits.h> >+#include <elf.h> >+#include <getopt.h> >+#include <fnmatch.h> >+#include <asm/unistd.h> >+#include <sys/wait.h> >+#include <syslog.h> >+#include <zlib.h> >+ >+#define streq(a,b) (strcmp((a),(b)) == 0) >+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) >+ >+#include "list.h" >+static inline void try_old_version(const char *progname, char *argv[]) >+{ >+} >+extern long init_module(void *, unsigned long, const char *); >+extern long delete_module(const char *, unsigned int); >+ >+struct module { >+ struct list_head list; >+ char *modname; >+ char filename[0]; >+}; >+ >+#ifndef MODULE_DIR >+#define MODULE_DIR "/lib/modules" >+#endif >+ >+typedef void (*errfn_t)(const char *fmt, ...); >+ >+/* Do we use syslog or stderr for messages? */ >+static int log; >+ >+static void message(const char *prefix, const char *fmt, va_list *arglist) >+{ >+ char *buf, *buf2; >+ >+ vasprintf(&buf, fmt, *arglist); >+ asprintf(&buf2, "%s%s", prefix, buf); >+ >+ if (log) >+ syslog(LOG_NOTICE, "%s", buf2); >+ else >+ fprintf(stderr, "%s", buf2); >+ free(buf2); >+ free(buf); >+} >+void *grab_contents(gzFile *gzfd, unsigned long *size) >+{ >+ unsigned int max = 16384; >+ void *buffer = malloc(max); >+ int ret; >+ >+ if (!buffer) >+ return NULL; >+ >+ *size = 0; >+ while ((ret = gzread(gzfd, buffer + *size, max - *size)) > 0) { >+ *size += ret; >+ if (*size == max) { >+ buffer = realloc(buffer, max *= 2); >+ if (!buffer) >+ return NULL; >+ } >+ } >+ if (ret < 0) { >+ free(buffer); >+ buffer = NULL; >+ } >+ return buffer; >+} >+ >+void *grab_fd(int fd, unsigned long *size) >+{ >+ gzFile gzfd; >+ >+ gzfd = gzdopen(fd, "rb"); >+ if (!gzfd) >+ return NULL; >+ >+ /* gzclose(gzfd) would close fd, which would drop locks. >+ Don't blame zlib: POSIX locking semantics are so horribly >+ broken that they should be ripped out. */ >+ return grab_contents(gzfd, size); >+} >+void release_file(void *data, unsigned long size) >+{ >+ free(data); >+} >+ >+ >+static int warned = 0; >+static void warn(const char *fmt, ...) >+{ >+ va_list arglist; >+ warned++; >+ va_start(arglist, fmt); >+ message("WARNING: ", fmt, &arglist); >+ va_end(arglist); >+} >+ >+static void fatal(const char *fmt, ...) >+{ >+ va_list arglist; >+ va_start(arglist, fmt); >+ message("FATAL: ", fmt, &arglist); >+ va_end(arglist); >+ exit(1); >+} >+ >+ >+static void grammar(const char *cmd, const char *filename, unsigned int line) >+{ >+ warn("%s line %u: ignoring bad line starting with '%s'\n", >+ filename, line, cmd); >+} >+ >+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; >+} >+ >+#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr) >+ >+static void print_usage(const char *progname) >+{ >+ fprintf(stderr, >+ "Usage: %s [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b] [-o <modname>] <modname> [parameters...]\n" >+ "%s -r [-n] [-i] [-v] <modulename> ...\n" >+ "%s -l -t <dirname> [ -a <modulename> ...]\n", >+ progname, progname, progname); >+ exit(1); >+} >+ >+static int fgetc_wrapped(FILE *file, unsigned int *linenum) >+{ >+ for (;;) { >+ int ch = fgetc(file); >+ if (ch != '\\') >+ return ch; >+ ch = fgetc(file); >+ if (ch != '\n') >+ return ch; >+ if (linenum) >+ (*linenum)++; >+ } >+} >+ >+static char *getline_wrapped(FILE *file, unsigned int *linenum) >+{ >+ int size = 1024; >+ int i = 0; >+ char *buf = NOFAIL(malloc(size)); >+ for(;;) { >+ int ch = fgetc_wrapped(file, linenum); >+ if (i == size) { >+ size *= 2; >+ buf = NOFAIL(realloc(buf, size)); >+ } >+ if (ch < 0 && i == 0) { >+ free(buf); >+ return NULL; >+ } >+ if (ch < 0 || ch == '\n') { >+ if (linenum) >+ (*linenum)++; >+ buf[i] = '\0'; >+ return NOFAIL(realloc(buf, i+1)); >+ } >+ buf[i++] = ch; >+ } >+} >+ >+static struct module *find_module(const char *filename, struct list_head *list) >+{ >+ struct module *i; >+ >+ list_for_each_entry(i, list, list) { >+ if (strcmp(i->filename, filename) == 0) >+ return i; >+ } >+ return NULL; >+} >+ >+/* Convert filename to the module name. Works if filename == modname, too. */ >+static void filename2modname(char *modname, const char *filename) >+{ >+ const char *afterslash; >+ unsigned int i; >+ >+ afterslash = strrchr(filename, '/'); >+ if (!afterslash) >+ afterslash = filename; >+ else >+ afterslash++; >+ >+ /* Convert to underscores, stop at first . */ >+ for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) { >+ if (afterslash[i] == '-') >+ modname[i] = '_'; >+ else >+ modname[i] = afterslash[i]; >+ } >+ modname[i] = '\0'; >+} >+ >+static int lock_file(const char *filename) >+{ >+ int fd = open(filename, O_RDWR, 0); >+ >+ if (fd >= 0) { >+ struct flock lock; >+ lock.l_type = F_WRLCK; >+ lock.l_whence = SEEK_SET; >+ lock.l_start = 0; >+ lock.l_len = 1; >+ fcntl(fd, F_SETLKW, &lock); >+ } else >+ /* Read-only filesystem? There goes locking... */ >+ fd = open(filename, O_RDONLY, 0); >+ return fd; >+} >+ >+static void unlock_file(int fd) >+{ >+ /* Valgrind is picky... */ >+ close(fd); >+} >+ >+static void add_module(char *filename, int namelen, struct list_head *list) >+{ >+ struct module *mod; >+ >+ /* If it's a duplicate: move it to the end, so it gets >+ inserted where it is *first* required. */ >+ mod = find_module(filename, list); >+ if (mod) >+ list_del(&mod->list); >+ else { >+ /* No match. Create a new module. */ >+ mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1)); >+ memcpy(mod->filename, filename, namelen); >+ mod->filename[namelen] = '\0'; >+ mod->modname = NOFAIL(malloc(namelen + 1)); >+ filename2modname(mod->modname, mod->filename); >+ } >+ >+ list_add_tail(&mod->list, list); >+} >+ >+/* Compare len chars of a to b, with _ and - equivalent. */ >+static int modname_equal(const char *a, const char *b, unsigned int len) >+{ >+ unsigned int i; >+ >+ if (strlen(b) != len) >+ return 0; >+ >+ for (i = 0; i < len; i++) { >+ if ((a[i] == '_' || a[i] == '-') >+ && (b[i] == '_' || b[i] == '-')) >+ continue; >+ if (a[i] != b[i]) >+ return 0; >+ } >+ return 1; >+} >+ >+/* Fills in list of modules if this is the line we want. */ >+static int add_modules_dep_line(char *line, >+ const char *name, >+ struct list_head *list) >+{ >+ char *ptr; >+ int len; >+ char *modname; >+ >+ /* Ignore lines without : or which start with a # */ >+ ptr = strchr(line, ':'); >+ if (ptr == NULL || line[strspn(line, "\t ")] == '#') >+ return 0; >+ >+ /* Is this the module we are looking for? */ >+ *ptr = '\0'; >+ if (strrchr(line, '/')) >+ modname = strrchr(line, '/') + 1; >+ else >+ modname = line; >+ >+ len = strlen(modname); >+ if (strchr(modname, '.')) >+ len = strchr(modname, '.') - modname; >+ if (!modname_equal(modname, name, len)) >+ return 0; >+ >+ /* Create the list. */ >+ add_module(line, ptr - line, list); >+ >+ ptr++; >+ for(;;) { >+ char *dep_start; >+ ptr += strspn(ptr, " \t"); >+ if (*ptr == '\0') >+ break; >+ dep_start = ptr; >+ ptr += strcspn(ptr, " \t"); >+ add_module(dep_start, ptr - dep_start, list); >+ } >+ return 1; >+} >+ >+static void read_depends(const char *dirname, >+ const char *start_name, >+ struct list_head *list) >+{ >+ char *modules_dep_name; >+ char *line; >+ FILE *modules_dep; >+ int done = 0; >+ >+ asprintf(&modules_dep_name, "%s/%s", dirname, "modules.dep"); >+ modules_dep = fopen(modules_dep_name, "r"); >+ if (!modules_dep) >+ fatal("Could not load %s: %s\n", >+ modules_dep_name, strerror(errno)); >+ >+ /* Stop at first line, as we can have duplicates (eg. symlinks >+ from boot/ */ >+ while (!done && (line = getline_wrapped(modules_dep, NULL)) != NULL) { >+ done = add_modules_dep_line(line, start_name, list); >+ free(line); >+ } >+ fclose(modules_dep); >+ free(modules_dep_name); >+} >+ >+/* We use error numbers in a loose translation... */ >+static const char *insert_moderror(int err) >+{ >+ switch (err) { >+ case ENOEXEC: >+ return "Invalid module format"; >+ case ENOENT: >+ return "Unknown symbol in module, or unknown parameter (see dmesg)"; >+ case ENOSYS: >+ return "Kernel does not have module support"; >+ default: >+ return strerror(err); >+ } >+} >+ >+static const char *remove_moderror(int err) >+{ >+ switch (err) { >+ case ENOENT: >+ return "No such module"; >+ case ENOSYS: >+ return "Kernel does not have module unloading support"; >+ default: >+ return strerror(err); >+ } >+} >+ >+/* Is module in /proc/modules? If so, fill in usecount if not NULL. >+ 0 means no, 1 means yes, -1 means unknown. >+ */ >+static int module_in_kernel(const char *modname, unsigned int *usecount) >+{ >+ FILE *proc_modules; >+ char *line; >+ >+again: >+ /* Might not be mounted yet. Don't fail. */ >+ proc_modules = fopen("/proc/modules", "r"); >+ if (!proc_modules) >+ return -1; >+ >+ while ((line = getline_wrapped(proc_modules, NULL)) != NULL) { >+ char *entry = strtok(line, " \n"); >+ >+ if (entry && streq(entry, modname)) { >+ /* If it exists, usecount is the third entry. */ >+ if (!strtok(NULL, " \n")) >+ goto out; >+ >+ if (!(entry = strtok(NULL, " \n"))) /* usecount */ >+ goto out; >+ else >+ if (usecount) >+ *usecount = atoi(entry); >+ >+ /* Followed by - then status. */ >+ if (strtok(NULL, " \n") >+ && (entry = strtok(NULL, " \n")) != NULL) { >+ /* Locking will fail on ro fs, we might hit >+ * cases where module is in flux. Spin. */ >+ if (streq(entry, "Loading") >+ || streq(entry, "Unloading")) { >+ usleep(100000); >+ free(line); >+ fclose(proc_modules); >+ goto again; >+ } >+ } >+ >+ out: >+ free(line); >+ fclose(proc_modules); >+ return 1; >+ } >+ free(line); >+ } >+ fclose(proc_modules); >+ return 0; >+} >+ >+static void replace_modname(struct module *module, >+ void *mem, unsigned long len, >+ const char *oldname, const char *newname) >+{ >+ char *p; >+ >+ /* 64 - sizeof(unsigned long) - 1 */ >+ if (strlen(newname) > 55) >+ fatal("New name %s is too long\n", newname); >+ >+ /* Find where it is in the module structure. Don't assume layout! */ >+ for (p = mem; p < (char *)mem + len - strlen(oldname); p++) { >+ if (memcmp(p, oldname, strlen(oldname)) == 0) { >+ strcpy(p, newname); >+ return; >+ } >+ } >+ >+ warn("Could not find old name in %s to replace!\n", module->filename); >+} >+ >+static void *get_section32(void *file, >+ unsigned long size, >+ const char *name, >+ unsigned long *secsize) >+{ >+ Elf32_Ehdr *hdr = file; >+ Elf32_Shdr *sechdrs = file + hdr->e_shoff; >+ const char *secnames; >+ unsigned int i; >+ >+ /* Too short? */ >+ if (size < sizeof(*hdr)) >+ return NULL; >+ if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0])) >+ return NULL; >+ if (size < sechdrs[hdr->e_shstrndx].sh_offset) >+ return NULL; >+ >+ secnames = file + sechdrs[hdr->e_shstrndx].sh_offset; >+ for (i = 1; i < hdr->e_shnum; i++) >+ if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) { >+ *secsize = sechdrs[i].sh_size; >+ return file + sechdrs[i].sh_offset; >+ } >+ return NULL; >+} >+ >+static void *get_section64(void *file, >+ unsigned long size, >+ const char *name, >+ unsigned long *secsize) >+{ >+ Elf64_Ehdr *hdr = file; >+ Elf64_Shdr *sechdrs = file + hdr->e_shoff; >+ const char *secnames; >+ unsigned int i; >+ >+ /* Too short? */ >+ if (size < sizeof(*hdr)) >+ return NULL; >+ if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0])) >+ return NULL; >+ if (size < sechdrs[hdr->e_shstrndx].sh_offset) >+ return NULL; >+ >+ secnames = file + sechdrs[hdr->e_shstrndx].sh_offset; >+ for (i = 1; i < hdr->e_shnum; i++) >+ if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) { >+ *secsize = sechdrs[i].sh_size; >+ return file + sechdrs[i].sh_offset; >+ } >+ return NULL; >+} >+ >+static int elf_ident(void *mod, unsigned long size) >+{ >+ /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */ >+ char *ident = mod; >+ >+ if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0) >+ return ELFCLASSNONE; >+ return ident[EI_CLASS]; >+} >+ >+static void *get_section(void *file, >+ unsigned long size, >+ const char *name, >+ unsigned long *secsize) >+{ >+ switch (elf_ident(file, size)) { >+ case ELFCLASS32: >+ return get_section32(file, size, name, secsize); >+ case ELFCLASS64: >+ return get_section64(file, size, name, secsize); >+ default: >+ return NULL; >+ } >+} >+ >+static void rename_module(struct module *module, >+ void *mod, >+ unsigned long len, >+ const char *newname) >+{ >+ void *modstruct; >+ unsigned long modstruct_len; >+ >+ /* Old-style */ >+ modstruct = get_section(mod, len, ".gnu.linkonce.this_module", >+ &modstruct_len); >+ /* New-style */ >+ if (!modstruct) >+ modstruct = get_section(mod, len, "__module", &modstruct_len); >+ if (!modstruct) >+ warn("Could not find module name to change in %s\n", >+ module->filename); >+ else >+ replace_modname(module, modstruct, modstruct_len, >+ module->modname, newname); >+} >+ >+/* Kernel told to ignore these sections if SHF_ALLOC not set. */ >+static void invalidate_section32(void *mod, const char *secname) >+{ >+ Elf32_Ehdr *hdr = mod; >+ Elf32_Shdr *sechdrs = mod + hdr->e_shoff; >+ const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset; >+ unsigned int i; >+ >+ for (i = 1; i < hdr->e_shnum; i++) >+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) >+ sechdrs[i].sh_flags &= ~SHF_ALLOC; >+} >+ >+static void invalidate_section64(void *mod, const char *secname) >+{ >+ Elf64_Ehdr *hdr = mod; >+ Elf64_Shdr *sechdrs = mod + hdr->e_shoff; >+ const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset; >+ unsigned int i; >+ >+ for (i = 1; i < hdr->e_shnum; i++) >+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) >+ sechdrs[i].sh_flags &= ~(unsigned long long)SHF_ALLOC; >+} >+ >+static void strip_section(struct module *module, >+ void *mod, >+ unsigned long len, >+ const char *secname) >+{ >+ switch (elf_ident(mod, len)) { >+ case ELFCLASS32: >+ invalidate_section32(mod, secname); >+ break; >+ case ELFCLASS64: >+ invalidate_section64(mod, secname); >+ break; >+ default: >+ warn("Unknown module format in %s: not forcing version\n", >+ module->filename); >+ } >+} >+ >+static const char *next_string(const char *string, unsigned long *secsize) >+{ >+ /* Skip non-zero chars */ >+ while (string[0]) { >+ string++; >+ if ((*secsize)-- <= 1) >+ return NULL; >+ } >+ >+ /* Skip any zero padding. */ >+ while (!string[0]) { >+ string++; >+ if ((*secsize)-- <= 1) >+ return NULL; >+ } >+ return string; >+} >+ >+static void clear_magic(struct module *module, void *mod, unsigned long len) >+{ >+ const char *p; >+ unsigned long modlen; >+ >+ /* Old-style: __vermagic section */ >+ strip_section(module, mod, len, "__vermagic"); >+ >+ /* New-style: in .modinfo section */ >+ for (p = get_section(mod, len, ".modinfo", &modlen); >+ p; >+ p = next_string(p, &modlen)) { >+ if (strncmp(p, "vermagic=", strlen("vermagic=")) == 0) { >+ memset((char *)p, 0, strlen(p)); >+ return; >+ } >+ } >+} >+ >+struct module_options >+{ >+ struct module_options *next; >+ char *modulename; >+ char *options; >+}; >+ >+struct module_command >+{ >+ struct module_command *next; >+ char *modulename; >+ char *command; >+}; >+ >+struct module_alias >+{ >+ struct module_alias *next; >+ char *module; >+}; >+ >+struct module_blacklist >+{ >+ struct module_blacklist *next; >+ char *modulename; >+}; >+ >+/* Link in a new option line from the config file. */ >+static struct module_options * >+add_options(const char *modname, >+ const char *option, >+ struct module_options *options) >+{ >+ struct module_options *new; >+ char *tab; >+ >+ new = NOFAIL(malloc(sizeof(*new))); >+ new->modulename = NOFAIL(strdup(modname)); >+ new->options = NOFAIL(strdup(option)); >+ /* We can handle tabs, kernel can't. */ >+ for (tab = strchr(new->options, '\t'); tab; tab = strchr(tab, '\t')) >+ *tab = ' '; >+ new->next = options; >+ return new; >+} >+ >+/* Link in a new install line from the config file. */ >+static struct module_command * >+add_command(const char *modname, >+ const char *command, >+ struct module_command *commands) >+{ >+ struct module_command *new; >+ >+ new = NOFAIL(malloc(sizeof(*new))); >+ new->modulename = NOFAIL(strdup(modname)); >+ new->command = NOFAIL(strdup(command)); >+ new->next = commands; >+ return new; >+} >+ >+/* Link in a new alias line from the config file. */ >+static struct module_alias * >+add_alias(const char *modname, struct module_alias *aliases) >+{ >+ struct module_alias *new; >+ >+ new = NOFAIL(malloc(sizeof(*new))); >+ new->module = NOFAIL(strdup(modname)); >+ new->next = aliases; >+ return new; >+} >+ >+/* Link in a new blacklist line from the config file. */ >+static struct module_blacklist * >+add_blacklist(const char *modname, struct module_blacklist *blacklist) >+{ >+ struct module_blacklist *new; >+ >+ new = NOFAIL(malloc(sizeof(*new))); >+ new->modulename = NOFAIL(strdup(modname)); >+ new->next = blacklist; >+ return new; >+} >+ >+/* Find blacklist commands if any. */ >+static int >+find_blacklist(const char *modname, const struct module_blacklist *blacklist) >+{ >+ while (blacklist) { >+ if (strcmp(blacklist->modulename, modname) == 0) >+ return 1; >+ blacklist = blacklist->next; >+ } >+ return 0; >+} >+ >+/* return a new alias list, with backlisted elems filtered out */ >+static struct module_alias * >+apply_blacklist(const struct module_alias *aliases, >+ const struct module_blacklist *blacklist) >+{ >+ struct module_alias *result = NULL; >+ while (aliases) { >+ char *modname = aliases->module; >+ if (!find_blacklist(modname, blacklist)) >+ result = add_alias(modname, result); >+ aliases = aliases->next; >+ } >+ return result; >+} >+ >+/* Find install commands if any. */ >+static const char *find_command(const char *modname, >+ const struct module_command *commands) >+{ >+ while (commands) { >+ if (fnmatch(commands->modulename, modname, 0) == 0) >+ return commands->command; >+ commands = commands->next; >+ } >+ return NULL; >+} >+ >+static char *append_option(char *options, const char *newoption) >+{ >+ options = NOFAIL(realloc(options, strlen(options) + 1 >+ + strlen(newoption) + 1)); >+ if (strlen(options)) strcat(options, " "); >+ strcat(options, newoption); >+ return options; >+} >+ >+/* Add to options */ >+static char *add_extra_options(const char *modname, >+ char *optstring, >+ const struct module_options *options) >+{ >+ while (options) { >+ if (strcmp(options->modulename, modname) == 0) >+ optstring = append_option(optstring, options->options); >+ options = options->next; >+ } >+ return optstring; >+} >+ >+/* If we don't flush, then child processes print before we do */ >+static void verbose_printf(int verbose, const char *fmt, ...) >+{ >+ va_list arglist; >+ >+ if (verbose) { >+ va_start(arglist, fmt); >+ vprintf(fmt, arglist); >+ fflush(stdout); >+ va_end(arglist); >+ } >+} >+ >+/* Do an install/remove command: replace $CMDLINE_OPTS if it's specified. */ >+static void do_command(const char *modname, >+ const char *command, >+ int verbose, int dry_run, >+ errfn_t error, >+ const char *type, >+ const char *cmdline_opts) >+{ >+ int ret; >+ char *p, *replaced_cmd = NOFAIL(strdup(command)); >+ >+ while ((p = strstr(replaced_cmd, "$CMDLINE_OPTS")) != NULL) { >+ char *new; >+ asprintf(&new, "%.*s%s%s", >+ p - replaced_cmd, replaced_cmd, cmdline_opts, >+ p + strlen("$CMDLINE_OPTS")); >+ NOFAIL(new); >+ free(replaced_cmd); >+ replaced_cmd = new; >+ } >+ >+ verbose_printf(verbose, "%s %s\n", type, replaced_cmd); >+ if (dry_run) >+ return; >+ >+ setenv("MODPROBE_MODULE", modname, 1); >+ ret = system(replaced_cmd); >+ if (ret == -1 || WEXITSTATUS(ret)) >+ error("Error running %s command for %s\n", type, modname); >+ free(replaced_cmd); >+} >+ >+/* Actually do the insert. Frees second arg. */ >+static void insmod(struct list_head *list, >+ char *optstring, >+ const char *newname, >+ int first_time, >+ errfn_t error, >+ int dry_run, >+ int verbose, >+ const struct module_options *options, >+ const struct module_command *commands, >+ int ignore_commands, >+ int ignore_proc, >+ int strip_vermagic, >+ int strip_modversion, >+ const char *cmdline_opts) >+{ >+ int ret, fd; >+ unsigned long len; >+ void *map; >+ const char *command; >+ struct module *mod = list_entry(list->next, struct module, list); >+ >+ /* Take us off the list. */ >+ list_del(&mod->list); >+ >+ /* Do things we (or parent) depend on first, but don't die if >+ * they fail. */ >+ if (!list_empty(list)) { >+ insmod(list, NOFAIL(strdup("")), NULL, 0, warn, >+ dry_run, verbose, options, commands, 0, ignore_proc, >+ strip_vermagic, strip_modversion, cmdline_opts); >+ } >+ >+ /* Lock before we look, in case it's initializing. */ >+ fd = lock_file(mod->filename); >+ if (fd < 0) { >+ error("Could not open '%s': %s\n", >+ mod->filename, strerror(errno)); >+ goto out_optstring; >+ } >+ >+ /* Don't do ANYTHING if already in kernel. */ >+ if (!ignore_proc >+ && module_in_kernel(newname ?: mod->modname, NULL) == 1) { >+ if (first_time) >+ error("Module %s already in kernel.\n", >+ newname ?: mod->modname); >+ goto out_unlock; >+ } >+ >+ command = find_command(mod->modname, commands); >+ if (command && !ignore_commands) { >+ /* It might recurse: unlock. */ >+ unlock_file(fd); >+ do_command(mod->modname, command, verbose, dry_run, error, >+ "install", cmdline_opts); >+ goto out_optstring; >+ } >+ >+ map = grab_fd(fd, &len); >+ if (!map) { >+ error("Could not read '%s': %s\n", >+ mod->filename, strerror(errno)); >+ goto out_unlock; >+ } >+ >+ /* Rename it? */ >+ if (newname) >+ rename_module(mod, map, len, newname); >+ >+ if (strip_modversion) >+ strip_section(mod, map, len, "__versions"); >+ if (strip_vermagic) >+ clear_magic(mod, map, len); >+ >+ /* Config file might have given more options */ >+ optstring = add_extra_options(mod->modname, optstring, options); >+ >+ verbose_printf(verbose, "insmod %s %s\n", mod->filename, optstring); >+ >+ if (dry_run) >+ goto out; >+ >+ ret = init_module(map, len, optstring); >+ if (ret != 0) { >+ if (errno == EEXIST) { >+ if (first_time) >+ error("Module %s already in kernel.\n", >+ newname ?: mod->modname); >+ goto out_unlock; >+ } >+ error("Error inserting %s (%s): %s\n", >+ mod->modname, mod->filename, insert_moderror(errno)); >+ } >+ out: >+ release_file(map, len); >+ out_unlock: >+ unlock_file(fd); >+ out_optstring: >+ free(optstring); >+ return; >+} >+ >+/* Do recursive removal. */ >+static void rmmod(struct list_head *list, >+ const char *name, >+ int first_time, >+ errfn_t error, >+ int dry_run, >+ int verbose, >+ struct module_command *commands, >+ int ignore_commands, >+ int ignore_inuse, >+ const char *cmdline_opts) >+{ >+ const char *command; >+ unsigned int usecount = 0; >+ int lock; >+ struct module *mod = list_entry(list->next, struct module, list); >+ >+ /* Take first one off the list. */ >+ list_del(&mod->list); >+ >+ /* Ignore failure; it's best effort here. */ >+ lock = lock_file(mod->filename); >+ >+ if (!name) >+ name = mod->modname; >+ >+ /* Even if renamed, find commands to orig. name. */ >+ command = find_command(mod->modname, commands); >+ if (command && !ignore_commands) { >+ /* It might recurse: unlock. */ >+ unlock_file(lock); >+ do_command(mod->modname, command, verbose, dry_run, error, >+ "remove", cmdline_opts); >+ goto remove_rest_no_unlock; >+ } >+ >+ if (module_in_kernel(name, &usecount) == 0) >+ goto nonexistent_module; >+ >+ if (usecount != 0) { >+ if (!ignore_inuse) >+ error("Module %s is in use.\n", name); >+ goto remove_rest; >+ } >+ >+ verbose_printf(verbose, "rmmod %s\n", mod->filename); >+ >+ if (dry_run) >+ goto remove_rest; >+ >+ if (delete_module(name, O_EXCL) != 0) { >+ if (errno == ENOENT) >+ goto nonexistent_module; >+ error("Error removing %s (%s): %s\n", >+ name, mod->filename, >+ remove_moderror(errno)); >+ } >+ >+ remove_rest: >+ unlock_file(lock); >+ remove_rest_no_unlock: >+ /* Now do things we depend. */ >+ if (!list_empty(list)) >+ rmmod(list, NULL, 0, warn, dry_run, verbose, commands, >+ 0, 1, cmdline_opts); >+ return; >+ >+nonexistent_module: >+ if (first_time) >+ fatal("Module %s is not in kernel.\n", mod->modname); >+ goto remove_rest; >+} >+ >+/* Does path contain directory(s) subpath? */ >+static int type_matches(const char *path, const char *subpath) >+{ >+ char *subpath_with_slashes; >+ int ret; >+ >+ asprintf(&subpath_with_slashes, "/%s/", subpath); >+ NOFAIL(subpath_with_slashes); >+ >+ ret = (strstr(path, subpath_with_slashes) != NULL); >+ free(subpath_with_slashes); >+ return ret; >+} >+ >+static char *underscores(char *string) >+{ >+ if (string) { >+ unsigned int i; >+ for (i = 0; string[i]; i++) >+ if (string[i] == '-') >+ string[i] = '_'; >+ } >+ return string; >+} >+ >+static int do_wildcard(const char *dirname, >+ const char *type, >+ const char *wildcard) >+{ >+ char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1]; >+ char *line, *wcard; >+ FILE *modules_dep; >+ >+ /* Canonicalize wildcard */ >+ wcard = strdup(wildcard); >+ underscores(wcard); >+ >+ sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep"); >+ modules_dep = fopen(modules_dep_name, "r"); >+ if (!modules_dep) >+ fatal("Could not load %s: %s\n", >+ modules_dep_name, strerror(errno)); >+ >+ while ((line = getline_wrapped(modules_dep, NULL)) != NULL) { >+ char *ptr; >+ >+ /* Ignore lines without : or which start with a # */ >+ ptr = strchr(line, ':'); >+ if (ptr == NULL || line[strspn(line, "\t ")] == '#') >+ goto next; >+ *ptr = '\0'; >+ >+ /* "type" must match complete directory component(s). */ >+ if (!type || type_matches(line, type)) { >+ char modname[strlen(line)+1]; >+ >+ filename2modname(modname, line); >+ if (fnmatch(wcard, modname, 0) == 0) >+ printf("%s\n", line); >+ } >+ next: >+ free(line); >+ } >+ >+ free(wcard); >+ return 0; >+} >+ >+static char *strsep_skipspace(char **string, char *delim) >+{ >+ if (!*string) >+ return NULL; >+ *string += strspn(*string, delim); >+ return strsep(string, delim); >+} >+ >+/* Recursion */ >+static int read_config(const char *filename, >+ const char *name, >+ int dump_only, >+ int removing, >+ struct module_options **options, >+ struct module_command **commands, >+ struct module_alias **alias, >+ struct module_blacklist **blacklist); >+ >+/* FIXME: Maybe should be extended to "alias a b [and|or c]...". --RR */ >+static int read_config_file(const char *filename, >+ const char *name, >+ int dump_only, >+ int removing, >+ struct module_options **options, >+ struct module_command **commands, >+ struct module_alias **aliases, >+ struct module_blacklist **blacklist) >+{ >+ char *line; >+ unsigned int linenum = 0; >+ FILE *cfile; >+ >+ cfile = fopen(filename, "r"); >+ if (!cfile) >+ return 0; >+ >+ while ((line = getline_wrapped(cfile, &linenum)) != NULL) { >+ char *ptr = line; >+ char *cmd, *modname; >+ >+ if (dump_only) >+ printf("%s\n", line); >+ >+ cmd = strsep_skipspace(&ptr, "\t "); >+ if (cmd == NULL || cmd[0] == '#' || cmd[0] == '\0') >+ continue; >+ >+ if (strcmp(cmd, "alias") == 0) { >+ char *wildcard >+ = underscores(strsep_skipspace(&ptr, "\t ")); >+ char *realname >+ = underscores(strsep_skipspace(&ptr, "\t ")); >+ >+ if (!wildcard || !realname) >+ grammar(cmd, filename, linenum); >+ else if (fnmatch(wildcard,name,0) == 0) >+ *aliases = add_alias(realname, *aliases); >+ } else if (strcmp(cmd, "include") == 0) { >+ struct module_alias *newalias = NULL; >+ char *newfilename; >+ >+ newfilename = strsep_skipspace(&ptr, "\t "); >+ if (!newfilename) >+ grammar(cmd, filename, linenum); >+ else { >+ if (!read_config(newfilename, name, >+ dump_only, removing, >+ options, commands, &newalias, >+ blacklist)) >+ warn("Failed to open included" >+ " config file %s: %s\n", >+ newfilename, strerror(errno)); >+ >+ /* Files included override aliases, >+ etc that was already set ... */ >+ if (newalias) >+ *aliases = newalias; >+ } >+ } else if (strcmp(cmd, "options") == 0) { >+ modname = strsep_skipspace(&ptr, "\t "); >+ if (!modname || !ptr) >+ grammar(cmd, filename, linenum); >+ else { >+ ptr += strspn(ptr, "\t "); >+ *options = add_options(underscores(modname), >+ ptr, *options); >+ } >+ } else if (strcmp(cmd, "install") == 0) { >+ modname = strsep_skipspace(&ptr, "\t "); >+ if (!modname || !ptr) >+ grammar(cmd, filename, linenum); >+ else if (!removing) { >+ ptr += strspn(ptr, "\t "); >+ *commands = add_command(underscores(modname), >+ ptr, *commands); >+ } >+ } else if (strcmp(cmd, "blacklist") == 0) { >+ modname = strsep_skipspace(&ptr, "\t "); >+ if (!modname) >+ grammar(cmd, filename, linenum); >+ else if (!removing) { >+ *blacklist = add_blacklist(underscores(modname), >+ *blacklist); >+ } >+ } else if (strcmp(cmd, "remove") == 0) { >+ modname = strsep_skipspace(&ptr, "\t "); >+ if (!modname || !ptr) >+ grammar(cmd, filename, linenum); >+ else if (removing) { >+ ptr += strspn(ptr, "\t "); >+ *commands = add_command(underscores(modname), >+ ptr, *commands); >+ } >+ } else >+ grammar(cmd, filename, linenum); >+ >+ free(line); >+ } >+ fclose(cfile); >+ return 1; >+} >+ >+/* Simple format, ignore lines starting with #, one command per line. >+ Returns true or false. */ >+static int read_config(const char *filename, >+ const char *name, >+ int dump_only, >+ int removing, >+ struct module_options **options, >+ struct module_command **commands, >+ struct module_alias **aliases, >+ struct module_blacklist **blacklist) >+{ >+ DIR *dir; >+ int ret = 0; >+ >+ /* ignore everything in this directory */ >+ if (streq(filename, "/etc/modprobe.d/arch")) >+ return 1; >+ >+ /* Reiser4 has file/directory duality: treat it as both. */ >+ dir = opendir(filename); >+ if (dir) { >+ struct dirent *i; >+ while ((i = readdir(dir)) != NULL) { >+ if (!streq(i->d_name,".") && !streq(i->d_name,"..")) { >+ char sub[strlen(filename) + 1 >+ + strlen(i->d_name) + 1]; >+ >+ sprintf(sub, "%s/%s", filename, i->d_name); >+ if (!read_config(sub, name, >+ dump_only, removing, options, >+ commands, aliases, blacklist)) >+ warn("Failed to open" >+ " config file %s: %s\n", >+ sub, strerror(errno)); >+ } >+ } >+ closedir(dir); >+ ret = 1; >+ } >+ >+ if (read_config_file(filename, name, dump_only, removing, >+ options, commands, aliases, blacklist)) >+ ret = 1; >+ >+ return ret; >+} >+ >+static const char *default_configs[] = >+{ >+ "/etc/modprobe.conf", >+ "/etc/modprobe.d", >+}; >+ >+static void read_toplevel_config(const char *filename, >+ const char *name, >+ int dump_only, >+ int removing, >+ struct module_options **options, >+ struct module_command **commands, >+ struct module_alias **aliases, >+ struct module_blacklist **blacklist) >+{ >+ unsigned int i; >+ >+ if (filename) { >+ if (!read_config(filename, name, dump_only, removing, >+ options, commands, aliases, blacklist)) >+ fatal("Failed to open config file %s: %s\n", >+ filename, strerror(errno)); >+ return; >+ } >+ >+ /* Try defaults. */ >+ for (i = 0; i < ARRAY_SIZE(default_configs); i++) { >+ if (read_config(default_configs[i], name, dump_only, removing, >+ options, commands, aliases, blacklist)) >+ return; >+ } >+} >+ >+static void add_to_env_var(const char *option) >+{ >+ const char *oldenv; >+ >+ if ((oldenv = getenv("MODPROBE_OPTIONS")) != NULL) { >+ char *newenv; >+ asprintf(&newenv, "%s %s", oldenv, option); >+ setenv("MODPROBE_OPTIONS", newenv, 1); >+ } else >+ setenv("MODPROBE_OPTIONS", option, 1); >+} >+ >+/* Prepend options from environment. */ >+static char **merge_args(char *args, char *argv[], int *argc) >+{ >+ char *arg, *argstring; >+ char **newargs = NULL; >+ unsigned int i, num_env = 0; >+ >+ if (!args) >+ return argv; >+ >+ argstring = NOFAIL(strdup(args)); >+ for (arg = strtok(argstring, " "); arg; arg = strtok(NULL, " ")) { >+ num_env++; >+ newargs = NOFAIL(realloc(newargs, >+ sizeof(newargs[0]) >+ * (num_env + *argc + 1))); >+ newargs[num_env] = arg; >+ } >+ >+ /* Append commandline args */ >+ newargs[0] = argv[0]; >+ for (i = 1; i <= *argc; i++) >+ newargs[num_env+i] = argv[i]; >+ >+ *argc += num_env; >+ return newargs; >+} >+ >+static char *gather_options(char *argv[]) >+{ >+ char *optstring = NOFAIL(strdup("")); >+ >+ /* Rest is module options */ >+ while (*argv) { >+ /* Quote value if it contains spaces. */ >+ unsigned int eq = strcspn(*argv, "="); >+ >+ if (strchr(*argv+eq, ' ') && !strchr(*argv, '"')) { >+ char quoted[strlen(*argv) + 3]; >+ (*argv)[eq] = '\0'; >+ sprintf(quoted, "%s=\"%s\"", *argv, *argv+eq+1); >+ optstring = append_option(optstring, quoted); >+ } else >+ optstring = append_option(optstring, *argv); >+ argv++; >+ } >+ return optstring; >+} >+ >+static void handle_module(const char *modname, >+ struct list_head *todo_list, >+ const char *newname, >+ int remove, >+ char *options, >+ int first_time, >+ errfn_t error, >+ int dry_run, >+ int verbose, >+ struct module_options *modoptions, >+ struct module_command *commands, >+ int ignore_commands, >+ int ignore_proc, >+ int strip_vermagic, >+ int strip_modversion, >+ int unknown_silent, >+ const char *cmdline_opts) >+{ >+ if (list_empty(todo_list)) { >+ const char *command; >+ >+ /* The dependencies have to be real modules, but >+ handle case where the first is completely bogus. */ >+ command = find_command(modname, commands); >+ if (command && !ignore_commands) { >+ do_command(modname, command, verbose, dry_run, error, >+ remove ? "remove":"install", cmdline_opts); >+ return; >+ } >+ >+ if (unknown_silent) >+ exit(1); >+ error("Module %s not found.\n", modname); >+ return; >+ } >+ >+ if (remove) >+ rmmod(todo_list, newname, first_time, error, dry_run, verbose, >+ commands, ignore_commands, 0, cmdline_opts); >+ else >+ insmod(todo_list, NOFAIL(strdup(options)), newname, >+ first_time, error, dry_run, verbose, modoptions, >+ commands, ignore_commands, ignore_proc, strip_vermagic, >+ strip_modversion, cmdline_opts); >+} >+ >+static struct option options[] = { { "verbose", 0, NULL, 'v' }, >+ { "version", 0, NULL, 'V' }, >+ { "config", 1, NULL, 'C' }, >+ { "name", 1, NULL, 'o' }, >+ { "remove", 0, NULL, 'r' }, >+ { "showconfig", 0, NULL, 'c' }, >+ { "autoclean", 0, NULL, 'k' }, >+ { "quiet", 0, NULL, 'q' }, >+ { "show", 0, NULL, 'n' }, >+ { "dry-run", 0, NULL, 'n' }, >+ { "syslog", 0, NULL, 's' }, >+ { "type", 1, NULL, 't' }, >+ { "list", 0, NULL, 'l' }, >+ { "all", 0, NULL, 'a' }, >+ { "ignore-install", 0, NULL, 'i' }, >+ { "ignore-remove", 0, NULL, 'i' }, >+ { "force", 0, NULL, 'f' }, >+ { "force-vermagic", 0, NULL, 1 }, >+ { "force-modversion", 0, NULL, 2 }, >+ { "set-version", 1, NULL, 'S' }, >+ { "show-depends", 0, NULL, 'D' }, >+ { "first-time", 0, NULL, 3 }, >+ { "use-blacklist", 0, NULL, 'b' }, >+ { NULL, 0, NULL, 0 } }; >+ >+#define MODPROBE_DEVFSD_CONF "/etc/modprobe.devfs" >+ >+/* This is a horrible hack to allow devfsd, which calls modprobe with >+ -C /etc/modules.conf or /etc/modules.devfs, to work. FIXME. */ >+/* Modern devfsd or variants should use -q explicitly in 2.6. */ >+static int is_devfs_call(char *argv[]) >+{ >+ unsigned int i; >+ >+ /* Look for "/dev" arg */ >+ for (i = 1; argv[i]; i++) { >+ if (strncmp(argv[i], "/dev/", 5) == 0) >+ return 1; >+ } >+ return 0; >+} >+ >+int main(int argc, char *argv[]) >+{ >+ struct utsname buf; >+ struct stat statbuf; >+ int opt; >+ int dump_only = 0; >+ int dry_run = 0; >+ int remove = 0; >+ int verbose = 0; >+ int unknown_silent = 0; >+ int list_only = 0; >+ int all = 0; >+ int ignore_commands = 0; >+ int strip_vermagic = 0; >+ int strip_modversion = 0; >+ int ignore_proc = 0; >+ int first_time = 0; >+ int use_blacklist = 0; >+ unsigned int i, num_modules; >+ char *type = NULL; >+ const char *config = NULL; >+ char *dirname, *optstring; >+ char *newname = NULL; >+ char *aliasfilename, *symfilename; >+ errfn_t error = fatal; >+ >+ /* Prepend options from environment. */ >+ argv = merge_args(getenv("MODPROBE_OPTIONS"), argv, &argc); >+ >+ /* --set-version overrides version, and disables backwards compat. */ >+ for (opt = 1; opt < argc; opt++) >+ if (strncmp(argv[opt],"--set-version",strlen("--set-version")) >+ == 0) >+ break; >+ >+ if (opt == argc) >+ try_old_version("modprobe", argv); >+ >+ uname(&buf); >+ while ((opt = getopt_long(argc, argv, "vVC:o:rknqQsclt:aifb", options, NULL)) != -1){ >+ switch (opt) { >+ case 'v': >+ add_to_env_var("-v"); >+ verbose = 1; >+ break; >+ case 'V': >+ puts("module-init-tools version 3.2.2"); >+ exit(0); >+ case 'S': >+ strncpy(buf.release, optarg, sizeof(buf.release)); >+ buf.release[sizeof(buf.release)-1] = '\0'; >+ break; >+ case 'C': >+ if (is_devfs_call(argv)) { >+ if (streq("/etc/modules.devfs", optarg)) { >+ config = MODPROBE_DEVFSD_CONF; >+ add_to_env_var("-C"); >+ add_to_env_var(config); >+ /* Fall thru to -q */ >+ } else if (streq("/etc/modules.conf", optarg)) >+ /* Ignore config, fall thru to -q */ >+ ; >+ else { >+ /* False alarm. Treat as normal. */ >+ config = optarg; >+ add_to_env_var("-C"); >+ add_to_env_var(config); >+ break; >+ } >+ } else { >+ config = optarg; >+ add_to_env_var("-C"); >+ add_to_env_var(config); >+ break; >+ } >+ case 'q': >+ unknown_silent = 1; >+ add_to_env_var("-q"); >+ break; >+ case 'D': >+ dry_run = 1; >+ ignore_proc = 1; >+ verbose = 1; >+ add_to_env_var("-D"); >+ break; >+ case 'o': >+ newname = optarg; >+ break; >+ case 'r': >+ remove = 1; >+ break; >+ case 'c': >+ dump_only = 1; >+ break; >+ case 't': >+ type = optarg; >+ break; >+ case 'l': >+ list_only = 1; >+ break; >+ case 'a': >+ all = 1; >+ error = warn; >+ break; >+ case 'k': >+ /* FIXME: This should actually do something */ >+ break; >+ case 'n': >+ dry_run = 1; >+ break; >+ case 's': >+ add_to_env_var("-s"); >+ log = 1; >+ break; >+ case 'i': >+ ignore_commands = 1; >+ break; >+ case 'f': >+ strip_vermagic = 1; >+ strip_modversion = 1; >+ break; >+ case 'b': >+ use_blacklist = 1; >+ break; >+ case 1: >+ strip_vermagic = 1; >+ break; >+ case 2: >+ strip_modversion = 1; >+ break; >+ case 3: >+ first_time = 1; >+ break; >+ default: >+ print_usage(argv[0]); >+ } >+ } >+ >+ /* If stderr not open, go to syslog */ >+ if (log || fstat(STDERR_FILENO, &statbuf) != 0) { >+ openlog("modprobe", LOG_CONS, LOG_DAEMON); >+ log = 1; >+ } >+ >+ if (argc < optind + 1 && !dump_only && !list_only && !remove) >+ print_usage(argv[0]); >+ >+ dirname = NOFAIL(malloc(strlen(buf.release) + sizeof(MODULE_DIR) + 1)); >+ sprintf(dirname, "%s/%s", MODULE_DIR, buf.release); >+ aliasfilename = NOFAIL(malloc(strlen(dirname) >+ + sizeof("/modules.alias"))); >+ sprintf(aliasfilename, "%s/modules.alias", dirname); >+ symfilename = NOFAIL(malloc(strlen(dirname) >+ + sizeof("/modules.symbols"))); >+ sprintf(symfilename, "%s/modules.symbols", dirname); >+ >+ /* Old-style -t xxx wildcard? Only with -l. */ >+ if (list_only) { >+ if (optind+1 < argc) >+ fatal("Can't have multiple wildcards\n"); >+ /* fprintf(stderr, "man find\n"); return 1; */ >+ return do_wildcard(dirname, type, argv[optind]?:"*"); >+ } >+ if (type) >+ fatal("-t only supported with -l"); >+ >+ if (dump_only) { >+ struct module_command *commands = NULL; >+ struct module_options *modoptions = NULL; >+ struct module_alias *aliases = NULL; >+ struct module_blacklist *blacklist = NULL; >+ >+ read_toplevel_config(config, "", 1, 0, >+ &modoptions, &commands, &aliases, &blacklist); >+ read_config(aliasfilename, "", 1, 0,&modoptions, &commands, >+ &aliases, &blacklist); >+ read_config(symfilename, "", 1, 0, &modoptions, &commands, >+ &aliases, &blacklist); >+ exit(0); >+ } >+ >+ if (remove || all) { >+ num_modules = argc - optind; >+ optstring = NOFAIL(strdup("")); >+ } else { >+ num_modules = 1; >+ optstring = gather_options(argv+optind+1); >+ } >+ >+ /* num_modules is always 1 except for -r or -a. */ >+ for (i = 0; i < num_modules; i++) { >+ struct module_command *commands = NULL; >+ struct module_options *modoptions = NULL; >+ struct module_alias *aliases = NULL; >+ struct module_blacklist *blacklist = NULL; >+ LIST_HEAD(list); >+ char *modulearg = argv[optind + i]; >+ >+ /* Convert name we are looking for */ >+ underscores(modulearg); >+ >+ /* Returns the resolved alias, options */ >+ read_toplevel_config(config, modulearg, 0, >+ remove, &modoptions, &commands, &aliases, &blacklist); >+ >+ /* No luck? Try symbol names, if starts with symbol:. */ >+ if (!aliases >+ && strncmp(modulearg, "symbol:", strlen("symbol:")) == 0) >+ read_config(symfilename, modulearg, 0, >+ remove, &modoptions, &commands, >+ &aliases, &blacklist); >+ >+ if (!aliases) { >+ /* We only use canned aliases as last resort. */ >+ read_depends(dirname, modulearg, &list); >+ >+ if (list_empty(&list) >+ && !find_command(modulearg, commands)) >+ { >+ read_config(aliasfilename, modulearg, 0, >+ remove, &modoptions, &commands, >+ &aliases, &blacklist); >+ aliases = apply_blacklist(aliases, blacklist); >+ } >+ } >+ >+ if (aliases) { >+ errfn_t err = error; >+ >+ /* More than one alias? Don't bail out on failure. */ >+ if (aliases->next) >+ err = warn; >+ while (aliases) { >+ /* Add the options for this alias. */ >+ char *opts = NOFAIL(strdup(optstring)); >+ opts = add_extra_options(modulearg, >+ opts, modoptions); >+ >+ read_depends(dirname, aliases->module, &list); >+ handle_module(aliases->module, &list, newname, >+ remove, opts, first_time, err, >+ dry_run, verbose, modoptions, >+ commands, ignore_commands, >+ ignore_proc, strip_vermagic, >+ strip_modversion, >+ unknown_silent, >+ optstring); >+ >+ aliases = aliases->next; >+ INIT_LIST_HEAD(&list); >+ } >+ } else { >+ if (use_blacklist >+ && find_blacklist(modulearg, blacklist)) >+ continue; >+ >+ handle_module(modulearg, &list, newname, remove, >+ optstring, first_time, error, dry_run, >+ verbose, modoptions, commands, >+ ignore_commands, ignore_proc, >+ strip_vermagic, strip_modversion, >+ unknown_silent, optstring); >+ } >+ } >+ if (log) >+ closelog(); >+ >+ return 0; >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 284957
:
204076
|
204078
|
204079
|
204080
|
204084
|
204086
|
204087
|
204089
|
204130
|
204289
|
204291