blob: 6fa1066131653acf911257293cf05b2af873c485 [file] [log] [blame]
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001/*
2 * kmod-modprob - manage linux kernel modules using libkmod.
3 *
4 * Copyright (C) 2011 ProFUSION embedded systems
5 *
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;
39static int dry_run = 0;
40static int ignore_loaded = 0;
Lucas De Marchi81229852011-12-16 02:58:48 -020041static int lookup_only = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020042static int first_time = 0;
43static int ignore_commands = 0;
44static int use_blacklist = 0;
45static int force = 0;
46static int strip_modversion = 0;
47static int strip_vermagic = 0;
48static int remove_dependencies = 0;
49
50static const char cmdopts_s[] = "arRibft:lDcnC:d:S:sqvVh";
51static const struct option cmdopts[] = {
52 {"all", no_argument, 0, 'a'},
53 {"remove", no_argument, 0, 'r'},
54 {"remove-dependencies", no_argument, 0, 5},
55 {"resolve-alias", no_argument, 0, 'R'},
56 {"first-time", no_argument, 0, 3},
57 {"ignore-install", no_argument, 0, 'i'},
58 {"ignore-remove", no_argument, 0, 'i'},
59 {"use-blacklist", no_argument, 0, 'b'},
60 {"force", no_argument, 0, 'f'},
61 {"force-modversion", no_argument, 0, 2},
62 {"force-vermagic", no_argument, 0, 1},
63
64 {"type", required_argument, 0, 't'},
65 {"list", no_argument, 0, 'l'},
66 {"show-depends", no_argument, 0, 'D'},
67 {"showconfig", no_argument, 0, 'c'},
68 {"show-config", no_argument, 0, 'c'},
69 {"show-modversions", no_argument, 0, 4},
70 {"dump-modversions", no_argument, 0, 4},
71
72 {"dry-run", no_argument, 0, 'n'},
73 {"show", no_argument, 0, 'n'},
74
75 {"config", required_argument, 0, 'C'},
76 {"dirname", required_argument, 0, 'd'},
77 {"set-version", required_argument, 0, 'S'},
78
79 {"syslog", no_argument, 0, 's'},
80 {"quiet", no_argument, 0, 'q'},
81 {"verbose", no_argument, 0, 'v'},
82 {"version", no_argument, 0, 'V'},
83 {"help", no_argument, 0, 'h'},
84 {NULL, 0, 0, 0}
85};
86
87static void help(const char *progname)
88{
89 fprintf(stderr,
90 "Usage:\n"
91 "\t%s [options] [-i] [-b] modulename\n"
92 "\t%s [options] -a [-i] [-b] modulename [modulename...]\n"
93 "\t%s [options] -r [-i] modulename\n"
94 "\t%s [options] -r -a [-i] modulename [modulename...]\n"
95 "\t%s [options] -l [-t dirname] [wildcard]\n"
96 "\t%s [options] -c\n"
97 "\t%s [options] --dump-modversions filename\n"
98 "Management Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -020099 "\t-a, --all Consider every non-argument to\n"
100 "\t be a module name to be inserted\n"
101 "\t or removed (-r)\n"
102 "\t-r, --remove Remove modules instead of inserting\n"
103 "\t --remove-dependencies Also remove modules depending on it\n"
104 "\t-R, --resolve-alias Only lookup and print alias and exit\n"
105 "\t --first-time Fail if module already inserted or removed\n"
106 "\t-i, --ignore-install Ignore install commands\n"
107 "\t-i, --ignore-remove Ignore remove commands\n"
108 "\t-b, --use-blacklist Apply blacklist to resolved alias.\n"
109 "\t-f, --force Force module insertion or removal.\n"
110 "\t implies --force-modversions and\n"
111 "\t --force-vermagic\n"
112 "\t --force-modversion Ignore module's version\n"
113 "\t --force-vermagic Ignore module's version magic\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200114 "\n"
115 "Query Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200116 "\t-t, --type=DIR Limit type used by --list\n"
117 "\t-l, --list List known modules\n"
118 "\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
Kay Sieversa308abe2011-12-20 17:58:05 +0100128 "\t-C, --config=FILE Use FILE instead of " SYSCONFDIR "/modprobe.d\n"
129 "\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
145 if (verbose <= DEFAULT_VERBOSE)
146 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
210static int show_list(struct kmod_ctx *ctx, const char *list_type, const char *pattern)
211{
212 ERR("TODO - list is missing in kmod.\n");
213 /*
214 needs:
215 struct kmod_list *kmod_get_dependencies(struct kmod_ctx *ctx);
216 kmod_dependency_get_name()
217 kmod_dependency_get_dependencies()
218 kmod_dependency_unref_list()
219 */
220 return -ENOENT;
221}
222
223static int show_config(struct kmod_ctx *ctx)
224{
225 ERR("TODO - config is missing in kmod.\n");
226 /*
227 needs:
228 struct kmod_list *kmod_get_config(struct kmod_ctx *ctx);
229 kmod_config_get_type() {alias,options,blacklist,install,remove,softdeps}
230 kmod_config_get_key()
231 kmod_config_get_value()
232 kmod_config_unref_list()
233 */
234 return -ENOENT;
235}
236
237static int show_modversions(struct kmod_ctx *ctx, const char *filename)
238{
Gustavo Sverzut Barbieri0e3e2f42011-12-19 12:45:22 -0200239 struct kmod_list *l, *list = NULL;
240 struct kmod_module *mod;
241 int err = kmod_module_new_from_path(ctx, filename, &mod);
242 if (err < 0) {
243 LOG("Module %s not found.\n", filename);
244 return err;
245 }
246
247 err = kmod_module_get_versions(mod, &list);
248 if (err < 0) {
249 LOG("Could not get modversions of %s: %s\n",
250 filename, strerror(-err));
251 kmod_module_unref(mod);
252 return err;
253 }
254
255 kmod_list_foreach(l, list) {
256 const char *symbol = kmod_module_version_get_symbol(l);
257 uint64_t crc = kmod_module_version_get_crc(l);
258 printf("0x%08"PRIx64"\t%s\n", crc, symbol);
259 }
260 kmod_module_versions_free_list(list);
261 kmod_module_unref(mod);
262 return 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200263}
264
265static int command_do(struct kmod_module *module, const char *type, const char *command, const char *cmdline_opts)
266{
267 const char *modname = kmod_module_get_name(module);
268 char *p, *cmd = NULL;
269 size_t cmdlen, cmdline_opts_len, varlen;
270 int ret = 0;
271
272 if (cmdline_opts == NULL)
273 cmdline_opts = "";
274 cmdline_opts_len = strlen(cmdline_opts);
275
276 cmd = strdup(command);
277 if (cmd == NULL)
278 return -ENOMEM;
279 cmdlen = strlen(cmd);
280 varlen = sizeof("$CMDLINE_OPTS") - 1;
281 while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) {
282 size_t prefixlen = p - cmd;
283 size_t suffixlen = cmdlen - prefixlen - varlen;
284 size_t slen = cmdlen - varlen + cmdline_opts_len;
285 char *suffix = p + varlen;
286 char *s = malloc(slen + 1);
287 if (s == NULL) {
288 free(cmd);
289 return -ENOMEM;
290 }
291 memcpy(s, cmd, p - cmd);
292 memcpy(s + prefixlen, cmdline_opts, cmdline_opts_len);
293 memcpy(s + prefixlen + cmdline_opts_len, suffix, suffixlen);
294 s[slen] = '\0';
295
296 free(cmd);
297 cmd = s;
298 cmdlen = slen;
299 }
300
301 SHOW("%s %s\n", type, cmd);
302 if (dry_run)
303 goto end;
304
305 setenv("MODPROBE_MODULE", modname, 1);
306 ret = system(cmd);
307 unsetenv("MODPROBE_MODULE");
308 if (ret == -1 || WEXITSTATUS(ret)) {
309 LOG("Error running %s command for %s\n", type, modname);
310 if (ret != -1)
311 ret = -WEXITSTATUS(ret);
312 }
313
314end:
315 free(cmd);
316 return ret;
317}
318
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200319static int rmmod_do_dependencies(struct kmod_module *parent);
320static int rmmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200321
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200322static 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 -0200323{
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200324 struct kmod_list *d;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200325 int err = 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200326
327 kmod_list_foreach_reverse(d, deps) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200328 struct kmod_module *dm = kmod_module_get_module(d);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200329 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200330 const char *cmd, *dmname = kmod_module_get_name(dm);
331 int r;
332
333 r = rmmod_do_dependencies(dm);
334 if (r < 0) {
335 WRN("could not remove dependencies of '%s': %s\n",
336 dmname, strerror(-r));
337 goto dep_error;
338 }
339
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200340 r = kmod_module_get_softdeps(dm, &pre, &post);
341 if (r < 0) {
342 WRN("could not get softdeps of '%s': %s\n",
343 dmname, strerror(-r));
344 goto dep_done;
345 }
346
347 r = rmmod_do_soft_dependencies(dm, post);
348 if (r < 0) {
349 WRN("could not remove post soft softdeps of '%s': %s\n",
350 dmname, strerror(-r));
351 goto dep_error;
352 }
353
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200354 if (!ignore_loaded) {
355 int state = kmod_module_get_initstate(dm);
356 if (state != KMOD_MODULE_LIVE &&
357 state != KMOD_MODULE_COMING)
358 goto dep_done;
359 }
360
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200361 cmd = kmod_module_get_remove_commands(dm);
362 if (cmd) {
363 r = command_do(dm, "remove", cmd, NULL);
364 if (r < 0) {
365 WRN("failed to execute remove command of '%s': "
366 "%s\n", dmname, strerror(-r));
367 goto dep_error;
368 } else
369 goto dep_done;
370 }
371
372 r = kmod_module_get_refcnt(dm);
373 if (r < 0) {
374 WRN("could not get module '%s' refcnt: %s\n",
375 dmname, strerror(-r));
376 goto dep_error;
377 } else if (r > 0 && !ignore_loaded) {
378 LOG("Module %s is in use.\n", dmname);
379 r = -EBUSY;
380 goto dep_error;
381 }
382
383 SHOW("rmmod %s\n", dmname);
384
385 if (!dry_run) {
386 r = kmod_module_remove_module(dm, 0);
387 if (r < 0) {
388 WRN("could not remove '%s': %s\n",
389 dmname, strerror(-r));
390 goto dep_error;
391 }
392 }
393
394 dep_done:
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200395 r = rmmod_do_soft_dependencies(dm, pre);
396 if (r < 0) {
397 WRN("could not remove pre softdeps of '%s': %s\n",
398 dmname, strerror(-r));
399 goto dep_error;
400 }
401 kmod_module_unref_list(pre);
402 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200403 kmod_module_unref(dm);
404 continue;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200405
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200406 dep_error:
407 err = r;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200408 kmod_module_unref_list(pre);
409 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200410 kmod_module_unref(dm);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200411 if (stop_on_errors)
412 break;
413 else
414 continue;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200415 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200416
417 return err;
418}
419
420static int rmmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps)
421{
422 return rmmod_do_deps_list(mod, deps, 0);
423}
424
425static int rmmod_do_dependencies(struct kmod_module *parent)
426{
427 struct kmod_list *deps = kmod_module_get_holders(parent);
428 int err = rmmod_do_deps_list(parent, deps, 1);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200429 kmod_module_unref_list(deps);
430 return err;
431}
432
433static int rmmod_do(struct kmod_module *mod)
434{
435 const char *modname = kmod_module_get_name(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200436 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200437 int err;
438
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200439 if (!ignore_commands) {
440 const char *cmd;
441
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200442 err = kmod_module_get_softdeps(mod, &pre, &post);
443 if (err < 0) {
444 WRN("could not get softdeps of '%s': %s\n",
445 modname, strerror(-err));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200446 return err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200447 }
448
449 err = rmmod_do_soft_dependencies(mod, post);
450 if (err < 0) {
451 WRN("could not remove post softdeps of '%s': %s\n",
452 modname, strerror(-err));
453 goto error;
454 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200455
456 cmd = kmod_module_get_remove_commands(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200457 if (cmd != NULL) {
458 err = command_do(mod, "remove", cmd, NULL);
459 goto done;
460 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200461 }
462
463 if (!ignore_loaded) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200464 int state = kmod_module_get_initstate(mod);
465
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200466 if (state < 0) {
467 LOG ("Module %s not found.\n", modname);
468 return -ENOENT;
469 } else if (state == KMOD_MODULE_BUILTIN) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200470 LOG("Module %s is builtin.\n", modname);
471 return -ENOENT;
472 } else if (state != KMOD_MODULE_LIVE) {
473 if (first_time) {
474 LOG("Module %s is not in kernel.\n", modname);
475 return -ENOENT;
476 } else
477 return 0;
478 }
479 }
480
481 /* not in original modprobe -r, but helpful */
482 if (remove_dependencies) {
483 err = rmmod_do_dependencies(mod);
484 if (err < 0)
485 return err;
486 }
487
488 if (!ignore_loaded) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200489 int usage = kmod_module_get_refcnt(mod);
490 if (usage > 0) {
491 LOG("Module %s is in use.\n", modname);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200492 err = -EBUSY;
493 goto error;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200494 }
495 }
496
497 SHOW("rmmod %s\n", modname);
498
499 if (dry_run)
500 err = 0;
501 else {
502 int flags = 0;
503
504 if (force)
505 flags |= KMOD_REMOVE_FORCE;
506
507 err = kmod_module_remove_module(mod, flags);
508 if (err == -EEXIST) {
509 if (!first_time)
510 err = 0;
511 else
512 LOG("Module %s is not in kernel.\n", modname);
513 }
514 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200515
516done:
517 if (!ignore_commands) {
518 err = rmmod_do_soft_dependencies(mod, pre);
519 if (err < 0) {
520 WRN("could not remove pre softdeps of '%s': %s\n",
521 modname, strerror(-err));
522 goto error;
523 }
524 }
525
526error:
527 kmod_module_unref_list(pre);
528 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200529 return err;
530}
531
532static int rmmod_path(struct kmod_ctx *ctx, const char *path)
533{
534 struct kmod_module *mod;
535 int err;
536
537 err = kmod_module_new_from_path(ctx, path, &mod);
538 if (err < 0) {
539 LOG("Module %s not found.\n", path);
540 return err;
541 }
542 err = rmmod_do(mod);
543 kmod_module_unref(mod);
544 return err;
545}
546
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200547static int rmmod_alias(struct kmod_ctx *ctx, const char *alias)
548{
549 struct kmod_list *l, *list = NULL;
550 int err;
551
552 err = kmod_module_new_from_lookup(ctx, alias, &list);
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200553 if (err < 0)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200554 return err;
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200555
556 if (list == NULL)
557 LOG("Module %s not found.\n", alias);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200558
559 kmod_list_foreach(l, list) {
560 struct kmod_module *mod = kmod_module_get_module(l);
561 err = rmmod_do(mod);
562 kmod_module_unref(mod);
563 if (err < 0)
564 break;
565 }
566
567 kmod_module_unref_list(list);
568 return err;
569}
570
571static int rmmod(struct kmod_ctx *ctx, const char *name)
572{
573 struct stat st;
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200574
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200575 if (stat(name, &st) == 0)
576 return rmmod_path(ctx, name);
577 else
578 return rmmod_alias(ctx, name);
579}
580
581static int rmmod_all(struct kmod_ctx *ctx, char **args, int nargs)
582{
583 int i, err = 0;
584
585 for (i = 0; i < nargs; i++) {
586 int r = rmmod(ctx, args[i]);
587 if (r < 0)
588 err = r;
589 }
590
591 return err;
592}
593
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200594static int insmod_do_dependencies(struct kmod_module *parent);
595static int insmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200596
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200597static 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 -0200598{
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200599 struct kmod_list *d;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200600 int err = 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200601
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200602 kmod_list_foreach(d, deps) {
603 struct kmod_module *dm = kmod_module_get_module(d);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200604 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200605 const char *cmd, *opts, *dmname = kmod_module_get_name(dm);
606 int r;
607
608 r = insmod_do_dependencies(dm);
609 if (r < 0) {
610 WRN("could not insert dependencies of '%s': %s\n",
611 dmname, strerror(-r));
612 goto dep_error;
613 }
614
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200615 r = kmod_module_get_softdeps(dm, &pre, &post);
616 if (r < 0) {
617 WRN("could not get softdeps of '%s': %s\n",
618 dmname, strerror(-r));
619 goto dep_done;
620 }
621
622 r = insmod_do_soft_dependencies(dm, pre);
623 if (r < 0) {
624 WRN("could not insert pre softdeps of '%s': %s\n",
625 dmname, strerror(-r));
626 goto dep_error;
627 }
628
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200629 if (!ignore_loaded) {
630 int state = kmod_module_get_initstate(dm);
631 if (state == KMOD_MODULE_LIVE ||
632 state == KMOD_MODULE_COMING ||
633 state == KMOD_MODULE_BUILTIN)
634 goto dep_done;
635 }
636
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200637 cmd = kmod_module_get_install_commands(dm);
638 if (cmd) {
639 r = command_do(dm, "install", cmd, NULL);
640 if (r < 0) {
641 WRN("failed to execute install command of '%s':"
642 " %s\n", dmname, strerror(-r));
643 goto dep_error;
644 } else
645 goto dep_done;
646 }
647
648 opts = kmod_module_get_options(dm);
649 SHOW("insmod %s %s\n",
650 kmod_module_get_path(dm), opts ? opts : "");
651
652 if (!dry_run) {
653 int flags = 0;
654
655 if (strip_modversion || force)
656 flags |= KMOD_INSERT_FORCE_MODVERSION;
657 if (strip_vermagic || force)
658 flags |= KMOD_INSERT_FORCE_VERMAGIC;
659
660 r = kmod_module_insert_module(dm, flags, opts);
661 if (r < 0) {
662 WRN("could not insert '%s': %s\n",
663 dmname, strerror(-r));
664 goto dep_error;
665 }
666 }
667
668 dep_done:
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200669 r = insmod_do_soft_dependencies(dm, post);
670 if (r < 0) {
671 WRN("could not insert post softdeps of '%s': %s\n",
672 dmname, strerror(-r));
673 goto dep_error;
674 }
675
676 kmod_module_unref_list(pre);
677 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200678 kmod_module_unref(dm);
679 continue;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200680
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200681 dep_error:
682 err = r;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200683 kmod_module_unref_list(pre);
684 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200685 kmod_module_unref(dm);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200686 if (stop_on_errors)
687 break;
688 else
689 continue;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200690 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200691
692 return err;
693}
694
695static int insmod_do_soft_dependencies(struct kmod_module *mod, struct kmod_list *deps)
696{
697 return insmod_do_deps_list(mod, deps, 0);
698}
699
700static int insmod_do_dependencies(struct kmod_module *parent)
701{
702 struct kmod_list *deps = kmod_module_get_dependencies(parent);
703 int err = insmod_do_deps_list(parent, deps, 1);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200704 kmod_module_unref_list(deps);
705 return err;
706}
707
708static int insmod_do(struct kmod_module *mod, const char *extra_opts)
709{
710 const char *modname = kmod_module_get_name(mod);
711 const char *conf_opts = kmod_module_get_options(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200712 struct kmod_list *pre = NULL, *post = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200713 char *opts = NULL;
714 int err;
715
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200716 if (!ignore_commands) {
717 const char *cmd;
718
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200719 err = kmod_module_get_softdeps(mod, &pre, &post);
720 if (err < 0) {
721 WRN("could not get softdeps of '%s': %s\n",
722 modname, strerror(-err));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200723 return err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200724 }
725
726 err = insmod_do_soft_dependencies(mod, pre);
727 if (err < 0) {
728 WRN("could not insert pre softdeps of '%s': %s\n",
729 modname, strerror(-err));
730 goto error;
731 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200732
733 cmd = kmod_module_get_install_commands(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200734 if (cmd != NULL) {
735 err = command_do(mod, "install", cmd, extra_opts);
736 goto done;
737 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200738 }
739
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200740 if (!ignore_loaded) {
741 int state = kmod_module_get_initstate(mod);
742
Lucas De Marchi95dd8372011-12-20 13:11:33 -0200743 if (state == KMOD_MODULE_BUILTIN) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200744 if (first_time) {
745 LOG("Module %s already in kernel (builtin).\n",
746 modname);
747 return -EEXIST;
748 }
749 return 0;
750 } else if (state == KMOD_MODULE_LIVE) {
751 if (first_time) {
752 LOG("Module %s already in kernel.\n", modname);
753 return -EEXIST;
754 }
755 return 0;
756 }
757 }
758
Lucas De Marchi95dd8372011-12-20 13:11:33 -0200759 /*
760 * At this point it's not possible to be a install/remove command
761 * anymore. So if we can't get module's path, it's because it was
762 * really intended to be a module and it doesn't exist
763 */
764 if (kmod_module_get_path(mod) == NULL) {
765 LOG("Module %s not found.\n", modname);
766 return -ENOENT;
767 }
768
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200769 err = insmod_do_dependencies(mod);
770 if (err < 0)
771 return err;
772
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200773 if (conf_opts || extra_opts) {
774 if (conf_opts == NULL)
775 opts = strdup(extra_opts);
776 else if (extra_opts == NULL)
777 opts = strdup(conf_opts);
778 else if (asprintf(&opts, "%s %s", conf_opts, extra_opts) < 0)
779 opts = NULL;
780
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200781 if (opts == NULL) {
782 err = -ENOMEM;
783 goto error;
784 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200785 }
786
787 SHOW("insmod %s %s\n", kmod_module_get_path(mod), opts ? opts : "");
788
789 if (dry_run)
790 err = 0;
791 else {
792 int flags = 0;
793
794 if (strip_modversion || force)
795 flags |= KMOD_INSERT_FORCE_MODVERSION;
796 if (strip_vermagic || force)
797 flags |= KMOD_INSERT_FORCE_VERMAGIC;
798
799 err = kmod_module_insert_module(mod, flags, opts);
800 if (err == -EEXIST) {
801 if (!first_time)
802 err = 0;
803 else
804 ERR("Module %s already in kernel.\n",
805 kmod_module_get_name(mod));
806 }
807 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200808
809done:
810 if (!ignore_commands) {
811 err = insmod_do_soft_dependencies(mod, post);
812 if (err < 0) {
813 WRN("could not insert post softdeps of '%s': %s\n",
814 modname, strerror(-err));
815 goto error;
816 }
817 }
818
819error:
820 kmod_module_unref_list(pre);
821 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200822 free(opts);
823 return err;
824}
825
826static int insmod_path(struct kmod_ctx *ctx, const char *path, const char *extra_options)
827{
828 struct kmod_module *mod;
829 int err;
830
831 err = kmod_module_new_from_path(ctx, path, &mod);
832 if (err < 0) {
833 LOG("Module %s not found.\n", path);
834 return err;
835 }
836 err = insmod_do(mod, extra_options);
837 kmod_module_unref(mod);
838 return err;
839}
840
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200841static int insmod_alias(struct kmod_ctx *ctx, const char *alias, const char *extra_options)
842{
843 struct kmod_list *l, *list = NULL;
844 int err;
845
846 err = kmod_module_new_from_lookup(ctx, alias, &list);
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200847 if (err < 0)
848 return err;
849
850 if (list == NULL) {
851 LOG("Module %s not found.\n", alias);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200852 return err;
853 }
854
855 if (use_blacklist) {
856 struct kmod_list *filtered = NULL;
857 err = kmod_module_get_filtered_blacklist(ctx, list, &filtered);
858 DBG("using blacklist: input %p, output=%p\n", list, filtered);
859 kmod_module_unref_list(list);
860 if (err < 0) {
861 LOG("Could not filter alias list!\n");
862 return err;
863 }
864 list = filtered;
865 }
866
867 kmod_list_foreach(l, list) {
868 struct kmod_module *mod = kmod_module_get_module(l);
Lucas De Marchi81229852011-12-16 02:58:48 -0200869 if (lookup_only)
870 printf("%s\n", kmod_module_get_name(mod));
871 else
872 err = insmod_do(mod, extra_options);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200873 kmod_module_unref(mod);
874 if (err < 0)
875 break;
876 }
877
878 kmod_module_unref_list(list);
879 return err;
880}
881
882static int insmod(struct kmod_ctx *ctx, const char *name, const char *extra_options)
883{
884 struct stat st;
885 if (stat(name, &st) == 0)
886 return insmod_path(ctx, name, extra_options);
887 else
888 return insmod_alias(ctx, name, extra_options);
889}
890
891static int insmod_all(struct kmod_ctx *ctx, char **args, int nargs)
892{
893 int i, err = 0;
894
895 for (i = 0; i < nargs; i++) {
896 int r = insmod(ctx, args[i], NULL);
897 if (r < 0)
898 err = r;
899 }
900
901 return err;
902}
903
904static void env_modprobe_options_append(const char *value)
905{
906 const char *old = getenv("MODPROBE_OPTIONS");
907 char *env;
908
909 if (old == NULL) {
910 setenv("MODPROBE_OPTIONS", value, 1);
911 return;
912 }
913
914 if (asprintf(&env, "%s %s", old, value) < 0) {
915 ERR("could not append value to $MODPROBE_OPTIONS\n");
916 return;
917 }
918
919 if (setenv("MODPROBE_OPTIONS", env, 1) < 0)
920 ERR("could not setenv(MODPROBE_OPTIONS, \"%s\")\n", env);
921 free(env);
922}
923
924static int options_from_array(char **args, int nargs, char **output)
925{
926 char *opts = NULL;
927 size_t optslen = 0;
928 int i, err = 0;
929
930 for (i = 1; i < nargs; i++) {
931 size_t len = strlen(args[i]);
932 size_t qlen = 0;
933 const char *value;
934 void *tmp;
935
936 value = strchr(args[i], '=');
937 if (value) {
938 value++;
939 if (*value != '"' && *value != '\'') {
940 if (strchr(value, ' '))
941 qlen = 2;
942 }
943 }
944
945 tmp = realloc(opts, optslen + len + qlen + 2);
946 if (!tmp) {
947 err = -errno;
948 free(opts);
949 opts = NULL;
950 ERR("could not gather module options: out-of-memory\n");
951 break;
952 }
953 opts = tmp;
954 if (optslen > 0) {
955 opts[optslen] = ' ';
956 optslen++;
957 }
958 if (qlen == 0) {
959 memcpy(opts + optslen, args[i], len + 1);
960 optslen += len;
961 } else {
962 size_t keylen = value - args[i];
963 size_t valuelen = len - keylen;
964 memcpy(opts + optslen, args[i], keylen);
965 optslen += keylen;
966 opts[optslen] = '"';
967 optslen++;
968 memcpy(opts + optslen, value, valuelen);
969 optslen += valuelen;
970 opts[optslen] = '"';
971 optslen++;
972 opts[optslen] = '\0';
973 }
974 }
975
976 *output = opts;
977 return err;
978}
979
980static char **prepend_options_from_env(int *p_argc, char **orig_argv)
981{
982 const char *p, *env = getenv("MODPROBE_OPTIONS");
983 char **new_argv, *str_start, *str_end, *str, *s, *quote;
984 int i, argc = *p_argc;
985 size_t envlen, space_count = 0;
986
987 if (env == NULL)
988 return orig_argv;
989
990 for (p = env; *p != '\0'; p++) {
991 if (*p == ' ')
992 space_count++;
993 }
994
995 envlen = p - env;
996 new_argv = malloc(sizeof(char *) * (argc + space_count + 3 + envlen));
997 if (new_argv == NULL)
998 return NULL;
999
1000 new_argv[0] = orig_argv[0];
1001 str_start = str = (char *) (new_argv + argc + space_count + 3);
1002 memcpy(str, env, envlen + 1);
1003
1004 str_end = str_start + envlen;
1005
1006 quote = NULL;
1007 for (i = 1, s = str; *s != '\0'; s++) {
1008 if (quote == NULL) {
1009 if (*s == ' ') {
1010 new_argv[i] = str;
1011 i++;
1012 *s = '\0';
1013 str = s + 1;
1014 } else if (*s == '"' || *s == '\'')
1015 quote = s;
1016 } else {
1017 if (*s == *quote) {
1018 if (quote == str) {
1019 new_argv[i] = str + 1;
1020 i++;
1021 *s = '\0';
1022 str = s + 1;
1023 } else {
1024 char *it;
1025 for (it = quote; it < s - 1; it++)
1026 it[0] = it[1];
1027 for (it = s - 1; it < str_end - 2; it++)
1028 it[0] = it[2];
1029 str_end -= 2;
1030 *str_end = '\0';
1031 s -= 2;
1032 }
1033 quote = NULL;
1034 }
1035 }
1036 }
1037 if (str < s) {
1038 new_argv[i] = str;
1039 i++;
1040 }
1041
1042 memcpy(new_argv + i, orig_argv + 1, sizeof(char *) * (argc - 1));
1043 new_argv[i + argc] = NULL;
1044 *p_argc = i + argc - 1;
1045
1046 return new_argv;
1047}
1048
1049static void log_syslog(void *data, int priority, const char *file, int line,
1050 const char *fn, const char *format,
1051 va_list args)
1052{
1053 char *str, buf[32];
1054 const char *prioname;
1055
1056 switch (priority) {
1057 case LOG_CRIT:
1058 prioname = "FATAL";
1059 break;
1060 case LOG_ERR:
1061 prioname = "ERROR";
1062 break;
1063 case LOG_WARNING:
1064 prioname = "WARNING";
1065 break;
1066 case LOG_NOTICE:
1067 prioname = "NOTICE";
1068 break;
1069 case LOG_INFO:
1070 prioname = "INFO";
1071 break;
1072 case LOG_DEBUG:
1073 prioname = "DEBUG";
1074 break;
1075 default:
1076 snprintf(buf, sizeof(buf), "LOG-%03d", priority);
1077 prioname = buf;
1078 }
1079
1080 if (vasprintf(&str, format, args) < 0)
1081 return;
1082#ifdef ENABLE_DEBUG
1083 syslog(LOG_NOTICE, "%s: %s:%d %s() %s", prioname, file, line, fn, str);
1084#else
1085 syslog(LOG_NOTICE, "%s: %s", prioname, str);
1086#endif
1087 free(str);
1088 (void)data;
1089}
1090
1091int main(int argc, char **orig_argv)
1092{
1093 struct kmod_ctx *ctx;
1094 char **args = NULL, **argv;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001095 const char **config_paths = NULL;
1096 int nargs = 0, n_config_paths = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001097 char dirname_buf[PATH_MAX];
1098 const char *dirname = NULL;
1099 const char *root = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001100 const char *kversion = NULL;
1101 const char *list_type = NULL;
1102 int use_all = 0;
1103 int do_remove = 0;
1104 int do_show_config = 0;
1105 int do_show_modversions = 0;
1106 int do_show_list = 0;
1107 int err;
1108
1109 argv = prepend_options_from_env(&argc, orig_argv);
1110 if (argv == NULL) {
1111 fputs("Error: could not prepend options from command line\n",
1112 stderr);
1113 return EXIT_FAILURE;
1114 }
1115
1116 for (;;) {
1117 int c, idx = 0;
1118 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
1119 if (c == -1)
1120 break;
1121 switch (c) {
1122 case 'a':
1123 log_priority = LOG_WARNING;
1124 use_all = 1;
1125 break;
1126 case 'r':
1127 do_remove = 1;
1128 break;
1129 case 5:
1130 remove_dependencies = 1;
1131 break;
1132 case 'R':
Lucas De Marchi81229852011-12-16 02:58:48 -02001133 lookup_only = 1;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001134 break;
1135 case 3:
1136 first_time = 1;
1137 break;
1138 case 'i':
1139 ignore_commands = 1;
1140 break;
1141 case 'b':
1142 use_blacklist = 1;
1143 break;
1144 case 'f':
1145 force = 1;
1146 break;
1147 case 2:
1148 strip_modversion = 1;
1149 break;
1150 case 1:
1151 strip_vermagic = 1;
1152 break;
1153 case 't':
1154 list_type = optarg;
1155 break;
1156 case 'l':
1157 do_show_list = 1;
1158 break;
1159 case 'D':
1160 ignore_loaded = 1;
1161 dry_run = 1;
1162 verbose++;
1163 break;
1164 case 'c':
1165 do_show_config = 1;
1166 break;
1167 case 4:
1168 do_show_modversions = 1;
1169 break;
1170 case 'n':
1171 dry_run = 1;
1172 break;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001173 case 'C': {
1174 size_t bytes = sizeof(char *) * (n_config_paths + 2);
1175 void *tmp = realloc(config_paths, bytes);
1176 if (!tmp) {
1177 fputs("Error: out-of-memory\n", stderr);
1178 goto cmdline_failed;
1179 }
1180 config_paths = tmp;
1181 config_paths[n_config_paths] = optarg;
1182 n_config_paths++;
1183 config_paths[n_config_paths] = NULL;
1184
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001185 env_modprobe_options_append("-C");
1186 env_modprobe_options_append(optarg);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001187 break;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001188 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001189 case 'd':
1190 root = optarg;
1191 break;
1192 case 'S':
1193 kversion = optarg;
1194 break;
1195 case 's':
1196 env_modprobe_options_append("-s");
1197 use_syslog = 1;
1198 break;
1199 case 'q':
1200 env_modprobe_options_append("-q");
1201 verbose--;
1202 break;
1203 case 'v':
1204 env_modprobe_options_append("-v");
1205 verbose++;
1206 break;
1207 case 'V':
1208 puts(PACKAGE " version " VERSION);
1209 if (argv != orig_argv)
1210 free(argv);
1211 return EXIT_SUCCESS;
1212 case 'h':
1213 help(argv[0]);
1214 if (argv != orig_argv)
1215 free(argv);
1216 return EXIT_SUCCESS;
1217 case '?':
1218 goto cmdline_failed;
1219 default:
1220 fprintf(stderr,
1221 "Error: unexpected getopt_long() value '%c'.\n",
1222 c);
1223 goto cmdline_failed;
1224 }
1225 }
1226
1227 args = argv + optind;
1228 nargs = argc - optind;
1229
1230 if (!do_show_config && !do_show_list) {
1231 if (nargs == 0) {
1232 fputs("Error: missing parameters. See -h.\n", stderr);
1233 goto cmdline_failed;
1234 }
1235 }
1236
1237 if (!do_show_list && list_type != NULL) {
1238 fputs("Error: -t (--type) only supported with -l (--list).\n",
1239 stderr);
1240 goto cmdline_failed;
1241 }
1242
1243 if (root != NULL || kversion != NULL) {
1244 struct utsname u;
1245 if (root == NULL)
1246 root = "";
1247 if (kversion == NULL) {
1248 if (uname(&u) < 0) {
1249 fprintf(stderr, "Error: uname() failed: %s\n",
1250 strerror(errno));
1251 goto cmdline_failed;
1252 }
1253 kversion = u.release;
1254 }
Kay Sieversa308abe2011-12-20 17:58:05 +01001255 snprintf(dirname_buf, sizeof(dirname_buf), "%s" ROOTPREFIX "/lib/modules/%s",
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001256 root, kversion);
1257 dirname = dirname_buf;
1258 }
1259
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001260 ctx = kmod_new(dirname, config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001261 if (!ctx) {
1262 fputs("Error: kmod_new() failed!\n", stderr);
1263 goto cmdline_failed;
1264 }
1265 kmod_load_resources(ctx);
1266
1267 kmod_set_log_priority(ctx, verbose);
1268 if (use_syslog) {
1269 openlog("modprobe", LOG_CONS, LOG_DAEMON);
1270 kmod_set_log_fn(ctx, log_syslog, NULL);
1271 }
1272
1273 if (do_show_list)
1274 err = show_list(ctx, list_type, nargs > 0 ? args[0] : NULL);
1275 else if (do_show_config)
1276 err = show_config(ctx);
1277 else if (do_show_modversions)
1278 err = show_modversions(ctx, args[0]);
1279 else if (do_remove)
1280 err = rmmod_all(ctx, args, use_all ? nargs : 1);
1281 else if (use_all)
1282 err = insmod_all(ctx, args, nargs);
1283 else {
1284 char *opts;
1285 err = options_from_array(args, nargs, &opts);
1286 if (err == 0) {
1287 err = insmod(ctx, args[0], opts);
1288 free(opts);
1289 }
1290 }
1291
1292 kmod_unref(ctx);
1293
1294 if (use_syslog)
1295 closelog();
1296
1297 if (argv != orig_argv)
1298 free(argv);
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001299 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001300 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1301
1302cmdline_failed:
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 EXIT_FAILURE;
1307}