Magellan Linux

Annotation of /tags/mkinitrd-6_1_11/busybox/modutils/modprobe.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 928 - (hide annotations) (download)
Wed Oct 28 13:31:19 2009 UTC (14 years, 7 months ago) by niro
File MIME type: text/plain
File size: 7846 byte(s)
tagged 'mkinitrd-6_1_11'
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Modprobe written from scratch for BusyBox
4     *
5 niro 816 * Copyright (c) 2008 Timo Teras <timo.teras@iki.fi>
6     * Copyright (c) 2008 Vladimir Dronnikov
7 niro 532 *
8     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 niro 816 */
10 niro 532
11 niro 816 #include "libbb.h"
12     #include "modutils.h"
13 niro 532 #include <sys/utsname.h>
14     #include <fnmatch.h>
15    
16 niro 816 struct modprobe_option {
17     char *module;
18     char *option;
19 niro 532 };
20    
21 niro 816 struct modprobe_conf {
22     char probename[MODULE_NAME_LEN];
23     llist_t *options;
24     llist_t *aliases;
25     #if ENABLE_FEATURE_MODPROBE_BLACKLIST
26     #define add_to_blacklist(conf, name) llist_add_to(&conf->blacklist, name)
27     #define check_blacklist(conf, name) (llist_find(conf->blacklist, name) == NULL)
28     llist_t *blacklist;
29     #else
30     #define add_to_blacklist(conf, name) do {} while (0)
31     #define check_blacklist(conf, name) (1)
32     #endif
33 niro 532 };
34    
35 niro 816 #define MODPROBE_OPTS "acdlnrt:VC:" USE_FEATURE_MODPROBE_BLACKLIST("b")
36     enum {
37     MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */
38     MODPROBE_OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << 1), /* c */
39     MODPROBE_OPT_D = (INSMOD_OPT_UNUSED << 2), /* d */
40     MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 3), /* l */
41     MODPROBE_OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << 4), /* n */
42     MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 5), /* r */
43     MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << 6), /* t */
44     MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << 7), /* V */
45     MODPROBE_OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << 8), /* C */
46     MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST,
47 niro 532 };
48    
49 niro 816 static llist_t *loaded;
50 niro 532
51 niro 816 static int read_config(struct modprobe_conf *conf, const char *path);
52 niro 532
53 niro 816 static void add_option(llist_t **all_opts, const char *module, const char *opts)
54     {
55     struct modprobe_option *o;
56 niro 532
57 niro 816 o = xzalloc(sizeof(struct modprobe_option));
58     if (module)
59     o->module = filename2modname(module, NULL);
60     o->option = xstrdup(opts);
61     llist_add_to(all_opts, o);
62     }
63 niro 532
64 niro 816 static int FAST_FUNC config_file_action(const char *filename,
65     struct stat *statbuf UNUSED_PARAM,
66     void *userdata,
67     int depth UNUSED_PARAM)
68 niro 532 {
69 niro 816 struct modprobe_conf *conf = (struct modprobe_conf *) userdata;
70     RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN);
71     char *tokens[3];
72     parser_t *p;
73     int rc = TRUE;
74 niro 532
75 niro 816 if (bb_basename(filename)[0] == '.')
76     goto error;
77 niro 532
78 niro 816 p = config_open2(filename, fopen_for_read);
79     if (p == NULL) {
80     rc = FALSE;
81     goto error;
82     }
83 niro 532
84 niro 816 while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) {
85     if (strcmp(tokens[0], "alias") == 0) {
86     filename2modname(tokens[1], modname);
87     if (tokens[2] &&
88     fnmatch(modname, conf->probename, 0) == 0)
89     llist_add_to(&conf->aliases,
90     filename2modname(tokens[2], NULL));
91     } else if (strcmp(tokens[0], "options") == 0) {
92     if (tokens[2])
93     add_option(&conf->options, tokens[1], tokens[2]);
94     } else if (strcmp(tokens[0], "include") == 0) {
95     read_config(conf, tokens[1]);
96     } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST &&
97     strcmp(tokens[0], "blacklist") == 0) {
98     add_to_blacklist(conf, xstrdup(tokens[1]));
99 niro 532 }
100     }
101 niro 816 config_close(p);
102     error:
103     if (ENABLE_FEATURE_CLEAN_UP)
104     RELEASE_CONFIG_BUFFER(modname);
105     return rc;
106 niro 532 }
107    
108 niro 816 static int read_config(struct modprobe_conf *conf, const char *path)
109 niro 532 {
110 niro 816 return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
111     config_file_action, NULL, conf, 1);
112 niro 532 }
113    
114 niro 816 static char *gather_options(llist_t *first, const char *module, int usecmdline)
115 niro 532 {
116 niro 816 struct modprobe_option *opt;
117     llist_t *n;
118     char *opts = xstrdup("");
119     int optlen = 0;
120 niro 532
121 niro 816 for (n = first; n != NULL; n = n->link) {
122     opt = (struct modprobe_option *) n->data;
123 niro 532
124 niro 816 if (opt->module == NULL && !usecmdline)
125 niro 532 continue;
126 niro 816 if (opt->module != NULL && strcmp(opt->module, module) != 0)
127     continue;
128 niro 532
129 niro 816 opts = xrealloc(opts, optlen + strlen(opt->option) + 2);
130     optlen += sprintf(opts + optlen, "%s ", opt->option);
131 niro 532 }
132 niro 816 return opts;
133 niro 532 }
134    
135 niro 816 static int do_modprobe(struct modprobe_conf *conf, const char *module)
136 niro 532 {
137 niro 816 RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN);
138     llist_t *deps = NULL;
139     char *fn, *options, *colon = NULL, *tokens[2];
140     parser_t *p;
141     int rc = -1;
142 niro 532
143 niro 816 p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, fopen_for_read);
144     if (p == NULL)
145     goto error;
146 niro 532
147 niro 816 while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) {
148     colon = last_char_is(tokens[0], ':');
149     if (colon == NULL)
150 niro 532 continue;
151    
152 niro 816 filename2modname(tokens[0], modname);
153     if (strcmp(modname, module) == 0)
154     break;
155 niro 532
156 niro 816 colon = NULL;
157     }
158     if (colon == NULL)
159     goto error_not_found;
160 niro 532
161 niro 816 colon[0] = '\0';
162     llist_add_to(&deps, xstrdup(tokens[0]));
163     if (tokens[1])
164     string_to_llist(tokens[1], &deps, " ");
165 niro 532
166 niro 816 if (!(option_mask32 & MODPROBE_OPT_REMOVE))
167     deps = llist_rev(deps);
168 niro 532
169 niro 816 rc = 0;
170     while (deps && rc == 0) {
171     fn = llist_pop(&deps);
172     filename2modname(fn, modname);
173     if (option_mask32 & MODPROBE_OPT_REMOVE) {
174     if (bb_delete_module(modname, O_EXCL) != 0)
175     rc = errno;
176     } else if (llist_find(loaded, modname) == NULL) {
177     options = gather_options(conf->options, modname,
178     strcmp(modname, module) == 0);
179     rc = bb_init_module(fn, options);
180     if (rc == 0)
181     llist_add_to(&loaded, xstrdup(modname));
182     if (ENABLE_FEATURE_CLEAN_UP)
183     free(options);
184 niro 532 }
185    
186     if (ENABLE_FEATURE_CLEAN_UP)
187 niro 816 free(fn);
188 niro 532 }
189    
190 niro 816 error_not_found:
191     config_close(p);
192     error:
193     if (ENABLE_FEATURE_CLEAN_UP)
194     RELEASE_CONFIG_BUFFER(modname);
195     if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT))
196     bb_error_msg("Failed to %sload module %s: %s.",
197     (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "",
198     module, moderror(rc));
199     return rc;
200 niro 532 }
201    
202 niro 816 int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
203     int modprobe_main(int argc UNUSED_PARAM, char **argv)
204 niro 532 {
205 niro 816 struct utsname uts;
206     int rc;
207     unsigned opt;
208     llist_t *options = NULL;
209 niro 532
210 niro 816 opt_complementary = "q-v:v-q";
211     opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS,
212     NULL, NULL);
213     argv += optind;
214 niro 532
215 niro 816 if (opt & (MODPROBE_OPT_DUMP_ONLY | MODPROBE_OPT_LIST_ONLY |
216     MODPROBE_OPT_SHOW_ONLY))
217     bb_error_msg_and_die("not supported");
218 niro 532
219 niro 816 /* goto modules location */
220     xchdir(CONFIG_DEFAULT_MODULES_DIR);
221     uname(&uts);
222     xchdir(uts.release);
223 niro 532
224 niro 816 if (!argv[0]) {
225     if (opt & MODPROBE_OPT_REMOVE) {
226     if (bb_delete_module(NULL, O_NONBLOCK|O_EXCL) != 0)
227     bb_perror_msg_and_die("rmmod");
228 niro 532 }
229 niro 816 return EXIT_SUCCESS;
230 niro 532 }
231 niro 816 if (!(opt & MODPROBE_OPT_INSERT_ALL)) {
232     /* If not -a, we have only one module name,
233     * the rest of parameters are options */
234     add_option(&options, NULL, parse_cmdline_module_options(argv));
235     argv[1] = NULL;
236 niro 532 }
237    
238 niro 816 /* cache modules */
239     {
240     char *s;
241     parser_t *parser = config_open2("/proc/modules", fopen_for_read);
242     while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
243     llist_add_to(&loaded, xstrdup(s));
244     config_close(parser);
245 niro 532 }
246    
247 niro 816 while (*argv) {
248     const char *arg = *argv;
249     struct modprobe_conf *conf;
250 niro 532
251 niro 816 conf = xzalloc(sizeof(*conf));
252     conf->options = options;
253     filename2modname(arg, conf->probename);
254     read_config(conf, "/etc/modprobe.conf");
255     read_config(conf, "/etc/modprobe.d");
256     if (ENABLE_FEATURE_MODUTILS_SYMBOLS
257     && conf->aliases == NULL
258     && strncmp(arg, "symbol:", 7) == 0
259     ) {
260     read_config(conf, "modules.symbols");
261 niro 532 }
262    
263 niro 816 if (ENABLE_FEATURE_MODUTILS_ALIAS && conf->aliases == NULL)
264     read_config(conf, "modules.alias");
265 niro 532
266 niro 816 if (conf->aliases == NULL) {
267     /* Try if module by literal name is found; literal
268     * names are blacklist only if '-b' is given. */
269     if (!(opt & MODPROBE_OPT_BLACKLIST) ||
270     check_blacklist(conf, conf->probename)) {
271     rc = do_modprobe(conf, conf->probename);
272     if (rc < 0 && !(opt & INSMOD_OPT_SILENT))
273     bb_error_msg("Module %s not found.", arg);
274 niro 532 }
275 niro 816 } else {
276     /* Probe all aliases */
277     while (conf->aliases != NULL) {
278     char *realname = llist_pop(&conf->aliases);
279     if (check_blacklist(conf, realname))
280     do_modprobe(conf, realname);
281     if (ENABLE_FEATURE_CLEAN_UP)
282     free(realname);
283 niro 532 }
284     }
285 niro 816 argv++;
286 niro 532 }
287    
288 niro 816 return EXIT_SUCCESS;
289 niro 532 }