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