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