4 * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33 static struct kmod_ctx
*ctx
;
35 static int command_do(struct kmod_module
*module
, const char *type
, const char *command
, const char *cmdline_opts
)
37 const char *modname
= kmod_module_get_name(module
);
39 size_t cmdlen
, cmdline_opts_len
, varlen
;
42 if (cmdline_opts
== NULL
)
44 cmdline_opts_len
= strlen(cmdline_opts
);
46 cmd
= strdup(command
);
50 varlen
= sizeof("$CMDLINE_OPTS") - 1;
51 while ((p
= strstr(cmd
, "$CMDLINE_OPTS")) != NULL
) {
52 size_t prefixlen
= p
- cmd
;
53 size_t suffixlen
= cmdlen
- prefixlen
- varlen
;
54 size_t slen
= cmdlen
- varlen
+ cmdline_opts_len
;
55 char *suffix
= p
+ varlen
;
56 char *s
= malloc(slen
+ 1);
61 memcpy(s
, cmd
, p
- cmd
);
62 memcpy(s
+ prefixlen
, cmdline_opts
, cmdline_opts_len
);
63 memcpy(s
+ prefixlen
+ cmdline_opts_len
, suffix
, suffixlen
);
71 setenv("MODPROBE_MODULE", modname
, 1);
73 unsetenv("MODPROBE_MODULE");
74 if (ret
== -1 || WEXITSTATUS(ret
)) {
75 //LOG("Error running %s command for %s\n", type, modname);
77 ret
= -WEXITSTATUS(ret
);
85 static int insmod_do_dependencies(struct kmod_module
*parent
);
86 static int insmod_do_soft_dependencies(struct kmod_module
*mod
, struct kmod_list
*deps
);
88 static int insmod_do_deps_list(struct kmod_module
*parent
, struct kmod_list
*deps
, unsigned stop_on_errors
)
93 kmod_list_foreach(d
, deps
) {
94 struct kmod_module
*dm
= kmod_module_get_module(d
);
95 struct kmod_list
*pre
= NULL
, *post
= NULL
;
96 const char *cmd
, *opts
, *dmname
= kmod_module_get_name(dm
);
100 r
= insmod_do_dependencies(dm
);
102 //WRN("could not insert dependencies of '%s': %s\n", dmname, strerror(-r));
106 r
= kmod_module_get_softdeps(dm
, &pre
, &post
);
108 //WRN("could not get softdeps of '%s': %s\n", dmname, strerror(-r));
112 r
= insmod_do_soft_dependencies(dm
, pre
);
114 //WRN("could not insert pre softdeps of '%s': %s\n", dmname, strerror(-r));
118 state
= kmod_module_get_initstate(dm
);
119 if (state
== KMOD_MODULE_LIVE
||
120 state
== KMOD_MODULE_COMING
||
121 state
== KMOD_MODULE_BUILTIN
)
124 cmd
= kmod_module_get_install_commands(dm
);
126 r
= command_do(dm
, "install", cmd
, NULL
);
128 //WRN("failed to execute install command of '%s':" " %s\n", dmname, strerror(-r));
134 opts
= kmod_module_get_options(dm
);
136 r
= kmod_module_insert_module(dm
, 0, opts
);
138 //WRN("could not insert '%s': %s\n", dmname, strerror(-r));
143 r
= insmod_do_soft_dependencies(dm
, post
);
145 //WRN("could not insert post softdeps of '%s': %s\n", dmname, strerror(-r));
149 kmod_module_unref_list(pre
);
150 kmod_module_unref_list(post
);
151 kmod_module_unref(dm
);
156 kmod_module_unref_list(pre
);
157 kmod_module_unref_list(post
);
158 kmod_module_unref(dm
);
168 static int insmod_do_soft_dependencies(struct kmod_module
*mod
, struct kmod_list
*deps
)
170 return insmod_do_deps_list(mod
, deps
, 0);
173 static int insmod_do_dependencies(struct kmod_module
*parent
)
175 struct kmod_list
*deps
= kmod_module_get_dependencies(parent
);
176 int err
= insmod_do_deps_list(parent
, deps
, 1);
177 kmod_module_unref_list(deps
);
181 static int insmod_do(struct kmod_module
*mod
, const char *extra_opts
)
183 const char *modname
= kmod_module_get_name(mod
);
184 const char *conf_opts
= kmod_module_get_options(mod
);
185 struct kmod_list
*pre
= NULL
, *post
= NULL
;
191 err
= kmod_module_get_softdeps(mod
, &pre
, &post
);
193 //WRN("could not get softdeps of '%s': %s\n", modname, strerror(-err));
197 err
= insmod_do_soft_dependencies(mod
, pre
);
199 //WRN("could not insert pre softdeps of '%s': %s\n", modname, strerror(-err));
203 cmd
= kmod_module_get_install_commands(mod
);
205 err
= command_do(mod
, "install", cmd
, extra_opts
);
209 state
= kmod_module_get_initstate(mod
);
210 if (state
== KMOD_MODULE_BUILTIN
|| state
== KMOD_MODULE_LIVE
)
214 * At this point it's not possible to be a install/remove command
215 * anymore. So if we can't get module's path, it's because it was
216 * really intended to be a module and it doesn't exist
218 if (kmod_module_get_path(mod
) == NULL
) {
219 //LOG("Module %s not found.\n", modname);
223 err
= insmod_do_dependencies(mod
);
227 if (conf_opts
|| extra_opts
) {
228 if (conf_opts
== NULL
)
229 opts
= strdup(extra_opts
);
230 else if (extra_opts
== NULL
)
231 opts
= strdup(conf_opts
);
232 else if (asprintf(&opts
, "%s %s", conf_opts
, extra_opts
) < 0)
241 err
= kmod_module_insert_module(mod
, 0, opts
);
246 err
= insmod_do_soft_dependencies(mod
, post
);
248 //WRN("could not insert post softdeps of '%s': %s\n", modname, strerror(-err));
253 kmod_module_unref_list(pre
);
254 kmod_module_unref_list(post
);
259 static int insmod_path(struct kmod_ctx
*ctx
, const char *path
, const char *extra_options
)
261 struct kmod_module
*mod
;
264 err
= kmod_module_new_from_path(ctx
, path
, &mod
);
266 //LOG("Module %s not found.\n", path);
269 err
= insmod_do(mod
, extra_options
);
270 kmod_module_unref(mod
);
274 static int insmod_alias(struct kmod_ctx
*ctx
, const char *alias
, const char *extra_options
)
276 struct kmod_list
*l
, *list
= NULL
;
277 struct kmod_list
*filtered
= NULL
;
280 err
= kmod_module_new_from_lookup(ctx
, alias
, &list
);
285 //LOG("Module %s not found.\n", alias);
289 err
= kmod_module_get_filtered_blacklist(ctx
, list
, &filtered
);
290 kmod_module_unref_list(list
);
292 //LOG("Could not filter alias list!\n");
297 kmod_list_foreach(l
, list
) {
298 struct kmod_module
*mod
= kmod_module_get_module(l
);
299 err
= insmod_do(mod
, extra_options
);
300 kmod_module_unref(mod
);
305 kmod_module_unref_list(list
);
309 static int insmod(struct kmod_ctx
*ctx
, const char *name
, const char *extra_options
)
312 if (stat(name
, &st
) == 0)
313 return insmod_path(ctx
, name
, extra_options
);
315 return insmod_alias(ctx
, name
, extra_options
);
318 static int builtin_kmod(struct udev_device
*dev
, int argc
, char *argv
[], bool test
)
320 struct udev
*udev
= udev_device_get_udev(dev
);
327 err(udev
, "missing command + argument\n");
331 for (i
= 2; argv
[i
]; i
++) {
332 info(udev
, "%s '%s'\n", argv
[1], argv
[i
]);
333 insmod(ctx
, argv
[i
], NULL
);
339 static int builtin_kmod_load(struct udev
*udev
)
342 ctx
= kmod_new(NULL
, NULL
);
346 info(udev
, "load module index\n");
350 static int builtin_kmod_unload(struct udev
*udev
)
353 info(udev
, "unload module index\n");
357 const struct udev_builtin udev_builtin_kmod
= {
360 .load
= builtin_kmod_load
,
361 .unload
= builtin_kmod_unload
,
362 .help
= "kernel module loader",