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