]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/modules-load/modules-load.c
dbus: fix return value of dispatch_rqueue()
[thirdparty/systemd.git] / src / modules-load / modules-load.c
CommitLineData
b2423f1f
LP
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
5430f7f2
LP
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
b2423f1f
LP
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
5430f7f2 16 Lesser General Public License for more details.
b2423f1f 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
b2423f1f
LP
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>
fabe5c0e 29#include <getopt.h>
83684a35 30#include <libkmod.h>
b2423f1f
LP
31
32#include "log.h"
33#include "util.h"
34#include "strv.h"
2c21044f 35#include "conf-files.h"
03658d4f 36#include "virt.h"
a5c32cff 37#include "fileio.h"
03658d4f
LP
38
39static char **arg_proc_cmdline_modules = NULL;
b2423f1f 40
fabe5c0e
LP
41static 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
cdb454f2
LP
51#pragma GCC diagnostic push
52#pragma GCC diagnostic ignored "-Wformat-nonliteral"
83684a35
TG
53static void systemd_kmod_log(void *data, int priority, const char *file, int line,
54 const char *fn, const char *format, va_list args)
55{
e62abb62 56 log_metav(priority, file, line, fn, format, args);
83684a35 57}
cdb454f2 58#pragma GCC diagnostic pop
83684a35 59
03658d4f 60static int add_modules(const char *p) {
fabe5c0e
LP
61 char **t;
62 _cleanup_strv_free_ char **k = NULL;
03658d4f
LP
63
64 k = strv_split(p, ",");
0d0f0c50
SL
65 if (!k)
66 return log_oom();
03658d4f
LP
67
68 t = strv_merge(arg_proc_cmdline_modules, k);
0d0f0c50
SL
69 if (!t)
70 return log_oom();
03658d4f
LP
71
72 strv_free(arg_proc_cmdline_modules);
73 arg_proc_cmdline_modules = t;
74
75 return 0;
76}
77
78static int parse_proc_cmdline(void) {
7fd1b19b 79 _cleanup_free_ char *line = NULL;
c007bb1b 80 char *w, *state;
03658d4f
LP
81 int r;
82 size_t l;
83
84 if (detect_container(NULL) > 0)
85 return 0;
86
87 r = read_one_line_file("/proc/cmdline", &line);
88 if (r < 0) {
89 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
90 return 0;
91 }
92
93 FOREACH_WORD_QUOTED(w, l, line, state) {
7fd1b19b 94 _cleanup_free_ char *word;
03658d4f
LP
95
96 word = strndup(w, l);
c007bb1b
ZJS
97 if (!word)
98 return log_oom();
03658d4f 99
91ac7425 100 if (startswith(word, "modules-load=")) {
03658d4f 101
b2fc39a6 102 r = add_modules(word + 13);
03658d4f 103 if (r < 0)
c007bb1b 104 return r;
03658d4f 105
91ac7425 106 } else if (startswith(word, "rd.modules-load=")) {
03658d4f
LP
107
108 if (in_initrd()) {
b2fc39a6 109 r = add_modules(word + 16);
03658d4f 110 if (r < 0)
c007bb1b 111 return r;
03658d4f
LP
112 }
113
114 }
03658d4f
LP
115 }
116
c007bb1b 117 return 0;
03658d4f
LP
118}
119
120static int load_module(struct kmod_ctx *ctx, const char *m) {
27fda47f 121 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
03658d4f
LP
122 struct kmod_list *itr, *modlist = NULL;
123 int r = 0;
124
125 log_debug("load: %s\n", m);
126
127 r = kmod_module_new_from_lookup(ctx, m, &modlist);
128 if (r < 0) {
129 log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
130 return r;
131 }
132
27fda47f
MS
133 if (!modlist) {
134 log_error("Failed to find module '%s'", m);
8f9c0b4c 135 return -ENOENT;
27fda47f
MS
136 }
137
03658d4f
LP
138 kmod_list_foreach(itr, modlist) {
139 struct kmod_module *mod;
27fda47f 140 int state, err;
03658d4f
LP
141
142 mod = kmod_module_get_module(itr);
27fda47f
MS
143 state = kmod_module_get_initstate(mod);
144
145 switch (state) {
146 case KMOD_MODULE_BUILTIN:
147 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
148 break;
149
150 case KMOD_MODULE_LIVE:
b56c267f 151 log_debug("Module '%s' is already loaded", kmod_module_get_name(mod));
27fda47f
MS
152 break;
153
154 default:
155 err = kmod_module_probe_insert_module(mod, probe_flags,
156 NULL, NULL, NULL, NULL);
157
158 if (err == 0)
159 log_info("Inserted module '%s'", kmod_module_get_name(mod));
160 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
161 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
162 else {
163 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
164 strerror(-err));
165 r = err;
166 }
03658d4f
LP
167 }
168
169 kmod_module_unref(mod);
170 }
171
172 kmod_module_unref_list(modlist);
173
174 return r;
175}
176
fabe5c0e
LP
177static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
178 _cleanup_fclose_ FILE *f = NULL;
179 int r;
180
181 assert(ctx);
182 assert(path);
183
184 r = search_and_fopen_nulstr(path, "re", conf_file_dirs, &f);
185 if (r < 0) {
186 if (ignore_enoent && r == -ENOENT)
187 return 0;
188
189 log_error("Failed to open %s, ignoring: %s", path, strerror(-r));
190 return r;
191 }
192
193 log_debug("apply: %s\n", path);
194 for (;;) {
195 char line[LINE_MAX], *l;
196 int k;
197
198 if (!fgets(line, sizeof(line), f)) {
199 if (feof(f))
200 break;
201
202 log_error("Failed to read file '%s', ignoring: %m", path);
203 return -errno;
204 }
205
206 l = strstrip(line);
207 if (!*l)
208 continue;
d3b6d0c2 209 if (strchr(COMMENTS "\n", *l))
fabe5c0e
LP
210 continue;
211
212 k = load_module(ctx, l);
213 if (k < 0 && r == 0)
214 r = k;
215 }
216
217 return r;
218}
219
220static int help(void) {
221
222 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
223 "Loads statically configured kernel modules.\n\n"
224 " -h --help Show this help\n",
225 program_invocation_short_name);
226
227 return 0;
228}
229
230static int parse_argv(int argc, char *argv[]) {
231
232 static const struct option options[] = {
233 { "help", no_argument, NULL, 'h' },
234 { NULL, 0, NULL, 0 }
235 };
236
237 int c;
238
239 assert(argc >= 0);
240 assert(argv);
241
242 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
243
244 switch (c) {
245
246 case 'h':
247 help();
248 return 0;
249
250 case '?':
251 return -EINVAL;
252
253 default:
254 log_error("Unknown option code %c", c);
255 return -EINVAL;
256 }
257 }
258
259 return 1;
260}
261
b2423f1f 262int main(int argc, char *argv[]) {
fabe5c0e 263 int r, k;
83684a35 264 struct kmod_ctx *ctx;
b2423f1f 265
fabe5c0e
LP
266 r = parse_argv(argc, argv);
267 if (r <= 0)
268 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 269
4cfa2c99 270 log_set_target(LOG_TARGET_AUTO);
b2423f1f
LP
271 log_parse_environment();
272 log_open();
273
4c12626c
LP
274 umask(0022);
275
03658d4f
LP
276 if (parse_proc_cmdline() < 0)
277 return EXIT_FAILURE;
278
4e2075ce
LP
279 ctx = kmod_new(NULL, NULL);
280 if (!ctx) {
83684a35 281 log_error("Failed to allocate memory for kmod.");
b2423f1f
LP
282 goto finish;
283 }
284
83684a35 285 kmod_load_resources(ctx);
83684a35 286 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
b2423f1f 287
fabe5c0e 288 r = 0;
03658d4f 289
fabe5c0e
LP
290 if (argc > optind) {
291 int i;
b2423f1f 292
fabe5c0e
LP
293 for (i = optind; i < argc; i++) {
294 k = apply_file(ctx, argv[i], false);
295 if (k < 0 && r == 0)
296 r = k;
b2423f1f
LP
297 }
298
fabe5c0e
LP
299 } else {
300 _cleanup_free_ char **files = NULL;
301 char **fn, **i;
b2423f1f 302
fabe5c0e
LP
303 STRV_FOREACH(i, arg_proc_cmdline_modules) {
304 k = load_module(ctx, *i);
03658d4f 305 if (k < 0)
83684a35 306 r = EXIT_FAILURE;
b2423f1f
LP
307 }
308
fabe5c0e
LP
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;
b2423f1f
LP
313 }
314
fabe5c0e
LP
315 STRV_FOREACH(fn, files) {
316 k = apply_file(ctx, *fn, true);
317 if (k < 0 && r == 0)
318 r = k;
319 }
b2423f1f
LP
320 }
321
b2423f1f 322finish:
83684a35 323 kmod_unref(ctx);
03658d4f 324 strv_free(arg_proc_cmdline_modules);
b2423f1f 325
fabe5c0e 326 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 327}