chiark / gitweb /
modules-load: initalize files to null
[elogind.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                 return log_oom();
54
55         t = strv_merge(arg_proc_cmdline_modules, k);
56         strv_free(k);
57         if (!t)
58                 return log_oom();
59
60         strv_free(arg_proc_cmdline_modules);
61         arg_proc_cmdline_modules = t;
62
63         return 0;
64 }
65
66 static 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
89                 if (startswith(word, "modules-load=")) {
90
91                         r = add_modules(word + 13);
92                         if (r < 0)
93                                 goto finish;
94
95                 } else if (startswith(word, "rd.modules-load=")) {
96
97                         if (in_initrd()) {
98                                 r = add_modules(word + 16);
99                                 if (r < 0)
100                                         goto finish;
101                         }
102
103                 }
104
105                 free(word);
106         }
107
108         r = 0;
109
110 finish:
111         free(line);
112         return r;
113 }
114
115 static int load_module(struct kmod_ctx *ctx, const char *m) {
116         const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
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
128         if (!modlist) {
129                 log_error("Failed to find module '%s'", m);
130                 return -ENOENT;
131         }
132
133         kmod_list_foreach(itr, modlist) {
134                 struct kmod_module *mod;
135                 int state, err;
136
137                 mod = kmod_module_get_module(itr);
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                         }
162                 }
163
164                 kmod_module_unref(mod);
165         }
166
167         kmod_module_unref_list(modlist);
168
169         return r;
170 }
171
172 int main(int argc, char *argv[]) {
173         int r = EXIT_FAILURE, k;
174         char **files = NULL, **fn, **i;
175         struct kmod_ctx *ctx;
176
177         if (argc > 1) {
178                 log_error("This program takes no argument.");
179                 return EXIT_FAILURE;
180         }
181
182         log_set_target(LOG_TARGET_AUTO);
183         log_parse_environment();
184         log_open();
185
186         umask(0022);
187
188         if (parse_proc_cmdline() < 0)
189                 return EXIT_FAILURE;
190
191         ctx = kmod_new(NULL, NULL);
192         if (!ctx) {
193                 log_error("Failed to allocate memory for kmod.");
194                 goto finish;
195         }
196
197         kmod_load_resources(ctx);
198         kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
199
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",
209                             "/etc/modules-load.d",
210                             "/run/modules-load.d",
211                             "/usr/local/lib/modules-load.d",
212                             "/usr/lib/modules-load.d",
213 #ifdef HAVE_SPLIT_USR
214                             "/lib/modules-load.d",
215 #endif
216                             NULL);
217         if (k < 0) {
218                 log_error("Failed to enumerate modules-load.d files: %s", strerror(-k));
219                 r = EXIT_FAILURE;
220                 goto finish;
221         }
222
223         STRV_FOREACH(fn, files) {
224                 FILE *f;
225
226                 f = fopen(*fn, "re");
227                 if (!f) {
228                         if (errno == ENOENT)
229                                 continue;
230
231                         log_error("Failed to open %s: %m", *fn);
232                         r = EXIT_FAILURE;
233                         continue;
234                 }
235
236                 log_debug("apply: %s\n", *fn);
237                 for (;;) {
238                         char line[LINE_MAX], *l;
239
240                         if (!fgets(line, sizeof(line), f))
241                                 break;
242
243                         l = strstrip(line);
244                         if (*l == '#' || *l == 0)
245                                 continue;
246
247                         k = load_module(ctx, l);
248                         if (k < 0)
249                                 r = EXIT_FAILURE;
250                 }
251
252                 if (ferror(f)) {
253                         log_error("Failed to read from file: %m");
254                         r = EXIT_FAILURE;
255                 }
256
257                 fclose(f);
258         }
259
260 finish:
261         strv_free(files);
262         kmod_unref(ctx);
263         strv_free(arg_proc_cmdline_modules);
264
265         return r;
266 }