]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/modules-load/modules-load.c
Remove unused variables
[thirdparty/systemd.git] / src / modules-load / modules-load.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <limits.h>
28 #include <dirent.h>
29 #include <getopt.h>
30 #include <libkmod.h>
31
32 #include "log.h"
33 #include "util.h"
34 #include "strv.h"
35 #include "conf-files.h"
36 #include "fileio.h"
37 #include "build.h"
38
39 static char **arg_proc_cmdline_modules = NULL;
40
41 static const char conf_file_dirs[] =
42 "/etc/modules-load.d\0"
43 "/run/modules-load.d\0"
44 "/usr/local/lib/modules-load.d\0"
45 "/usr/lib/modules-load.d\0"
46 #ifdef HAVE_SPLIT_USR
47 "/lib/modules-load.d\0"
48 #endif
49 ;
50
51 #pragma GCC diagnostic push
52 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
53 static void systemd_kmod_log(void *data, int priority, const char *file, int line,
54 const char *fn, const char *format, va_list args) {
55 log_metav(priority, file, line, fn, format, args);
56 }
57 #pragma GCC diagnostic pop
58
59 static int add_modules(const char *p) {
60 _cleanup_strv_free_ char **k = NULL;
61
62 k = strv_split(p, ",");
63 if (!k)
64 return log_oom();
65
66 if (strv_extend_strv(&arg_proc_cmdline_modules, k) < 0)
67 return log_oom();
68
69 return 0;
70 }
71
72 static int parse_proc_cmdline(void) {
73 _cleanup_free_ char *line = NULL;
74 char *w, *state;
75 size_t l;
76 int r;
77
78 r = proc_cmdline(&line);
79 if (r < 0)
80 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
81 if (r <= 0)
82 return 0;
83
84 FOREACH_WORD_QUOTED(w, l, line, state) {
85 _cleanup_free_ char *word;
86
87 word = strndup(w, l);
88 if (!word)
89 return log_oom();
90
91 if (startswith(word, "modules-load=")) {
92
93 r = add_modules(word + 13);
94 if (r < 0)
95 return r;
96
97 } else if (startswith(word, "rd.modules-load=")) {
98
99 if (in_initrd()) {
100 r = add_modules(word + 16);
101 if (r < 0)
102 return r;
103 }
104
105 }
106 }
107
108 return 0;
109 }
110
111 static int load_module(struct kmod_ctx *ctx, const char *m) {
112 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
113 struct kmod_list *itr, *modlist = NULL;
114 int r = 0;
115
116 log_debug("load: %s", m);
117
118 r = kmod_module_new_from_lookup(ctx, m, &modlist);
119 if (r < 0) {
120 log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
121 return r;
122 }
123
124 if (!modlist) {
125 log_error("Failed to find module '%s'", m);
126 return -ENOENT;
127 }
128
129 kmod_list_foreach(itr, modlist) {
130 struct kmod_module *mod;
131 int state, err;
132
133 mod = kmod_module_get_module(itr);
134 state = kmod_module_get_initstate(mod);
135
136 switch (state) {
137 case KMOD_MODULE_BUILTIN:
138 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
139 break;
140
141 case KMOD_MODULE_LIVE:
142 log_debug("Module '%s' is already loaded", kmod_module_get_name(mod));
143 break;
144
145 default:
146 err = kmod_module_probe_insert_module(mod, probe_flags,
147 NULL, NULL, NULL, NULL);
148
149 if (err == 0)
150 log_info("Inserted module '%s'", kmod_module_get_name(mod));
151 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
152 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
153 else {
154 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
155 strerror(-err));
156 r = err;
157 }
158 }
159
160 kmod_module_unref(mod);
161 }
162
163 kmod_module_unref_list(modlist);
164
165 return r;
166 }
167
168 static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
169 _cleanup_fclose_ FILE *f = NULL;
170 int r;
171
172 assert(ctx);
173 assert(path);
174
175 r = search_and_fopen_nulstr(path, "re", conf_file_dirs, &f);
176 if (r < 0) {
177 if (ignore_enoent && r == -ENOENT)
178 return 0;
179
180 log_error("Failed to open %s, ignoring: %s", path, strerror(-r));
181 return r;
182 }
183
184 log_debug("apply: %s", path);
185 for (;;) {
186 char line[LINE_MAX], *l;
187 int k;
188
189 if (!fgets(line, sizeof(line), f)) {
190 if (feof(f))
191 break;
192
193 log_error("Failed to read file '%s', ignoring: %m", path);
194 return -errno;
195 }
196
197 l = strstrip(line);
198 if (!*l)
199 continue;
200 if (strchr(COMMENTS "\n", *l))
201 continue;
202
203 k = load_module(ctx, l);
204 if (k < 0 && r == 0)
205 r = k;
206 }
207
208 return r;
209 }
210
211 static int help(void) {
212
213 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
214 "Loads statically configured kernel modules.\n\n"
215 " -h --help Show this help\n"
216 " --version Show package version\n",
217 program_invocation_short_name);
218
219 return 0;
220 }
221
222 static int parse_argv(int argc, char *argv[]) {
223
224 enum {
225 ARG_VERSION = 0x100,
226 };
227
228 static const struct option options[] = {
229 { "help", no_argument, NULL, 'h' },
230 { "version", no_argument, NULL, ARG_VERSION },
231 {}
232 };
233
234 int c;
235
236 assert(argc >= 0);
237 assert(argv);
238
239 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
240
241 switch (c) {
242
243 case 'h':
244 return help();
245
246 case ARG_VERSION:
247 puts(PACKAGE_STRING);
248 puts(SYSTEMD_FEATURES);
249 return 0;
250
251 case '?':
252 return -EINVAL;
253
254 default:
255 assert_not_reached("Unhandled option");
256 }
257 }
258
259 return 1;
260 }
261
262 int main(int argc, char *argv[]) {
263 int r, k;
264 struct kmod_ctx *ctx;
265
266 r = parse_argv(argc, argv);
267 if (r <= 0)
268 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
269
270 log_set_target(LOG_TARGET_AUTO);
271 log_parse_environment();
272 log_open();
273
274 umask(0022);
275
276 if (parse_proc_cmdline() < 0)
277 return EXIT_FAILURE;
278
279 ctx = kmod_new(NULL, NULL);
280 if (!ctx) {
281 log_error("Failed to allocate memory for kmod.");
282 goto finish;
283 }
284
285 kmod_load_resources(ctx);
286 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
287
288 r = 0;
289
290 if (argc > optind) {
291 int i;
292
293 for (i = optind; i < argc; i++) {
294 k = apply_file(ctx, argv[i], false);
295 if (k < 0 && r == 0)
296 r = k;
297 }
298
299 } else {
300 _cleanup_free_ char **files = NULL;
301 char **fn, **i;
302
303 STRV_FOREACH(i, arg_proc_cmdline_modules) {
304 k = load_module(ctx, *i);
305 if (k < 0 && r == 0)
306 r = k;
307 }
308
309 r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
310 if (r < 0) {
311 log_error("Failed to enumerate modules-load.d files: %s", strerror(-r));
312 goto finish;
313 }
314
315 STRV_FOREACH(fn, files) {
316 k = apply_file(ctx, *fn, true);
317 if (k < 0 && r == 0)
318 r = k;
319 }
320 }
321
322 finish:
323 kmod_unref(ctx);
324 strv_free(arg_proc_cmdline_modules);
325
326 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
327 }