summaryrefslogtreecommitdiffstats
path: root/meta-initramfs/recipes-devtools/klibc/klibc-2.0/modprobe.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-initramfs/recipes-devtools/klibc/klibc-2.0/modprobe.patch')
-rw-r--r--meta-initramfs/recipes-devtools/klibc/klibc-2.0/modprobe.patch1984
1 files changed, 1984 insertions, 0 deletions
diff --git a/meta-initramfs/recipes-devtools/klibc/klibc-2.0/modprobe.patch b/meta-initramfs/recipes-devtools/klibc/klibc-2.0/modprobe.patch
new file mode 100644
index 000000000..eb2fb39e6
--- /dev/null
+++ b/meta-initramfs/recipes-devtools/klibc/klibc-2.0/modprobe.patch
@@ -0,0 +1,1984 @@
1Patch was imported from the OpenEmbedded git server
2(git://git.openembedded.org/openembedded)
3as of commit id 70ae69edb02e0174db0841ae501299159c888514
4Signed-off-by: Thomas Kunze <thommycheck@gmx.de>
5Minor adjustments tracking upstream changes
6Signed-off-by: Andrea Adami <andrea.adami@gmail.com>
7
8diff --git a/usr/utils/Kbuild b/usr/utils/Kbuild
9--- a/usr/utils/Kbuild
10+++ b/usr/utils/Kbuild
11@@ -4,7 +4,7 @@
12
13 progs := chroot dd mkdir mkfifo mknod mount pivot_root umount
14 progs += true false sleep ln mv nuke minips cat ls losetup
15-progs += uname halt kill readlink cpio sync dmesg
16+progs += uname halt kill readlink cpio sync dmesg modprobe
17
18 static-y := $(addprefix static/, $(progs))
19 shared-y := $(addprefix shared/, $(progs))
20@@ -58,6 +58,8 @@ static/sync-y := sync.o
21 shared/sync-y := sync.o
22 static/losetup-y := losetup.o
23 shared/losetup-y := losetup.o
24+static/modprobe-y := modprobe.o
25+shared/modprobe-y := modprobe.o
26
27 # Additionally linked targets
28 always := static/reboot static/poweroff shared/reboot shared/poweroff
29diff --git a/usr/utils/list.h b/usr/utils/list.h
30--- /dev/null
31+++ b/usr/utils/list.h
32@@ -0,0 +1,238 @@
33+/* Stolen from Linux Kernel Source's list.h -- GPL. */
34+#ifndef _MODINITTOOLS_LIST_H
35+#define _MODINITTOOLS_LIST_H
36+
37+#undef offsetof
38+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
39+
40+/**
41+ * container_of - cast a member of a structure out to the containing structure
42+ *
43+ * @ptr: the pointer to the member.
44+ * @type: the type of the container struct this is embedded in.
45+ * @member: the name of the member within the struct.
46+ *
47+ */
48+#define container_of(ptr, type, member) ({ \
49+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
50+ (type *)( (char *)__mptr - offsetof(type,member) );})
51+
52+/*
53+ * Simple doubly linked list implementation.
54+ *
55+ * Some of the internal functions ("__xxx") are useful when
56+ * manipulating whole lists rather than single entries, as
57+ * sometimes we already know the next/prev entries and we can
58+ * generate better code by using them directly rather than
59+ * using the generic single-entry routines.
60+ */
61+
62+struct list_head {
63+ struct list_head *next, *prev;
64+};
65+
66+#define LIST_HEAD_INIT(name) { &(name), &(name) }
67+
68+#define LIST_HEAD(name) \
69+ struct list_head name = LIST_HEAD_INIT(name)
70+
71+#define INIT_LIST_HEAD(ptr) do { \
72+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
73+} while (0)
74+
75+/*
76+ * Insert a new entry between two known consecutive entries.
77+ *
78+ * This is only for internal list manipulation where we know
79+ * the prev/next entries already!
80+ */
81+static inline void __list_add(struct list_head *new,
82+ struct list_head *prev,
83+ struct list_head *next)
84+{
85+ next->prev = new;
86+ new->next = next;
87+ new->prev = prev;
88+ prev->next = new;
89+}
90+
91+/**
92+ * list_add - add a new entry
93+ * @new: new entry to be added
94+ * @head: list head to add it after
95+ *
96+ * Insert a new entry after the specified head.
97+ * This is good for implementing stacks.
98+ */
99+static inline void list_add(struct list_head *new, struct list_head *head)
100+{
101+ __list_add(new, head, head->next);
102+}
103+
104+/**
105+ * list_add_tail - add a new entry
106+ * @new: new entry to be added
107+ * @head: list head to add it before
108+ *
109+ * Insert a new entry before the specified head.
110+ * This is useful for implementing queues.
111+ */
112+static inline void list_add_tail(struct list_head *new, struct list_head *head)
113+{
114+ __list_add(new, head->prev, head);
115+}
116+
117+/*
118+ * Delete a list entry by making the prev/next entries
119+ * point to each other.
120+ *
121+ * This is only for internal list manipulation where we know
122+ * the prev/next entries already!
123+ */
124+static inline void __list_del(struct list_head * prev, struct list_head * next)
125+{
126+ next->prev = prev;
127+ prev->next = next;
128+}
129+
130+/**
131+ * list_del - deletes entry from list.
132+ * @entry: the element to delete from the list.
133+ * Note: list_empty on entry does not return true after this, the entry is
134+ * in an undefined state.
135+ */
136+static inline void list_del(struct list_head *entry)
137+{
138+ __list_del(entry->prev, entry->next);
139+}
140+
141+/**
142+ * list_del_init - deletes entry from list and reinitialize it.
143+ * @entry: the element to delete from the list.
144+ */
145+static inline void list_del_init(struct list_head *entry)
146+{
147+ __list_del(entry->prev, entry->next);
148+ INIT_LIST_HEAD(entry);
149+}
150+
151+/**
152+ * list_move - delete from one list and add as another's head
153+ * @list: the entry to move
154+ * @head: the head that will precede our entry
155+ */
156+static inline void list_move(struct list_head *list, struct list_head *head)
157+{
158+ __list_del(list->prev, list->next);
159+ list_add(list, head);
160+}
161+
162+/**
163+ * list_move_tail - delete from one list and add as another's tail
164+ * @list: the entry to move
165+ * @head: the head that will follow our entry
166+ */
167+static inline void list_move_tail(struct list_head *list,
168+ struct list_head *head)
169+{
170+ __list_del(list->prev, list->next);
171+ list_add_tail(list, head);
172+}
173+
174+/**
175+ * list_empty - tests whether a list is empty
176+ * @head: the list to test.
177+ */
178+static inline int list_empty(struct list_head *head)
179+{
180+ return head->next == head;
181+}
182+
183+static inline void __list_splice(struct list_head *list,
184+ struct list_head *head)
185+{
186+ struct list_head *first = list->next;
187+ struct list_head *last = list->prev;
188+ struct list_head *at = head->next;
189+
190+ first->prev = head;
191+ head->next = first;
192+
193+ last->next = at;
194+ at->prev = last;
195+}
196+
197+/**
198+ * list_splice - join two lists
199+ * @list: the new list to add.
200+ * @head: the place to add it in the first list.
201+ */
202+static inline void list_splice(struct list_head *list, struct list_head *head)
203+{
204+ if (!list_empty(list))
205+ __list_splice(list, head);
206+}
207+
208+/**
209+ * list_splice_init - join two lists and reinitialise the emptied list.
210+ * @list: the new list to add.
211+ * @head: the place to add it in the first list.
212+ *
213+ * The list at @list is reinitialised
214+ */
215+static inline void list_splice_init(struct list_head *list,
216+ struct list_head *head)
217+{
218+ if (!list_empty(list)) {
219+ __list_splice(list, head);
220+ INIT_LIST_HEAD(list);
221+ }
222+}
223+
224+/**
225+ * list_entry - get the struct for this entry
226+ * @ptr: the &struct list_head pointer.
227+ * @type: the type of the struct this is embedded in.
228+ * @member: the name of the list_struct within the struct.
229+ */
230+#define list_entry(ptr, type, member) \
231+ container_of(ptr, type, member)
232+
233+/**
234+ * list_for_each - iterate over a list
235+ * @pos: the &struct list_head to use as a loop counter.
236+ * @head: the head for your list.
237+ */
238+#define list_for_each(pos, head) \
239+ for (pos = (head)->next; pos != (head); pos = pos->next)
240+
241+/**
242+ * list_for_each_prev - iterate over a list backwards
243+ * @pos: the &struct list_head to use as a loop counter.
244+ * @head: the head for your list.
245+ */
246+#define list_for_each_prev(pos, head) \
247+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
248+
249+/**
250+ * list_for_each_safe - iterate over a list safe against removal of list entry
251+ * @pos: the &struct list_head to use as a loop counter.
252+ * @n: another &struct list_head to use as temporary storage
253+ * @head: the head for your list.
254+ */
255+#define list_for_each_safe(pos, n, head) \
256+ for (pos = (head)->next, n = pos->next; pos != (head); \
257+ pos = n, n = pos->next)
258+
259+/**
260+ * list_for_each_entry - iterate over list of given type
261+ * @pos: the type * to use as a loop counter.
262+ * @head: the head for your list.
263+ * @member: the name of the list_struct within the struct.
264+ */
265+#define list_for_each_entry(pos, head, member) \
266+ for (pos = list_entry((head)->next, typeof(*pos), member); \
267+ &pos->member != (head); \
268+ pos = list_entry(pos->member.next, typeof(*pos), member))
269+
270+#endif
271diff --git a/usr/utils/modprobe.c b/usr/utils/modprobe.c
272--- /dev/null
273+++ b/usr/utils/modprobe.c
274@@ -0,0 +1,1710 @@
275+/* modprobe.c: insert a module into the kernel, intelligently.
276+ Copyright (C) 2001 Rusty Russell.
277+ Copyright (C) 2002, 2003 Rusty Russell, IBM Corporation.
278+
279+ This program is free software; you can redistribute it and/or modify
280+ it under the terms of the GNU General Public License as published by
281+ the Free Software Foundation; either version 2 of the License, or
282+ (at your option) any later version.
283+
284+ This program is distributed in the hope that it will be useful,
285+ but WITHOUT ANY WARRANTY; without even the implied warranty of
286+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287+ GNU General Public License for more details.
288+
289+ You should have received a copy of the GNU General Public License
290+ along with this program; if not, write to the Free Software
291+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
292+*/
293+#define _GNU_SOURCE /* asprintf */
294+
295+#include <sys/utsname.h>
296+#include <sys/types.h>
297+#include <sys/stat.h>
298+#include <sys/mman.h>
299+#include <fcntl.h>
300+#include <stdarg.h>
301+#include <stdio.h>
302+#include <stdlib.h>
303+#include <ctype.h>
304+#include <string.h>
305+#include <errno.h>
306+#include <unistd.h>
307+#include <dirent.h>
308+#include <limits.h>
309+#include <elf.h>
310+#include <getopt.h>
311+#include <fnmatch.h>
312+#include <asm/unistd.h>
313+#include <sys/wait.h>
314+#include <syslog.h>
315+#include <zlib.h>
316+
317+#define streq(a,b) (strcmp((a),(b)) == 0)
318+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
319+
320+#include "list.h"
321+static inline void try_old_version(const char *progname, char *argv[])
322+{
323+}
324+extern long init_module(void *, unsigned long, const char *);
325+extern long delete_module(const char *, unsigned int);
326+
327+struct module {
328+ struct list_head list;
329+ char *modname;
330+ char filename[0];
331+};
332+
333+#ifndef MODULE_DIR
334+#define MODULE_DIR "/lib/modules"
335+#endif
336+
337+typedef void (*errfn_t)(const char *fmt, ...);
338+
339+/* Do we use syslog or stderr for messages? */
340+static int log;
341+
342+static void message(const char *prefix, const char *fmt, va_list *arglist)
343+{
344+ char *buf, *buf2;
345+
346+ vasprintf(&buf, fmt, *arglist);
347+ asprintf(&buf2, "%s%s", prefix, buf);
348+
349+ if (log)
350+ syslog(LOG_NOTICE, "%s", buf2);
351+ else
352+ fprintf(stderr, "%s", buf2);
353+ free(buf2);
354+ free(buf);
355+}
356+void *grab_contents(gzFile *gzfd, unsigned long *size)
357+{
358+ unsigned int max = 16384;
359+ void *buffer = malloc(max);
360+ int ret;
361+
362+ if (!buffer)
363+ return NULL;
364+
365+ *size = 0;
366+ while ((ret = gzread(gzfd, buffer + *size, max - *size)) > 0) {
367+ *size += ret;
368+ if (*size == max) {
369+ buffer = realloc(buffer, max *= 2);
370+ if (!buffer)
371+ return NULL;
372+ }
373+ }
374+ if (ret < 0) {
375+ free(buffer);
376+ buffer = NULL;
377+ }
378+ return buffer;
379+}
380+
381+void *grab_fd(int fd, unsigned long *size)
382+{
383+ gzFile gzfd;
384+
385+ gzfd = gzdopen(fd, "rb");
386+ if (!gzfd)
387+ return NULL;
388+
389+ /* gzclose(gzfd) would close fd, which would drop locks.
390+ Don't blame zlib: POSIX locking semantics are so horribly
391+ broken that they should be ripped out. */
392+ return grab_contents(gzfd, size);
393+}
394+void release_file(void *data, unsigned long size)
395+{
396+ free(data);
397+}
398+
399+
400+static int warned = 0;
401+static void warn(const char *fmt, ...)
402+{
403+ va_list arglist;
404+ warned++;
405+ va_start(arglist, fmt);
406+ message("WARNING: ", fmt, &arglist);
407+ va_end(arglist);
408+}
409+
410+static void fatal(const char *fmt, ...)
411+{
412+ va_list arglist;
413+ va_start(arglist, fmt);
414+ message("FATAL: ", fmt, &arglist);
415+ va_end(arglist);
416+ exit(1);
417+}
418+
419+
420+static void grammar(const char *cmd, const char *filename, unsigned int line)
421+{
422+ warn("%s line %u: ignoring bad line starting with '%s'\n",
423+ filename, line, cmd);
424+}
425+
426+static void *do_nofail(void *ptr, const char *file, int line, const char *expr)
427+{
428+ if (!ptr) {
429+ fatal("Memory allocation failure %s line %d: %s.\n",
430+ file, line, expr);
431+ }
432+ return ptr;
433+}
434+
435+#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
436+
437+static void print_usage(const char *progname)
438+{
439+ fprintf(stderr,
440+ "Usage: %s [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b] [-o <modname>] <modname> [parameters...]\n"
441+ "%s -r [-n] [-i] [-v] <modulename> ...\n"
442+ "%s -l -t <dirname> [ -a <modulename> ...]\n",
443+ progname, progname, progname);
444+ exit(1);
445+}
446+
447+static int fgetc_wrapped(FILE *file, unsigned int *linenum)
448+{
449+ for (;;) {
450+ int ch = fgetc(file);
451+ if (ch != '\\')
452+ return ch;
453+ ch = fgetc(file);
454+ if (ch != '\n')
455+ return ch;
456+ if (linenum)
457+ (*linenum)++;
458+ }
459+}
460+
461+static char *getline_wrapped(FILE *file, unsigned int *linenum)
462+{
463+ int size = 1024;
464+ int i = 0;
465+ char *buf = NOFAIL(malloc(size));
466+ for(;;) {
467+ int ch = fgetc_wrapped(file, linenum);
468+ if (i == size) {
469+ size *= 2;
470+ buf = NOFAIL(realloc(buf, size));
471+ }
472+ if (ch < 0 && i == 0) {
473+ free(buf);
474+ return NULL;
475+ }
476+ if (ch < 0 || ch == '\n') {
477+ if (linenum)
478+ (*linenum)++;
479+ buf[i] = '\0';
480+ return NOFAIL(realloc(buf, i+1));
481+ }
482+ buf[i++] = ch;
483+ }
484+}
485+
486+static struct module *find_module(const char *filename, struct list_head *list)
487+{
488+ struct module *i;
489+
490+ list_for_each_entry(i, list, list) {
491+ if (strcmp(i->filename, filename) == 0)
492+ return i;
493+ }
494+ return NULL;
495+}
496+
497+/* Convert filename to the module name. Works if filename == modname, too. */
498+static void filename2modname(char *modname, const char *filename)
499+{
500+ const char *afterslash;
501+ unsigned int i;
502+
503+ afterslash = strrchr(filename, '/');
504+ if (!afterslash)
505+ afterslash = filename;
506+ else
507+ afterslash++;
508+
509+ /* Convert to underscores, stop at first . */
510+ for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
511+ if (afterslash[i] == '-')
512+ modname[i] = '_';
513+ else
514+ modname[i] = afterslash[i];
515+ }
516+ modname[i] = '\0';
517+}
518+
519+static int lock_file(const char *filename)
520+{
521+ int fd = open(filename, O_RDWR, 0);
522+
523+ if (fd >= 0) {
524+ struct flock lock;
525+ lock.l_type = F_WRLCK;
526+ lock.l_whence = SEEK_SET;
527+ lock.l_start = 0;
528+ lock.l_len = 1;
529+ fcntl(fd, F_SETLKW, &lock);
530+ } else
531+ /* Read-only filesystem? There goes locking... */
532+ fd = open(filename, O_RDONLY, 0);
533+ return fd;
534+}
535+
536+static void unlock_file(int fd)
537+{
538+ /* Valgrind is picky... */
539+ close(fd);
540+}
541+
542+static void add_module(char *filename, int namelen, struct list_head *list)
543+{
544+ struct module *mod;
545+
546+ /* If it's a duplicate: move it to the end, so it gets
547+ inserted where it is *first* required. */
548+ mod = find_module(filename, list);
549+ if (mod)
550+ list_del(&mod->list);
551+ else {
552+ /* No match. Create a new module. */
553+ mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1));
554+ memcpy(mod->filename, filename, namelen);
555+ mod->filename[namelen] = '\0';
556+ mod->modname = NOFAIL(malloc(namelen + 1));
557+ filename2modname(mod->modname, mod->filename);
558+ }
559+
560+ list_add_tail(&mod->list, list);
561+}
562+
563+/* Compare len chars of a to b, with _ and - equivalent. */
564+static int modname_equal(const char *a, const char *b, unsigned int len)
565+{
566+ unsigned int i;
567+
568+ if (strlen(b) != len)
569+ return 0;
570+
571+ for (i = 0; i < len; i++) {
572+ if ((a[i] == '_' || a[i] == '-')
573+ && (b[i] == '_' || b[i] == '-'))
574+ continue;
575+ if (a[i] != b[i])
576+ return 0;
577+ }
578+ return 1;
579+}
580+
581+/* Fills in list of modules if this is the line we want. */
582+static int add_modules_dep_line(char *line,
583+ const char *name,
584+ struct list_head *list)
585+{
586+ char *ptr;
587+ int len;
588+ char *modname;
589+
590+ /* Ignore lines without : or which start with a # */
591+ ptr = strchr(line, ':');
592+ if (ptr == NULL || line[strspn(line, "\t ")] == '#')
593+ return 0;
594+
595+ /* Is this the module we are looking for? */
596+ *ptr = '\0';
597+ if (strrchr(line, '/'))
598+ modname = strrchr(line, '/') + 1;
599+ else
600+ modname = line;
601+
602+ len = strlen(modname);
603+ if (strchr(modname, '.'))
604+ len = strchr(modname, '.') - modname;
605+ if (!modname_equal(modname, name, len))
606+ return 0;
607+
608+ /* Create the list. */
609+ add_module(line, ptr - line, list);
610+
611+ ptr++;
612+ for(;;) {
613+ char *dep_start;
614+ ptr += strspn(ptr, " \t");
615+ if (*ptr == '\0')
616+ break;
617+ dep_start = ptr;
618+ ptr += strcspn(ptr, " \t");
619+ add_module(dep_start, ptr - dep_start, list);
620+ }
621+ return 1;
622+}
623+
624+static void read_depends(const char *dirname,
625+ const char *start_name,
626+ struct list_head *list)
627+{
628+ char *modules_dep_name;
629+ char *line;
630+ FILE *modules_dep;
631+ int done = 0;
632+
633+ asprintf(&modules_dep_name, "%s/%s", dirname, "modules.dep");
634+ modules_dep = fopen(modules_dep_name, "r");
635+ if (!modules_dep)
636+ fatal("Could not load %s: %s\n",
637+ modules_dep_name, strerror(errno));
638+
639+ /* Stop at first line, as we can have duplicates (eg. symlinks
640+ from boot/ */
641+ while (!done && (line = getline_wrapped(modules_dep, NULL)) != NULL) {
642+ done = add_modules_dep_line(line, start_name, list);
643+ free(line);
644+ }
645+ fclose(modules_dep);
646+ free(modules_dep_name);
647+}
648+
649+/* We use error numbers in a loose translation... */
650+static const char *insert_moderror(int err)
651+{
652+ switch (err) {
653+ case ENOEXEC:
654+ return "Invalid module format";
655+ case ENOENT:
656+ return "Unknown symbol in module, or unknown parameter (see dmesg)";
657+ case ENOSYS:
658+ return "Kernel does not have module support";
659+ default:
660+ return strerror(err);
661+ }
662+}
663+
664+static const char *remove_moderror(int err)
665+{
666+ switch (err) {
667+ case ENOENT:
668+ return "No such module";
669+ case ENOSYS:
670+ return "Kernel does not have module unloading support";
671+ default:
672+ return strerror(err);
673+ }
674+}
675+
676+/* Is module in /proc/modules? If so, fill in usecount if not NULL.
677+ 0 means no, 1 means yes, -1 means unknown.
678+ */
679+static int module_in_kernel(const char *modname, unsigned int *usecount)
680+{
681+ FILE *proc_modules;
682+ char *line;
683+
684+again:
685+ /* Might not be mounted yet. Don't fail. */
686+ proc_modules = fopen("/proc/modules", "r");
687+ if (!proc_modules)
688+ return -1;
689+
690+ while ((line = getline_wrapped(proc_modules, NULL)) != NULL) {
691+ char *entry = strtok(line, " \n");
692+
693+ if (entry && streq(entry, modname)) {
694+ /* If it exists, usecount is the third entry. */
695+ if (!strtok(NULL, " \n"))
696+ goto out;
697+
698+ if (!(entry = strtok(NULL, " \n"))) /* usecount */
699+ goto out;
700+ else
701+ if (usecount)
702+ *usecount = atoi(entry);
703+
704+ /* Followed by - then status. */
705+ if (strtok(NULL, " \n")
706+ && (entry = strtok(NULL, " \n")) != NULL) {
707+ /* Locking will fail on ro fs, we might hit
708+ * cases where module is in flux. Spin. */
709+ if (streq(entry, "Loading")
710+ || streq(entry, "Unloading")) {
711+ usleep(100000);
712+ free(line);
713+ fclose(proc_modules);
714+ goto again;
715+ }
716+ }
717+
718+ out:
719+ free(line);
720+ fclose(proc_modules);
721+ return 1;
722+ }
723+ free(line);
724+ }
725+ fclose(proc_modules);
726+ return 0;
727+}
728+
729+static void replace_modname(struct module *module,
730+ void *mem, unsigned long len,
731+ const char *oldname, const char *newname)
732+{
733+ char *p;
734+
735+ /* 64 - sizeof(unsigned long) - 1 */
736+ if (strlen(newname) > 55)
737+ fatal("New name %s is too long\n", newname);
738+
739+ /* Find where it is in the module structure. Don't assume layout! */
740+ for (p = mem; p < (char *)mem + len - strlen(oldname); p++) {
741+ if (memcmp(p, oldname, strlen(oldname)) == 0) {
742+ strcpy(p, newname);
743+ return;
744+ }
745+ }
746+
747+ warn("Could not find old name in %s to replace!\n", module->filename);
748+}
749+
750+static void *get_section32(void *file,
751+ unsigned long size,
752+ const char *name,
753+ unsigned long *secsize)
754+{
755+ Elf32_Ehdr *hdr = file;
756+ Elf32_Shdr *sechdrs = file + hdr->e_shoff;
757+ const char *secnames;
758+ unsigned int i;
759+
760+ /* Too short? */
761+ if (size < sizeof(*hdr))
762+ return NULL;
763+ if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
764+ return NULL;
765+ if (size < sechdrs[hdr->e_shstrndx].sh_offset)
766+ return NULL;
767+
768+ secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
769+ for (i = 1; i < hdr->e_shnum; i++)
770+ if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {
771+ *secsize = sechdrs[i].sh_size;
772+ return file + sechdrs[i].sh_offset;
773+ }
774+ return NULL;
775+}
776+
777+static void *get_section64(void *file,
778+ unsigned long size,
779+ const char *name,
780+ unsigned long *secsize)
781+{
782+ Elf64_Ehdr *hdr = file;
783+ Elf64_Shdr *sechdrs = file + hdr->e_shoff;
784+ const char *secnames;
785+ unsigned int i;
786+
787+ /* Too short? */
788+ if (size < sizeof(*hdr))
789+ return NULL;
790+ if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
791+ return NULL;
792+ if (size < sechdrs[hdr->e_shstrndx].sh_offset)
793+ return NULL;
794+
795+ secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
796+ for (i = 1; i < hdr->e_shnum; i++)
797+ if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {
798+ *secsize = sechdrs[i].sh_size;
799+ return file + sechdrs[i].sh_offset;
800+ }
801+ return NULL;
802+}
803+
804+static int elf_ident(void *mod, unsigned long size)
805+{
806+ /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
807+ char *ident = mod;
808+
809+ if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0)
810+ return ELFCLASSNONE;
811+ return ident[EI_CLASS];
812+}
813+
814+static void *get_section(void *file,
815+ unsigned long size,
816+ const char *name,
817+ unsigned long *secsize)
818+{
819+ switch (elf_ident(file, size)) {
820+ case ELFCLASS32:
821+ return get_section32(file, size, name, secsize);
822+ case ELFCLASS64:
823+ return get_section64(file, size, name, secsize);
824+ default:
825+ return NULL;
826+ }
827+}
828+
829+static void rename_module(struct module *module,
830+ void *mod,
831+ unsigned long len,
832+ const char *newname)
833+{
834+ void *modstruct;
835+ unsigned long modstruct_len;
836+
837+ /* Old-style */
838+ modstruct = get_section(mod, len, ".gnu.linkonce.this_module",
839+ &modstruct_len);
840+ /* New-style */
841+ if (!modstruct)
842+ modstruct = get_section(mod, len, "__module", &modstruct_len);
843+ if (!modstruct)
844+ warn("Could not find module name to change in %s\n",
845+ module->filename);
846+ else
847+ replace_modname(module, modstruct, modstruct_len,
848+ module->modname, newname);
849+}
850+
851+/* Kernel told to ignore these sections if SHF_ALLOC not set. */
852+static void invalidate_section32(void *mod, const char *secname)
853+{
854+ Elf32_Ehdr *hdr = mod;
855+ Elf32_Shdr *sechdrs = mod + hdr->e_shoff;
856+ const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset;
857+ unsigned int i;
858+
859+ for (i = 1; i < hdr->e_shnum; i++)
860+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0)
861+ sechdrs[i].sh_flags &= ~SHF_ALLOC;
862+}
863+
864+static void invalidate_section64(void *mod, const char *secname)
865+{
866+ Elf64_Ehdr *hdr = mod;
867+ Elf64_Shdr *sechdrs = mod + hdr->e_shoff;
868+ const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset;
869+ unsigned int i;
870+
871+ for (i = 1; i < hdr->e_shnum; i++)
872+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0)
873+ sechdrs[i].sh_flags &= ~(unsigned long long)SHF_ALLOC;
874+}
875+
876+static void strip_section(struct module *module,
877+ void *mod,
878+ unsigned long len,
879+ const char *secname)
880+{
881+ switch (elf_ident(mod, len)) {
882+ case ELFCLASS32:
883+ invalidate_section32(mod, secname);
884+ break;
885+ case ELFCLASS64:
886+ invalidate_section64(mod, secname);
887+ break;
888+ default:
889+ warn("Unknown module format in %s: not forcing version\n",
890+ module->filename);
891+ }
892+}
893+
894+static const char *next_string(const char *string, unsigned long *secsize)
895+{
896+ /* Skip non-zero chars */
897+ while (string[0]) {
898+ string++;
899+ if ((*secsize)-- <= 1)
900+ return NULL;
901+ }
902+
903+ /* Skip any zero padding. */
904+ while (!string[0]) {
905+ string++;
906+ if ((*secsize)-- <= 1)
907+ return NULL;
908+ }
909+ return string;
910+}
911+
912+static void clear_magic(struct module *module, void *mod, unsigned long len)
913+{
914+ const char *p;
915+ unsigned long modlen;
916+
917+ /* Old-style: __vermagic section */
918+ strip_section(module, mod, len, "__vermagic");
919+
920+ /* New-style: in .modinfo section */
921+ for (p = get_section(mod, len, ".modinfo", &modlen);
922+ p;
923+ p = next_string(p, &modlen)) {
924+ if (strncmp(p, "vermagic=", strlen("vermagic=")) == 0) {
925+ memset((char *)p, 0, strlen(p));
926+ return;
927+ }
928+ }
929+}
930+
931+struct module_options
932+{
933+ struct module_options *next;
934+ char *modulename;
935+ char *options;
936+};
937+
938+struct module_command
939+{
940+ struct module_command *next;
941+ char *modulename;
942+ char *command;
943+};
944+
945+struct module_alias
946+{
947+ struct module_alias *next;
948+ char *module;
949+};
950+
951+struct module_blacklist
952+{
953+ struct module_blacklist *next;
954+ char *modulename;
955+};
956+
957+/* Link in a new option line from the config file. */
958+static struct module_options *
959+add_options(const char *modname,
960+ const char *option,
961+ struct module_options *options)
962+{
963+ struct module_options *new;
964+ char *tab;
965+
966+ new = NOFAIL(malloc(sizeof(*new)));
967+ new->modulename = NOFAIL(strdup(modname));
968+ new->options = NOFAIL(strdup(option));
969+ /* We can handle tabs, kernel can't. */
970+ for (tab = strchr(new->options, '\t'); tab; tab = strchr(tab, '\t'))
971+ *tab = ' ';
972+ new->next = options;
973+ return new;
974+}
975+
976+/* Link in a new install line from the config file. */
977+static struct module_command *
978+add_command(const char *modname,
979+ const char *command,
980+ struct module_command *commands)
981+{
982+ struct module_command *new;
983+
984+ new = NOFAIL(malloc(sizeof(*new)));
985+ new->modulename = NOFAIL(strdup(modname));
986+ new->command = NOFAIL(strdup(command));
987+ new->next = commands;
988+ return new;
989+}
990+
991+/* Link in a new alias line from the config file. */
992+static struct module_alias *
993+add_alias(const char *modname, struct module_alias *aliases)
994+{
995+ struct module_alias *new;
996+
997+ new = NOFAIL(malloc(sizeof(*new)));
998+ new->module = NOFAIL(strdup(modname));
999+ new->next = aliases;
1000+ return new;
1001+}
1002+
1003+/* Link in a new blacklist line from the config file. */
1004+static struct module_blacklist *
1005+add_blacklist(const char *modname, struct module_blacklist *blacklist)
1006+{
1007+ struct module_blacklist *new;
1008+
1009+ new = NOFAIL(malloc(sizeof(*new)));
1010+ new->modulename = NOFAIL(strdup(modname));
1011+ new->next = blacklist;
1012+ return new;
1013+}
1014+
1015+/* Find blacklist commands if any. */
1016+static int
1017+find_blacklist(const char *modname, const struct module_blacklist *blacklist)
1018+{
1019+ while (blacklist) {
1020+ if (strcmp(blacklist->modulename, modname) == 0)
1021+ return 1;
1022+ blacklist = blacklist->next;
1023+ }
1024+ return 0;
1025+}
1026+
1027+/* return a new alias list, with backlisted elems filtered out */
1028+static struct module_alias *
1029+apply_blacklist(const struct module_alias *aliases,
1030+ const struct module_blacklist *blacklist)
1031+{
1032+ struct module_alias *result = NULL;
1033+ while (aliases) {
1034+ char *modname = aliases->module;
1035+ if (!find_blacklist(modname, blacklist))
1036+ result = add_alias(modname, result);
1037+ aliases = aliases->next;
1038+ }
1039+ return result;
1040+}
1041+
1042+/* Find install commands if any. */
1043+static const char *find_command(const char *modname,
1044+ const struct module_command *commands)
1045+{
1046+ while (commands) {
1047+ if (fnmatch(commands->modulename, modname, 0) == 0)
1048+ return commands->command;
1049+ commands = commands->next;
1050+ }
1051+ return NULL;
1052+}
1053+
1054+static char *append_option(char *options, const char *newoption)
1055+{
1056+ options = NOFAIL(realloc(options, strlen(options) + 1
1057+ + strlen(newoption) + 1));
1058+ if (strlen(options)) strcat(options, " ");
1059+ strcat(options, newoption);
1060+ return options;
1061+}
1062+
1063+/* Add to options */
1064+static char *add_extra_options(const char *modname,
1065+ char *optstring,
1066+ const struct module_options *options)
1067+{
1068+ while (options) {
1069+ if (strcmp(options->modulename, modname) == 0)
1070+ optstring = append_option(optstring, options->options);
1071+ options = options->next;
1072+ }
1073+ return optstring;
1074+}
1075+
1076+/* If we don't flush, then child processes print before we do */
1077+static void verbose_printf(int verbose, const char *fmt, ...)
1078+{
1079+ va_list arglist;
1080+
1081+ if (verbose) {
1082+ va_start(arglist, fmt);
1083+ vprintf(fmt, arglist);
1084+ fflush(stdout);
1085+ va_end(arglist);
1086+ }
1087+}
1088+
1089+/* Do an install/remove command: replace $CMDLINE_OPTS if it's specified. */
1090+static void do_command(const char *modname,
1091+ const char *command,
1092+ int verbose, int dry_run,
1093+ errfn_t error,
1094+ const char *type,
1095+ const char *cmdline_opts)
1096+{
1097+ int ret;
1098+ char *p, *replaced_cmd = NOFAIL(strdup(command));
1099+
1100+ while ((p = strstr(replaced_cmd, "$CMDLINE_OPTS")) != NULL) {
1101+ char *new;
1102+ asprintf(&new, "%.*s%s%s",
1103+ p - replaced_cmd, replaced_cmd, cmdline_opts,
1104+ p + strlen("$CMDLINE_OPTS"));
1105+ NOFAIL(new);
1106+ free(replaced_cmd);
1107+ replaced_cmd = new;
1108+ }
1109+
1110+ verbose_printf(verbose, "%s %s\n", type, replaced_cmd);
1111+ if (dry_run)
1112+ return;
1113+
1114+ setenv("MODPROBE_MODULE", modname, 1);
1115+ ret = system(replaced_cmd);
1116+ if (ret == -1 || WEXITSTATUS(ret))
1117+ error("Error running %s command for %s\n", type, modname);
1118+ free(replaced_cmd);
1119+}
1120+
1121+/* Actually do the insert. Frees second arg. */
1122+static void insmod(struct list_head *list,
1123+ char *optstring,
1124+ const char *newname,
1125+ int first_time,
1126+ errfn_t error,
1127+ int dry_run,
1128+ int verbose,
1129+ const struct module_options *options,
1130+ const struct module_command *commands,
1131+ int ignore_commands,
1132+ int ignore_proc,
1133+ int strip_vermagic,
1134+ int strip_modversion,
1135+ const char *cmdline_opts)
1136+{
1137+ int ret, fd;
1138+ unsigned long len;
1139+ void *map;
1140+ const char *command;
1141+ struct module *mod = list_entry(list->next, struct module, list);
1142+
1143+ /* Take us off the list. */
1144+ list_del(&mod->list);
1145+
1146+ /* Do things we (or parent) depend on first, but don't die if
1147+ * they fail. */
1148+ if (!list_empty(list)) {
1149+ insmod(list, NOFAIL(strdup("")), NULL, 0, warn,
1150+ dry_run, verbose, options, commands, 0, ignore_proc,
1151+ strip_vermagic, strip_modversion, cmdline_opts);
1152+ }
1153+
1154+ /* Lock before we look, in case it's initializing. */
1155+ fd = lock_file(mod->filename);
1156+ if (fd < 0) {
1157+ error("Could not open '%s': %s\n",
1158+ mod->filename, strerror(errno));
1159+ goto out_optstring;
1160+ }
1161+
1162+ /* Don't do ANYTHING if already in kernel. */
1163+ if (!ignore_proc
1164+ && module_in_kernel(newname ?: mod->modname, NULL) == 1) {
1165+ if (first_time)
1166+ error("Module %s already in kernel.\n",
1167+ newname ?: mod->modname);
1168+ goto out_unlock;
1169+ }
1170+
1171+ command = find_command(mod->modname, commands);
1172+ if (command && !ignore_commands) {
1173+ /* It might recurse: unlock. */
1174+ unlock_file(fd);
1175+ do_command(mod->modname, command, verbose, dry_run, error,
1176+ "install", cmdline_opts);
1177+ goto out_optstring;
1178+ }
1179+
1180+ map = grab_fd(fd, &len);
1181+ if (!map) {
1182+ error("Could not read '%s': %s\n",
1183+ mod->filename, strerror(errno));
1184+ goto out_unlock;
1185+ }
1186+
1187+ /* Rename it? */
1188+ if (newname)
1189+ rename_module(mod, map, len, newname);
1190+
1191+ if (strip_modversion)
1192+ strip_section(mod, map, len, "__versions");
1193+ if (strip_vermagic)
1194+ clear_magic(mod, map, len);
1195+
1196+ /* Config file might have given more options */
1197+ optstring = add_extra_options(mod->modname, optstring, options);
1198+
1199+ verbose_printf(verbose, "insmod %s %s\n", mod->filename, optstring);
1200+
1201+ if (dry_run)
1202+ goto out;
1203+
1204+ ret = init_module(map, len, optstring);
1205+ if (ret != 0) {
1206+ if (errno == EEXIST) {
1207+ if (first_time)
1208+ error("Module %s already in kernel.\n",
1209+ newname ?: mod->modname);
1210+ goto out_unlock;
1211+ }
1212+ error("Error inserting %s (%s): %s\n",
1213+ mod->modname, mod->filename, insert_moderror(errno));
1214+ }
1215+ out:
1216+ release_file(map, len);
1217+ out_unlock:
1218+ unlock_file(fd);
1219+ out_optstring:
1220+ free(optstring);
1221+ return;
1222+}
1223+
1224+/* Do recursive removal. */
1225+static void rmmod(struct list_head *list,
1226+ const char *name,
1227+ int first_time,
1228+ errfn_t error,
1229+ int dry_run,
1230+ int verbose,
1231+ struct module_command *commands,
1232+ int ignore_commands,
1233+ int ignore_inuse,
1234+ const char *cmdline_opts)
1235+{
1236+ const char *command;
1237+ unsigned int usecount = 0;
1238+ int lock;
1239+ struct module *mod = list_entry(list->next, struct module, list);
1240+
1241+ /* Take first one off the list. */
1242+ list_del(&mod->list);
1243+
1244+ /* Ignore failure; it's best effort here. */
1245+ lock = lock_file(mod->filename);
1246+
1247+ if (!name)
1248+ name = mod->modname;
1249+
1250+ /* Even if renamed, find commands to orig. name. */
1251+ command = find_command(mod->modname, commands);
1252+ if (command && !ignore_commands) {
1253+ /* It might recurse: unlock. */
1254+ unlock_file(lock);
1255+ do_command(mod->modname, command, verbose, dry_run, error,
1256+ "remove", cmdline_opts);
1257+ goto remove_rest_no_unlock;
1258+ }
1259+
1260+ if (module_in_kernel(name, &usecount) == 0)
1261+ goto nonexistent_module;
1262+
1263+ if (usecount != 0) {
1264+ if (!ignore_inuse)
1265+ error("Module %s is in use.\n", name);
1266+ goto remove_rest;
1267+ }
1268+
1269+ verbose_printf(verbose, "rmmod %s\n", mod->filename);
1270+
1271+ if (dry_run)
1272+ goto remove_rest;
1273+
1274+ if (delete_module(name, O_EXCL) != 0) {
1275+ if (errno == ENOENT)
1276+ goto nonexistent_module;
1277+ error("Error removing %s (%s): %s\n",
1278+ name, mod->filename,
1279+ remove_moderror(errno));
1280+ }
1281+
1282+ remove_rest:
1283+ unlock_file(lock);
1284+ remove_rest_no_unlock:
1285+ /* Now do things we depend. */
1286+ if (!list_empty(list))
1287+ rmmod(list, NULL, 0, warn, dry_run, verbose, commands,
1288+ 0, 1, cmdline_opts);
1289+ return;
1290+
1291+nonexistent_module:
1292+ if (first_time)
1293+ fatal("Module %s is not in kernel.\n", mod->modname);
1294+ goto remove_rest;
1295+}
1296+
1297+/* Does path contain directory(s) subpath? */
1298+static int type_matches(const char *path, const char *subpath)
1299+{
1300+ char *subpath_with_slashes;
1301+ int ret;
1302+
1303+ asprintf(&subpath_with_slashes, "/%s/", subpath);
1304+ NOFAIL(subpath_with_slashes);
1305+
1306+ ret = (strstr(path, subpath_with_slashes) != NULL);
1307+ free(subpath_with_slashes);
1308+ return ret;
1309+}
1310+
1311+static char *underscores(char *string)
1312+{
1313+ if (string) {
1314+ unsigned int i;
1315+ for (i = 0; string[i]; i++)
1316+ if (string[i] == '-')
1317+ string[i] = '_';
1318+ }
1319+ return string;
1320+}
1321+
1322+static int do_wildcard(const char *dirname,
1323+ const char *type,
1324+ const char *wildcard)
1325+{
1326+ char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1];
1327+ char *line, *wcard;
1328+ FILE *modules_dep;
1329+
1330+ /* Canonicalize wildcard */
1331+ wcard = strdup(wildcard);
1332+ underscores(wcard);
1333+
1334+ sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep");
1335+ modules_dep = fopen(modules_dep_name, "r");
1336+ if (!modules_dep)
1337+ fatal("Could not load %s: %s\n",
1338+ modules_dep_name, strerror(errno));
1339+
1340+ while ((line = getline_wrapped(modules_dep, NULL)) != NULL) {
1341+ char *ptr;
1342+
1343+ /* Ignore lines without : or which start with a # */
1344+ ptr = strchr(line, ':');
1345+ if (ptr == NULL || line[strspn(line, "\t ")] == '#')
1346+ goto next;
1347+ *ptr = '\0';
1348+
1349+ /* "type" must match complete directory component(s). */
1350+ if (!type || type_matches(line, type)) {
1351+ char modname[strlen(line)+1];
1352+
1353+ filename2modname(modname, line);
1354+ if (fnmatch(wcard, modname, 0) == 0)
1355+ printf("%s\n", line);
1356+ }
1357+ next:
1358+ free(line);
1359+ }
1360+
1361+ free(wcard);
1362+ return 0;
1363+}
1364+
1365+static char *strsep_skipspace(char **string, char *delim)
1366+{
1367+ if (!*string)
1368+ return NULL;
1369+ *string += strspn(*string, delim);
1370+ return strsep(string, delim);
1371+}
1372+
1373+/* Recursion */
1374+static int read_config(const char *filename,
1375+ const char *name,
1376+ int dump_only,
1377+ int removing,
1378+ struct module_options **options,
1379+ struct module_command **commands,
1380+ struct module_alias **alias,
1381+ struct module_blacklist **blacklist);
1382+
1383+/* FIXME: Maybe should be extended to "alias a b [and|or c]...". --RR */
1384+static int read_config_file(const char *filename,
1385+ const char *name,
1386+ int dump_only,
1387+ int removing,
1388+ struct module_options **options,
1389+ struct module_command **commands,
1390+ struct module_alias **aliases,
1391+ struct module_blacklist **blacklist)
1392+{
1393+ char *line;
1394+ unsigned int linenum = 0;
1395+ FILE *cfile;
1396+
1397+ cfile = fopen(filename, "r");
1398+ if (!cfile)
1399+ return 0;
1400+
1401+ while ((line = getline_wrapped(cfile, &linenum)) != NULL) {
1402+ char *ptr = line;
1403+ char *cmd, *modname;
1404+
1405+ if (dump_only)
1406+ printf("%s\n", line);
1407+
1408+ cmd = strsep_skipspace(&ptr, "\t ");
1409+ if (cmd == NULL || cmd[0] == '#' || cmd[0] == '\0')
1410+ continue;
1411+
1412+ if (strcmp(cmd, "alias") == 0) {
1413+ char *wildcard
1414+ = underscores(strsep_skipspace(&ptr, "\t "));
1415+ char *realname
1416+ = underscores(strsep_skipspace(&ptr, "\t "));
1417+
1418+ if (!wildcard || !realname)
1419+ grammar(cmd, filename, linenum);
1420+ else if (fnmatch(wildcard,name,0) == 0)
1421+ *aliases = add_alias(realname, *aliases);
1422+ } else if (strcmp(cmd, "include") == 0) {
1423+ struct module_alias *newalias = NULL;
1424+ char *newfilename;
1425+
1426+ newfilename = strsep_skipspace(&ptr, "\t ");
1427+ if (!newfilename)
1428+ grammar(cmd, filename, linenum);
1429+ else {
1430+ if (!read_config(newfilename, name,
1431+ dump_only, removing,
1432+ options, commands, &newalias,
1433+ blacklist))
1434+ warn("Failed to open included"
1435+ " config file %s: %s\n",
1436+ newfilename, strerror(errno));
1437+
1438+ /* Files included override aliases,
1439+ etc that was already set ... */
1440+ if (newalias)
1441+ *aliases = newalias;
1442+ }
1443+ } else if (strcmp(cmd, "options") == 0) {
1444+ modname = strsep_skipspace(&ptr, "\t ");
1445+ if (!modname || !ptr)
1446+ grammar(cmd, filename, linenum);
1447+ else {
1448+ ptr += strspn(ptr, "\t ");
1449+ *options = add_options(underscores(modname),
1450+ ptr, *options);
1451+ }
1452+ } else if (strcmp(cmd, "install") == 0) {
1453+ modname = strsep_skipspace(&ptr, "\t ");
1454+ if (!modname || !ptr)
1455+ grammar(cmd, filename, linenum);
1456+ else if (!removing) {
1457+ ptr += strspn(ptr, "\t ");
1458+ *commands = add_command(underscores(modname),
1459+ ptr, *commands);
1460+ }
1461+ } else if (strcmp(cmd, "blacklist") == 0) {
1462+ modname = strsep_skipspace(&ptr, "\t ");
1463+ if (!modname)
1464+ grammar(cmd, filename, linenum);
1465+ else if (!removing) {
1466+ *blacklist = add_blacklist(underscores(modname),
1467+ *blacklist);
1468+ }
1469+ } else if (strcmp(cmd, "remove") == 0) {
1470+ modname = strsep_skipspace(&ptr, "\t ");
1471+ if (!modname || !ptr)
1472+ grammar(cmd, filename, linenum);
1473+ else if (removing) {
1474+ ptr += strspn(ptr, "\t ");
1475+ *commands = add_command(underscores(modname),
1476+ ptr, *commands);
1477+ }
1478+ } else
1479+ grammar(cmd, filename, linenum);
1480+
1481+ free(line);
1482+ }
1483+ fclose(cfile);
1484+ return 1;
1485+}
1486+
1487+/* Simple format, ignore lines starting with #, one command per line.
1488+ Returns true or false. */
1489+static int read_config(const char *filename,
1490+ const char *name,
1491+ int dump_only,
1492+ int removing,
1493+ struct module_options **options,
1494+ struct module_command **commands,
1495+ struct module_alias **aliases,
1496+ struct module_blacklist **blacklist)
1497+{
1498+ DIR *dir;
1499+ int ret = 0;
1500+
1501+ /* ignore everything in this directory */
1502+ if (streq(filename, "/etc/modprobe.d/arch"))
1503+ return 1;
1504+
1505+ /* Reiser4 has file/directory duality: treat it as both. */
1506+ dir = opendir(filename);
1507+ if (dir) {
1508+ struct dirent *i;
1509+ while ((i = readdir(dir)) != NULL) {
1510+ if (!streq(i->d_name,".") && !streq(i->d_name,"..")) {
1511+ char sub[strlen(filename) + 1
1512+ + strlen(i->d_name) + 1];
1513+
1514+ sprintf(sub, "%s/%s", filename, i->d_name);
1515+ if (!read_config(sub, name,
1516+ dump_only, removing, options,
1517+ commands, aliases, blacklist))
1518+ warn("Failed to open"
1519+ " config file %s: %s\n",
1520+ sub, strerror(errno));
1521+ }
1522+ }
1523+ closedir(dir);
1524+ ret = 1;
1525+ }
1526+
1527+ if (read_config_file(filename, name, dump_only, removing,
1528+ options, commands, aliases, blacklist))
1529+ ret = 1;
1530+
1531+ return ret;
1532+}
1533+
1534+static const char *default_configs[] =
1535+{
1536+ "/etc/modprobe.conf",
1537+ "/etc/modprobe.d",
1538+};
1539+
1540+static void read_toplevel_config(const char *filename,
1541+ const char *name,
1542+ int dump_only,
1543+ int removing,
1544+ struct module_options **options,
1545+ struct module_command **commands,
1546+ struct module_alias **aliases,
1547+ struct module_blacklist **blacklist)
1548+{
1549+ unsigned int i;
1550+
1551+ if (filename) {
1552+ if (!read_config(filename, name, dump_only, removing,
1553+ options, commands, aliases, blacklist))
1554+ fatal("Failed to open config file %s: %s\n",
1555+ filename, strerror(errno));
1556+ return;
1557+ }
1558+
1559+ /* Try defaults. */
1560+ for (i = 0; i < ARRAY_SIZE(default_configs); i++) {
1561+ if (read_config(default_configs[i], name, dump_only, removing,
1562+ options, commands, aliases, blacklist))
1563+ return;
1564+ }
1565+}
1566+
1567+static void add_to_env_var(const char *option)
1568+{
1569+ const char *oldenv;
1570+
1571+ if ((oldenv = getenv("MODPROBE_OPTIONS")) != NULL) {
1572+ char *newenv;
1573+ asprintf(&newenv, "%s %s", oldenv, option);
1574+ setenv("MODPROBE_OPTIONS", newenv, 1);
1575+ } else
1576+ setenv("MODPROBE_OPTIONS", option, 1);
1577+}
1578+
1579+/* Prepend options from environment. */
1580+static char **merge_args(char *args, char *argv[], int *argc)
1581+{
1582+ char *arg, *argstring;
1583+ char **newargs = NULL;
1584+ unsigned int i, num_env = 0;
1585+
1586+ if (!args)
1587+ return argv;
1588+
1589+ argstring = NOFAIL(strdup(args));
1590+ for (arg = strtok(argstring, " "); arg; arg = strtok(NULL, " ")) {
1591+ num_env++;
1592+ newargs = NOFAIL(realloc(newargs,
1593+ sizeof(newargs[0])
1594+ * (num_env + *argc + 1)));
1595+ newargs[num_env] = arg;
1596+ }
1597+
1598+ /* Append commandline args */
1599+ newargs[0] = argv[0];
1600+ for (i = 1; i <= *argc; i++)
1601+ newargs[num_env+i] = argv[i];
1602+
1603+ *argc += num_env;
1604+ return newargs;
1605+}
1606+
1607+static char *gather_options(char *argv[])
1608+{
1609+ char *optstring = NOFAIL(strdup(""));
1610+
1611+ /* Rest is module options */
1612+ while (*argv) {
1613+ /* Quote value if it contains spaces. */
1614+ unsigned int eq = strcspn(*argv, "=");
1615+
1616+ if (strchr(*argv+eq, ' ') && !strchr(*argv, '"')) {
1617+ char quoted[strlen(*argv) + 3];
1618+ (*argv)[eq] = '\0';
1619+ sprintf(quoted, "%s=\"%s\"", *argv, *argv+eq+1);
1620+ optstring = append_option(optstring, quoted);
1621+ } else
1622+ optstring = append_option(optstring, *argv);
1623+ argv++;
1624+ }
1625+ return optstring;
1626+}
1627+
1628+static void handle_module(const char *modname,
1629+ struct list_head *todo_list,
1630+ const char *newname,
1631+ int remove,
1632+ char *options,
1633+ int first_time,
1634+ errfn_t error,
1635+ int dry_run,
1636+ int verbose,
1637+ struct module_options *modoptions,
1638+ struct module_command *commands,
1639+ int ignore_commands,
1640+ int ignore_proc,
1641+ int strip_vermagic,
1642+ int strip_modversion,
1643+ int unknown_silent,
1644+ const char *cmdline_opts)
1645+{
1646+ if (list_empty(todo_list)) {
1647+ const char *command;
1648+
1649+ /* The dependencies have to be real modules, but
1650+ handle case where the first is completely bogus. */
1651+ command = find_command(modname, commands);
1652+ if (command && !ignore_commands) {
1653+ do_command(modname, command, verbose, dry_run, error,
1654+ remove ? "remove":"install", cmdline_opts);
1655+ return;
1656+ }
1657+
1658+ if (unknown_silent)
1659+ exit(1);
1660+ error("Module %s not found.\n", modname);
1661+ return;
1662+ }
1663+
1664+ if (remove)
1665+ rmmod(todo_list, newname, first_time, error, dry_run, verbose,
1666+ commands, ignore_commands, 0, cmdline_opts);
1667+ else
1668+ insmod(todo_list, NOFAIL(strdup(options)), newname,
1669+ first_time, error, dry_run, verbose, modoptions,
1670+ commands, ignore_commands, ignore_proc, strip_vermagic,
1671+ strip_modversion, cmdline_opts);
1672+}
1673+
1674+static struct option options[] = { { "verbose", 0, NULL, 'v' },
1675+ { "version", 0, NULL, 'V' },
1676+ { "config", 1, NULL, 'C' },
1677+ { "name", 1, NULL, 'o' },
1678+ { "remove", 0, NULL, 'r' },
1679+ { "showconfig", 0, NULL, 'c' },
1680+ { "autoclean", 0, NULL, 'k' },
1681+ { "quiet", 0, NULL, 'q' },
1682+ { "show", 0, NULL, 'n' },
1683+ { "dry-run", 0, NULL, 'n' },
1684+ { "syslog", 0, NULL, 's' },
1685+ { "type", 1, NULL, 't' },
1686+ { "list", 0, NULL, 'l' },
1687+ { "all", 0, NULL, 'a' },
1688+ { "ignore-install", 0, NULL, 'i' },
1689+ { "ignore-remove", 0, NULL, 'i' },
1690+ { "force", 0, NULL, 'f' },
1691+ { "force-vermagic", 0, NULL, 1 },
1692+ { "force-modversion", 0, NULL, 2 },
1693+ { "set-version", 1, NULL, 'S' },
1694+ { "show-depends", 0, NULL, 'D' },
1695+ { "first-time", 0, NULL, 3 },
1696+ { "use-blacklist", 0, NULL, 'b' },
1697+ { NULL, 0, NULL, 0 } };
1698+
1699+#define MODPROBE_DEVFSD_CONF "/etc/modprobe.devfs"
1700+
1701+/* This is a horrible hack to allow devfsd, which calls modprobe with
1702+ -C /etc/modules.conf or /etc/modules.devfs, to work. FIXME. */
1703+/* Modern devfsd or variants should use -q explicitly in 2.6. */
1704+static int is_devfs_call(char *argv[])
1705+{
1706+ unsigned int i;
1707+
1708+ /* Look for "/dev" arg */
1709+ for (i = 1; argv[i]; i++) {
1710+ if (strncmp(argv[i], "/dev/", 5) == 0)
1711+ return 1;
1712+ }
1713+ return 0;
1714+}
1715+
1716+int main(int argc, char *argv[])
1717+{
1718+ struct utsname buf;
1719+ struct stat statbuf;
1720+ int opt;
1721+ int dump_only = 0;
1722+ int dry_run = 0;
1723+ int remove = 0;
1724+ int verbose = 0;
1725+ int unknown_silent = 0;
1726+ int list_only = 0;
1727+ int all = 0;
1728+ int ignore_commands = 0;
1729+ int strip_vermagic = 0;
1730+ int strip_modversion = 0;
1731+ int ignore_proc = 0;
1732+ int first_time = 0;
1733+ int use_blacklist = 0;
1734+ unsigned int i, num_modules;
1735+ char *type = NULL;
1736+ const char *config = NULL;
1737+ char *dirname, *optstring;
1738+ char *newname = NULL;
1739+ char *aliasfilename, *symfilename;
1740+ errfn_t error = fatal;
1741+
1742+ /* Prepend options from environment. */
1743+ argv = merge_args(getenv("MODPROBE_OPTIONS"), argv, &argc);
1744+
1745+ /* --set-version overrides version, and disables backwards compat. */
1746+ for (opt = 1; opt < argc; opt++)
1747+ if (strncmp(argv[opt],"--set-version",strlen("--set-version"))
1748+ == 0)
1749+ break;
1750+
1751+ if (opt == argc)
1752+ try_old_version("modprobe", argv);
1753+
1754+ uname(&buf);
1755+ while ((opt = getopt_long(argc, argv, "vVC:o:rknqQsclt:aifb", options, NULL)) != -1){
1756+ switch (opt) {
1757+ case 'v':
1758+ add_to_env_var("-v");
1759+ verbose = 1;
1760+ break;
1761+ case 'V':
1762+ puts("module-init-tools version 3.2.2");
1763+ exit(0);
1764+ case 'S':
1765+ strncpy(buf.release, optarg, sizeof(buf.release));
1766+ buf.release[sizeof(buf.release)-1] = '\0';
1767+ break;
1768+ case 'C':
1769+ if (is_devfs_call(argv)) {
1770+ if (streq("/etc/modules.devfs", optarg)) {
1771+ config = MODPROBE_DEVFSD_CONF;
1772+ add_to_env_var("-C");
1773+ add_to_env_var(config);
1774+ /* Fall thru to -q */
1775+ } else if (streq("/etc/modules.conf", optarg))
1776+ /* Ignore config, fall thru to -q */
1777+ ;
1778+ else {
1779+ /* False alarm. Treat as normal. */
1780+ config = optarg;
1781+ add_to_env_var("-C");
1782+ add_to_env_var(config);
1783+ break;
1784+ }
1785+ } else {
1786+ config = optarg;
1787+ add_to_env_var("-C");
1788+ add_to_env_var(config);
1789+ break;
1790+ }
1791+ case 'q':
1792+ unknown_silent = 1;
1793+ add_to_env_var("-q");
1794+ break;
1795+ case 'D':
1796+ dry_run = 1;
1797+ ignore_proc = 1;
1798+ verbose = 1;
1799+ add_to_env_var("-D");
1800+ break;
1801+ case 'o':
1802+ newname = optarg;
1803+ break;
1804+ case 'r':
1805+ remove = 1;
1806+ break;
1807+ case 'c':
1808+ dump_only = 1;
1809+ break;
1810+ case 't':
1811+ type = optarg;
1812+ break;
1813+ case 'l':
1814+ list_only = 1;
1815+ break;
1816+ case 'a':
1817+ all = 1;
1818+ error = warn;
1819+ break;
1820+ case 'k':
1821+ /* FIXME: This should actually do something */
1822+ break;
1823+ case 'n':
1824+ dry_run = 1;
1825+ break;
1826+ case 's':
1827+ add_to_env_var("-s");
1828+ log = 1;
1829+ break;
1830+ case 'i':
1831+ ignore_commands = 1;
1832+ break;
1833+ case 'f':
1834+ strip_vermagic = 1;
1835+ strip_modversion = 1;
1836+ break;
1837+ case 'b':
1838+ use_blacklist = 1;
1839+ break;
1840+ case 1:
1841+ strip_vermagic = 1;
1842+ break;
1843+ case 2:
1844+ strip_modversion = 1;
1845+ break;
1846+ case 3:
1847+ first_time = 1;
1848+ break;
1849+ default:
1850+ print_usage(argv[0]);
1851+ }
1852+ }
1853+
1854+ /* If stderr not open, go to syslog */
1855+ if (log || fstat(STDERR_FILENO, &statbuf) != 0) {
1856+ openlog("modprobe", LOG_CONS, LOG_DAEMON);
1857+ log = 1;
1858+ }
1859+
1860+ if (argc < optind + 1 && !dump_only && !list_only && !remove)
1861+ print_usage(argv[0]);
1862+
1863+ dirname = NOFAIL(malloc(strlen(buf.release) + sizeof(MODULE_DIR) + 1));
1864+ sprintf(dirname, "%s/%s", MODULE_DIR, buf.release);
1865+ aliasfilename = NOFAIL(malloc(strlen(dirname)
1866+ + sizeof("/modules.alias")));
1867+ sprintf(aliasfilename, "%s/modules.alias", dirname);
1868+ symfilename = NOFAIL(malloc(strlen(dirname)
1869+ + sizeof("/modules.symbols")));
1870+ sprintf(symfilename, "%s/modules.symbols", dirname);
1871+
1872+ /* Old-style -t xxx wildcard? Only with -l. */
1873+ if (list_only) {
1874+ if (optind+1 < argc)
1875+ fatal("Can't have multiple wildcards\n");
1876+ /* fprintf(stderr, "man find\n"); return 1; */
1877+ return do_wildcard(dirname, type, argv[optind]?:"*");
1878+ }
1879+ if (type)
1880+ fatal("-t only supported with -l");
1881+
1882+ if (dump_only) {
1883+ struct module_command *commands = NULL;
1884+ struct module_options *modoptions = NULL;
1885+ struct module_alias *aliases = NULL;
1886+ struct module_blacklist *blacklist = NULL;
1887+
1888+ read_toplevel_config(config, "", 1, 0,
1889+ &modoptions, &commands, &aliases, &blacklist);
1890+ read_config(aliasfilename, "", 1, 0,&modoptions, &commands,
1891+ &aliases, &blacklist);
1892+ read_config(symfilename, "", 1, 0, &modoptions, &commands,
1893+ &aliases, &blacklist);
1894+ exit(0);
1895+ }
1896+
1897+ if (remove || all) {
1898+ num_modules = argc - optind;
1899+ optstring = NOFAIL(strdup(""));
1900+ } else {
1901+ num_modules = 1;
1902+ optstring = gather_options(argv+optind+1);
1903+ }
1904+
1905+ /* num_modules is always 1 except for -r or -a. */
1906+ for (i = 0; i < num_modules; i++) {
1907+ struct module_command *commands = NULL;
1908+ struct module_options *modoptions = NULL;
1909+ struct module_alias *aliases = NULL;
1910+ struct module_blacklist *blacklist = NULL;
1911+ LIST_HEAD(list);
1912+ char *modulearg = argv[optind + i];
1913+
1914+ /* Convert name we are looking for */
1915+ underscores(modulearg);
1916+
1917+ /* Returns the resolved alias, options */
1918+ read_toplevel_config(config, modulearg, 0,
1919+ remove, &modoptions, &commands, &aliases, &blacklist);
1920+
1921+ /* No luck? Try symbol names, if starts with symbol:. */
1922+ if (!aliases
1923+ && strncmp(modulearg, "symbol:", strlen("symbol:")) == 0)
1924+ read_config(symfilename, modulearg, 0,
1925+ remove, &modoptions, &commands,
1926+ &aliases, &blacklist);
1927+
1928+ if (!aliases) {
1929+ /* We only use canned aliases as last resort. */
1930+ read_depends(dirname, modulearg, &list);
1931+
1932+ if (list_empty(&list)
1933+ && !find_command(modulearg, commands))
1934+ {
1935+ read_config(aliasfilename, modulearg, 0,
1936+ remove, &modoptions, &commands,
1937+ &aliases, &blacklist);
1938+ aliases = apply_blacklist(aliases, blacklist);
1939+ }
1940+ }
1941+
1942+ if (aliases) {
1943+ errfn_t err = error;
1944+
1945+ /* More than one alias? Don't bail out on failure. */
1946+ if (aliases->next)
1947+ err = warn;
1948+ while (aliases) {
1949+ /* Add the options for this alias. */
1950+ char *opts = NOFAIL(strdup(optstring));
1951+ opts = add_extra_options(modulearg,
1952+ opts, modoptions);
1953+
1954+ read_depends(dirname, aliases->module, &list);
1955+ handle_module(aliases->module, &list, newname,
1956+ remove, opts, first_time, err,
1957+ dry_run, verbose, modoptions,
1958+ commands, ignore_commands,
1959+ ignore_proc, strip_vermagic,
1960+ strip_modversion,
1961+ unknown_silent,
1962+ optstring);
1963+
1964+ aliases = aliases->next;
1965+ INIT_LIST_HEAD(&list);
1966+ }
1967+ } else {
1968+ if (use_blacklist
1969+ && find_blacklist(modulearg, blacklist))
1970+ continue;
1971+
1972+ handle_module(modulearg, &list, newname, remove,
1973+ optstring, first_time, error, dry_run,
1974+ verbose, modoptions, commands,
1975+ ignore_commands, ignore_proc,
1976+ strip_vermagic, strip_modversion,
1977+ unknown_silent, optstring);
1978+ }
1979+ }
1980+ if (log)
1981+ closelog();
1982+
1983+ return 0;
1984+}