]>
Commit | Line | Data |
---|---|---|
72c51a9e GSB |
1 | /* |
2 | * kmod-insmod - insert modules into linux kernel using libkmod. | |
3 | * | |
e6b0e49b | 4 | * Copyright (C) 2011-2013 ProFUSION embedded systems |
72c51a9e | 5 | * |
cb451f35 LDM |
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. | |
72c51a9e GSB |
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 | |
cb451f35 LDM |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | |
72c51a9e | 15 | * |
cb451f35 LDM |
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/>. | |
72c51a9e | 18 | */ |
cb451f35 | 19 | |
c2e4286b LDM |
20 | #include <errno.h> |
21 | #include <getopt.h> | |
72c51a9e GSB |
22 | #include <stdio.h> |
23 | #include <stdlib.h> | |
72c51a9e | 24 | #include <string.h> |
c2e4286b | 25 | |
5b0436a7 LDM |
26 | #include <shared/util.h> |
27 | ||
f357866d | 28 | #include <libkmod/libkmod.h> |
72c51a9e | 29 | |
4a2e20df LDM |
30 | #include "kmod.h" |
31 | ||
72c51a9e GSB |
32 | static const char cmdopts_s[] = "psfVh"; |
33 | static const struct option cmdopts[] = { | |
34 | {"version", no_argument, 0, 'V'}, | |
35 | {"help", no_argument, 0, 'h'}, | |
36 | {NULL, 0, 0, 0} | |
37 | }; | |
38 | ||
4a2e20df | 39 | static void help(void) |
72c51a9e | 40 | { |
34e06bfb | 41 | printf("Usage:\n" |
72c51a9e GSB |
42 | "\t%s [options] filename [args]\n" |
43 | "Options:\n" | |
44 | "\t-V, --version show version\n" | |
45 | "\t-h, --help show this help\n", | |
7c04aeee | 46 | program_invocation_short_name); |
72c51a9e GSB |
47 | } |
48 | ||
49 | static const char *mod_strerror(int err) | |
50 | { | |
51 | switch (err) { | |
52 | case ENOEXEC: | |
53 | return "Invalid module format"; | |
54 | case ENOENT: | |
55 | return "Unknown symbol in module"; | |
56 | case ESRCH: | |
57 | return "Module has wrong symbol version"; | |
58 | case EINVAL: | |
59 | return "Invalid parameters"; | |
60 | default: | |
61 | return strerror(err); | |
62 | } | |
63 | } | |
64 | ||
ad602696 | 65 | static int do_insmod(int argc, char *argv[]) |
72c51a9e GSB |
66 | { |
67 | struct kmod_ctx *ctx; | |
68 | struct kmod_module *mod; | |
69 | const char *filename; | |
70 | char *opts = NULL; | |
71 | size_t optslen = 0; | |
72 | int i, err; | |
2411c077 | 73 | const char *null_config = NULL; |
2b2a503e | 74 | unsigned int flags = 0; |
72c51a9e GSB |
75 | |
76 | for (;;) { | |
77 | int c, idx = 0; | |
78 | c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx); | |
79 | if (c == -1) | |
80 | break; | |
81 | switch (c) { | |
82 | case 'p': | |
83 | case 's': | |
d64b286a MAP |
84 | /* ignored, for compatibility only */ |
85 | break; | |
72c51a9e | 86 | case 'f': |
2b2a503e PDS |
87 | flags |= KMOD_PROBE_FORCE_MODVERSION; |
88 | flags |= KMOD_PROBE_FORCE_VERMAGIC; | |
72c51a9e GSB |
89 | break; |
90 | case 'h': | |
4a2e20df | 91 | help(); |
72c51a9e GSB |
92 | return EXIT_SUCCESS; |
93 | case 'V': | |
94 | puts(PACKAGE " version " VERSION); | |
655de275 | 95 | puts(KMOD_FEATURES); |
72c51a9e GSB |
96 | return EXIT_SUCCESS; |
97 | case '?': | |
98 | return EXIT_FAILURE; | |
99 | default: | |
e2f9478f | 100 | ERR("unexpected getopt_long() value '%c'.\n", |
72c51a9e GSB |
101 | c); |
102 | return EXIT_FAILURE; | |
103 | } | |
104 | } | |
105 | ||
106 | if (optind >= argc) { | |
e2f9478f | 107 | ERR("missing filename.\n"); |
72c51a9e GSB |
108 | return EXIT_FAILURE; |
109 | } | |
110 | ||
111 | filename = argv[optind]; | |
5b0436a7 | 112 | if (streq(filename, "-")) { |
e2f9478f | 113 | ERR("this tool does not support loading from stdin!\n"); |
72c51a9e GSB |
114 | return EXIT_FAILURE; |
115 | } | |
116 | ||
117 | for (i = optind + 1; i < argc; i++) { | |
118 | size_t len = strlen(argv[i]); | |
119 | void *tmp = realloc(opts, optslen + len + 2); | |
120 | if (tmp == NULL) { | |
e2f9478f | 121 | ERR("out of memory\n"); |
72c51a9e GSB |
122 | free(opts); |
123 | return EXIT_FAILURE; | |
124 | } | |
125 | opts = tmp; | |
126 | if (optslen > 0) { | |
127 | opts[optslen] = ' '; | |
128 | optslen++; | |
129 | } | |
130 | memcpy(opts + optslen, argv[i], len); | |
131 | optslen += len; | |
132 | opts[optslen] = '\0'; | |
133 | } | |
134 | ||
2411c077 | 135 | ctx = kmod_new(NULL, &null_config); |
72c51a9e | 136 | if (!ctx) { |
e2f9478f | 137 | ERR("kmod_new() failed!\n"); |
72c51a9e GSB |
138 | free(opts); |
139 | return EXIT_FAILURE; | |
140 | } | |
141 | ||
142 | err = kmod_module_new_from_path(ctx, filename, &mod); | |
143 | if (err < 0) { | |
e2f9478f LDM |
144 | ERR("could not load module %s: %s\n", filename, |
145 | strerror(-err)); | |
72c51a9e GSB |
146 | goto end; |
147 | } | |
148 | ||
2b2a503e | 149 | err = kmod_module_insert_module(mod, flags, opts); |
72c51a9e | 150 | if (err < 0) { |
e2f9478f LDM |
151 | ERR("could not insert module %s: %s\n", filename, |
152 | mod_strerror(-err)); | |
72c51a9e GSB |
153 | } |
154 | kmod_module_unref(mod); | |
155 | ||
156 | end: | |
157 | kmod_unref(ctx); | |
158 | free(opts); | |
159 | return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; | |
160 | } | |
ad602696 | 161 | |
ad602696 LDM |
162 | const struct kmod_cmd kmod_cmd_compat_insmod = { |
163 | .name = "insmod", | |
164 | .cmd = do_insmod, | |
165 | .help = "compat insmod command", | |
166 | }; |