]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/modules-load/modules-load.c
treewide: a few more log_*_errno + return simplifications
[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"
a5c32cff 36#include "fileio.h"
eb9da376 37#include "build.h"
03658d4f
LP
38
39static char **arg_proc_cmdline_modules = NULL;
b2423f1f 40
7f0a55d4 41static const char conf_file_dirs[] = CONF_DIRS_NULSTR("modules-load");
fabe5c0e 42
83684a35 43static void systemd_kmod_log(void *data, int priority, const char *file, int line,
f168c273 44 const char *fn, const char *format, va_list args) {
bcfce235
LP
45
46 DISABLE_WARNING_FORMAT_NONLITERAL;
79008bdd 47 log_internalv(priority, 0, file, line, fn, format, args);
bcfce235 48 REENABLE_WARNING;
83684a35
TG
49}
50
03658d4f 51static int add_modules(const char *p) {
fabe5c0e 52 _cleanup_strv_free_ char **k = NULL;
03658d4f
LP
53
54 k = strv_split(p, ",");
0d0f0c50
SL
55 if (!k)
56 return log_oom();
03658d4f 57
e3e45d4f 58 if (strv_extend_strv(&arg_proc_cmdline_modules, k) < 0)
0d0f0c50 59 return log_oom();
03658d4f 60
03658d4f
LP
61 return 0;
62}
63
059cb385 64static int parse_proc_cmdline_item(const char *key, const char *value) {
74df0fca 65 int r;
03658d4f 66
059cb385
LP
67 if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) {
68 r = add_modules(value);
141a79f4
ZJS
69 if (r < 0)
70 return r;
03658d4f
LP
71 }
72
c007bb1b 73 return 0;
03658d4f
LP
74}
75
76static int load_module(struct kmod_ctx *ctx, const char *m) {
27fda47f 77 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
03658d4f
LP
78 struct kmod_list *itr, *modlist = NULL;
79 int r = 0;
80
9f6445e3 81 log_debug("load: %s", m);
03658d4f
LP
82
83 r = kmod_module_new_from_lookup(ctx, m, &modlist);
f647962d
MS
84 if (r < 0)
85 return log_error_errno(r, "Failed to lookup alias '%s': %m", m);
03658d4f 86
27fda47f
MS
87 if (!modlist) {
88 log_error("Failed to find module '%s'", m);
8f9c0b4c 89 return -ENOENT;
27fda47f
MS
90 }
91
03658d4f
LP
92 kmod_list_foreach(itr, modlist) {
93 struct kmod_module *mod;
27fda47f 94 int state, err;
03658d4f
LP
95
96 mod = kmod_module_get_module(itr);
27fda47f
MS
97 state = kmod_module_get_initstate(mod);
98
99 switch (state) {
100 case KMOD_MODULE_BUILTIN:
101 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
102 break;
103
104 case KMOD_MODULE_LIVE:
b56c267f 105 log_debug("Module '%s' is already loaded", kmod_module_get_name(mod));
27fda47f
MS
106 break;
107
108 default:
109 err = kmod_module_probe_insert_module(mod, probe_flags,
110 NULL, NULL, NULL, NULL);
111
112 if (err == 0)
113 log_info("Inserted module '%s'", kmod_module_get_name(mod));
114 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
115 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
116 else {
c33b3297 117 log_error_errno(err, "Failed to insert '%s': %m", kmod_module_get_name(mod));
27fda47f
MS
118 r = err;
119 }
03658d4f
LP
120 }
121
122 kmod_module_unref(mod);
123 }
124
125 kmod_module_unref_list(modlist);
126
127 return r;
128}
129
fabe5c0e
LP
130static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
131 _cleanup_fclose_ FILE *f = NULL;
132 int r;
133
134 assert(ctx);
135 assert(path);
136
4cf7ea55 137 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
fabe5c0e
LP
138 if (r < 0) {
139 if (ignore_enoent && r == -ENOENT)
140 return 0;
141
8d3d7072 142 return log_error_errno(r, "Failed to open %s, ignoring: %m", path);
fabe5c0e
LP
143 }
144
9f6445e3 145 log_debug("apply: %s", path);
fabe5c0e
LP
146 for (;;) {
147 char line[LINE_MAX], *l;
148 int k;
149
150 if (!fgets(line, sizeof(line), f)) {
151 if (feof(f))
152 break;
153
154 log_error("Failed to read file '%s', ignoring: %m", path);
155 return -errno;
156 }
157
158 l = strstrip(line);
159 if (!*l)
160 continue;
d3b6d0c2 161 if (strchr(COMMENTS "\n", *l))
fabe5c0e
LP
162 continue;
163
164 k = load_module(ctx, l);
165 if (k < 0 && r == 0)
166 r = k;
167 }
168
169 return r;
170}
171
601185b4 172static void help(void) {
fabe5c0e
LP
173 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
174 "Loads statically configured kernel modules.\n\n"
eb9da376
LP
175 " -h --help Show this help\n"
176 " --version Show package version\n",
fabe5c0e 177 program_invocation_short_name);
fabe5c0e
LP
178}
179
180static int parse_argv(int argc, char *argv[]) {
181
eb9da376
LP
182 enum {
183 ARG_VERSION = 0x100,
184 };
185
fabe5c0e
LP
186 static const struct option options[] = {
187 { "help", no_argument, NULL, 'h' },
eb9da376
LP
188 { "version", no_argument, NULL, ARG_VERSION },
189 {}
fabe5c0e
LP
190 };
191
192 int c;
193
194 assert(argc >= 0);
195 assert(argv);
196
601185b4 197 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
fabe5c0e
LP
198
199 switch (c) {
200
201 case 'h':
601185b4
ZJS
202 help();
203 return 0;
eb9da376
LP
204
205 case ARG_VERSION:
206 puts(PACKAGE_STRING);
207 puts(SYSTEMD_FEATURES);
fabe5c0e
LP
208 return 0;
209
210 case '?':
211 return -EINVAL;
212
213 default:
eb9da376 214 assert_not_reached("Unhandled option");
fabe5c0e 215 }
fabe5c0e
LP
216
217 return 1;
218}
219
b2423f1f 220int main(int argc, char *argv[]) {
fabe5c0e 221 int r, k;
83684a35 222 struct kmod_ctx *ctx;
b2423f1f 223
fabe5c0e
LP
224 r = parse_argv(argc, argv);
225 if (r <= 0)
226 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 227
4cfa2c99 228 log_set_target(LOG_TARGET_AUTO);
b2423f1f
LP
229 log_parse_environment();
230 log_open();
231
4c12626c
LP
232 umask(0022);
233
b5884878
LP
234 r = parse_proc_cmdline(parse_proc_cmdline_item);
235 if (r < 0)
da927ba9 236 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
03658d4f 237
4e2075ce
LP
238 ctx = kmod_new(NULL, NULL);
239 if (!ctx) {
83684a35 240 log_error("Failed to allocate memory for kmod.");
b2423f1f
LP
241 goto finish;
242 }
243
83684a35 244 kmod_load_resources(ctx);
83684a35 245 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
b2423f1f 246
fabe5c0e 247 r = 0;
03658d4f 248
fabe5c0e
LP
249 if (argc > optind) {
250 int i;
b2423f1f 251
fabe5c0e
LP
252 for (i = optind; i < argc; i++) {
253 k = apply_file(ctx, argv[i], false);
254 if (k < 0 && r == 0)
255 r = k;
b2423f1f
LP
256 }
257
fabe5c0e
LP
258 } else {
259 _cleanup_free_ char **files = NULL;
260 char **fn, **i;
b2423f1f 261
fabe5c0e
LP
262 STRV_FOREACH(i, arg_proc_cmdline_modules) {
263 k = load_module(ctx, *i);
b857193b
LP
264 if (k < 0 && r == 0)
265 r = k;
b2423f1f
LP
266 }
267
4b462d1a
LP
268 k = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
269 if (k < 0) {
da927ba9 270 log_error_errno(k, "Failed to enumerate modules-load.d files: %m");
4b462d1a
LP
271 if (r == 0)
272 r = k;
fabe5c0e 273 goto finish;
b2423f1f
LP
274 }
275
fabe5c0e
LP
276 STRV_FOREACH(fn, files) {
277 k = apply_file(ctx, *fn, true);
278 if (k < 0 && r == 0)
279 r = k;
280 }
b2423f1f
LP
281 }
282
b2423f1f 283finish:
83684a35 284 kmod_unref(ctx);
03658d4f 285 strv_free(arg_proc_cmdline_modules);
b2423f1f 286
fabe5c0e 287 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 288}