blob: bbbb1f0dcd726c420b3136be340c4a4a1079b9a8 [file] [log] [blame]
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001/*
Lucas De Marchi8b013762012-01-12 17:14:30 -02002 * kmod-modprobe - manage linux kernel modules using libkmod.
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02003 *
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>
Lucas De Marchi0cf28322012-01-12 02:21:26 -020022#include <stdbool.h>
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020023#include <getopt.h>
24#include <errno.h>
25#include <string.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/utsname.h>
Thierry Vignaudeff917c2012-01-17 17:32:48 -020029#include <sys/wait.h>
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020030#include <unistd.h>
31#include <syslog.h>
32#include <limits.h>
33
34#include "libkmod.h"
Lucas De Marchi8b013762012-01-12 17:14:30 -020035#include "libkmod-array.h"
Lucas De Marchibc434962012-01-13 02:35:34 -020036#include "macro.h"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020037
38static int log_priority = LOG_CRIT;
39static int use_syslog = 0;
40
41#define DEFAULT_VERBOSE LOG_WARNING
42static int verbose = DEFAULT_VERBOSE;
Gustavo Sverzut Barbieri525fa072012-01-08 13:58:28 -020043static int do_show = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020044static int dry_run = 0;
45static int ignore_loaded = 0;
Lucas De Marchi81229852011-12-16 02:58:48 -020046static int lookup_only = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020047static int first_time = 0;
48static int ignore_commands = 0;
49static int use_blacklist = 0;
50static int force = 0;
51static int strip_modversion = 0;
52static int strip_vermagic = 0;
53static int remove_dependencies = 0;
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -020054static int quiet_inuse = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020055
Dave Reisnercc988302012-01-26 11:36:35 -050056static const char cmdopts_s[] = "arRibfDcnC:d:S:sqvVh";
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020057static const struct option cmdopts[] = {
58 {"all", no_argument, 0, 'a'},
59 {"remove", no_argument, 0, 'r'},
60 {"remove-dependencies", no_argument, 0, 5},
61 {"resolve-alias", no_argument, 0, 'R'},
62 {"first-time", no_argument, 0, 3},
63 {"ignore-install", no_argument, 0, 'i'},
64 {"ignore-remove", no_argument, 0, 'i'},
65 {"use-blacklist", no_argument, 0, 'b'},
66 {"force", no_argument, 0, 'f'},
67 {"force-modversion", no_argument, 0, 2},
68 {"force-vermagic", no_argument, 0, 1},
69
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020070 {"show-depends", no_argument, 0, 'D'},
71 {"showconfig", no_argument, 0, 'c'},
72 {"show-config", no_argument, 0, 'c'},
73 {"show-modversions", no_argument, 0, 4},
74 {"dump-modversions", no_argument, 0, 4},
75
76 {"dry-run", no_argument, 0, 'n'},
77 {"show", no_argument, 0, 'n'},
78
79 {"config", required_argument, 0, 'C'},
80 {"dirname", required_argument, 0, 'd'},
81 {"set-version", required_argument, 0, 'S'},
82
83 {"syslog", no_argument, 0, 's'},
84 {"quiet", no_argument, 0, 'q'},
85 {"verbose", no_argument, 0, 'v'},
86 {"version", no_argument, 0, 'V'},
87 {"help", no_argument, 0, 'h'},
88 {NULL, 0, 0, 0}
89};
90
91static void help(const char *progname)
92{
93 fprintf(stderr,
94 "Usage:\n"
95 "\t%s [options] [-i] [-b] modulename\n"
96 "\t%s [options] -a [-i] [-b] modulename [modulename...]\n"
97 "\t%s [options] -r [-i] modulename\n"
98 "\t%s [options] -r -a [-i] modulename [modulename...]\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -020099 "\t%s [options] -c\n"
100 "\t%s [options] --dump-modversions filename\n"
101 "Management Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200102 "\t-a, --all Consider every non-argument to\n"
103 "\t be a module name to be inserted\n"
104 "\t or removed (-r)\n"
105 "\t-r, --remove Remove modules instead of inserting\n"
106 "\t --remove-dependencies Also remove modules depending on it\n"
107 "\t-R, --resolve-alias Only lookup and print alias and exit\n"
108 "\t --first-time Fail if module already inserted or removed\n"
109 "\t-i, --ignore-install Ignore install commands\n"
110 "\t-i, --ignore-remove Ignore remove commands\n"
111 "\t-b, --use-blacklist Apply blacklist to resolved alias.\n"
112 "\t-f, --force Force module insertion or removal.\n"
113 "\t implies --force-modversions and\n"
114 "\t --force-vermagic\n"
115 "\t --force-modversion Ignore module's version\n"
116 "\t --force-vermagic Ignore module's version magic\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200117 "\n"
118 "Query Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200119 "\t-D, --show-depends Only print module dependencies and exit\n"
120 "\t-c, --showconfig Print out known configuration and exit\n"
121 "\t-c, --show-config Same as --showconfig\n"
122 "\t --show-modversions Dump module symbol version and exit\n"
123 "\t --dump-modversions Same as --show-modversions\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200124 "\n"
125 "General Options:\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200126 "\t-n, --dry-run Do not execute operations, just print out\n"
127 "\t-n, --show Same as --dry-run\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200128
Lucas De Marchi2c966932011-12-20 16:39:59 -0200129 "\t-C, --config=FILE Use FILE instead of default search paths\n"
Kay Sieversa308abe2011-12-20 17:58:05 +0100130 "\t-d, --dirname=DIR Use DIR as filesystem root for " ROOTPREFIX "/lib/modules\n"
Gustavo Sverzut Barbieriab70dce2011-12-19 13:02:15 -0200131 "\t-S, --set-version=VERSION Use VERSION instead of `uname -r`\n"
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200132
133 "\t-s, --syslog print to syslog, not stderr\n"
134 "\t-q, --quiet disable messages\n"
135 "\t-v, --verbose enables more messages\n"
136 "\t-V, --version show version\n"
137 "\t-h, --help show this help\n",
138 progname, progname, progname, progname, progname, progname,
139 progname);
140}
141
142static inline void _show(const char *fmt, ...)
143{
144 va_list args;
145
Gustavo Sverzut Barbieri525fa072012-01-08 13:58:28 -0200146 if (!do_show && verbose <= DEFAULT_VERBOSE)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200147 return;
148
149 va_start(args, fmt);
150 vfprintf(stdout, fmt, args);
151 fflush(stdout);
152 va_end(args);
153}
154
155static inline void _log(int prio, const char *fmt, ...)
156{
157 const char *prioname;
158 char buf[32], *msg;
159 va_list args;
160
161 if (prio > verbose)
162 return;
163
164 va_start(args, fmt);
165 if (vasprintf(&msg, fmt, args) < 0)
166 msg = NULL;
167 va_end(args);
168 if (msg == NULL)
169 return;
170
171 switch (prio) {
172 case LOG_CRIT:
173 prioname = "FATAL";
174 break;
175 case LOG_ERR:
176 prioname = "ERROR";
177 break;
178 case LOG_WARNING:
179 prioname = "WARNING";
180 break;
181 case LOG_NOTICE:
182 prioname = "NOTICE";
183 break;
184 case LOG_INFO:
185 prioname = "INFO";
186 break;
187 case LOG_DEBUG:
188 prioname = "DEBUG";
189 break;
190 default:
191 snprintf(buf, sizeof(buf), "LOG-%03d", prio);
192 prioname = buf;
193 }
194
195 if (use_syslog)
196 syslog(LOG_NOTICE, "%s: %s", prioname, msg);
197 else
198 fprintf(stderr, "%s: %s", prioname, msg);
199 free(msg);
200
201 if (prio <= LOG_CRIT)
202 exit(EXIT_FAILURE);
203}
204#define ERR(...) _log(LOG_ERR, __VA_ARGS__)
205#define WRN(...) _log(LOG_WARNING, __VA_ARGS__)
206#define INF(...) _log(LOG_INFO, __VA_ARGS__)
207#define DBG(...) _log(LOG_DEBUG, __VA_ARGS__)
208#define LOG(...) _log(log_priority, __VA_ARGS__)
209#define SHOW(...) _show(__VA_ARGS__)
210
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200211static int show_config(struct kmod_ctx *ctx)
212{
Lucas De Marchibc434962012-01-13 02:35:34 -0200213 struct config_iterators {
214 const char *name;
215 struct kmod_config_iter *(*get_iter)(const struct kmod_ctx *ctx);
216 } ci[] = {
217 { "blacklist", kmod_config_get_blacklists },
218 { "install", kmod_config_get_install_commands },
219 { "remove", kmod_config_get_remove_commands },
220 { "alias", kmod_config_get_aliases },
221 { "option", kmod_config_get_options },
222 { "softdep", kmod_config_get_softdeps },
223 };
224 size_t i;
225
226 for (i = 0; i < ARRAY_SIZE(ci); i++) {
227 struct kmod_config_iter *iter = ci[i].get_iter(ctx);
228
229 if (iter == NULL)
230 continue;
231
232 while (kmod_config_iter_next(iter)) {
233 const char *val;
234
235 printf("%s %s", ci[i].name,
236 kmod_config_iter_get_key(iter));
237 val = kmod_config_iter_get_value(iter);
238 if (val != NULL) {
239 putchar(' ');
240 puts(val);
241 } else
242 putchar('\n');
243 }
244
245 kmod_config_iter_free_iter(iter);
246 }
247
Lucas De Marchi09e9ae52012-01-17 10:05:02 -0200248 fflush(stdout);
249
Lucas De Marchi49a16372012-01-16 16:00:35 -0200250 kmod_dump_index(ctx, KMOD_INDEX_MODULES_ALIAS, STDOUT_FILENO);
251 kmod_dump_index(ctx, KMOD_INDEX_MODULES_SYMBOL, STDOUT_FILENO);
252
Lucas De Marchibc434962012-01-13 02:35:34 -0200253 return 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200254}
255
256static int show_modversions(struct kmod_ctx *ctx, const char *filename)
257{
Gustavo Sverzut Barbieri0e3e2f42011-12-19 12:45:22 -0200258 struct kmod_list *l, *list = NULL;
259 struct kmod_module *mod;
260 int err = kmod_module_new_from_path(ctx, filename, &mod);
261 if (err < 0) {
262 LOG("Module %s not found.\n", filename);
263 return err;
264 }
265
266 err = kmod_module_get_versions(mod, &list);
267 if (err < 0) {
Dave Reisner63698372012-01-04 10:41:50 -0500268 LOG("could not get modversions of %s: %s\n",
Gustavo Sverzut Barbieri0e3e2f42011-12-19 12:45:22 -0200269 filename, strerror(-err));
270 kmod_module_unref(mod);
271 return err;
272 }
273
274 kmod_list_foreach(l, list) {
275 const char *symbol = kmod_module_version_get_symbol(l);
276 uint64_t crc = kmod_module_version_get_crc(l);
277 printf("0x%08"PRIx64"\t%s\n", crc, symbol);
278 }
279 kmod_module_versions_free_list(list);
280 kmod_module_unref(mod);
281 return 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200282}
283
Lucas De Marchi8f192212012-01-11 15:38:50 -0200284static int command_do(struct kmod_module *module, const char *type,
285 const char *command, const char *cmdline_opts)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200286{
287 const char *modname = kmod_module_get_name(module);
288 char *p, *cmd = NULL;
289 size_t cmdlen, cmdline_opts_len, varlen;
290 int ret = 0;
291
292 if (cmdline_opts == NULL)
293 cmdline_opts = "";
294 cmdline_opts_len = strlen(cmdline_opts);
295
296 cmd = strdup(command);
297 if (cmd == NULL)
298 return -ENOMEM;
299 cmdlen = strlen(cmd);
300 varlen = sizeof("$CMDLINE_OPTS") - 1;
301 while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) {
302 size_t prefixlen = p - cmd;
303 size_t suffixlen = cmdlen - prefixlen - varlen;
304 size_t slen = cmdlen - varlen + cmdline_opts_len;
305 char *suffix = p + varlen;
306 char *s = malloc(slen + 1);
307 if (s == NULL) {
308 free(cmd);
309 return -ENOMEM;
310 }
311 memcpy(s, cmd, p - cmd);
312 memcpy(s + prefixlen, cmdline_opts, cmdline_opts_len);
313 memcpy(s + prefixlen + cmdline_opts_len, suffix, suffixlen);
314 s[slen] = '\0';
315
316 free(cmd);
317 cmd = s;
318 cmdlen = slen;
319 }
320
321 SHOW("%s %s\n", type, cmd);
322 if (dry_run)
323 goto end;
324
325 setenv("MODPROBE_MODULE", modname, 1);
326 ret = system(cmd);
327 unsetenv("MODPROBE_MODULE");
328 if (ret == -1 || WEXITSTATUS(ret)) {
329 LOG("Error running %s command for %s\n", type, modname);
330 if (ret != -1)
331 ret = -WEXITSTATUS(ret);
332 }
333
334end:
335 free(cmd);
336 return ret;
337}
338
Lucas De Marchia872bba2012-01-12 15:23:51 -0200339static int rmmod_do_remove_module(struct kmod_module *mod)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200340{
Lucas De Marchia872bba2012-01-12 15:23:51 -0200341 const char *modname = kmod_module_get_name(mod);
342 int flags = 0, err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200343
Lucas De Marchia872bba2012-01-12 15:23:51 -0200344 SHOW("rmmod %s\n", kmod_module_get_name(mod));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200345
Lucas De Marchia872bba2012-01-12 15:23:51 -0200346 if (dry_run)
347 return 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200348
Lucas De Marchia872bba2012-01-12 15:23:51 -0200349 if (force)
350 flags |= KMOD_REMOVE_FORCE;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200351
Lucas De Marchia872bba2012-01-12 15:23:51 -0200352 err = kmod_module_remove_module(mod, flags);
353 if (err == -EEXIST) {
354 if (!first_time)
355 err = 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200356 else
Lucas De Marchia872bba2012-01-12 15:23:51 -0200357 LOG("Module %s is not in kernel.\n", modname);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200358 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200359
360 return err;
361}
362
Lucas De Marchia872bba2012-01-12 15:23:51 -0200363static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies);
364
365static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors)
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200366{
Lucas De Marchia872bba2012-01-12 15:23:51 -0200367 struct kmod_list *l;
368
369 kmod_list_foreach_reverse(l, list) {
370 struct kmod_module *m = kmod_module_get_module(l);
371 int r = rmmod_do_module(m, false);
372 kmod_module_unref(m);
373
374 if (r < 0 && stop_on_errors)
375 return r;
376 }
377
378 return 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200379}
380
Lucas De Marchia872bba2012-01-12 15:23:51 -0200381static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200382{
383 const char *modname = kmod_module_get_name(mod);
Lucas De Marchia872bba2012-01-12 15:23:51 -0200384 struct kmod_list *pre = NULL, *post = NULL;
385 const char *cmd = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200386 int err;
387
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200388 if (!ignore_commands) {
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200389 err = kmod_module_get_softdeps(mod, &pre, &post);
390 if (err < 0) {
391 WRN("could not get softdeps of '%s': %s\n",
Lucas De Marchi8f192212012-01-11 15:38:50 -0200392 modname, strerror(-err));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200393 return err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200394 }
395
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200396 cmd = kmod_module_get_remove_commands(mod);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200397 }
398
Lucas De Marchia872bba2012-01-12 15:23:51 -0200399 if (cmd == NULL && !ignore_loaded) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200400 int state = kmod_module_get_initstate(mod);
401
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200402 if (state < 0) {
403 LOG ("Module %s not found.\n", modname);
Lucas De Marchie4e1e642012-01-12 15:36:54 -0200404 err = -ENOENT;
405 goto error;
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200406 } else if (state == KMOD_MODULE_BUILTIN) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200407 LOG("Module %s is builtin.\n", modname);
Lucas De Marchie4e1e642012-01-12 15:36:54 -0200408 err = -ENOENT;
409 goto error;
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200410 } else if (state != KMOD_MODULE_LIVE) {
411 if (first_time) {
412 LOG("Module %s is not in kernel.\n", modname);
Lucas De Marchie4e1e642012-01-12 15:36:54 -0200413 err = -ENOENT;
414 goto error;
415 } else {
416 err = 0;
417 goto error;
418 }
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200419 }
420 }
421
Lucas De Marchia872bba2012-01-12 15:23:51 -0200422 rmmod_do_deps_list(post, false);
423
424 if (do_dependencies && remove_dependencies) {
425 struct kmod_list *deps = kmod_module_get_dependencies(mod);
426
427 err = rmmod_do_deps_list(deps, true);
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200428 if (err < 0)
Lucas De Marchia872bba2012-01-12 15:23:51 -0200429 goto error;
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200430 }
431
432 if (!ignore_loaded) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200433 int usage = kmod_module_get_refcnt(mod);
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200434
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200435 if (usage > 0) {
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200436 if (!quiet_inuse)
437 LOG("Module %s is in use.\n", modname);
438
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200439 err = -EBUSY;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200440 goto error;
441 }
442 }
443
Lucas De Marchia872bba2012-01-12 15:23:51 -0200444 if (cmd == NULL)
445 err = rmmod_do_remove_module(mod);
446 else
447 err = command_do(mod, "remove", cmd, NULL);
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200448
Lucas De Marchia872bba2012-01-12 15:23:51 -0200449 if (err < 0)
450 goto error;
Lucas De Marchid8a6c0c2012-01-01 06:07:46 -0200451
Lucas De Marchia872bba2012-01-12 15:23:51 -0200452 rmmod_do_deps_list(pre, false);
Dave Reisner0e9bd2d2011-12-31 18:02:45 -0500453
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200454error:
455 kmod_module_unref_list(pre);
456 kmod_module_unref_list(post);
Lucas De Marchia872bba2012-01-12 15:23:51 -0200457
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200458 return err;
459}
460
Lucas De Marchi569f1602012-01-21 02:45:06 -0200461static int rmmod(struct kmod_ctx *ctx, const char *alias)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200462{
463 struct kmod_list *l, *list = NULL;
464 int err;
465
466 err = kmod_module_new_from_lookup(ctx, alias, &list);
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200467 if (err < 0)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200468 return err;
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200469
470 if (list == NULL)
471 LOG("Module %s not found.\n", alias);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200472
473 kmod_list_foreach(l, list) {
474 struct kmod_module *mod = kmod_module_get_module(l);
Lucas De Marchia872bba2012-01-12 15:23:51 -0200475 err = rmmod_do_module(mod, true);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200476 kmod_module_unref(mod);
477 if (err < 0)
478 break;
479 }
480
481 kmod_module_unref_list(list);
482 return err;
483}
484
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200485static int rmmod_all(struct kmod_ctx *ctx, char **args, int nargs)
486{
487 int i, err = 0;
488
489 for (i = 0; i < nargs; i++) {
490 int r = rmmod(ctx, args[i]);
491 if (r < 0)
492 err = r;
493 }
494
495 return err;
496}
497
Lucas De Marchi8b013762012-01-12 17:14:30 -0200498#define INSMOD_RECURSION_STEP 15
499
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200500static int concat_options(const char *conf_opts, const char *extra_opts,
501 char **opts)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200502{
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200503 if (conf_opts == NULL && extra_opts == NULL)
504 *opts = NULL;
505 else if (conf_opts == NULL)
506 *opts = strdup(extra_opts);
507 else if (extra_opts == NULL)
508 *opts = strdup(conf_opts);
509 else if (asprintf(opts, "%s %s", conf_opts, extra_opts) < 0)
510 return -ENOMEM;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200511
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200512 return 0;
513}
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200514
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200515static int insmod_do_insert_module(struct kmod_module *mod, const char *opts)
516{
517 int flags = 0, err;
Lucas De Marchiaf0ff2f2012-01-11 18:29:55 -0200518
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200519 SHOW("insmod %s %s\n", kmod_module_get_path(mod), opts ? opts : "");
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200520
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200521 if (dry_run)
522 return 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200523
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200524 if (strip_modversion || force)
525 flags |= KMOD_INSERT_FORCE_MODVERSION;
526 if (strip_vermagic || force)
527 flags |= KMOD_INSERT_FORCE_VERMAGIC;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200528
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200529 err = kmod_module_insert_module(mod, flags, opts);
530 switch (err) {
531 case -EEXIST:
532 /*
533 * We checked for EEXIST with an earlier call to
534 * retrieve the initstate, but to avoid a race
535 * condition, we don't make any assumptions and handle
536 * the error again here
537 */
538 if (!first_time)
539 err = 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200540 else
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200541 ERR("Module %s already in kernel.\n",
542 kmod_module_get_name(mod));
543 break;
544 case -EPERM:
545 ERR("could not insert '%s': %s\n", kmod_module_get_name(mod),
546 strerror(-err));
547 break;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200548 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200549
550 return err;
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200551
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200552}
553
Lucas De Marchi8b013762012-01-12 17:14:30 -0200554static bool insmod_recursion_has_loop(struct kmod_module *mod,
555 struct array *recursion)
556{
557 unsigned int i;
558
559 /*
560 * Don't check every time to not impact normal use cases. If the
561 * recursion hits INSMOD_RECURSION_STEP, then search loop in
562 * @recursion.
563 */
564 if ((recursion->count + 1) % INSMOD_RECURSION_STEP != 0)
565 return false;
566
567 for (i = 0; i < recursion->count; i++) {
568 if (recursion->array[i] != mod)
569 continue;
570
571 ERR("Dependency loop detected while inserting '%s'. Operation aborted.\n",
572 kmod_module_get_name(mod));
573
574 for (; i < recursion->count; i++)
575 ERR("\t%s\n", kmod_module_get_name(recursion->array[i]));
576
577 return true;
578 }
579
580 return false;
581}
582
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200583static int insmod_do_module(struct kmod_module *mod, const char *extra_opts,
Lucas De Marchi8b013762012-01-12 17:14:30 -0200584 bool do_dependencies, struct array *recursion);
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200585
586static int insmod_do_deps_list(struct kmod_list *list,
Lucas De Marchi8b013762012-01-12 17:14:30 -0200587 bool stop_on_errors, struct array *recursion)
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200588{
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200589 struct kmod_list *l;
Lucas De Marchi8b013762012-01-12 17:14:30 -0200590 struct kmod_module *m;
591 int r;
592
593 if (list == NULL)
594 return 0;
595
596 m = kmod_module_get_module(list);
597 r = insmod_recursion_has_loop(m, recursion);
598 kmod_module_unref(m);
599
600 if (r)
601 return -ELOOP;
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200602
603 kmod_list_foreach(l, list) {
Lucas De Marchi8b013762012-01-12 17:14:30 -0200604 m = kmod_module_get_module(l);
605 array_append(recursion, m);
606 r = insmod_do_module(m, NULL, false, recursion);
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200607 kmod_module_unref(m);
Lucas De Marchi8b013762012-01-12 17:14:30 -0200608 array_pop(recursion);
609
610 if (r == -ELOOP)
611 return r;
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200612
613 if (r < 0 && stop_on_errors)
614 return r;
615 }
616
617 return 0;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200618}
619
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200620static int insmod_do_module(struct kmod_module *mod, const char *extra_opts,
Lucas De Marchi8b013762012-01-12 17:14:30 -0200621 bool do_dependencies, struct array *recursion)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200622{
623 const char *modname = kmod_module_get_name(mod);
624 const char *conf_opts = kmod_module_get_options(mod);
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200625 struct kmod_list *pre = NULL, *post = NULL;
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200626 const char *cmd = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200627 char *opts = NULL;
628 int err;
629
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200630 if (!ignore_commands) {
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200631 err = kmod_module_get_softdeps(mod, &pre, &post);
632 if (err < 0) {
633 WRN("could not get softdeps of '%s': %s\n",
Lucas De Marchi8f192212012-01-11 15:38:50 -0200634 modname, strerror(-err));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200635 return err;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200636 }
637
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200638 cmd = kmod_module_get_install_commands(mod);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200639 }
640
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200641 if (cmd == NULL && !ignore_loaded) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200642 int state = kmod_module_get_initstate(mod);
643
Lucas De Marchi95dd8372011-12-20 13:11:33 -0200644 if (state == KMOD_MODULE_BUILTIN) {
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200645 if (first_time) {
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200646 err = -EEXIST;
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200647 LOG("Module %s already in kernel (builtin).\n",
Lucas De Marchi8f192212012-01-11 15:38:50 -0200648 modname);
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200649 } else
650 err = 0;
651
652 goto error;
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200653 } else if (state == KMOD_MODULE_LIVE) {
654 if (first_time) {
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200655 err = -EEXIST;
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200656 LOG("Module %s already in kernel.\n", modname);
Lucas De Marchi9bf60d22011-12-19 02:18:14 -0200657
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200658 } else
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200659 err = 0;
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200660
Dave Reisnerb54f1bf2012-01-10 13:36:27 -0500661 goto error;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200662 }
663 }
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200664
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200665 if (cmd == NULL && kmod_module_get_path(mod) == NULL) {
666 err = -ENOENT;
667 LOG("Module %s not found.\n", modname);
668 goto error;
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200669 }
670
Lucas De Marchi8b013762012-01-12 17:14:30 -0200671 err = insmod_do_deps_list(pre, false, recursion);
672 if (err == -ELOOP)
673 goto error;
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200674
675 if (do_dependencies) {
676 struct kmod_list *deps = kmod_module_get_dependencies(mod);
677
Lucas De Marchi8b013762012-01-12 17:14:30 -0200678 err = insmod_do_deps_list(deps, true, recursion);
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200679 if (err < 0)
680 goto error;
681 }
682
683 if ((err = concat_options(conf_opts, extra_opts, &opts)) < 0)
684 goto error;
685
686 if (cmd == NULL)
687 err = insmod_do_insert_module(mod, opts);
688 else
689 err = command_do(mod, "install", cmd, NULL);
690
691 if (err < 0)
692 goto error;
693
Lucas De Marchi8b013762012-01-12 17:14:30 -0200694 err = insmod_do_deps_list(post, false, recursion);
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200695
Gustavo Sverzut Barbierie793f1e2011-12-16 22:35:28 -0200696error:
697 kmod_module_unref_list(pre);
698 kmod_module_unref_list(post);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200699 free(opts);
Lucas De Marchi0cf28322012-01-12 02:21:26 -0200700
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200701 return err;
702}
703
Lucas De Marchi92122612012-01-11 21:48:08 -0200704static int handle_failed_lookup(struct kmod_ctx *ctx, const char *alias)
705{
706 struct kmod_module *mod;
707 int state, err;
708
709 DBG("lookup failed - trying to check if it's builtin\n");
710
711 err = kmod_module_new_from_name(ctx, alias, &mod);
712 if (err < 0)
713 return err;
714
715 state = kmod_module_get_initstate(mod);
716 kmod_module_unref(mod);
717
718 if (state != KMOD_MODULE_BUILTIN) {
719 LOG("Module %s not found.\n", alias);
720 return -ENOENT;
721 }
722
723 if (first_time) {
724 LOG("Module %s already in kernel (builtin).\n", alias);
725 return -ENOENT;
726 }
727
728 SHOW("builtin %s\n", alias);
729 return 0;
730}
731
Lucas De Marchi569f1602012-01-21 02:45:06 -0200732static int insmod(struct kmod_ctx *ctx, const char *alias,
Lucas De Marchi8f192212012-01-11 15:38:50 -0200733 const char *extra_options)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200734{
735 struct kmod_list *l, *list = NULL;
736 int err;
737
738 err = kmod_module_new_from_lookup(ctx, alias, &list);
Lucas De Marchie5e2a682011-12-19 02:26:34 -0200739 if (err < 0)
740 return err;
741
Lucas De Marchi92122612012-01-11 21:48:08 -0200742 if (list == NULL)
743 return handle_failed_lookup(ctx, alias);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200744
745 if (use_blacklist) {
746 struct kmod_list *filtered = NULL;
747 err = kmod_module_get_filtered_blacklist(ctx, list, &filtered);
748 DBG("using blacklist: input %p, output=%p\n", list, filtered);
749 kmod_module_unref_list(list);
750 if (err < 0) {
Dave Reisner63698372012-01-04 10:41:50 -0500751 LOG("could not filter alias list!\n");
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200752 return err;
753 }
754 list = filtered;
755 }
756
757 kmod_list_foreach(l, list) {
758 struct kmod_module *mod = kmod_module_get_module(l);
Lucas De Marchi8b013762012-01-12 17:14:30 -0200759
Lucas De Marchi81229852011-12-16 02:58:48 -0200760 if (lookup_only)
761 printf("%s\n", kmod_module_get_name(mod));
Lucas De Marchi8b013762012-01-12 17:14:30 -0200762 else {
763 struct array recursion;
764
765 array_init(&recursion, INSMOD_RECURSION_STEP);
766 err = insmod_do_module(mod, extra_options, true,
767 &recursion);
768 array_free_array(&recursion);
769 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200770 kmod_module_unref(mod);
771 if (err < 0)
772 break;
773 }
774
775 kmod_module_unref_list(list);
776 return err;
777}
778
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200779static int insmod_all(struct kmod_ctx *ctx, char **args, int nargs)
780{
781 int i, err = 0;
782
783 for (i = 0; i < nargs; i++) {
784 int r = insmod(ctx, args[i], NULL);
785 if (r < 0)
786 err = r;
787 }
788
789 return err;
790}
791
792static void env_modprobe_options_append(const char *value)
793{
794 const char *old = getenv("MODPROBE_OPTIONS");
795 char *env;
796
797 if (old == NULL) {
798 setenv("MODPROBE_OPTIONS", value, 1);
799 return;
800 }
801
802 if (asprintf(&env, "%s %s", old, value) < 0) {
803 ERR("could not append value to $MODPROBE_OPTIONS\n");
804 return;
805 }
806
807 if (setenv("MODPROBE_OPTIONS", env, 1) < 0)
808 ERR("could not setenv(MODPROBE_OPTIONS, \"%s\")\n", env);
809 free(env);
810}
811
812static int options_from_array(char **args, int nargs, char **output)
813{
814 char *opts = NULL;
815 size_t optslen = 0;
816 int i, err = 0;
817
818 for (i = 1; i < nargs; i++) {
819 size_t len = strlen(args[i]);
820 size_t qlen = 0;
821 const char *value;
822 void *tmp;
823
824 value = strchr(args[i], '=');
825 if (value) {
826 value++;
827 if (*value != '"' && *value != '\'') {
828 if (strchr(value, ' '))
829 qlen = 2;
830 }
831 }
832
833 tmp = realloc(opts, optslen + len + qlen + 2);
834 if (!tmp) {
835 err = -errno;
836 free(opts);
837 opts = NULL;
838 ERR("could not gather module options: out-of-memory\n");
839 break;
840 }
841 opts = tmp;
842 if (optslen > 0) {
843 opts[optslen] = ' ';
844 optslen++;
845 }
846 if (qlen == 0) {
847 memcpy(opts + optslen, args[i], len + 1);
848 optslen += len;
849 } else {
850 size_t keylen = value - args[i];
851 size_t valuelen = len - keylen;
852 memcpy(opts + optslen, args[i], keylen);
853 optslen += keylen;
854 opts[optslen] = '"';
855 optslen++;
856 memcpy(opts + optslen, value, valuelen);
857 optslen += valuelen;
858 opts[optslen] = '"';
859 optslen++;
860 opts[optslen] = '\0';
861 }
862 }
863
864 *output = opts;
865 return err;
866}
867
868static char **prepend_options_from_env(int *p_argc, char **orig_argv)
869{
870 const char *p, *env = getenv("MODPROBE_OPTIONS");
871 char **new_argv, *str_start, *str_end, *str, *s, *quote;
872 int i, argc = *p_argc;
873 size_t envlen, space_count = 0;
874
875 if (env == NULL)
876 return orig_argv;
877
878 for (p = env; *p != '\0'; p++) {
879 if (*p == ' ')
880 space_count++;
881 }
882
883 envlen = p - env;
884 new_argv = malloc(sizeof(char *) * (argc + space_count + 3 + envlen));
885 if (new_argv == NULL)
886 return NULL;
887
888 new_argv[0] = orig_argv[0];
889 str_start = str = (char *) (new_argv + argc + space_count + 3);
890 memcpy(str, env, envlen + 1);
891
892 str_end = str_start + envlen;
893
894 quote = NULL;
895 for (i = 1, s = str; *s != '\0'; s++) {
896 if (quote == NULL) {
897 if (*s == ' ') {
898 new_argv[i] = str;
899 i++;
900 *s = '\0';
901 str = s + 1;
902 } else if (*s == '"' || *s == '\'')
903 quote = s;
904 } else {
905 if (*s == *quote) {
906 if (quote == str) {
907 new_argv[i] = str + 1;
908 i++;
909 *s = '\0';
910 str = s + 1;
911 } else {
912 char *it;
913 for (it = quote; it < s - 1; it++)
914 it[0] = it[1];
915 for (it = s - 1; it < str_end - 2; it++)
916 it[0] = it[2];
917 str_end -= 2;
918 *str_end = '\0';
919 s -= 2;
920 }
921 quote = NULL;
922 }
923 }
924 }
925 if (str < s) {
926 new_argv[i] = str;
927 i++;
928 }
929
930 memcpy(new_argv + i, orig_argv + 1, sizeof(char *) * (argc - 1));
931 new_argv[i + argc] = NULL;
932 *p_argc = i + argc - 1;
933
934 return new_argv;
935}
936
937static void log_syslog(void *data, int priority, const char *file, int line,
Lucas De Marchi8f192212012-01-11 15:38:50 -0200938 const char *fn, const char *format, va_list args)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200939{
940 char *str, buf[32];
941 const char *prioname;
942
943 switch (priority) {
944 case LOG_CRIT:
945 prioname = "FATAL";
946 break;
947 case LOG_ERR:
948 prioname = "ERROR";
949 break;
950 case LOG_WARNING:
951 prioname = "WARNING";
952 break;
953 case LOG_NOTICE:
954 prioname = "NOTICE";
955 break;
956 case LOG_INFO:
957 prioname = "INFO";
958 break;
959 case LOG_DEBUG:
960 prioname = "DEBUG";
961 break;
962 default:
963 snprintf(buf, sizeof(buf), "LOG-%03d", priority);
964 prioname = buf;
965 }
966
967 if (vasprintf(&str, format, args) < 0)
968 return;
969#ifdef ENABLE_DEBUG
970 syslog(LOG_NOTICE, "%s: %s:%d %s() %s", prioname, file, line, fn, str);
971#else
972 syslog(LOG_NOTICE, "%s: %s", prioname, str);
973#endif
974 free(str);
975 (void)data;
976}
977
Lucas De Marchifa29c0e2011-12-22 03:54:46 -0200978static int do_modprobe(int argc, char **orig_argv)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200979{
980 struct kmod_ctx *ctx;
981 char **args = NULL, **argv;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -0200982 const char **config_paths = NULL;
983 int nargs = 0, n_config_paths = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200984 char dirname_buf[PATH_MAX];
985 const char *dirname = NULL;
986 const char *root = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200987 const char *kversion = NULL;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200988 int use_all = 0;
989 int do_remove = 0;
990 int do_show_config = 0;
991 int do_show_modversions = 0;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -0200992 int err;
993
994 argv = prepend_options_from_env(&argc, orig_argv);
995 if (argv == NULL) {
996 fputs("Error: could not prepend options from command line\n",
997 stderr);
998 return EXIT_FAILURE;
999 }
1000
1001 for (;;) {
1002 int c, idx = 0;
1003 c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
1004 if (c == -1)
1005 break;
1006 switch (c) {
1007 case 'a':
1008 log_priority = LOG_WARNING;
1009 use_all = 1;
1010 break;
1011 case 'r':
1012 do_remove = 1;
1013 break;
1014 case 5:
1015 remove_dependencies = 1;
1016 break;
1017 case 'R':
Lucas De Marchi81229852011-12-16 02:58:48 -02001018 lookup_only = 1;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001019 break;
1020 case 3:
1021 first_time = 1;
1022 break;
1023 case 'i':
1024 ignore_commands = 1;
1025 break;
1026 case 'b':
1027 use_blacklist = 1;
1028 break;
1029 case 'f':
1030 force = 1;
1031 break;
1032 case 2:
1033 strip_modversion = 1;
1034 break;
1035 case 1:
1036 strip_vermagic = 1;
1037 break;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001038 case 'D':
1039 ignore_loaded = 1;
1040 dry_run = 1;
Gustavo Sverzut Barbieri525fa072012-01-08 13:58:28 -02001041 do_show = 1;
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001042 break;
1043 case 'c':
1044 do_show_config = 1;
1045 break;
1046 case 4:
1047 do_show_modversions = 1;
1048 break;
1049 case 'n':
1050 dry_run = 1;
1051 break;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001052 case 'C': {
1053 size_t bytes = sizeof(char *) * (n_config_paths + 2);
1054 void *tmp = realloc(config_paths, bytes);
1055 if (!tmp) {
1056 fputs("Error: out-of-memory\n", stderr);
1057 goto cmdline_failed;
1058 }
1059 config_paths = tmp;
1060 config_paths[n_config_paths] = optarg;
1061 n_config_paths++;
1062 config_paths[n_config_paths] = NULL;
1063
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001064 env_modprobe_options_append("-C");
1065 env_modprobe_options_append(optarg);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001066 break;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001067 }
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001068 case 'd':
1069 root = optarg;
1070 break;
1071 case 'S':
1072 kversion = optarg;
1073 break;
1074 case 's':
1075 env_modprobe_options_append("-s");
1076 use_syslog = 1;
1077 break;
1078 case 'q':
1079 env_modprobe_options_append("-q");
1080 verbose--;
1081 break;
1082 case 'v':
1083 env_modprobe_options_append("-v");
1084 verbose++;
1085 break;
1086 case 'V':
1087 puts(PACKAGE " version " VERSION);
1088 if (argv != orig_argv)
1089 free(argv);
Gustavo Sverzut Barbieri5f9f58f2011-12-21 23:54:35 -02001090 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001091 return EXIT_SUCCESS;
1092 case 'h':
Lucas De Marchi3e8de632011-12-23 01:36:10 -02001093 help(basename(argv[0]));
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001094 if (argv != orig_argv)
1095 free(argv);
Gustavo Sverzut Barbieri5f9f58f2011-12-21 23:54:35 -02001096 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001097 return EXIT_SUCCESS;
1098 case '?':
1099 goto cmdline_failed;
1100 default:
Lucas De Marchi8f192212012-01-11 15:38:50 -02001101 fprintf(stderr, "Error: unexpected getopt_long() value '%c'.\n",
1102 c);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001103 goto cmdline_failed;
1104 }
1105 }
1106
1107 args = argv + optind;
1108 nargs = argc - optind;
1109
Dave Reisnerb09668c2011-12-31 16:51:40 -05001110 if (!do_show_config) {
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001111 if (nargs == 0) {
1112 fputs("Error: missing parameters. See -h.\n", stderr);
1113 goto cmdline_failed;
1114 }
1115 }
1116
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001117 if (root != NULL || kversion != NULL) {
1118 struct utsname u;
1119 if (root == NULL)
1120 root = "";
1121 if (kversion == NULL) {
1122 if (uname(&u) < 0) {
1123 fprintf(stderr, "Error: uname() failed: %s\n",
1124 strerror(errno));
1125 goto cmdline_failed;
1126 }
1127 kversion = u.release;
1128 }
Lucas De Marchi8f192212012-01-11 15:38:50 -02001129 snprintf(dirname_buf, sizeof(dirname_buf),
1130 "%s" ROOTPREFIX "/lib/modules/%s", root,
1131 kversion);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001132 dirname = dirname_buf;
1133 }
1134
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001135 ctx = kmod_new(dirname, config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001136 if (!ctx) {
1137 fputs("Error: kmod_new() failed!\n", stderr);
1138 goto cmdline_failed;
1139 }
1140 kmod_load_resources(ctx);
1141
1142 kmod_set_log_priority(ctx, verbose);
1143 if (use_syslog) {
1144 openlog("modprobe", LOG_CONS, LOG_DAEMON);
1145 kmod_set_log_fn(ctx, log_syslog, NULL);
1146 }
1147
Dave Reisnerb09668c2011-12-31 16:51:40 -05001148 if (do_show_config)
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001149 err = show_config(ctx);
1150 else if (do_show_modversions)
1151 err = show_modversions(ctx, args[0]);
1152 else if (do_remove)
1153 err = rmmod_all(ctx, args, use_all ? nargs : 1);
1154 else if (use_all)
1155 err = insmod_all(ctx, args, nargs);
1156 else {
1157 char *opts;
1158 err = options_from_array(args, nargs, &opts);
1159 if (err == 0) {
1160 err = insmod(ctx, args[0], opts);
1161 free(opts);
1162 }
1163 }
1164
1165 kmod_unref(ctx);
1166
1167 if (use_syslog)
1168 closelog();
1169
1170 if (argv != orig_argv)
1171 free(argv);
Lucas De Marchi8f192212012-01-11 15:38:50 -02001172
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001173 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001174 return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1175
1176cmdline_failed:
1177 if (argv != orig_argv)
1178 free(argv);
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -02001179 free(config_paths);
Gustavo Sverzut Barbieric3d0a5f2011-12-11 19:36:18 -02001180 return EXIT_FAILURE;
1181}
Lucas De Marchifa29c0e2011-12-22 03:54:46 -02001182
1183#ifndef KMOD_BUNDLE_TOOL
1184int main(int argc, char *argv[])
1185{
1186 return do_modprobe(argc, argv);
1187}
1188
1189#else
1190#include "kmod.h"
1191
1192const struct kmod_cmd kmod_cmd_compat_modprobe = {
1193 .name = "modprobe",
1194 .cmd = do_modprobe,
1195 .help = "compat modprobe command",
1196};
1197
1198#endif