blob: 7d9c667f465595afab051de0ef16fd4a2dd66366 [file] [log] [blame]
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001/*
2 * kmod-modprob - manage linux kernel modules using libkmod.
3 *
Lucas De Marchia66a6a92012-01-09 00:40:50 -02004 * Copyright (C) 2011-2012 ProFUSION embedded systems
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02005 *
Lucas De Marchicb451f32011-12-12 18:24:35 -02006 * 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.
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020010 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Lucas De Marchicb451f32011-12-12 18:24:35 -020013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020015 *
Lucas De Marchicb451f32011-12-12 18:24:35 -020016 * 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/>.
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020018 */
Lucas De Marchicb451f32011-12-12 18:24:35 -020019
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020020#include <stdio.h>
21#include <stdlib.h>
22#include <getopt.h>
23#include <errno.h>
24#include <string.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/utsname.h>
28#include <unistd.h>
29#include <syslog.h>
30#include <limits.h>
31
32#include "libkmod.h"
33
34static int log_priority = LOG_CRIT;
35static int use_syslog = 0;
36
37#define DEFAULT_VERBOSE LOG_WARNING
38static int verbose = DEFAULT_VERBOSE;
Gustavo Sverzut Barbieri525fa072012-01-08 13:58:28 -020039static int do_show = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020040static int dry_run = 0;
41static int ignore_loaded = 0;
Lucas De Marchi81229852011-12-16 02:58:48 -020042static int lookup_only = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020043static int first_time = 0;
44static int ignore_commands = 0;
45static int use_blacklist = 0;
46static int force = 0;
47static int strip_modversion = 0;
48static int strip_vermagic = 0;
49static int remove_dependencies = 0;
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -020050static int quiet_inuse = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020051
Dave Reisnerb09668c2011-12-31 16:51:40 -050052static const char cmdopts_s[] = "arRibft:DcnC:d:S:sqvVh";
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020053static const struct option cmdopts[] = {
54 {"all", no_argument, 0, 'a'},
55 {"remove", no_argument, 0, 'r'},
56 {"remove-dependencies", no_argument, 0, 5},
57 {"resolve-alias", no_argument, 0, 'R'},
58 {"first-time", no_argument, 0, 3},
59 {"ignore-install", no_argument, 0, 'i'},
60 {"ignore-remove", no_argument, 0, 'i'},
61 {"use-blacklist", no_argument, 0, 'b'},
62 {"force", no_argument, 0, 'f'},
63 {"force-modversion", no_argument, 0, 2},
64 {"force-vermagic", no_argument, 0, 1},
65
66 {"type", required_argument, 0, 't'},
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020067 {"show-depends", no_argument, 0, 'D'},
68 {"showconfig", no_argument, 0, 'c'},
69 {"show-config", no_argument, 0, 'c'},
70 {"show-modversions", no_argument, 0, 4},
71 {"dump-modversions", no_argument, 0, 4},
72
73 {"dry-run", no_argument, 0, 'n'},
74 {"show", no_argument, 0, 'n'},
75
76 {"config", required_argument, 0, 'C'},
77 {"dirname", required_argument, 0, 'd'},
78 {"set-version", required_argument, 0, 'S'},
79
80 {"syslog", no_argument, 0, 's'},
81 {"quiet", no_argument, 0, 'q'},
82 {"verbose", no_argument, 0, 'v'},
83 {"version", no_argument, 0, 'V'},
84 {"help", no_argument, 0, 'h'},
85 {NULL, 0, 0, 0}
86};
87
88static void help(const char *progname)
89{
90 fprintf(stderr,
91 "Usage:\n"
92 "\t%s [options] [-i] [-b] modulename\n"
93 "\t%s [options] -a [-i] [-b] modulename [modulename...]\n"
94 "\t%s [options] -r [-i] modulename\n"
95 "\t%s [options] -r -a [-i] modulename [modulename...]\n"
96 "\t%s [options] -l [-t dirname] [wildcard]\n"
97 "\t%s [options] -c\n"
98 "\t%s [options] --dump-modversions filename\n"
99 "Management Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200100 "\t-a, --all Consider every non-argument to\n"
101 "\t be a module name to be inserted\n"
102 "\t or removed (-r)\n"
103 "\t-r, --remove Remove modules instead of inserting\n"
104 "\t --remove-dependencies Also remove modules depending on it\n"
105 "\t-R, --resolve-alias Only lookup and print alias and exit\n"
106 "\t --first-time Fail if module already inserted or removed\n"
107 "\t-i, --ignore-install Ignore install commands\n"
108 "\t-i, --ignore-remove Ignore remove commands\n"
109 "\t-b, --use-blacklist Apply blacklist to resolved alias.\n"
110 "\t-f, --force Force module insertion or removal.\n"
111 "\t implies --force-modversions and\n"
112 "\t --force-vermagic\n"
113 "\t --force-modversion Ignore module's version\n"
114 "\t --force-vermagic Ignore module's version magic\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200115 "\n"
116 "Query Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200117 "\t-t, --type=DIR Limit type used by --list\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200118 "\t-D, --show-depends Only print module dependencies and exit\n"
119 "\t-c, --showconfig Print out known configuration and exit\n"
120 "\t-c, --show-config Same as --showconfig\n"
121 "\t --show-modversions Dump module symbol version and exit\n"
122 "\t --dump-modversions Same as --show-modversions\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200123 "\n"
124 "General Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200125 "\t-n, --dry-run Do not execute operations, just print out\n"
126 "\t-n, --show Same as --dry-run\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200127
Lucas De Marchi2c966932011-12-20 16:39:59 -0200128 "\t-C, --config=FILE Use FILE instead of default search paths\n"
Kay Sieversa308abe2011-12-20 17:58:05 +0100129 "\t-d, --dirname=DIR Use DIR as filesystem root for " ROOTPREFIX "/lib/modules\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200130 "\t-S, --set-version=VERSION Use VERSION instead of `uname -r`\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200131
132 "\t-s, --syslog print to syslog, not stderr\n"
133 "\t-q, --quiet disable messages\n"
134 "\t-v, --verbose enables more messages\n"
135 "\t-V, --version show version\n"
136 "\t-h, --help show this help\n",
137 progname, progname, progname, progname, progname, progname,
138 progname);
139}
140
141static inline void _show(const char *fmt, ...)
142{
143 va_list args;
144
Gustavo Sverzut Barbieri525fa072012-01-08 13:58:28 -0200145 if (!do_show && verbose <= DEFAULT_VERBOSE)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200146 return;
147
148 va_start(args, fmt);
149 vfprintf(stdout, fmt, args);
150 fflush(stdout);
151 va_end(args);
152}
153
154static inline void _log(int prio, const char *fmt, ...)
155{
156 const char *prioname;
157 char buf[32], *msg;
158 va_list args;
159
160 if (prio > verbose)
161 return;
162
163 va_start(args, fmt);
164 if (vasprintf(&msg, fmt, args) < 0)
165 msg = NULL;
166 va_end(args);
167 if (msg == NULL)
168 return;
169
170 switch (prio) {
171 case LOG_CRIT:
172 prioname = "FATAL";
173 break;
174 case LOG_ERR:
175 prioname = "ERROR";
176 break;
177 case LOG_WARNING:
178 prioname = "WARNING";
179 break;
180 case LOG_NOTICE:
181 prioname = "NOTICE";
182 break;
183 case LOG_INFO:
184 prioname = "INFO";
185 break;
186 case LOG_DEBUG:
187 prioname = "DEBUG";
188 break;
189 default:
190 snprintf(buf, sizeof(buf), "LOG-%03d", prio);
191 prioname = buf;
192 }
193
194 if (use_syslog)
195 syslog(LOG_NOTICE, "%s: %s", prioname, msg);
196 else
197 fprintf(stderr, "%s: %s", prioname, msg);
198 free(msg);
199
200 if (prio <= LOG_CRIT)
201 exit(EXIT_FAILURE);
202}
203#define ERR(...) _log(LOG_ERR, __VA_ARGS__)
204#define WRN(...) _log(LOG_WARNING, __VA_ARGS__)
205#define INF(...) _log(LOG_INFO, __VA_ARGS__)
206#define DBG(...) _log(LOG_DEBUG, __VA_ARGS__)
207#define LOG(...) _log(log_priority, __VA_ARGS__)
208#define SHOW(...) _show(__VA_ARGS__)
209
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200210static int show_config(struct kmod_ctx *ctx)
211{
212 ERR("TODO - config is missing in kmod.\n");
213 /*
214 needs:
215 struct kmod_list *kmod_get_config(struct kmod_ctx *ctx);
216 kmod_config_get_type() {alias,options,blacklist,install,remove,softdeps}
217 kmod_config_get_key()
218 kmod_config_get_value()
219 kmod_config_unref_list()
220 */
221 return -ENOENT;
222}
223
224static int show_modversions(struct kmod_ctx *ctx, const char *filename)
225{
Gustavo Sverzut Barbieri0e3e2f42011-12-19 12:45:22 -0200226 struct kmod_list *l, *list = NULL;
227 struct kmod_module *mod;
228 int err = kmod_module_new_from_path(ctx, filename, &mod);
229 if (err < 0) {
230 LOG("Module %s not found.\n", filename);
231 return err;
232 }
233
234 err = kmod_module_get_versions(mod, &list);
235 if (err < 0) {
Dave Reisner63698372012-01-04 10:41:50 -0500236 LOG("could not get modversions of %s: %s\n",
Gustavo Sverzut Barbieri0e3e2f42011-12-19 12:45:22 -0200237 filename, strerror(-err));
238 kmod_module_unref(mod);
239 return err;
240 }
241
242 kmod_list_foreach(l, list) {
243 const char *symbol = kmod_module_version_get_symbol(l);
244 uint64_t crc = kmod_module_version_get_crc(l);
245 printf("0x%08"PRIx64"\t%s\n", crc, symbol);
246 }
247 kmod_module_versions_free_list(list);
248 kmod_module_unref(mod);
249 return 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200250}
251
252static int command_do(struct kmod_module *module, const char *type, const char *command, const char *cmdline_opts)
253{
254 const char *modname = kmod_module_get_name(module);
255 char *p, *cmd = NULL;
256 size_t cmdlen, cmdline_opts_len, varlen;
257 int ret = 0;
258
259 if (cmdline_opts == NULL)
260 cmdline_opts = "";
261 cmdline_opts_len = strlen(cmdline_opts);
262
263 cmd = strdup(command);
264 if (cmd == NULL)
265 return -ENOMEM;
266 cmdlen = strlen(cmd);
267 varlen = sizeof("$CMDLINE_OPTS") - 1;
268 while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) {
269 size_t prefixlen = p - cmd;
270 size_t suffixlen = cmdlen - prefixlen - varlen;
271 size_t slen = cmdlen - varlen + cmdline_opts_len;
272 char *suffix = p + varlen;
273 char *s = malloc(slen + 1);
274 if (s == NULL) {
275 free(cmd);
276 return -ENOMEM;
277 }
278 memcpy(s, cmd, p - cmd);
279 memcpy(s + prefixlen, cmdline_opts, cmdline_opts_len);
280 memcpy(s + prefixlen + cmdline_opts_len, suffix, suffixlen);
281 s[slen] = '\0';
282
283 free(cmd);
284 cmd = s;
285 cmdlen = slen;
286 }
287
288 SHOW("%s %s\n", type, cmd);
289 if (dry_run)
290 goto end;
291
292 setenv("MODPROBE_MODULE", modname, 1);
293 ret = system(cmd);
294 unsetenv("MODPROBE_MODULE");
295 if (ret == -1 || WEXITSTATUS(ret)) {
296 LOG("Error running %s command for %s\n", type, modname);
297 if (ret != -1)
298 ret = -WEXITSTATUS(ret);
299 }
300
301end:
302 free(cmd);
303 return ret;
304}
305
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200306static int rmmod_do_dependencies(struct kmod_module *parent);
307static int rmmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200308
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200309static int rmmod_do_deps_list(struct kmod_module *parent, struct kmod_list *deps, unsigned stop_on_errors)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200310{
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200311 struct kmod_list *d;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200312 int err = 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200313
314 kmod_list_foreach_reverse(d, deps) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200315 struct kmod_module *dm = kmod_module_get_module(d);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200316 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200317 const char *cmd, *dmname = kmod_module_get_name(dm);
318 int r;
319
320 r = rmmod_do_dependencies(dm);
321 if (r < 0) {
322 WRN("could not remove dependencies of '%s': %s\n",
323 dmname, strerror(-r));
324 goto dep_error;
325 }
326
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200327 r = kmod_module_get_softdeps(dm, &pre, &post);
328 if (r < 0) {
329 WRN("could not get softdeps of '%s': %s\n",
330 dmname, strerror(-r));
331 goto dep_done;
332 }
333
334 r = rmmod_do_soft_dependencies(dm, post);
335 if (r < 0) {
336 WRN("could not remove post soft softdeps of '%s': %s\n",
337 dmname, strerror(-r));
338 goto dep_error;
339 }
340
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200341 if (!ignore_loaded) {
342 int state = kmod_module_get_initstate(dm);
343 if (state != KMOD_MODULE_LIVE &&
344 state != KMOD_MODULE_COMING)
345 goto dep_done;
346 }
347
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200348 cmd = kmod_module_get_remove_commands(dm);
349 if (cmd) {
350 r = command_do(dm, "remove", cmd, NULL);
351 if (r < 0) {
352 WRN("failed to execute remove command of '%s': "
353 "%s\n", dmname, strerror(-r));
354 goto dep_error;
355 } else
356 goto dep_done;
357 }
358
359 r = kmod_module_get_refcnt(dm);
360 if (r < 0) {
361 WRN("could not get module '%s' refcnt: %s\n",
362 dmname, strerror(-r));
363 goto dep_error;
364 } else if (r > 0 && !ignore_loaded) {
365 LOG("Module %s is in use.\n", dmname);
366 r = -EBUSY;
367 goto dep_error;
368 }
369
370 SHOW("rmmod %s\n", dmname);
371
372 if (!dry_run) {
373 r = kmod_module_remove_module(dm, 0);
374 if (r < 0) {
375 WRN("could not remove '%s': %s\n",
376 dmname, strerror(-r));
377 goto dep_error;
378 }
379 }
380
381 dep_done:
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200382 r = rmmod_do_soft_dependencies(dm, pre);
383 if (r < 0) {
384 WRN("could not remove pre softdeps of '%s': %s\n",
385 dmname, strerror(-r));
386 goto dep_error;
387 }
388 kmod_module_unref_list(pre);
389 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200390 kmod_module_unref(dm);
391 continue;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200392
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200393 dep_error:
394 err = r;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200395 kmod_module_unref_list(pre);
396 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200397 kmod_module_unref(dm);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200398 if (stop_on_errors)
399 break;
400 else
401 continue;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200402 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200403
404 return err;
405}
406
407static int rmmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps)
408{
409 return rmmod_do_deps_list(mod, deps, 0);
410}
411
412static int rmmod_do_dependencies(struct kmod_module *parent)
413{
414 struct kmod_list *deps = kmod_module_get_holders(parent);
415 int err = rmmod_do_deps_list(parent, deps, 1);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200416 kmod_module_unref_list(deps);
417 return err;
418}
419
420static int rmmod_do(struct kmod_module *mod)
421{
422 const char *modname = kmod_module_get_name(mod);
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200423 struct kmod_list *pre = NULL, *post = NULL, *deps;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200424 int err;
425
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200426 if (!ignore_commands) {
427 const char *cmd;
428
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200429 err = kmod_module_get_softdeps(mod, &pre, &post);
430 if (err < 0) {
431 WRN("could not get softdeps of '%s': %s\n",
432 modname, strerror(-err));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200433 return err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200434 }
435
436 err = rmmod_do_soft_dependencies(mod, post);
437 if (err < 0) {
438 WRN("could not remove post softdeps of '%s': %s\n",
439 modname, strerror(-err));
440 goto error;
441 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200442
443 cmd = kmod_module_get_remove_commands(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200444 if (cmd != NULL) {
445 err = command_do(mod, "remove", cmd, NULL);
446 goto done;
447 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200448 }
449
450 if (!ignore_loaded) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200451 int state = kmod_module_get_initstate(mod);
452
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200453 if (state < 0) {
454 LOG ("Module %s not found.\n", modname);
455 return -ENOENT;
456 } else if (state == KMOD_MODULE_BUILTIN) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200457 LOG("Module %s is builtin.\n", modname);
458 return -ENOENT;
459 } else if (state != KMOD_MODULE_LIVE) {
460 if (first_time) {
461 LOG("Module %s is not in kernel.\n", modname);
462 return -ENOENT;
463 } else
464 return 0;
465 }
466 }
467
468 /* not in original modprobe -r, but helpful */
469 if (remove_dependencies) {
470 err = rmmod_do_dependencies(mod);
471 if (err < 0)
472 return err;
473 }
474
475 if (!ignore_loaded) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200476 int usage = kmod_module_get_refcnt(mod);
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200477
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200478 if (usage > 0) {
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200479 if (!quiet_inuse)
480 LOG("Module %s is in use.\n", modname);
481
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200482 err = -EBUSY;
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200483 goto done_deps;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200484 }
485 }
486
487 SHOW("rmmod %s\n", modname);
488
489 if (dry_run)
490 err = 0;
491 else {
492 int flags = 0;
493
494 if (force)
495 flags |= KMOD_REMOVE_FORCE;
496
497 err = kmod_module_remove_module(mod, flags);
498 if (err == -EEXIST) {
499 if (!first_time)
500 err = 0;
501 else
502 LOG("Module %s is not in kernel.\n", modname);
503 }
504 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200505
506done:
507 if (!ignore_commands) {
508 err = rmmod_do_soft_dependencies(mod, pre);
509 if (err < 0) {
510 WRN("could not remove pre softdeps of '%s': %s\n",
511 modname, strerror(-err));
512 goto error;
513 }
514 }
515
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200516done_deps:
Dave Reisner0e9bd2d2011-12-31 18:02:45 -0500517 deps = kmod_module_get_dependencies(mod);
Lucas De Marchic9a14442012-01-01 05:55:25 -0200518 if (deps != NULL) {
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200519 struct kmod_list *itr;
520
521 first_time = 0;
522 ignore_commands = 0;
523 quiet_inuse = 1;
524
Dave Reisner0e9bd2d2011-12-31 18:02:45 -0500525 kmod_list_foreach(itr, deps) {
526 struct kmod_module *dep = kmod_module_get_module(itr);
Lucas De Marchic9a14442012-01-01 05:55:25 -0200527
528 if (kmod_module_get_refcnt(dep) == 0)
Dave Reisner0e9bd2d2011-12-31 18:02:45 -0500529 rmmod_do(dep);
Lucas De Marchic9a14442012-01-01 05:55:25 -0200530
531 kmod_module_unref(dep);
Dave Reisner0e9bd2d2011-12-31 18:02:45 -0500532 }
533 kmod_module_unref_list(deps);
534 }
535
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200536error:
537 kmod_module_unref_list(pre);
538 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200539 return err;
540}
541
542static int rmmod_path(struct kmod_ctx *ctx, const char *path)
543{
544 struct kmod_module *mod;
545 int err;
546
547 err = kmod_module_new_from_path(ctx, path, &mod);
548 if (err < 0) {
549 LOG("Module %s not found.\n", path);
550 return err;
551 }
552 err = rmmod_do(mod);
553 kmod_module_unref(mod);
554 return err;
555}
556
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200557static int rmmod_alias(struct kmod_ctx *ctx, const char *alias)
558{
559 struct kmod_list *l, *list = NULL;
560 int err;
561
562 err = kmod_module_new_from_lookup(ctx, alias, &list);
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200563 if (err < 0)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200564 return err;
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200565
566 if (list == NULL)
567 LOG("Module %s not found.\n", alias);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200568
569 kmod_list_foreach(l, list) {
570 struct kmod_module *mod = kmod_module_get_module(l);
571 err = rmmod_do(mod);
572 kmod_module_unref(mod);
573 if (err < 0)
574 break;
575 }
576
577 kmod_module_unref_list(list);
578 return err;
579}
580
581static int rmmod(struct kmod_ctx *ctx, const char *name)
582{
Dave Reisnerd98880a2011-12-31 18:02:30 -0500583 if (access(name, F_OK) == 0)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200584 return rmmod_path(ctx, name);
585 else
586 return rmmod_alias(ctx, name);
587}
588
589static int rmmod_all(struct kmod_ctx *ctx, char **args, int nargs)
590{
591 int i, err = 0;
592
593 for (i = 0; i < nargs; i++) {
594 int r = rmmod(ctx, args[i]);
595 if (r < 0)
596 err = r;
597 }
598
599 return err;
600}
601
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200602static int insmod_do_dependencies(struct kmod_module *parent);
603static int insmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200604
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200605static int insmod_do_deps_list(struct kmod_module *parent, struct kmod_list *deps, unsigned stop_on_errors)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200606{
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200607 struct kmod_list *d;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200608 int err = 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200609
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200610 kmod_list_foreach(d, deps) {
611 struct kmod_module *dm = kmod_module_get_module(d);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200612 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200613 const char *cmd, *opts, *dmname = kmod_module_get_name(dm);
614 int r;
615
616 r = insmod_do_dependencies(dm);
617 if (r < 0) {
618 WRN("could not insert dependencies of '%s': %s\n",
619 dmname, strerror(-r));
620 goto dep_error;
621 }
622
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200623 r = kmod_module_get_softdeps(dm, &pre, &post);
624 if (r < 0) {
625 WRN("could not get softdeps of '%s': %s\n",
626 dmname, strerror(-r));
627 goto dep_done;
628 }
629
630 r = insmod_do_soft_dependencies(dm, pre);
631 if (r < 0) {
632 WRN("could not insert pre softdeps of '%s': %s\n",
633 dmname, strerror(-r));
634 goto dep_error;
635 }
636
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200637 if (!ignore_loaded) {
638 int state = kmod_module_get_initstate(dm);
639 if (state == KMOD_MODULE_LIVE ||
640 state == KMOD_MODULE_COMING ||
641 state == KMOD_MODULE_BUILTIN)
642 goto dep_done;
643 }
644
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200645 cmd = kmod_module_get_install_commands(dm);
646 if (cmd) {
647 r = command_do(dm, "install", cmd, NULL);
648 if (r < 0) {
649 WRN("failed to execute install command of '%s':"
650 " %s\n", dmname, strerror(-r));
651 goto dep_error;
652 } else
653 goto dep_done;
654 }
655
656 opts = kmod_module_get_options(dm);
657 SHOW("insmod %s %s\n",
658 kmod_module_get_path(dm), opts ? opts : "");
659
660 if (!dry_run) {
661 int flags = 0;
662
663 if (strip_modversion || force)
664 flags |= KMOD_INSERT_FORCE_MODVERSION;
665 if (strip_vermagic || force)
666 flags |= KMOD_INSERT_FORCE_VERMAGIC;
667
668 r = kmod_module_insert_module(dm, flags, opts);
Lucas De Marchicb0d0b72012-01-08 18:08:05 -0200669 if (r == -EEXIST && !first_time)
670 r = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200671 if (r < 0) {
672 WRN("could not insert '%s': %s\n",
Lucas De Marchicb0d0b72012-01-08 18:08:05 -0200673 dmname, strerror(-r));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200674 goto dep_error;
675 }
676 }
677
678 dep_done:
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200679 r = insmod_do_soft_dependencies(dm, post);
680 if (r < 0) {
681 WRN("could not insert post softdeps of '%s': %s\n",
682 dmname, strerror(-r));
683 goto dep_error;
684 }
685
686 kmod_module_unref_list(pre);
687 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200688 kmod_module_unref(dm);
689 continue;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200690
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200691 dep_error:
692 err = r;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200693 kmod_module_unref_list(pre);
694 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200695 kmod_module_unref(dm);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200696 if (stop_on_errors)
697 break;
698 else
699 continue;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200700 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200701
702 return err;
703}
704
705static int insmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps)
706{
707 return insmod_do_deps_list(mod, deps, 0);
708}
709
710static int insmod_do_dependencies(struct kmod_module *parent)
711{
712 struct kmod_list *deps = kmod_module_get_dependencies(parent);
713 int err = insmod_do_deps_list(parent, deps, 1);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200714 kmod_module_unref_list(deps);
715 return err;
716}
717
718static int insmod_do(struct kmod_module *mod, const char *extra_opts)
719{
720 const char *modname = kmod_module_get_name(mod);
721 const char *conf_opts = kmod_module_get_options(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200722 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200723 char *opts = NULL;
724 int err;
725
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200726 if (!ignore_commands) {
727 const char *cmd;
728
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200729 err = kmod_module_get_softdeps(mod, &pre, &post);
730 if (err < 0) {
731 WRN("could not get softdeps of '%s': %s\n",
732 modname, strerror(-err));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200733 return err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200734 }
735
736 err = insmod_do_soft_dependencies(mod, pre);
737 if (err < 0) {
738 WRN("could not insert pre softdeps of '%s': %s\n",
739 modname, strerror(-err));
740 goto error;
741 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200742
743 cmd = kmod_module_get_install_commands(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200744 if (cmd != NULL) {
745 err = command_do(mod, "install", cmd, extra_opts);
746 goto done;
747 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200748 }
749
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200750 if (!ignore_loaded) {
751 int state = kmod_module_get_initstate(mod);
752
Lucas De Marchi95dd8372011-12-20 13:11:33 -0200753 if (state == KMOD_MODULE_BUILTIN) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200754 if (first_time) {
755 LOG("Module %s already in kernel (builtin).\n",
756 modname);
757 return -EEXIST;
758 }
759 return 0;
760 } else if (state == KMOD_MODULE_LIVE) {
761 if (first_time) {
762 LOG("Module %s already in kernel.\n", modname);
763 return -EEXIST;
764 }
765 return 0;
766 }
767 }
768
Lucas De Marchi95dd8372011-12-20 13:11:33 -0200769 /*
770 * At this point it's not possible to be a install/remove command
771 * anymore. So if we can't get module's path, it's because it was
772 * really intended to be a module and it doesn't exist
773 */
774 if (kmod_module_get_path(mod) == NULL) {
775 LOG("Module %s not found.\n", modname);
776 return -ENOENT;
777 }
778
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200779 err = insmod_do_dependencies(mod);
780 if (err < 0)
781 return err;
782
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200783 if (conf_opts || extra_opts) {
784 if (conf_opts == NULL)
785 opts = strdup(extra_opts);
786 else if (extra_opts == NULL)
787 opts = strdup(conf_opts);
788 else if (asprintf(&opts, "%s %s", conf_opts, extra_opts) < 0)
789 opts = NULL;
790
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200791 if (opts == NULL) {
792 err = -ENOMEM;
793 goto error;
794 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200795 }
796
797 SHOW("insmod %s %s\n", kmod_module_get_path(mod), opts ? opts : "");
798
799 if (dry_run)
800 err = 0;
801 else {
802 int flags = 0;
803
804 if (strip_modversion || force)
805 flags |= KMOD_INSERT_FORCE_MODVERSION;
806 if (strip_vermagic || force)
807 flags |= KMOD_INSERT_FORCE_VERMAGIC;
808
809 err = kmod_module_insert_module(mod, flags, opts);
810 if (err == -EEXIST) {
811 if (!first_time)
812 err = 0;
813 else
814 ERR("Module %s already in kernel.\n",
815 kmod_module_get_name(mod));
816 }
817 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200818
819done:
820 if (!ignore_commands) {
821 err = insmod_do_soft_dependencies(mod, post);
822 if (err < 0) {
823 WRN("could not insert post softdeps of '%s': %s\n",
824 modname, strerror(-err));
825 goto error;
826 }
827 }
828
829error:
830 kmod_module_unref_list(pre);
831 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200832 free(opts);
833 return err;
834}
835
836static int insmod_path(struct kmod_ctx *ctx, const char *path, const char *extra_options)
837{
838 struct kmod_module *mod;
839 int err;
840
841 err = kmod_module_new_from_path(ctx, path, &mod);
842 if (err < 0) {
843 LOG("Module %s not found.\n", path);
844 return err;
845 }
846 err = insmod_do(mod, extra_options);
847 kmod_module_unref(mod);
848 return err;
849}
850
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200851static int insmod_alias(struct kmod_ctx *ctx, const char *alias, const char *extra_options)
852{
853 struct kmod_list *l, *list = NULL;
854 int err;
855
856 err = kmod_module_new_from_lookup(ctx, alias, &list);
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200857 if (err < 0)
858 return err;
859
860 if (list == NULL) {
861 LOG("Module %s not found.\n", alias);
Dave Reisner7f374912012-01-05 22:56:54 -0500862 return -ENOENT;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200863 }
864
865 if (use_blacklist) {
866 struct kmod_list *filtered = NULL;
867 err = kmod_module_get_filtered_blacklist(ctx, list, &filtered);
868 DBG("using blacklist: input %p, output=%p\n", list, filtered);
869 kmod_module_unref_list(list);
870 if (err < 0) {
Dave Reisner63698372012-01-04 10:41:50 -0500871 LOG("could not filter alias list!\n");
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200872 return err;
873 }
874 list = filtered;
875 }
876
877 kmod_list_foreach(l, list) {
878 struct kmod_module *mod = kmod_module_get_module(l);
Lucas De Marchi81229852011-12-16 02:58:48 -0200879 if (lookup_only)
880 printf("%s\n", kmod_module_get_name(mod));
881 else
882 err = insmod_do(mod, extra_options);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200883 kmod_module_unref(mod);
884 if (err < 0)
885 break;
886 }
887
888 kmod_module_unref_list(list);
889 return err;
890}
891
892static int insmod(struct kmod_ctx *ctx, const char *name, const char *extra_options)
893{
894 struct stat st;
895 if (stat(name, &st) == 0)
896 return insmod_path(ctx, name, extra_options);
897 else
898 return insmod_alias(ctx, name, extra_options);
899}
900
901static int insmod_all(struct kmod_ctx *ctx, char **args, int nargs)
902{
903 int i, err = 0;
904
905 for (i = 0; i < nargs; i++) {
906 int r = insmod(ctx, args[i], NULL);
907 if (r < 0)
908 err = r;
909 }
910
911 return err;
912}
913
914static void env_modprobe_options_append(const char *value)
915{
916 const char *old = getenv("MODPROBE_OPTIONS");
917 char *env;
918
919 if (old == NULL) {
920 setenv("MODPROBE_OPTIONS", value, 1);
921 return;
922 }
923
924 if (asprintf(&env, "%s %s", old, value) < 0) {
925 ERR("could not append value to $MODPROBE_OPTIONS\n");
926 return;
927 }
928
929 if (setenv("MODPROBE_OPTIONS", env, 1) < 0)
930 ERR("could not setenv(MODPROBE_OPTIONS, \"%s\")\n", env);
931 free(env);
932}
933
934static int options_from_array(char **args, int nargs, char **output)
935{
936 char *opts = NULL;
937 size_t optslen = 0;
938 int i, err = 0;
939
940 for (i = 1; i < nargs; i++) {
941 size_t len = strlen(args[i]);
942 size_t qlen = 0;
943 const char *value;
944 void *tmp;
945
946 value = strchr(args[i], '=');
947 if (value) {
948 value++;
949 if (*value != '"' && *value != '\'') {
950 if (strchr(value, ' '))
951 qlen = 2;
952 }
953 }
954
955 tmp = realloc(opts, optslen + len + qlen + 2);
956 if (!tmp) {
957 err = -errno;
958 free(opts);
959 opts = NULL;
960 ERR("could not gather module options: out-of-memory\n");
961 break;
962 }
963 opts = tmp;
964 if (optslen > 0) {
965 opts[optslen] = ' ';
966 optslen++;
967 }
968 if (qlen == 0) {
969 memcpy(opts + optslen, args[i], len + 1);
970 optslen += len;
971 } else {
972 size_t keylen = value - args[i];
973 size_t valuelen = len - keylen;
974 memcpy(opts + optslen, args[i], keylen);
975 optslen += keylen;
976 opts[optslen] = '"';
977 optslen++;
978 memcpy(opts + optslen, value, valuelen);
979 optslen += valuelen;
980 opts[optslen] = '"';
981 optslen++;
982 opts[optslen] = '\0';
983 }
984 }
985
986 *output = opts;
987 return err;
988}
989
990static char **prepend_options_from_env(int *p_argc, char **orig_argv)
991{
992 const char *p, *env = getenv("MODPROBE_OPTIONS");
993 char **new_argv, *str_start, *str_end, *str, *s, *quote;
994 int i, argc = *p_argc;
995 size_t envlen, space_count = 0;
996
997 if (env == NULL)
998 return orig_argv;
999
1000 for (p = env; *p != '\0'; p++) {
1001 if (*p == ' ')
1002 space_count++;
1003 }
1004
1005 envlen = p - env;
1006 new_argv = malloc(sizeof(char *) * (argc + space_count + 3 + envlen));
1007 if (new_argv == NULL)
1008 return NULL;
1009
1010 new_argv[0] = orig_argv[0];
1011 str_start = str = (char *) (new_argv + argc + space_count + 3);
1012 memcpy(str, env, envlen + 1);
1013
1014 str_end = str_start + envlen;
1015
1016 quote = NULL;
1017 for (i = 1, s = str; *s != '\0'; s++) {
1018 if (quote == NULL) {
1019 if (*s == ' ') {
1020 new_argv[i] = str;
1021 i++;
1022 *s = '\0';
1023 str = s + 1;
1024 } else if (*s == '"' || *s == '\'')
1025 quote = s;
1026 } else {
1027 if (*s == *quote) {
1028 if (quote == str) {
1029 new_argv[i] = str + 1;
1030 i++;
1031 *s = '\0';
1032 str = s + 1;
1033 } else {
1034 char *it;
1035 for (it = quote; it < s - 1; it++)
1036 it[0] = it[1];
1037 for (it = s - 1; it < str_end - 2; it++)
1038 it[0] = it[2];
1039 str_end -= 2;
1040 *str_end = '\0';
1041 s -= 2;
1042 }
1043 quote = NULL;
1044 }
1045 }
1046 }
1047 if (str < s) {
1048 new_argv[i] = str;
1049 i++;
1050 }
1051
1052 memcpy(new_argv + i, orig_argv + 1, sizeof(char *) * (argc - 1));
1053 new_argv[i + argc] = NULL;
1054 *p_argc = i + argc - 1;
1055
1056 return new_argv;
1057}
1058
1059static void log_syslog(void *data, int priority, const char *file, int line,
1060 const char *fn, const char *format,
1061 va_list args)
1062{
1063 char *str, buf[32];
1064 const char *prioname;
1065
1066 switch (priority) {
1067 case LOG_CRIT:
1068 prioname = "FATAL";
1069 break;
1070 case LOG_ERR:
1071 prioname = "ERROR";
1072 break;
1073 case LOG_WARNING:
1074 prioname = "WARNING";
1075 break;
1076 case LOG_NOTICE:
1077 prioname = "NOTICE";
1078 break;
1079 case LOG_INFO:
1080 prioname = "INFO";
1081 break;
1082 case LOG_DEBUG:
1083 prioname = "DEBUG";
1084 break;
1085 default:
1086 snprintf(buf, sizeof(buf), "LOG-%03d", priority);
1087 prioname = buf;
1088 }
1089
1090 if (vasprintf(&str, format, args) < 0)
1091 return;
1092#ifdef ENABLE_DEBUG
1093 syslog(LOG_NOTICE, "%s: %s:%d %s() %s", prioname, file, line, fn, str);
1094#else
1095 syslog(LOG_NOTICE, "%s: %s", prioname, str);
1096#endif
1097 free(str);
1098 (void)data;
1099}
1100
Lucas De Marchifa29c0e2011-12-22 03:54:46 -02001101static int do_modprobe(int argc, char **orig_argv)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001102{
1103 struct kmod_ctx *ctx;
1104 char **args = NULL, **argv;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001105 const char **config_paths = NULL;
1106 int nargs = 0, n_config_paths = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001107 char dirname_buf[PATH_MAX];
1108 const char *dirname = NULL;
1109 const char *root = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001110 const char *kversion = NULL;
1111 const char *list_type = NULL;
1112 int use_all = 0;
1113 int do_remove = 0;
1114 int do_show_config = 0;
1115 int do_show_modversions = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001116 int err;
1117
1118 argv = prepend_options_from_env(&argc, orig_argv);
1119 if (argv == NULL) {
1120 fputs("Error: could not prepend options from command line\n",
1121 stderr);
1122 return EXIT_FAILURE;
1123 }
1124
1125 for (;;) {
1126 int c, idx = 0;
1127 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
1128 if (c == -1)
1129 break;
1130 switch (c) {
1131 case 'a':
1132 log_priority = LOG_WARNING;
1133 use_all = 1;
1134 break;
1135 case 'r':
1136 do_remove = 1;
1137 break;
1138 case 5:
1139 remove_dependencies = 1;
1140 break;
1141 case 'R':
Lucas De Marchi81229852011-12-16 02:58:48 -02001142 lookup_only = 1;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001143 break;
1144 case 3:
1145 first_time = 1;
1146 break;
1147 case 'i':
1148 ignore_commands = 1;
1149 break;
1150 case 'b':
1151 use_blacklist = 1;
1152 break;
1153 case 'f':
1154 force = 1;
1155 break;
1156 case 2:
1157 strip_modversion = 1;
1158 break;
1159 case 1:
1160 strip_vermagic = 1;
1161 break;
1162 case 't':
1163 list_type = optarg;
1164 break;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001165 case 'D':
1166 ignore_loaded = 1;
1167 dry_run = 1;
Gustavo Sverzut Barbieri525fa072012-01-08 13:58:28 -02001168 do_show = 1;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001169 break;
1170 case 'c':
1171 do_show_config = 1;
1172 break;
1173 case 4:
1174 do_show_modversions = 1;
1175 break;
1176 case 'n':
1177 dry_run = 1;
1178 break;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001179 case 'C': {
1180 size_t bytes = sizeof(char *) * (n_config_paths + 2);
1181 void *tmp = realloc(config_paths, bytes);
1182 if (!tmp) {
1183 fputs("Error: out-of-memory\n", stderr);
1184 goto cmdline_failed;
1185 }
1186 config_paths = tmp;
1187 config_paths[n_config_paths] = optarg;
1188 n_config_paths++;
1189 config_paths[n_config_paths] = NULL;
1190
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001191 env_modprobe_options_append("-C");
1192 env_modprobe_options_append(optarg);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001193 break;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001194 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001195 case 'd':
1196 root = optarg;
1197 break;
1198 case 'S':
1199 kversion = optarg;
1200 break;
1201 case 's':
1202 env_modprobe_options_append("-s");
1203 use_syslog = 1;
1204 break;
1205 case 'q':
1206 env_modprobe_options_append("-q");
1207 verbose--;
1208 break;
1209 case 'v':
1210 env_modprobe_options_append("-v");
1211 verbose++;
1212 break;
1213 case 'V':
1214 puts(PACKAGE " version " VERSION);
1215 if (argv != orig_argv)
1216 free(argv);
Gustavo Sverzut Barbieri5f9f58f2011-12-21 23:54:35 -02001217 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001218 return EXIT_SUCCESS;
1219 case 'h':
Lucas De Marchi3e8de632011-12-23 01:36:10 -02001220 help(basename(argv[0]));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001221 if (argv != orig_argv)
1222 free(argv);
Gustavo Sverzut Barbieri5f9f58f2011-12-21 23:54:35 -02001223 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001224 return EXIT_SUCCESS;
1225 case '?':
1226 goto cmdline_failed;
1227 default:
1228 fprintf(stderr,
1229 "Error: unexpected getopt_long() value '%c'.\n",
1230 c);
1231 goto cmdline_failed;
1232 }
1233 }
1234
1235 args = argv + optind;
1236 nargs = argc - optind;
1237
Dave Reisnerb09668c2011-12-31 16:51:40 -05001238 if (!do_show_config) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001239 if (nargs == 0) {
1240 fputs("Error: missing parameters. See -h.\n", stderr);
1241 goto cmdline_failed;
1242 }
1243 }
1244
Dave Reisnerb09668c2011-12-31 16:51:40 -05001245 if (list_type != NULL) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001246 fputs("Error: -t (--type) only supported with -l (--list).\n",
1247 stderr);
1248 goto cmdline_failed;
1249 }
1250
1251 if (root != NULL || kversion != NULL) {
1252 struct utsname u;
1253 if (root == NULL)
1254 root = "";
1255 if (kversion == NULL) {
1256 if (uname(&u) < 0) {
1257 fprintf(stderr, "Error: uname() failed: %s\n",
1258 strerror(errno));
1259 goto cmdline_failed;
1260 }
1261 kversion = u.release;
1262 }
Kay Sieversa308abe2011-12-20 17:58:05 +01001263 snprintf(dirname_buf, sizeof(dirname_buf), "%s" ROOTPREFIX "/lib/modules/%s",
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001264 root, kversion);
1265 dirname = dirname_buf;
1266 }
1267
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001268 ctx = kmod_new(dirname, config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001269 if (!ctx) {
1270 fputs("Error: kmod_new() failed!\n", stderr);
1271 goto cmdline_failed;
1272 }
1273 kmod_load_resources(ctx);
1274
1275 kmod_set_log_priority(ctx, verbose);
1276 if (use_syslog) {
1277 openlog("modprobe", LOG_CONS, LOG_DAEMON);
1278 kmod_set_log_fn(ctx, log_syslog, NULL);
1279 }
1280
Dave Reisnerb09668c2011-12-31 16:51:40 -05001281 if (do_show_config)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001282 err = show_config(ctx);
1283 else if (do_show_modversions)
1284 err = show_modversions(ctx, args[0]);
1285 else if (do_remove)
1286 err = rmmod_all(ctx, args, use_all ? nargs : 1);
1287 else if (use_all)
1288 err = insmod_all(ctx, args, nargs);
1289 else {
1290 char *opts;
1291 err = options_from_array(args, nargs, &opts);
1292 if (err == 0) {
1293 err = insmod(ctx, args[0], opts);
1294 free(opts);
1295 }
1296 }
1297
1298 kmod_unref(ctx);
1299
1300 if (use_syslog)
1301 closelog();
1302
1303 if (argv != orig_argv)
1304 free(argv);
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001305 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001306 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1307
1308cmdline_failed:
1309 if (argv != orig_argv)
1310 free(argv);
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001311 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001312 return EXIT_FAILURE;
1313}
Lucas De Marchifa29c0e2011-12-22 03:54:46 -02001314
1315#ifndef KMOD_BUNDLE_TOOL
1316int main(int argc, char *argv[])
1317{
1318 return do_modprobe(argc, argv);
1319}
1320
1321#else
1322#include "kmod.h"
1323
1324const struct kmod_cmd kmod_cmd_compat_modprobe = {
1325 .name = "modprobe",
1326 .cmd = do_modprobe,
1327 .help = "compat modprobe command",
1328};
1329
1330#endif