Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 284957 | Differences between
and this patch

Collapse All | Expand All

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

Return to bug 284957