~ubuntu-branches/ubuntu/vivid/kmod/vivid

« back to all changes in this revision

Viewing changes to .pc/bad_alias_assertion/tools/modprobe.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-04-18 13:16:44 UTC
  • mfrom: (4.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20130418131644-r9zy91dgcydczbmw
Tags: 9-3ubuntu1
Merge with Debian unstable, bringing in a backport of upstream's
comprehensive fix for the bad alias assertion bug (LP: #1073062)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * kmod-modprobe - manage linux kernel modules using libkmod.
 
3
 *
 
4
 * Copyright (C) 2011-2012  ProFUSION embedded systems
 
5
 *
 
6
 * This program is free software: you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation, either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <assert.h>
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <stdbool.h>
 
24
#include <getopt.h>
 
25
#include <errno.h>
 
26
#include <string.h>
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
#include <sys/utsname.h>
 
30
#include <sys/wait.h>
 
31
#include <unistd.h>
 
32
#include <syslog.h>
 
33
#include <limits.h>
 
34
 
 
35
#include "libkmod.h"
 
36
#include "libkmod-array.h"
 
37
#include "macro.h"
 
38
 
 
39
static int log_priority = LOG_CRIT;
 
40
static int use_syslog = 0;
 
41
 
 
42
#define DEFAULT_VERBOSE LOG_WARNING
 
43
static int verbose = DEFAULT_VERBOSE;
 
44
static int do_show = 0;
 
45
static int dry_run = 0;
 
46
static int ignore_loaded = 0;
 
47
static int lookup_only = 0;
 
48
static int first_time = 0;
 
49
static int ignore_commands = 0;
 
50
static int use_blacklist = 0;
 
51
static int force = 0;
 
52
static int strip_modversion = 0;
 
53
static int strip_vermagic = 0;
 
54
static int remove_dependencies = 0;
 
55
static int quiet_inuse = 0;
 
56
 
 
57
static const char cmdopts_s[] = "arRibfDcnC:d:S:sqvVh";
 
58
static const struct option cmdopts[] = {
 
59
        {"all", no_argument, 0, 'a'},
 
60
        {"remove", no_argument, 0, 'r'},
 
61
        {"remove-dependencies", no_argument, 0, 5},
 
62
        {"resolve-alias", no_argument, 0, 'R'},
 
63
        {"first-time", no_argument, 0, 3},
 
64
        {"ignore-install", no_argument, 0, 'i'},
 
65
        {"ignore-remove", no_argument, 0, 'i'},
 
66
        {"use-blacklist", no_argument, 0, 'b'},
 
67
        {"force", no_argument, 0, 'f'},
 
68
        {"force-modversion", no_argument, 0, 2},
 
69
        {"force-vermagic", no_argument, 0, 1},
 
70
 
 
71
        {"show-depends", no_argument, 0, 'D'},
 
72
        {"showconfig", no_argument, 0, 'c'},
 
73
        {"show-config", no_argument, 0, 'c'},
 
74
        {"show-modversions", no_argument, 0, 4},
 
75
        {"dump-modversions", no_argument, 0, 4},
 
76
 
 
77
        {"dry-run", no_argument, 0, 'n'},
 
78
        {"show", no_argument, 0, 'n'},
 
79
 
 
80
        {"config", required_argument, 0, 'C'},
 
81
        {"dirname", required_argument, 0, 'd'},
 
82
        {"set-version", required_argument, 0, 'S'},
 
83
 
 
84
        {"syslog", no_argument, 0, 's'},
 
85
        {"quiet", no_argument, 0, 'q'},
 
86
        {"verbose", no_argument, 0, 'v'},
 
87
        {"version", no_argument, 0, 'V'},
 
88
        {"help", no_argument, 0, 'h'},
 
89
        {NULL, 0, 0, 0}
 
90
};
 
91
 
 
92
static void help(const char *progname)
 
93
{
 
94
        fprintf(stderr,
 
95
                "Usage:\n"
 
96
                "\t%s [options] [-i] [-b] modulename\n"
 
97
                "\t%s [options] -a [-i] [-b] modulename [modulename...]\n"
 
98
                "\t%s [options] -r [-i] modulename\n"
 
99
                "\t%s [options] -r -a [-i] modulename [modulename...]\n"
 
100
                "\t%s [options] -c\n"
 
101
                "\t%s [options] --dump-modversions filename\n"
 
102
                "Management Options:\n"
 
103
                "\t-a, --all                   Consider every non-argument to\n"
 
104
                "\t                            be a module name to be inserted\n"
 
105
                "\t                            or removed (-r)\n"
 
106
                "\t-r, --remove                Remove modules instead of inserting\n"
 
107
                "\t    --remove-dependencies   Also remove modules depending on it\n"
 
108
                "\t-R, --resolve-alias         Only lookup and print alias and exit\n"
 
109
                "\t    --first-time            Fail if module already inserted or removed\n"
 
110
                "\t-i, --ignore-install        Ignore install commands\n"
 
111
                "\t-i, --ignore-remove         Ignore remove commands\n"
 
112
                "\t-b, --use-blacklist         Apply blacklist to resolved alias.\n"
 
113
                "\t-f, --force                 Force module insertion or removal.\n"
 
114
                "\t                            implies --force-modversions and\n"
 
115
                "\t                            --force-vermagic\n"
 
116
                "\t    --force-modversion      Ignore module's version\n"
 
117
                "\t    --force-vermagic        Ignore module's version magic\n"
 
118
                "\n"
 
119
                "Query Options:\n"
 
120
                "\t-D, --show-depends          Only print module dependencies and exit\n"
 
121
                "\t-c, --showconfig            Print out known configuration and exit\n"
 
122
                "\t-c, --show-config           Same as --showconfig\n"
 
123
                "\t    --show-modversions      Dump module symbol version and exit\n"
 
124
                "\t    --dump-modversions      Same as --show-modversions\n"
 
125
                "\n"
 
126
                "General Options:\n"
 
127
                "\t-n, --dry-run               Do not execute operations, just print out\n"
 
128
                "\t-n, --show                  Same as --dry-run\n"
 
129
 
 
130
                "\t-C, --config=FILE           Use FILE instead of default search paths\n"
 
131
                "\t-d, --dirname=DIR           Use DIR as filesystem root for " ROOTPREFIX "/lib/modules\n"
 
132
                "\t-S, --set-version=VERSION   Use VERSION instead of `uname -r`\n"
 
133
 
 
134
                "\t-s, --syslog                print to syslog, not stderr\n"
 
135
                "\t-q, --quiet                 disable messages\n"
 
136
                "\t-v, --verbose               enables more messages\n"
 
137
                "\t-V, --version               show version\n"
 
138
                "\t-h, --help                  show this help\n",
 
139
                progname, progname, progname, progname, progname, progname);
 
140
}
 
141
 
 
142
static inline void _show(const char *fmt, ...)
 
143
{
 
144
        va_list args;
 
145
 
 
146
        if (!do_show && verbose <= DEFAULT_VERBOSE)
 
147
                return;
 
148
 
 
149
        va_start(args, fmt);
 
150
        vfprintf(stdout, fmt, args);
 
151
        fflush(stdout);
 
152
        va_end(args);
 
153
}
 
154
 
 
155
static 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
 
 
211
static int show_config(struct kmod_ctx *ctx)
 
212
{
 
213
        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
                { "options", 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
 
 
248
        puts("\n# End of configuration files. Dumping indexes now:\n");
 
249
        fflush(stdout);
 
250
 
 
251
        kmod_dump_index(ctx, KMOD_INDEX_MODULES_ALIAS, STDOUT_FILENO);
 
252
        kmod_dump_index(ctx, KMOD_INDEX_MODULES_SYMBOL, STDOUT_FILENO);
 
253
 
 
254
        return 0;
 
255
}
 
256
 
 
257
static int show_modversions(struct kmod_ctx *ctx, const char *filename)
 
258
{
 
259
        struct kmod_list *l, *list = NULL;
 
260
        struct kmod_module *mod;
 
261
        int err = kmod_module_new_from_path(ctx, filename, &mod);
 
262
        if (err < 0) {
 
263
                LOG("Module %s not found.\n", filename);
 
264
                return err;
 
265
        }
 
266
 
 
267
        err = kmod_module_get_versions(mod, &list);
 
268
        if (err < 0) {
 
269
                LOG("could not get modversions of %s: %s\n",
 
270
                        filename, strerror(-err));
 
271
                kmod_module_unref(mod);
 
272
                return err;
 
273
        }
 
274
 
 
275
        kmod_list_foreach(l, list) {
 
276
                const char *symbol = kmod_module_version_get_symbol(l);
 
277
                uint64_t crc = kmod_module_version_get_crc(l);
 
278
                printf("0x%08"PRIx64"\t%s\n", crc, symbol);
 
279
        }
 
280
        kmod_module_versions_free_list(list);
 
281
        kmod_module_unref(mod);
 
282
        return 0;
 
283
}
 
284
 
 
285
static int command_do(struct kmod_module *module, const char *type,
 
286
                                const char *command, const char *cmdline_opts)
 
287
{
 
288
        const char *modname = kmod_module_get_name(module);
 
289
        char *p, *cmd = NULL;
 
290
        size_t cmdlen, cmdline_opts_len, varlen;
 
291
        int ret = 0;
 
292
 
 
293
        if (cmdline_opts == NULL)
 
294
                cmdline_opts = "";
 
295
        cmdline_opts_len = strlen(cmdline_opts);
 
296
 
 
297
        cmd = strdup(command);
 
298
        if (cmd == NULL)
 
299
                return -ENOMEM;
 
300
        cmdlen = strlen(cmd);
 
301
        varlen = sizeof("$CMDLINE_OPTS") - 1;
 
302
        while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) {
 
303
                size_t prefixlen = p - cmd;
 
304
                size_t suffixlen = cmdlen - prefixlen - varlen;
 
305
                size_t slen = cmdlen - varlen + cmdline_opts_len;
 
306
                char *suffix = p + varlen;
 
307
                char *s = malloc(slen + 1);
 
308
                if (s == NULL) {
 
309
                        free(cmd);
 
310
                        return -ENOMEM;
 
311
                }
 
312
                memcpy(s, cmd, p - cmd);
 
313
                memcpy(s + prefixlen, cmdline_opts, cmdline_opts_len);
 
314
                memcpy(s + prefixlen + cmdline_opts_len, suffix, suffixlen);
 
315
                s[slen] = '\0';
 
316
 
 
317
                free(cmd);
 
318
                cmd = s;
 
319
                cmdlen = slen;
 
320
        }
 
321
 
 
322
        SHOW("%s %s\n", type, cmd);
 
323
        if (dry_run)
 
324
                goto end;
 
325
 
 
326
        setenv("MODPROBE_MODULE", modname, 1);
 
327
        ret = system(cmd);
 
328
        unsetenv("MODPROBE_MODULE");
 
329
        if (ret == -1 || WEXITSTATUS(ret)) {
 
330
                LOG("Error running %s command for %s\n", type, modname);
 
331
                if (ret != -1)
 
332
                        ret = -WEXITSTATUS(ret);
 
333
        }
 
334
 
 
335
end:
 
336
        free(cmd);
 
337
        return ret;
 
338
}
 
339
 
 
340
static int rmmod_do_remove_module(struct kmod_module *mod)
 
341
{
 
342
        const char *modname = kmod_module_get_name(mod);
 
343
        struct kmod_list *deps, *itr;
 
344
        int flags = 0, err;
 
345
 
 
346
        SHOW("rmmod %s\n", kmod_module_get_name(mod));
 
347
 
 
348
        if (dry_run)
 
349
                return 0;
 
350
 
 
351
        if (force)
 
352
                flags |= KMOD_REMOVE_FORCE;
 
353
 
 
354
        err = kmod_module_remove_module(mod, flags);
 
355
        if (err == -EEXIST) {
 
356
                if (!first_time)
 
357
                        err = 0;
 
358
                else
 
359
                        LOG("Module %s is not in kernel.\n", modname);
 
360
        }
 
361
 
 
362
        deps = kmod_module_get_dependencies(mod);
 
363
        if (deps != NULL) {
 
364
                kmod_list_foreach(itr, deps) {
 
365
                        struct kmod_module *dep = kmod_module_get_module(itr);
 
366
                        if (kmod_module_get_refcnt(dep) == 0)
 
367
                                rmmod_do_remove_module(dep);
 
368
                        kmod_module_unref(dep);
 
369
                }
 
370
                kmod_module_unref_list(deps);
 
371
        }
 
372
 
 
373
        return err;
 
374
}
 
375
 
 
376
static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies);
 
377
 
 
378
static int rmmod_do_deps_list(struct kmod_list *list, bool stop_on_errors)
 
379
{
 
380
        struct kmod_list *l;
 
381
 
 
382
        kmod_list_foreach_reverse(l, list) {
 
383
                struct kmod_module *m = kmod_module_get_module(l);
 
384
                int r = rmmod_do_module(m, false);
 
385
                kmod_module_unref(m);
 
386
 
 
387
                if (r < 0 && stop_on_errors)
 
388
                        return r;
 
389
        }
 
390
 
 
391
        return 0;
 
392
}
 
393
 
 
394
static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies)
 
395
{
 
396
        const char *modname = kmod_module_get_name(mod);
 
397
        struct kmod_list *pre = NULL, *post = NULL;
 
398
        const char *cmd = NULL;
 
399
        int err;
 
400
 
 
401
        if (!ignore_commands) {
 
402
                err = kmod_module_get_softdeps(mod, &pre, &post);
 
403
                if (err < 0) {
 
404
                        WRN("could not get softdeps of '%s': %s\n",
 
405
                                                modname, strerror(-err));
 
406
                        return err;
 
407
                }
 
408
 
 
409
                cmd = kmod_module_get_remove_commands(mod);
 
410
        }
 
411
 
 
412
        if (cmd == NULL && !ignore_loaded) {
 
413
                int state = kmod_module_get_initstate(mod);
 
414
 
 
415
                if (state < 0) {
 
416
                        if (first_time) {
 
417
                                LOG("Module %s is not in kernel.\n", modname);
 
418
                                err = -ENOENT;
 
419
                        } else {
 
420
                                err = 0;
 
421
                        }
 
422
                        goto error;
 
423
                } else if (state == KMOD_MODULE_BUILTIN) {
 
424
                        LOG("Module %s is builtin.\n", modname);
 
425
                        err = -ENOENT;
 
426
                        goto error;
 
427
                }
 
428
        }
 
429
 
 
430
        rmmod_do_deps_list(post, false);
 
431
 
 
432
        if (do_dependencies && remove_dependencies) {
 
433
                struct kmod_list *deps = kmod_module_get_dependencies(mod);
 
434
 
 
435
                err = rmmod_do_deps_list(deps, true);
 
436
                if (err < 0)
 
437
                        goto error;
 
438
        }
 
439
 
 
440
        if (!ignore_loaded) {
 
441
                int usage = kmod_module_get_refcnt(mod);
 
442
 
 
443
                if (usage > 0) {
 
444
                        if (!quiet_inuse)
 
445
                                LOG("Module %s is in use.\n", modname);
 
446
 
 
447
                        err = -EBUSY;
 
448
                        goto error;
 
449
                }
 
450
        }
 
451
 
 
452
        if (cmd == NULL)
 
453
                err = rmmod_do_remove_module(mod);
 
454
        else
 
455
                err = command_do(mod, "remove", cmd, NULL);
 
456
 
 
457
        if (err < 0)
 
458
                goto error;
 
459
 
 
460
        rmmod_do_deps_list(pre, false);
 
461
 
 
462
error:
 
463
        kmod_module_unref_list(pre);
 
464
        kmod_module_unref_list(post);
 
465
 
 
466
        return err;
 
467
}
 
468
 
 
469
static int rmmod(struct kmod_ctx *ctx, const char *alias)
 
470
{
 
471
        struct kmod_list *l, *list = NULL;
 
472
        int err;
 
473
 
 
474
        err = kmod_module_new_from_lookup(ctx, alias, &list);
 
475
        if (err < 0)
 
476
                return err;
 
477
 
 
478
        if (list == NULL) {
 
479
                LOG("Module %s not found.\n", alias);
 
480
                err = -ENOENT;
 
481
        }
 
482
 
 
483
        kmod_list_foreach(l, list) {
 
484
                struct kmod_module *mod = kmod_module_get_module(l);
 
485
                err = rmmod_do_module(mod, true);
 
486
                kmod_module_unref(mod);
 
487
                if (err < 0)
 
488
                        break;
 
489
        }
 
490
 
 
491
        kmod_module_unref_list(list);
 
492
        return err;
 
493
}
 
494
 
 
495
static int rmmod_all(struct kmod_ctx *ctx, char **args, int nargs)
 
496
{
 
497
        int i, err = 0;
 
498
 
 
499
        for (i = 0; i < nargs; i++) {
 
500
                int r = rmmod(ctx, args[i]);
 
501
                if (r < 0)
 
502
                        err = r;
 
503
        }
 
504
 
 
505
        return err;
 
506
}
 
507
 
 
508
static int handle_failed_lookup(struct kmod_ctx *ctx, const char *alias)
 
509
{
 
510
        struct kmod_module *mod;
 
511
        int state, err;
 
512
 
 
513
        DBG("lookup failed - trying to check if it's builtin\n");
 
514
 
 
515
        err = kmod_module_new_from_name(ctx, alias, &mod);
 
516
        if (err < 0)
 
517
                return err;
 
518
 
 
519
        state = kmod_module_get_initstate(mod);
 
520
        kmod_module_unref(mod);
 
521
 
 
522
        if (state != KMOD_MODULE_BUILTIN) {
 
523
                LOG("Module %s not found.\n", alias);
 
524
                return -ENOENT;
 
525
        }
 
526
 
 
527
        if (first_time) {
 
528
                LOG("Module %s already in kernel (builtin).\n", alias);
 
529
                return -ENOENT;
 
530
        }
 
531
 
 
532
        SHOW("builtin %s\n", alias);
 
533
        return 0;
 
534
}
 
535
 
 
536
static void print_action(struct kmod_module *m, bool install,
 
537
                                                        const char *options)
 
538
{
 
539
        const char *path;
 
540
 
 
541
        if (install) {
 
542
                printf("install %s %s\n", kmod_module_get_install_commands(m),
 
543
                                                                options);
 
544
                return;
 
545
        }
 
546
 
 
547
        path = kmod_module_get_path(m);
 
548
 
 
549
        if (path == NULL) {
 
550
                assert(kmod_module_get_initstate(m) == KMOD_MODULE_BUILTIN);
 
551
                printf("builtin %s\n", kmod_module_get_name(m));
 
552
        } else
 
553
                printf("insmod %s %s\n", kmod_module_get_path(m), options);
 
554
}
 
555
 
 
556
static int insmod(struct kmod_ctx *ctx, const char *alias,
 
557
                                                const char *extra_options)
 
558
{
 
559
        struct kmod_list *l, *list = NULL;
 
560
        int err, flags = 0;
 
561
 
 
562
        void (*show)(struct kmod_module *m, bool install,
 
563
                                                const char *options) = NULL;
 
564
 
 
565
        err = kmod_module_new_from_lookup(ctx, alias, &list);
 
566
        if (err < 0)
 
567
                return err;
 
568
 
 
569
        if (list == NULL)
 
570
                return handle_failed_lookup(ctx, alias);
 
571
 
 
572
        if (strip_modversion || force)
 
573
                flags |= KMOD_PROBE_FORCE_MODVERSION;
 
574
        if (strip_vermagic || force)
 
575
                flags |= KMOD_PROBE_FORCE_VERMAGIC;
 
576
        if (ignore_commands)
 
577
                flags |= KMOD_PROBE_IGNORE_COMMAND;
 
578
        if (ignore_loaded)
 
579
                flags |= KMOD_PROBE_IGNORE_LOADED;
 
580
        if (dry_run)
 
581
                flags |= KMOD_PROBE_DRY_RUN;
 
582
        if (do_show || verbose > DEFAULT_VERBOSE)
 
583
                show = &print_action;
 
584
 
 
585
 
 
586
        if (use_blacklist)
 
587
                flags |= KMOD_PROBE_APPLY_BLACKLIST;
 
588
        if (first_time)
 
589
                flags |= KMOD_PROBE_FAIL_ON_LOADED;
 
590
 
 
591
        kmod_list_foreach(l, list) {
 
592
                struct kmod_module *mod = kmod_module_get_module(l);
 
593
 
 
594
                if (lookup_only)
 
595
                        printf("%s\n", kmod_module_get_name(mod));
 
596
                else {
 
597
                        err = kmod_module_probe_insert_module(mod, flags,
 
598
                                        extra_options, NULL, NULL, show);
 
599
                }
 
600
 
 
601
                if (err >= 0)
 
602
                        /* ignore flag return values such as a mod being blacklisted */
 
603
                        err = 0;
 
604
                else {
 
605
                        switch (err) {
 
606
                        case -EEXIST:
 
607
                                ERR("could not insert '%s': Module already in kernel\n",
 
608
                                                        kmod_module_get_name(mod));
 
609
                                break;
 
610
                        case -ENOENT:
 
611
                                ERR("could not insert '%s': Unknown symbol in module, "
 
612
                                                "or unknown parameter (see dmesg)\n",
 
613
                                                kmod_module_get_name(mod));
 
614
                                break;
 
615
                        default:
 
616
                                ERR("could not insert '%s': %s\n",
 
617
                                                kmod_module_get_name(mod),
 
618
                                                strerror(-err));
 
619
                                break;
 
620
                        }
 
621
                }
 
622
 
 
623
                kmod_module_unref(mod);
 
624
        }
 
625
 
 
626
        kmod_module_unref_list(list);
 
627
        return err;
 
628
}
 
629
 
 
630
static int insmod_all(struct kmod_ctx *ctx, char **args, int nargs)
 
631
{
 
632
        int i, err = 0;
 
633
 
 
634
        for (i = 0; i < nargs; i++) {
 
635
                int r = insmod(ctx, args[i], NULL);
 
636
                if (r < 0)
 
637
                        err = r;
 
638
        }
 
639
 
 
640
        return err;
 
641
}
 
642
 
 
643
static void env_modprobe_options_append(const char *value)
 
644
{
 
645
        const char *old = getenv("MODPROBE_OPTIONS");
 
646
        char *env;
 
647
 
 
648
        if (old == NULL) {
 
649
                setenv("MODPROBE_OPTIONS", value, 1);
 
650
                return;
 
651
        }
 
652
 
 
653
        if (asprintf(&env, "%s %s", old, value) < 0) {
 
654
                ERR("could not append value to $MODPROBE_OPTIONS\n");
 
655
                return;
 
656
        }
 
657
 
 
658
        if (setenv("MODPROBE_OPTIONS", env, 1) < 0)
 
659
                ERR("could not setenv(MODPROBE_OPTIONS, \"%s\")\n", env);
 
660
        free(env);
 
661
}
 
662
 
 
663
static int options_from_array(char **args, int nargs, char **output)
 
664
{
 
665
        char *opts = NULL;
 
666
        size_t optslen = 0;
 
667
        int i, err = 0;
 
668
 
 
669
        for (i = 1; i < nargs; i++) {
 
670
                size_t len = strlen(args[i]);
 
671
                size_t qlen = 0;
 
672
                const char *value;
 
673
                void *tmp;
 
674
 
 
675
                value = strchr(args[i], '=');
 
676
                if (value) {
 
677
                        value++;
 
678
                        if (*value != '"' && *value != '\'') {
 
679
                                if (strchr(value, ' '))
 
680
                                        qlen = 2;
 
681
                        }
 
682
                }
 
683
 
 
684
                tmp = realloc(opts, optslen + len + qlen + 2);
 
685
                if (!tmp) {
 
686
                        err = -errno;
 
687
                        free(opts);
 
688
                        opts = NULL;
 
689
                        ERR("could not gather module options: out-of-memory\n");
 
690
                        break;
 
691
                }
 
692
                opts = tmp;
 
693
                if (optslen > 0) {
 
694
                        opts[optslen] = ' ';
 
695
                        optslen++;
 
696
                }
 
697
                if (qlen == 0) {
 
698
                        memcpy(opts + optslen, args[i], len + 1);
 
699
                        optslen += len;
 
700
                } else {
 
701
                        size_t keylen = value - args[i];
 
702
                        size_t valuelen = len - keylen;
 
703
                        memcpy(opts + optslen, args[i], keylen);
 
704
                        optslen += keylen;
 
705
                        opts[optslen] = '"';
 
706
                        optslen++;
 
707
                        memcpy(opts + optslen, value, valuelen);
 
708
                        optslen += valuelen;
 
709
                        opts[optslen] = '"';
 
710
                        optslen++;
 
711
                        opts[optslen] = '\0';
 
712
                }
 
713
        }
 
714
 
 
715
        *output = opts;
 
716
        return err;
 
717
}
 
718
 
 
719
static char **prepend_options_from_env(int *p_argc, char **orig_argv)
 
720
{
 
721
        const char *p, *env = getenv("MODPROBE_OPTIONS");
 
722
        char **new_argv, *str_start, *str_end, *str, *s, *quote;
 
723
        int i, argc = *p_argc;
 
724
        size_t envlen, space_count = 0;
 
725
 
 
726
        if (env == NULL)
 
727
                return orig_argv;
 
728
 
 
729
        for (p = env; *p != '\0'; p++) {
 
730
                if (*p == ' ')
 
731
                        space_count++;
 
732
        }
 
733
 
 
734
        envlen = p - env;
 
735
        new_argv = malloc(sizeof(char *) * (argc + space_count + 3 + envlen));
 
736
        if (new_argv == NULL)
 
737
                return NULL;
 
738
 
 
739
        new_argv[0] = orig_argv[0];
 
740
        str_start = str = (char *) (new_argv + argc + space_count + 3);
 
741
        memcpy(str, env, envlen + 1);
 
742
 
 
743
        str_end = str_start + envlen;
 
744
 
 
745
        quote = NULL;
 
746
        for (i = 1, s = str; *s != '\0'; s++) {
 
747
                if (quote == NULL) {
 
748
                        if (*s == ' ') {
 
749
                                new_argv[i] = str;
 
750
                                i++;
 
751
                                *s = '\0';
 
752
                                str = s + 1;
 
753
                        } else if (*s == '"' || *s == '\'')
 
754
                                quote = s;
 
755
                } else {
 
756
                        if (*s == *quote) {
 
757
                                if (quote == str) {
 
758
                                        new_argv[i] = str + 1;
 
759
                                        i++;
 
760
                                        *s = '\0';
 
761
                                        str = s + 1;
 
762
                                } else {
 
763
                                        char *it;
 
764
                                        for (it = quote; it < s - 1; it++)
 
765
                                                it[0] = it[1];
 
766
                                        for (it = s - 1; it < str_end - 2; it++)
 
767
                                                it[0] = it[2];
 
768
                                        str_end -= 2;
 
769
                                        *str_end = '\0';
 
770
                                        s -= 2;
 
771
                                }
 
772
                                quote = NULL;
 
773
                        }
 
774
                }
 
775
        }
 
776
        if (str < s) {
 
777
                new_argv[i] = str;
 
778
                i++;
 
779
        }
 
780
 
 
781
        memcpy(new_argv + i, orig_argv + 1, sizeof(char *) * (argc - 1));
 
782
        new_argv[i + argc] = NULL;
 
783
        *p_argc = i + argc - 1;
 
784
 
 
785
        return new_argv;
 
786
}
 
787
 
 
788
static void log_syslog(void *data, int priority, const char *file, int line,
 
789
                        const char *fn, const char *format, va_list args)
 
790
{
 
791
        char *str, buf[32];
 
792
        const char *prioname;
 
793
 
 
794
        switch (priority) {
 
795
        case LOG_CRIT:
 
796
                prioname = "FATAL";
 
797
                break;
 
798
        case LOG_ERR:
 
799
                prioname = "ERROR";
 
800
                break;
 
801
        case LOG_WARNING:
 
802
                prioname = "WARNING";
 
803
                break;
 
804
        case LOG_NOTICE:
 
805
                prioname = "NOTICE";
 
806
                break;
 
807
        case LOG_INFO:
 
808
                prioname = "INFO";
 
809
                break;
 
810
        case LOG_DEBUG:
 
811
                prioname = "DEBUG";
 
812
                break;
 
813
        default:
 
814
                snprintf(buf, sizeof(buf), "LOG-%03d", priority);
 
815
                prioname = buf;
 
816
        }
 
817
 
 
818
        if (vasprintf(&str, format, args) < 0)
 
819
                return;
 
820
#ifdef ENABLE_DEBUG
 
821
        syslog(LOG_NOTICE, "%s: %s:%d %s() %s", prioname, file, line, fn, str);
 
822
#else
 
823
        syslog(LOG_NOTICE, "%s: %s", prioname, str);
 
824
#endif
 
825
        free(str);
 
826
        (void)data;
 
827
}
 
828
 
 
829
static int do_modprobe(int argc, char **orig_argv)
 
830
{
 
831
        struct kmod_ctx *ctx;
 
832
        char **args = NULL, **argv;
 
833
        const char **config_paths = NULL;
 
834
        int nargs = 0, n_config_paths = 0;
 
835
        char dirname_buf[PATH_MAX];
 
836
        const char *dirname = NULL;
 
837
        const char *root = NULL;
 
838
        const char *kversion = NULL;
 
839
        int use_all = 0;
 
840
        int do_remove = 0;
 
841
        int do_show_config = 0;
 
842
        int do_show_modversions = 0;
 
843
        int err;
 
844
 
 
845
        argv = prepend_options_from_env(&argc, orig_argv);
 
846
        if (argv == NULL) {
 
847
                fputs("Error: could not prepend options from command line\n",
 
848
                        stderr);
 
849
                return EXIT_FAILURE;
 
850
        }
 
851
 
 
852
        for (;;) {
 
853
                int c, idx = 0;
 
854
                c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
 
855
                if (c == -1)
 
856
                        break;
 
857
                switch (c) {
 
858
                case 'a':
 
859
                        log_priority = LOG_WARNING;
 
860
                        use_all = 1;
 
861
                        break;
 
862
                case 'r':
 
863
                        do_remove = 1;
 
864
                        break;
 
865
                case 5:
 
866
                        remove_dependencies = 1;
 
867
                        break;
 
868
                case 'R':
 
869
                        lookup_only = 1;
 
870
                        break;
 
871
                case 3:
 
872
                        first_time = 1;
 
873
                        break;
 
874
                case 'i':
 
875
                        ignore_commands = 1;
 
876
                        break;
 
877
                case 'b':
 
878
                        use_blacklist = 1;
 
879
                        break;
 
880
                case 'f':
 
881
                        force = 1;
 
882
                        break;
 
883
                case 2:
 
884
                        strip_modversion = 1;
 
885
                        break;
 
886
                case 1:
 
887
                        strip_vermagic = 1;
 
888
                        break;
 
889
                case 'D':
 
890
                        ignore_loaded = 1;
 
891
                        dry_run = 1;
 
892
                        do_show = 1;
 
893
                        break;
 
894
                case 'c':
 
895
                        do_show_config = 1;
 
896
                        break;
 
897
                case 4:
 
898
                        do_show_modversions = 1;
 
899
                        break;
 
900
                case 'n':
 
901
                        dry_run = 1;
 
902
                        break;
 
903
                case 'C': {
 
904
                        size_t bytes = sizeof(char *) * (n_config_paths + 2);
 
905
                        void *tmp = realloc(config_paths, bytes);
 
906
                        if (!tmp) {
 
907
                                fputs("Error: out-of-memory\n", stderr);
 
908
                                goto cmdline_failed;
 
909
                        }
 
910
                        config_paths = tmp;
 
911
                        config_paths[n_config_paths] = optarg;
 
912
                        n_config_paths++;
 
913
                        config_paths[n_config_paths] = NULL;
 
914
 
 
915
                        env_modprobe_options_append("-C");
 
916
                        env_modprobe_options_append(optarg);
 
917
                        break;
 
918
                }
 
919
                case 'd':
 
920
                        root = optarg;
 
921
                        break;
 
922
                case 'S':
 
923
                        kversion = optarg;
 
924
                        break;
 
925
                case 's':
 
926
                        env_modprobe_options_append("-s");
 
927
                        use_syslog = 1;
 
928
                        break;
 
929
                case 'q':
 
930
                        env_modprobe_options_append("-q");
 
931
                        verbose = LOG_EMERG;
 
932
                        break;
 
933
                case 'v':
 
934
                        env_modprobe_options_append("-v");
 
935
                        verbose++;
 
936
                        break;
 
937
                case 'V':
 
938
                        puts(PACKAGE " version " VERSION);
 
939
                        if (argv != orig_argv)
 
940
                                free(argv);
 
941
                        free(config_paths);
 
942
                        return EXIT_SUCCESS;
 
943
                case 'h':
 
944
                        help(basename(argv[0]));
 
945
                        if (argv != orig_argv)
 
946
                                free(argv);
 
947
                        free(config_paths);
 
948
                        return EXIT_SUCCESS;
 
949
                case '?':
 
950
                        goto cmdline_failed;
 
951
                default:
 
952
                        fprintf(stderr, "Error: unexpected getopt_long() value '%c'.\n",
 
953
                                                                        c);
 
954
                        goto cmdline_failed;
 
955
                }
 
956
        }
 
957
 
 
958
        args = argv + optind;
 
959
        nargs = argc - optind;
 
960
 
 
961
        if (!do_show_config) {
 
962
                if (nargs == 0) {
 
963
                        fputs("Error: missing parameters. See -h.\n", stderr);
 
964
                        goto cmdline_failed;
 
965
                }
 
966
        }
 
967
 
 
968
        if (root != NULL || kversion != NULL) {
 
969
                struct utsname u;
 
970
                if (root == NULL)
 
971
                        root = "";
 
972
                if (kversion == NULL) {
 
973
                        if (uname(&u) < 0) {
 
974
                                fprintf(stderr, "Error: uname() failed: %s\n",
 
975
                                        strerror(errno));
 
976
                                goto cmdline_failed;
 
977
                        }
 
978
                        kversion = u.release;
 
979
                }
 
980
                snprintf(dirname_buf, sizeof(dirname_buf),
 
981
                                "%s" ROOTPREFIX "/lib/modules/%s", root,
 
982
                                kversion);
 
983
                dirname = dirname_buf;
 
984
        }
 
985
 
 
986
        ctx = kmod_new(dirname, config_paths);
 
987
        if (!ctx) {
 
988
                fputs("Error: kmod_new() failed!\n", stderr);
 
989
                goto cmdline_failed;
 
990
        }
 
991
        kmod_load_resources(ctx);
 
992
 
 
993
        kmod_set_log_priority(ctx, verbose);
 
994
        if (use_syslog) {
 
995
                openlog("modprobe", LOG_CONS, LOG_DAEMON);
 
996
                kmod_set_log_fn(ctx, log_syslog, NULL);
 
997
        }
 
998
 
 
999
        if (do_show_config)
 
1000
                err = show_config(ctx);
 
1001
        else if (do_show_modversions)
 
1002
                err = show_modversions(ctx, args[0]);
 
1003
        else if (do_remove)
 
1004
                err = rmmod_all(ctx, args, nargs);
 
1005
        else if (use_all)
 
1006
                err = insmod_all(ctx, args, nargs);
 
1007
        else {
 
1008
                char *opts;
 
1009
                err = options_from_array(args, nargs, &opts);
 
1010
                if (err == 0) {
 
1011
                        err = insmod(ctx, args[0], opts);
 
1012
                        free(opts);
 
1013
                }
 
1014
        }
 
1015
 
 
1016
        kmod_unref(ctx);
 
1017
 
 
1018
        if (use_syslog)
 
1019
                closelog();
 
1020
 
 
1021
        if (argv != orig_argv)
 
1022
                free(argv);
 
1023
 
 
1024
        free(config_paths);
 
1025
        return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 
1026
 
 
1027
cmdline_failed:
 
1028
        if (argv != orig_argv)
 
1029
                free(argv);
 
1030
        free(config_paths);
 
1031
        return EXIT_FAILURE;
 
1032
}
 
1033
 
 
1034
#include "kmod.h"
 
1035
 
 
1036
const struct kmod_cmd kmod_cmd_compat_modprobe = {
 
1037
        .name = "modprobe",
 
1038
        .cmd = do_modprobe,
 
1039
        .help = "compat modprobe command",
 
1040
};