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