]> git.proxmox.com Git - systemd.git/blame - src/modules-load/modules-load.c
log.h: new log_oom() -> int -ENOMEM, use it
[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>
83684a35 29#include <libkmod.h>
b2423f1f
LP
30
31#include "log.h"
32#include "util.h"
33#include "strv.h"
2c21044f 34#include "conf-files.h"
03658d4f
LP
35#include "virt.h"
36
37static char **arg_proc_cmdline_modules = NULL;
b2423f1f 38
cdb454f2
LP
39#pragma GCC diagnostic push
40#pragma GCC diagnostic ignored "-Wformat-nonliteral"
83684a35
TG
41static void systemd_kmod_log(void *data, int priority, const char *file, int line,
42 const char *fn, const char *format, va_list args)
43{
e62abb62 44 log_metav(priority, file, line, fn, format, args);
83684a35 45}
cdb454f2 46#pragma GCC diagnostic pop
83684a35 47
03658d4f
LP
48static int add_modules(const char *p) {
49 char **t, **k;
50
51 k = strv_split(p, ",");
0d0f0c50
SL
52 if (!k)
53 return log_oom();
03658d4f
LP
54
55 t = strv_merge(arg_proc_cmdline_modules, k);
56 strv_free(k);
0d0f0c50
SL
57 if (!t)
58 return log_oom();
03658d4f
LP
59
60 strv_free(arg_proc_cmdline_modules);
61 arg_proc_cmdline_modules = t;
62
63 return 0;
64}
65
66static int parse_proc_cmdline(void) {
67 char *line, *w, *state;
68 int r;
69 size_t l;
70
71 if (detect_container(NULL) > 0)
72 return 0;
73
74 r = read_one_line_file("/proc/cmdline", &line);
75 if (r < 0) {
76 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
77 return 0;
78 }
79
80 FOREACH_WORD_QUOTED(w, l, line, state) {
81 char *word;
82
83 word = strndup(w, l);
84 if (!word) {
85 r = -ENOMEM;
86 goto finish;
87 }
88
91ac7425 89 if (startswith(word, "modules-load=")) {
03658d4f 90
b2fc39a6 91 r = add_modules(word + 13);
03658d4f
LP
92 if (r < 0)
93 goto finish;
94
91ac7425 95 } else if (startswith(word, "rd.modules-load=")) {
03658d4f
LP
96
97 if (in_initrd()) {
b2fc39a6 98 r = add_modules(word + 16);
03658d4f
LP
99 if (r < 0)
100 goto finish;
101 }
102
103 }
104
105 free(word);
106 }
107
108 r = 0;
109
110finish:
111 free(line);
112 return r;
113}
114
115static int load_module(struct kmod_ctx *ctx, const char *m) {
27fda47f 116 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
03658d4f
LP
117 struct kmod_list *itr, *modlist = NULL;
118 int r = 0;
119
120 log_debug("load: %s\n", m);
121
122 r = kmod_module_new_from_lookup(ctx, m, &modlist);
123 if (r < 0) {
124 log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
125 return r;
126 }
127
27fda47f
MS
128 if (!modlist) {
129 log_error("Failed to find module '%s'", m);
8f9c0b4c 130 return -ENOENT;
27fda47f
MS
131 }
132
03658d4f
LP
133 kmod_list_foreach(itr, modlist) {
134 struct kmod_module *mod;
27fda47f 135 int state, err;
03658d4f
LP
136
137 mod = kmod_module_get_module(itr);
27fda47f
MS
138 state = kmod_module_get_initstate(mod);
139
140 switch (state) {
141 case KMOD_MODULE_BUILTIN:
142 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
143 break;
144
145 case KMOD_MODULE_LIVE:
146 log_info("Module '%s' is already loaded", kmod_module_get_name(mod));
147 break;
148
149 default:
150 err = kmod_module_probe_insert_module(mod, probe_flags,
151 NULL, NULL, NULL, NULL);
152
153 if (err == 0)
154 log_info("Inserted module '%s'", kmod_module_get_name(mod));
155 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
156 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
157 else {
158 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
159 strerror(-err));
160 r = err;
161 }
03658d4f
LP
162 }
163
164 kmod_module_unref(mod);
165 }
166
167 kmod_module_unref_list(modlist);
168
169 return r;
170}
171
b2423f1f 172int main(int argc, char *argv[]) {
03658d4f
LP
173 int r = EXIT_FAILURE, k;
174 char **files, **fn, **i;
83684a35 175 struct kmod_ctx *ctx;
b2423f1f
LP
176
177 if (argc > 1) {
178 log_error("This program takes no argument.");
22f4096c 179 return EXIT_FAILURE;
b2423f1f
LP
180 }
181
4cfa2c99 182 log_set_target(LOG_TARGET_AUTO);
b2423f1f
LP
183 log_parse_environment();
184 log_open();
185
4c12626c
LP
186 umask(0022);
187
03658d4f
LP
188 if (parse_proc_cmdline() < 0)
189 return EXIT_FAILURE;
190
4e2075ce
LP
191 ctx = kmod_new(NULL, NULL);
192 if (!ctx) {
83684a35 193 log_error("Failed to allocate memory for kmod.");
b2423f1f
LP
194 goto finish;
195 }
196
83684a35 197 kmod_load_resources(ctx);
83684a35 198 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
b2423f1f 199
03658d4f
LP
200 r = EXIT_SUCCESS;
201
202 STRV_FOREACH(i, arg_proc_cmdline_modules) {
203 k = load_module(ctx, *i);
204 if (k < 0)
205 r = EXIT_FAILURE;
206 }
207
208 k = conf_files_list(&files, ".conf",
44143309 209 "/etc/modules-load.d",
fc1a2e06 210 "/run/modules-load.d",
223a3558 211 "/usr/local/lib/modules-load.d",
44143309 212 "/usr/lib/modules-load.d",
4e2075ce 213#ifdef HAVE_SPLIT_USR
223a3558 214 "/lib/modules-load.d",
4e2075ce 215#endif
03658d4f
LP
216 NULL);
217 if (k < 0) {
218 log_error("Failed to enumerate modules-load.d files: %s", strerror(-k));
219 r = EXIT_FAILURE;
b2423f1f
LP
220 goto finish;
221 }
222
db1413d7 223 STRV_FOREACH(fn, files) {
b2423f1f
LP
224 FILE *f;
225
db1413d7 226 f = fopen(*fn, "re");
b2423f1f 227 if (!f) {
db1413d7 228 if (errno == ENOENT)
70ca520f
LP
229 continue;
230
db1413d7 231 log_error("Failed to open %s: %m", *fn);
22f4096c 232 r = EXIT_FAILURE;
b2423f1f
LP
233 continue;
234 }
235
db1413d7 236 log_debug("apply: %s\n", *fn);
b2423f1f 237 for (;;) {
83684a35 238 char line[LINE_MAX], *l;
b2423f1f 239
4e2075ce 240 if (!fgets(line, sizeof(line), f))
b2423f1f
LP
241 break;
242
243 l = strstrip(line);
244 if (*l == '#' || *l == 0)
245 continue;
246
03658d4f
LP
247 k = load_module(ctx, l);
248 if (k < 0)
83684a35 249 r = EXIT_FAILURE;
b2423f1f
LP
250 }
251
252 if (ferror(f)) {
b2423f1f 253 log_error("Failed to read from file: %m");
83684a35 254 r = EXIT_FAILURE;
b2423f1f
LP
255 }
256
257 fclose(f);
258 }
259
b2423f1f 260finish:
83684a35
TG
261 strv_free(files);
262 kmod_unref(ctx);
03658d4f 263 strv_free(arg_proc_cmdline_modules);
b2423f1f
LP
264
265 return r;
266}