blob: 19f56a712b729d77d657196bc87096001bf2a201 [file] [log] [blame]
Lucas De Marchi7c2ab352011-11-29 18:07:43 -02001/*
2 * libkmod - interface to kernel module operations
3 *
Lucas De Marchie6b0e492013-01-16 11:27:21 -02004 * Copyright (C) 2011-2013 ProFUSION embedded systems
Lucas De Marchi342e9ce2013-11-14 00:33:28 -02005 * Copyright (C) 2013 Intel Corporation. All rights reserved.
Lucas De Marchi7c2ab352011-11-29 18:07:43 -02006 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
Lucas De Marchicb451f32011-12-12 18:24:35 -02009 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020011 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
Lucas De Marchidea2dfe2014-12-25 23:32:03 -020018 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020019 */
20
Lucas De Marchic2e42862014-10-03 01:41:42 -030021#include <ctype.h>
22#include <dirent.h>
23#include <errno.h>
24#include <stdarg.h>
25#include <stddef.h>
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020026#include <stdio.h>
27#include <stdlib.h>
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020028#include <string.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030029#include <unistd.h>
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020030#include <sys/stat.h>
31#include <sys/types.h>
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020032
Lucas De Marchi96573a02014-10-03 00:01:35 -030033#include <shared/util.h>
34
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020035#include "libkmod.h"
Lucas De Marchi83b855a2013-07-04 16:13:11 -030036#include "libkmod-internal.h"
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020037
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020038struct kmod_alias {
39 char *name;
Gustavo Sverzut Barbieri43c29d12011-12-04 17:32:44 -020040 char modname[];
Lucas De Marchi7c2ab352011-11-29 18:07:43 -020041};
42
Lucas De Marchi615c42b2011-12-07 03:18:57 -020043struct kmod_options {
44 char *options;
45 char modname[];
46};
47
Lucas De Marchia5cce6d2011-12-07 11:31:28 -020048struct kmod_command {
49 char *command;
50 char modname[];
51};
52
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -020053struct kmod_softdep {
54 char *name;
55 const char **pre;
56 const char **post;
57 unsigned int n_pre;
58 unsigned int n_post;
59};
60
Lucas De Marchic1c9c442011-12-24 10:50:47 -020061const char *kmod_blacklist_get_modname(const struct kmod_list *l)
62{
63 return l->data;
64}
65
Lucas De Marchib0ef19f2011-11-30 18:18:13 -020066const char *kmod_alias_get_name(const struct kmod_list *l) {
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020067 const struct kmod_alias *alias = l->data;
Lucas De Marchib0ef19f2011-11-30 18:18:13 -020068 return alias->name;
69}
70
71const char *kmod_alias_get_modname(const struct kmod_list *l) {
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020072 const struct kmod_alias *alias = l->data;
Lucas De Marchib0ef19f2011-11-30 18:18:13 -020073 return alias->modname;
74}
75
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020076const char *kmod_option_get_options(const struct kmod_list *l) {
77 const struct kmod_options *alias = l->data;
78 return alias->options;
79}
80
81const char *kmod_option_get_modname(const struct kmod_list *l) {
82 const struct kmod_options *alias = l->data;
83 return alias->modname;
84}
85
86const char *kmod_command_get_command(const struct kmod_list *l) {
87 const struct kmod_command *alias = l->data;
88 return alias->command;
89}
90
91const char *kmod_command_get_modname(const struct kmod_list *l) {
92 const struct kmod_command *alias = l->data;
93 return alias->modname;
94}
95
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -020096const char *kmod_softdep_get_name(const struct kmod_list *l) {
97 const struct kmod_softdep *dep = l->data;
98 return dep->name;
99}
100
101const char * const *kmod_softdep_get_pre(const struct kmod_list *l, unsigned int *count) {
102 const struct kmod_softdep *dep = l->data;
103 *count = dep->n_pre;
104 return dep->pre;
105}
106
107const char * const *kmod_softdep_get_post(const struct kmod_list *l, unsigned int *count) {
108 const struct kmod_softdep *dep = l->data;
109 *count = dep->n_post;
110 return dep->post;
111}
112
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200113static int kmod_config_add_command(struct kmod_config *config,
114 const char *modname,
115 const char *command,
116 const char *command_name,
117 struct kmod_list **list)
118{
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200119 _cleanup_free_ struct kmod_command *cmd;
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200120 struct kmod_list *l;
121 size_t modnamelen = strlen(modname) + 1;
122 size_t commandlen = strlen(command) + 1;
123
Lucas De Marchie5a7f6a2011-12-19 14:36:23 -0200124 DBG(config->ctx, "modname='%s' cmd='%s %s'\n", modname, command_name,
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200125 command);
126
127 cmd = malloc(sizeof(*cmd) + modnamelen + commandlen);
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200128 if (!cmd)
129 return -ENOMEM;
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200130
131 cmd->command = sizeof(*cmd) + modnamelen + (char *)cmd;
132 memcpy(cmd->modname, modname, modnamelen);
133 memcpy(cmd->command, command, commandlen);
134
135 l = kmod_list_append(*list, cmd);
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200136 if (!l)
137 return -ENOMEM;
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200138
139 *list = l;
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200140 cmd = NULL;
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200141 return 0;
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200142}
143
144static void kmod_config_free_command(struct kmod_config *config,
145 struct kmod_list *l,
146 struct kmod_list **list)
147{
148 struct kmod_command *cmd = l->data;
149
150 free(cmd);
151 *list = kmod_list_remove(l);
152}
153
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200154static int kmod_config_add_options(struct kmod_config *config,
155 const char *modname, const char *options)
156{
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200157 _cleanup_free_ struct kmod_options *opt;
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200158 struct kmod_list *list;
159 size_t modnamelen = strlen(modname) + 1;
160 size_t optionslen = strlen(options) + 1;
161
Lucas De Marchi23c0d012011-12-14 17:21:46 -0200162 DBG(config->ctx, "modname='%s' options='%s'\n", modname, options);
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200163
164 opt = malloc(sizeof(*opt) + modnamelen + optionslen);
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200165 if (!opt)
166 return -ENOMEM;
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200167
168 opt->options = sizeof(*opt) + modnamelen + (char *)opt;
169
170 memcpy(opt->modname, modname, modnamelen);
171 memcpy(opt->options, options, optionslen);
172 strchr_replace(opt->options, '\t', ' ');
173
174 list = kmod_list_append(config->options, opt);
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200175 if (!list)
176 return -ENOMEM;
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200177
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200178 opt = NULL;
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200179 config->options = list;
180 return 0;
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200181}
182
Lucas De Marchic35347f2011-12-12 10:48:02 -0200183static void kmod_config_free_options(struct kmod_config *config,
184 struct kmod_list *l)
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200185{
186 struct kmod_options *opt = l->data;
187
188 free(opt);
189
190 config->options = kmod_list_remove(l);
191}
192
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200193static int kmod_config_add_alias(struct kmod_config *config,
Lucas De Marchic35347f2011-12-12 10:48:02 -0200194 const char *name, const char *modname)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200195{
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200196 _cleanup_free_ struct kmod_alias *alias;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200197 struct kmod_list *list;
Gustavo Sverzut Barbieri43c29d12011-12-04 17:32:44 -0200198 size_t namelen = strlen(name) + 1, modnamelen = strlen(modname) + 1;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200199
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200200 DBG(config->ctx, "name=%s modname=%s\n", name, modname);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200201
Gustavo Sverzut Barbieri43c29d12011-12-04 17:32:44 -0200202 alias = malloc(sizeof(*alias) + namelen + modnamelen);
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200203 if (!alias)
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200204 return -ENOMEM;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200205
Gustavo Sverzut Barbieri43c29d12011-12-04 17:32:44 -0200206 alias->name = sizeof(*alias) + modnamelen + (char *)alias;
207
208 memcpy(alias->modname, modname, modnamelen);
209 memcpy(alias->name, name, namelen);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200210
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200211 list = kmod_list_append(config->aliases, alias);
212 if (!list)
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200213 return -ENOMEM;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200214
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200215 alias = NULL;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200216 config->aliases = list;
217 return 0;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200218}
219
Lucas De Marchic35347f2011-12-12 10:48:02 -0200220static void kmod_config_free_alias(struct kmod_config *config,
221 struct kmod_list *l)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200222{
223 struct kmod_alias *alias = l->data;
224
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200225 free(alias);
226
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200227 config->aliases = kmod_list_remove(l);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200228}
229
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200230static int kmod_config_add_blacklist(struct kmod_config *config,
Lucas De Marchic35347f2011-12-12 10:48:02 -0200231 const char *modname)
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200232{
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200233 _cleanup_free_ char *p;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200234 struct kmod_list *list;
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200235
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200236 DBG(config->ctx, "modname=%s\n", modname);
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200237
238 p = strdup(modname);
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200239 if (!p)
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200240 return -ENOMEM;
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200241
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200242 list = kmod_list_append(config->blacklists, p);
243 if (!list)
Lucas De Marchi342e9ce2013-11-14 00:33:28 -0200244 return -ENOMEM;
245
246 p = NULL;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200247 config->blacklists = list;
248 return 0;
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200249}
250
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200251static void kmod_config_free_blacklist(struct kmod_config *config,
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200252 struct kmod_list *l)
253{
254 free(l->data);
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200255 config->blacklists = kmod_list_remove(l);
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200256}
257
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200258static int kmod_config_add_softdep(struct kmod_config *config,
259 const char *modname,
260 const char *line)
261{
262 struct kmod_list *list;
263 struct kmod_softdep *dep;
264 const char *s, *p;
265 char *itr;
266 unsigned int n_pre = 0, n_post = 0;
267 size_t modnamelen = strlen(modname) + 1;
268 size_t buflen = 0;
269 bool was_space = false;
270 enum { S_NONE, S_PRE, S_POST } mode = S_NONE;
271
272 DBG(config->ctx, "modname=%s\n", modname);
273
274 /* analyze and count */
275 for (p = s = line; ; s++) {
276 size_t plen;
277
278 if (*s != '\0') {
279 if (!isspace(*s)) {
280 was_space = false;
281 continue;
282 }
283
284 if (was_space) {
285 p = s + 1;
286 continue;
287 }
288 was_space = true;
289
290 if (p >= s)
291 continue;
292 }
293 plen = s - p;
294
295 if (plen == sizeof("pre:") - 1 &&
296 memcmp(p, "pre:", sizeof("pre:") - 1) == 0)
297 mode = S_PRE;
298 else if (plen == sizeof("post:") - 1 &&
299 memcmp(p, "post:", sizeof("post:") - 1) == 0)
300 mode = S_POST;
301 else if (*s != '\0' || (*s == '\0' && !was_space)) {
302 if (mode == S_PRE) {
303 buflen += plen + 1;
304 n_pre++;
305 } else if (mode == S_POST) {
306 buflen += plen + 1;
307 n_post++;
308 }
309 }
310 p = s + 1;
311 if (*s == '\0')
312 break;
313 }
314
315 DBG(config->ctx, "%u pre, %u post\n", n_pre, n_post);
316
317 dep = malloc(sizeof(struct kmod_softdep) + modnamelen +
318 n_pre * sizeof(const char *) +
319 n_post * sizeof(const char *) +
320 buflen);
321 if (dep == NULL) {
322 ERR(config->ctx, "out-of-memory modname=%s\n", modname);
323 return -ENOMEM;
324 }
325 dep->n_pre = n_pre;
326 dep->n_post = n_post;
327 dep->pre = (const char **)((char *)dep + sizeof(struct kmod_softdep));
328 dep->post = dep->pre + n_pre;
329 dep->name = (char *)(dep->post + n_post);
330
331 memcpy(dep->name, modname, modnamelen);
332
333 /* copy strings */
334 itr = dep->name + modnamelen;
335 n_pre = 0;
336 n_post = 0;
337 mode = S_NONE;
338 for (p = s = line; ; s++) {
339 size_t plen;
340
341 if (*s != '\0') {
342 if (!isspace(*s)) {
343 was_space = false;
344 continue;
345 }
346
347 if (was_space) {
348 p = s + 1;
349 continue;
350 }
351 was_space = true;
352
353 if (p >= s)
354 continue;
355 }
356 plen = s - p;
357
358 if (plen == sizeof("pre:") - 1 &&
359 memcmp(p, "pre:", sizeof("pre:") - 1) == 0)
360 mode = S_PRE;
361 else if (plen == sizeof("post:") - 1 &&
362 memcmp(p, "post:", sizeof("post:") - 1) == 0)
363 mode = S_POST;
364 else if (*s != '\0' || (*s == '\0' && !was_space)) {
365 if (mode == S_PRE) {
366 dep->pre[n_pre] = itr;
367 memcpy(itr, p, plen);
368 itr[plen] = '\0';
369 itr += plen + 1;
370 n_pre++;
371 } else if (mode == S_POST) {
372 dep->post[n_post] = itr;
373 memcpy(itr, p, plen);
374 itr[plen] = '\0';
375 itr += plen + 1;
376 n_post++;
377 }
378 }
379 p = s + 1;
380 if (*s == '\0')
381 break;
382 }
383
384 list = kmod_list_append(config->softdeps, dep);
385 if (list == NULL) {
386 free(dep);
387 return -ENOMEM;
388 }
389 config->softdeps = list;
390
391 return 0;
392}
393
Lucas De Marchi6b04ef32012-01-13 10:49:31 -0200394static char *softdep_to_char(struct kmod_softdep *dep) {
395 const size_t sz_preprefix = sizeof("pre: ") - 1;
396 const size_t sz_postprefix = sizeof("post: ") - 1;
397 size_t sz = 1; /* at least '\0' */
398 size_t sz_pre, sz_post;
399 const char *start, *end;
400 char *s, *itr;
401
402 /*
403 * Rely on the fact that dep->pre[] and dep->post[] are strv's that
404 * point to a contiguous buffer
405 */
406 if (dep->n_pre > 0) {
407 start = dep->pre[0];
408 end = dep->pre[dep->n_pre - 1]
409 + strlen(dep->pre[dep->n_pre - 1]);
410 sz_pre = end - start;
411 sz += sz_pre + sz_preprefix;
412 } else
413 sz_pre = 0;
414
415 if (dep->n_post > 0) {
416 start = dep->post[0];
417 end = dep->post[dep->n_post - 1]
418 + strlen(dep->post[dep->n_post - 1]);
419 sz_post = end - start;
420 sz += sz_post + sz_postprefix;
421 } else
422 sz_post = 0;
423
424 itr = s = malloc(sz);
425 if (s == NULL)
426 return NULL;
427
428 if (sz_pre) {
429 char *p;
430
431 memcpy(itr, "pre: ", sz_preprefix);
432 itr += sz_preprefix;
433
434 /* include last '\0' */
435 memcpy(itr, dep->pre[0], sz_pre + 1);
436 for (p = itr; p < itr + sz_pre; p++) {
437 if (*p == '\0')
438 *p = ' ';
439 }
440 itr = p;
441 }
442
443 if (sz_post) {
444 char *p;
445
446 memcpy(itr, "post: ", sz_postprefix);
447 itr += sz_postprefix;
448
449 /* include last '\0' */
450 memcpy(itr, dep->post[0], sz_post + 1);
451 for (p = itr; p < itr + sz_post; p++) {
452 if (*p == '\0')
453 *p = ' ';
454 }
455 itr = p;
456 }
457
458 *itr = '\0';
459
460 return s;
461}
462
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200463static void kmod_config_free_softdep(struct kmod_config *config,
464 struct kmod_list *l)
465{
466 free(l->data);
467 config->softdeps = kmod_list_remove(l);
468}
469
Lucas De Marchi1684e442011-12-14 17:19:19 -0200470static void kcmdline_parse_result(struct kmod_config *config, char *modname,
471 char *param, char *value)
472{
Lucas De Marchi493dc652013-08-13 22:04:46 -0300473 if (modname == NULL || param == NULL)
Lucas De Marchi1684e442011-12-14 17:19:19 -0200474 return;
475
476 DBG(config->ctx, "%s %s\n", modname, param);
477
478 if (streq(modname, "modprobe") && !strncmp(param, "blacklist=", 10)) {
479 for (;;) {
480 char *t = strsep(&value, ",");
481 if (t == NULL)
482 break;
483
484 kmod_config_add_blacklist(config, t);
485 }
486 } else {
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300487 if (underscores(modname) < 0) {
488 ERR(config->ctx, "Ignoring bad option on kernel command line while parsing module name: '%s'\n",
489 modname);
490 }
491 kmod_config_add_options(config, modname, param);
Lucas De Marchi1684e442011-12-14 17:19:19 -0200492 }
493}
494
495static int kmod_config_parse_kcmdline(struct kmod_config *config)
496{
497 char buf[KCMD_LINE_SIZE];
498 int fd, err;
Michal Marekaa878542014-03-05 13:27:41 +0100499 char *p, *modname, *param = NULL, *value = NULL, is_module = 1;
Lucas De Marchi1684e442011-12-14 17:19:19 -0200500
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300501 fd = open("/proc/cmdline", O_RDONLY|O_CLOEXEC);
Lucas De Marchidd1cf102012-01-06 19:22:41 -0200502 if (fd < 0) {
503 err = -errno;
504 DBG(config->ctx, "could not open '/proc/cmdline' for reading: %m\n");
505 return err;
506 }
507
Lucas De Marchi1684e442011-12-14 17:19:19 -0200508 err = read_str_safe(fd, buf, sizeof(buf));
509 close(fd);
510 if (err < 0) {
511 ERR(config->ctx, "could not read from '/proc/cmdline': %s\n",
512 strerror(-err));
513 return err;
514 }
515
516 for (p = buf, modname = buf; *p != '\0' && *p != '\n'; p++) {
517 switch (*p) {
518 case ' ':
519 *p = '\0';
Michal Marekaa878542014-03-05 13:27:41 +0100520 if (is_module)
521 kcmdline_parse_result(config, modname, param, value);
Lucas De Marchi1684e442011-12-14 17:19:19 -0200522 param = value = NULL;
523 modname = p + 1;
Michal Marekaa878542014-03-05 13:27:41 +0100524 is_module = 1;
Lucas De Marchi1684e442011-12-14 17:19:19 -0200525 break;
526 case '.':
Lucas De Marchi66f32282012-10-08 19:04:16 -0300527 if (param == NULL) {
528 *p = '\0';
529 param = p + 1;
530 }
Lucas De Marchi1684e442011-12-14 17:19:19 -0200531 break;
532 case '=':
Lucas De Marchi135bffd2011-12-20 13:25:24 -0200533 if (param != NULL)
534 value = p + 1;
Michal Marekaa878542014-03-05 13:27:41 +0100535 else
536 is_module = 0;
Lucas De Marchi1684e442011-12-14 17:19:19 -0200537 break;
538 }
539 }
540
541 *p = '\0';
Michal Marekaa878542014-03-05 13:27:41 +0100542 if (is_module)
543 kcmdline_parse_result(config, modname, param, value);
Lucas De Marchi1684e442011-12-14 17:19:19 -0200544
545 return 0;
546}
547
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200548/*
549 * Take an fd and own it. It will be closed on return. filename is used only
550 * for debug messages
551 */
552static int kmod_config_parse(struct kmod_config *config, int fd,
553 const char *filename)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200554{
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200555 struct kmod_ctx *ctx = config->ctx;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200556 char *line;
557 FILE *fp;
Lucas De Marchi759214f2011-12-22 01:30:40 -0200558 unsigned int linenum = 0;
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200559 int err;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200560
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200561 fp = fdopen(fd, "r");
562 if (fp == NULL) {
563 err = -errno;
Lucas De Marchi050db082012-02-18 03:56:21 -0200564 ERR(config->ctx, "fd %d: %m\n", fd);
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200565 close(fd);
566 return err;
567 }
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200568
Lucas De Marchiaafd3832014-10-03 03:25:06 -0300569 while ((line = freadline_wrapped(fp, &linenum)) != NULL) {
Lucas De Marchic11e62b2011-12-01 18:59:54 -0200570 char *cmd, *saveptr;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200571
572 if (line[0] == '\0' || line[0] == '#')
573 goto done_next;
574
Lucas De Marchic11e62b2011-12-01 18:59:54 -0200575 cmd = strtok_r(line, "\t ", &saveptr);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200576 if (cmd == NULL)
577 goto done_next;
578
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200579 if (streq(cmd, "alias")) {
Lucas De Marchic11e62b2011-12-01 18:59:54 -0200580 char *alias = strtok_r(NULL, "\t ", &saveptr);
581 char *modname = strtok_r(NULL, "\t ", &saveptr);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200582
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300583 if (underscores(alias) < 0 || underscores(modname) < 0)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200584 goto syntax_error;
585
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300586 kmod_config_add_alias(config, alias, modname);
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200587 } else if (streq(cmd, "blacklist")) {
Lucas De Marchic11e62b2011-12-01 18:59:54 -0200588 char *modname = strtok_r(NULL, "\t ", &saveptr);
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200589
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300590 if (underscores(modname) < 0)
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200591 goto syntax_error;
592
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300593 kmod_config_add_blacklist(config, modname);
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200594 } else if (streq(cmd, "options")) {
595 char *modname = strtok_r(NULL, "\t ", &saveptr);
Lucas De Marchi83121fd2012-01-10 15:00:07 -0200596 char *options = strtok_r(NULL, "\0", &saveptr);
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200597
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300598 if (underscores(modname) < 0 || options == NULL)
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200599 goto syntax_error;
600
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300601 kmod_config_add_options(config, modname, options);
Leandro Pereira40ee8da2011-12-28 15:01:16 -0200602 } else if (streq(cmd, "install")) {
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200603 char *modname = strtok_r(NULL, "\t ", &saveptr);
Lucas De Marchi83121fd2012-01-10 15:00:07 -0200604 char *installcmd = strtok_r(NULL, "\0", &saveptr);
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200605
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300606 if (underscores(modname) < 0 || installcmd == NULL)
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200607 goto syntax_error;
608
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300609 kmod_config_add_command(config, modname, installcmd,
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200610 cmd, &config->install_commands);
Leandro Pereira40ee8da2011-12-28 15:01:16 -0200611 } else if (streq(cmd, "remove")) {
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200612 char *modname = strtok_r(NULL, "\t ", &saveptr);
Lucas De Marchi83121fd2012-01-10 15:00:07 -0200613 char *removecmd = strtok_r(NULL, "\0", &saveptr);
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200614
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300615 if (underscores(modname) < 0 || removecmd == NULL)
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200616 goto syntax_error;
617
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300618 kmod_config_add_command(config, modname, removecmd,
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200619 cmd, &config->remove_commands);
Leandro Pereira40ee8da2011-12-28 15:01:16 -0200620 } else if (streq(cmd, "softdep")) {
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200621 char *modname = strtok_r(NULL, "\t ", &saveptr);
Lucas De Marchi83121fd2012-01-10 15:00:07 -0200622 char *softdeps = strtok_r(NULL, "\0", &saveptr);
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200623
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300624 if (underscores(modname) < 0 || softdeps == NULL)
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200625 goto syntax_error;
626
Lucas De Marchi52c9c992014-10-09 10:59:08 -0300627 kmod_config_add_softdep(config, modname, softdeps);
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200628 } else if (streq(cmd, "include")
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200629 || streq(cmd, "config")) {
Lucas De Marchi0ad5dd02012-01-11 00:28:12 -0200630 ERR(ctx, "%s: command %s is deprecated and not parsed anymore\n",
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200631 filename, cmd);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200632 } else {
633syntax_error:
634 ERR(ctx, "%s line %u: ignoring bad line starting with '%s'\n",
635 filename, linenum, cmd);
636 }
637
638done_next:
639 free(line);
640 }
641
642 fclose(fp);
643
644 return 0;
645}
646
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200647void kmod_config_free(struct kmod_config *config)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200648{
649 while (config->aliases)
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200650 kmod_config_free_alias(config, config->aliases);
Lucas De Marchi81cf2062011-11-29 18:48:02 -0200651
652 while (config->blacklists)
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200653 kmod_config_free_blacklist(config, config->blacklists);
654
Lucas De Marchi615c42b2011-12-07 03:18:57 -0200655 while (config->options)
656 kmod_config_free_options(config, config->options);
657
Lucas De Marchia5cce6d2011-12-07 11:31:28 -0200658 while (config->install_commands) {
659 kmod_config_free_command(config, config->install_commands,
660 &config->install_commands);
661 }
662
663 while (config->remove_commands) {
664 kmod_config_free_command(config, config->remove_commands,
665 &config->remove_commands);
666 }
667
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200668 while (config->softdeps)
669 kmod_config_free_softdep(config, config->softdeps);
670
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200671 for (; config->paths != NULL;
672 config->paths = kmod_list_remove(config->paths))
673 free(config->paths->data);
674
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200675 free(config);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200676}
677
Lucas De Marchi98c80f42011-12-12 15:23:03 -0200678static bool conf_files_filter_out(struct kmod_ctx *ctx, DIR *d,
679 const char *path, const char *fn)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200680{
681 size_t len = strlen(fn);
Lucas De Marchi98c80f42011-12-12 15:23:03 -0200682 struct stat st;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200683
684 if (fn[0] == '.')
Lucas De Marchi8f767e22011-12-12 15:27:57 -0200685 return true;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200686
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200687 if (len < 6 || (!streq(&fn[len - 5], ".conf")
Dave Reisner9070b112011-12-31 11:19:55 -0500688 && !streq(&fn[len - 6], ".alias")))
Lucas De Marchi8f767e22011-12-12 15:27:57 -0200689 return true;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200690
Lucas De Marchi98c80f42011-12-12 15:23:03 -0200691 fstatat(dirfd(d), fn, &st, 0);
692
693 if (S_ISDIR(st.st_mode)) {
694 ERR(ctx, "Directories inside directories are not supported: "
695 "%s/%s\n", path, fn);
Lucas De Marchi8f767e22011-12-12 15:27:57 -0200696 return true;
Lucas De Marchi98c80f42011-12-12 15:23:03 -0200697 }
698
Lucas De Marchi8f767e22011-12-12 15:27:57 -0200699 return false;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200700}
701
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200702struct conf_file {
703 const char *path;
704 bool is_single;
705 char name[];
706};
707
708static int conf_files_insert_sorted(struct kmod_ctx *ctx,
709 struct kmod_list **list,
710 const char *path, const char *name)
711{
712 struct kmod_list *lpos, *tmp;
713 struct conf_file *cf;
714 size_t namelen;
715 int cmp = -1;
716 bool is_single = false;
717
718 if (name == NULL) {
719 name = basename(path);
720 is_single = true;
721 }
722
723 kmod_list_foreach(lpos, *list) {
724 cf = lpos->data;
725
726 if ((cmp = strcmp(name, cf->name)) <= 0)
727 break;
728 }
729
730 if (cmp == 0) {
731 DBG(ctx, "Ignoring duplicate config file: %s/%s\n", path,
732 name);
733 return -EEXIST;
734 }
735
736 namelen = strlen(name);
737 cf = malloc(sizeof(*cf) + namelen + 1);
738 if (cf == NULL)
739 return -ENOMEM;
740
741 memcpy(cf->name, name, namelen + 1);
742 cf->path = path;
743 cf->is_single = is_single;
744
745 if (lpos == NULL)
746 tmp = kmod_list_append(*list, cf);
747 else if (lpos == *list)
748 tmp = kmod_list_prepend(*list, cf);
749 else
750 tmp = kmod_list_insert_before(lpos, cf);
751
752 if (tmp == NULL) {
753 free(cf);
754 return -ENOMEM;
755 }
756
757 if (lpos == NULL || lpos == *list)
758 *list = tmp;
759
760 return 0;
761}
762
Lucas De Marchi47823962011-12-12 15:00:51 -0200763/*
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200764 * Insert configuration files in @list, ignoring duplicates
Lucas De Marchi47823962011-12-12 15:00:51 -0200765 */
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200766static int conf_files_list(struct kmod_ctx *ctx, struct kmod_list **list,
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200767 const char *path,
768 unsigned long long *path_stamp)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200769{
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200770 DIR *d;
771 int err;
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200772 struct stat st;
Lucas De Marchi7e0385c2013-08-27 23:29:47 -0300773 struct dirent *dent;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200774
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200775 if (stat(path, &st) != 0) {
776 err = -errno;
777 DBG(ctx, "could not stat '%s': %m\n", path);
778 return err;
779 }
780
Lucas De Marchi6068aaa2012-01-17 12:10:42 -0200781 *path_stamp = stat_mstamp(&st);
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200782
Michal Marek519d27d2014-03-04 16:51:25 +0100783 if (!S_ISDIR(st.st_mode)) {
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200784 conf_files_insert_sorted(ctx, list, path, NULL);
785 return 0;
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200786 }
Lucas De Marchi1c250ec2011-12-12 18:36:27 -0200787
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200788 d = opendir(path);
789 if (d == NULL) {
Gustavo Sverzut Barbieridfa96f12012-01-07 19:37:37 -0200790 ERR(ctx, "opendir(%s): %m\n", path);
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200791 return -EINVAL;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200792 }
793
Lucas De Marchi7e0385c2013-08-27 23:29:47 -0300794 for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
795 if (conf_files_filter_out(ctx, d, path, dent->d_name))
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200796 continue;
797
Lucas De Marchi7e0385c2013-08-27 23:29:47 -0300798 conf_files_insert_sorted(ctx, list, path, dent->d_name);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200799 }
800
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200801 closedir(d);
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200802 return 0;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200803}
804
Lucas De Marchic35347f2011-12-12 10:48:02 -0200805int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config,
806 const char * const *config_paths)
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200807{
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200808 struct kmod_config *config;
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200809 struct kmod_list *list = NULL;
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200810 struct kmod_list *path_list = NULL;
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200811 size_t i;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200812
Tom Gundersen82403332014-03-31 15:18:51 +0200813 conf_files_insert_sorted(ctx, &list, kmod_get_dirname(ctx), "modules.softdep");
814
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -0200815 for (i = 0; config_paths[i] != NULL; i++) {
816 const char *path = config_paths[i];
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200817 unsigned long long path_stamp = 0;
818 size_t pathlen;
819 struct kmod_list *tmp;
820 struct kmod_config_path *cf;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200821
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200822 if (conf_files_list(ctx, &list, path, &path_stamp) < 0)
823 continue;
824
825 pathlen = strlen(path) + 1;
826 cf = malloc(sizeof(*cf) + pathlen);
827 if (cf == NULL)
828 goto oom;
829
830 cf->stamp = path_stamp;
831 memcpy(cf->path, path, pathlen);
832
833 tmp = kmod_list_append(path_list, cf);
834 if (tmp == NULL)
835 goto oom;
836 path_list = tmp;
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200837 }
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -0200838
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200839 *p_config = config = calloc(1, sizeof(struct kmod_config));
840 if (config == NULL)
841 goto oom;
842
843 config->paths = path_list;
Lucas De Marchi29b69c02012-01-04 08:14:54 -0200844 config->ctx = ctx;
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200845
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200846 for (; list != NULL; list = kmod_list_remove(list)) {
Lucas De Marchi53d3a992016-08-08 11:42:52 -0300847 char buf[PATH_MAX];
848 const char *fn = buf;
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200849 struct conf_file *cf = list->data;
850 int fd;
Gustavo Sverzut Barbiericb8d4d32011-12-11 20:37:01 -0200851
Lucas De Marchi53d3a992016-08-08 11:42:52 -0300852 if (cf->is_single) {
853 fn = cf->path;
854 } else if (snprintf(buf, sizeof(buf), "%s/%s",
855 cf->path, cf->name) >= (int)sizeof(buf)) {
856 ERR(ctx, "Error parsing %s/%s: path too long\n",
857 cf->path, cf->name);
858 free(cf);
859 continue;
860 }
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200861
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200862 fd = open(fn, O_RDONLY|O_CLOEXEC);
863 DBG(ctx, "parsing file '%s' fd=%d\n", fn, fd);
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200864
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200865 if (fd >= 0)
866 kmod_config_parse(config, fd, fn);
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200867
Lucas De Marchi7fe5f7a2011-12-20 15:56:31 -0200868 free(cf);
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200869 }
870
Lucas De Marchi1684e442011-12-14 17:19:19 -0200871 kmod_config_parse_kcmdline(config);
872
Lucas De Marchib7b7ac22011-12-06 02:26:22 -0200873 return 0;
Lucas De Marchib6a4dfb2011-12-31 18:48:05 -0200874
875oom:
876 for (; list != NULL; list = kmod_list_remove(list))
877 free(list->data);
878
879 for (; path_list != NULL; path_list = kmod_list_remove(path_list))
880 free(path_list->data);
881
882 return -ENOMEM;
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200883}
Lucas De Marchi00178622012-01-13 02:24:18 -0200884
885/**********************************************************************
886 * struct kmod_config_iter functions
887 **********************************************************************/
888
889enum config_type {
890 CONFIG_TYPE_BLACKLIST = 0,
891 CONFIG_TYPE_INSTALL,
892 CONFIG_TYPE_REMOVE,
893 CONFIG_TYPE_ALIAS,
894 CONFIG_TYPE_OPTION,
895 CONFIG_TYPE_SOFTDEP,
896};
897
898struct kmod_config_iter {
899 enum config_type type;
Lucas De Marchi6b04ef32012-01-13 10:49:31 -0200900 bool intermediate;
Lucas De Marchi00178622012-01-13 02:24:18 -0200901 const struct kmod_list *list;
902 const struct kmod_list *curr;
Lucas De Marchi6b04ef32012-01-13 10:49:31 -0200903 void *data;
Lucas De Marchi00178622012-01-13 02:24:18 -0200904 const char *(*get_key)(const struct kmod_list *l);
905 const char *(*get_value)(const struct kmod_list *l);
906};
907
Lucas De Marchi6b04ef32012-01-13 10:49:31 -0200908static const char *softdep_get_plain_softdep(const struct kmod_list *l)
909{
910 char *s = softdep_to_char(l->data);
911 return s;
912}
913
Lucas De Marchi00178622012-01-13 02:24:18 -0200914static struct kmod_config_iter *kmod_config_iter_new(const struct kmod_ctx* ctx,
915 enum config_type type)
916{
917 struct kmod_config_iter *iter = calloc(1, sizeof(*iter));
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300918 const struct kmod_config *config = kmod_get_config(ctx);
Lucas De Marchi00178622012-01-13 02:24:18 -0200919
920 if (iter == NULL)
921 return NULL;
922
923 iter->type = type;
924
925 switch (type) {
926 case CONFIG_TYPE_BLACKLIST:
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300927 iter->list = config->blacklists;
Lucas De Marchi00178622012-01-13 02:24:18 -0200928 iter->get_key = kmod_blacklist_get_modname;
929 break;
930 case CONFIG_TYPE_INSTALL:
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300931 iter->list = config->install_commands;
Lucas De Marchi00178622012-01-13 02:24:18 -0200932 iter->get_key = kmod_command_get_modname;
933 iter->get_value = kmod_command_get_command;
934 break;
935 case CONFIG_TYPE_REMOVE:
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300936 iter->list = config->remove_commands;
Lucas De Marchi00178622012-01-13 02:24:18 -0200937 iter->get_key = kmod_command_get_modname;
938 iter->get_value = kmod_command_get_command;
939 break;
940 case CONFIG_TYPE_ALIAS:
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300941 iter->list = config->aliases;
Lucas De Marchi00178622012-01-13 02:24:18 -0200942 iter->get_key = kmod_alias_get_name;
943 iter->get_value = kmod_alias_get_modname;
944 break;
945 case CONFIG_TYPE_OPTION:
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300946 iter->list = config->options;
Lucas De Marchi00178622012-01-13 02:24:18 -0200947 iter->get_key = kmod_option_get_modname;
948 iter->get_value = kmod_option_get_options;
949 break;
950 case CONFIG_TYPE_SOFTDEP:
Lucas De Marchie7fc2c82012-06-12 01:43:46 -0300951 iter->list = config->softdeps;
Lucas De Marchi00178622012-01-13 02:24:18 -0200952 iter->get_key = kmod_softdep_get_name;
Lucas De Marchi6b04ef32012-01-13 10:49:31 -0200953 iter->get_value = softdep_get_plain_softdep;
954 iter->intermediate = true;
Lucas De Marchi00178622012-01-13 02:24:18 -0200955 break;
956 }
957
958 return iter;
959}
960
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -0200961/**
962 * SECTION:libkmod-config
963 * @short_description: retrieve current libkmod configuration
964 */
965
966/**
967 * kmod_config_get_blacklists:
968 * @ctx: kmod library context
969 *
970 * Retrieve an iterator to deal with the blacklist maintained inside the
971 * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
972 * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
973 * be made to initialize the iterator and check if it's valid.
974 *
Lucas De Marchi883d8c42012-04-19 11:08:24 -0300975 * Returns: a new iterator over the blacklists or NULL on failure. Free it
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -0200976 * with kmod_config_iter_free_iter().
977 */
Lucas De Marchi00178622012-01-13 02:24:18 -0200978KMOD_EXPORT struct kmod_config_iter *kmod_config_get_blacklists(const struct kmod_ctx *ctx)
979{
980 if (ctx == NULL)
981 return NULL;;
982
983 return kmod_config_iter_new(ctx, CONFIG_TYPE_BLACKLIST);
984}
985
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -0200986/**
987 * kmod_config_get_install_commands:
988 * @ctx: kmod library context
989 *
990 * Retrieve an iterator to deal with the install commands maintained inside the
991 * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
992 * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
993 * be made to initialize the iterator and check if it's valid.
994 *
Lucas De Marchi883d8c42012-04-19 11:08:24 -0300995 * Returns: a new iterator over the install commands or NULL on failure. Free
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -0200996 * it with kmod_config_iter_free_iter().
997 */
Lucas De Marchi00178622012-01-13 02:24:18 -0200998KMOD_EXPORT struct kmod_config_iter *kmod_config_get_install_commands(const struct kmod_ctx *ctx)
999{
1000 if (ctx == NULL)
1001 return NULL;;
1002
1003 return kmod_config_iter_new(ctx, CONFIG_TYPE_INSTALL);
1004}
1005
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001006/**
1007 * kmod_config_get_remove_commands:
1008 * @ctx: kmod library context
1009 *
1010 * Retrieve an iterator to deal with the remove commands maintained inside the
1011 * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1012 * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1013 * be made to initialize the iterator and check if it's valid.
1014 *
Lucas De Marchi883d8c42012-04-19 11:08:24 -03001015 * Returns: a new iterator over the remove commands or NULL on failure. Free
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001016 * it with kmod_config_iter_free_iter().
1017 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001018KMOD_EXPORT struct kmod_config_iter *kmod_config_get_remove_commands(const struct kmod_ctx *ctx)
1019{
1020 if (ctx == NULL)
1021 return NULL;;
1022
1023 return kmod_config_iter_new(ctx, CONFIG_TYPE_REMOVE);
1024}
1025
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001026/**
1027 * kmod_config_get_aliases:
1028 * @ctx: kmod library context
1029 *
1030 * Retrieve an iterator to deal with the aliases maintained inside the
1031 * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1032 * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1033 * be made to initialize the iterator and check if it's valid.
1034 *
Lucas De Marchi883d8c42012-04-19 11:08:24 -03001035 * Returns: a new iterator over the aliases or NULL on failure. Free it with
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001036 * kmod_config_iter_free_iter().
1037 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001038KMOD_EXPORT struct kmod_config_iter *kmod_config_get_aliases(const struct kmod_ctx *ctx)
1039{
1040 if (ctx == NULL)
1041 return NULL;;
1042
1043 return kmod_config_iter_new(ctx, CONFIG_TYPE_ALIAS);
1044}
1045
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001046/**
1047 * kmod_config_get_options:
1048 * @ctx: kmod library context
1049 *
1050 * Retrieve an iterator to deal with the options maintained inside the
1051 * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1052 * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1053 * be made to initialize the iterator and check if it's valid.
1054 *
Lucas De Marchi883d8c42012-04-19 11:08:24 -03001055 * Returns: a new iterator over the options or NULL on failure. Free it with
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001056 * kmod_config_iter_free_iter().
1057 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001058KMOD_EXPORT struct kmod_config_iter *kmod_config_get_options(const struct kmod_ctx *ctx)
1059{
1060 if (ctx == NULL)
1061 return NULL;;
1062
1063 return kmod_config_iter_new(ctx, CONFIG_TYPE_OPTION);
1064}
1065
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001066/**
1067 * kmod_config_get_softdeps:
1068 * @ctx: kmod library context
1069 *
1070 * Retrieve an iterator to deal with the softdeps maintained inside the
1071 * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1072 * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1073 * be made to initialize the iterator and check if it's valid.
1074 *
Lucas De Marchi883d8c42012-04-19 11:08:24 -03001075 * Returns: a new iterator over the softdeps or NULL on failure. Free it with
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001076 * kmod_config_iter_free_iter().
1077 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001078KMOD_EXPORT struct kmod_config_iter *kmod_config_get_softdeps(const struct kmod_ctx *ctx)
1079{
1080 if (ctx == NULL)
1081 return NULL;;
1082
1083 return kmod_config_iter_new(ctx, CONFIG_TYPE_SOFTDEP);
1084}
1085
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001086/**
1087 * kmod_config_iter_get_key:
1088 * @iter: iterator over a certain configuration
1089 *
1090 * When using a new allocated iterator, user must perform a call to
1091 * kmod_config_iter_next() to initialize iterator's position and check if it's
1092 * valid.
1093 *
1094 * Returns: the key of the current configuration pointed by @iter.
1095 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001096KMOD_EXPORT const char *kmod_config_iter_get_key(const struct kmod_config_iter *iter)
1097{
1098 if (iter == NULL || iter->curr == NULL)
1099 return NULL;
1100
1101 return iter->get_key(iter->curr);
1102}
1103
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001104/**
1105 * kmod_config_iter_get_value:
1106 * @iter: iterator over a certain configuration
1107 *
1108 * When using a new allocated iterator, user must perform a call to
1109 * kmod_config_iter_next() to initialize iterator's position and check if it's
1110 * valid.
1111 *
1112 * Returns: the value of the current configuration pointed by @iter.
1113 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001114KMOD_EXPORT const char *kmod_config_iter_get_value(const struct kmod_config_iter *iter)
1115{
Lucas De Marchi6b04ef32012-01-13 10:49:31 -02001116 const char *s;
1117
Lucas De Marchi00178622012-01-13 02:24:18 -02001118 if (iter == NULL || iter->curr == NULL)
1119 return NULL;
1120
1121 if (iter->get_value == NULL)
1122 return NULL;
1123
Lucas De Marchi6b04ef32012-01-13 10:49:31 -02001124 if (iter->intermediate) {
1125 struct kmod_config_iter *i = (struct kmod_config_iter *)iter;
1126
1127 free(i->data);
1128 s = i->data = (void *) iter->get_value(iter->curr);
1129 } else
1130 s = iter->get_value(iter->curr);
1131
1132 return s;
Lucas De Marchi00178622012-01-13 02:24:18 -02001133}
1134
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001135/**
1136 * kmod_config_iter_next:
1137 * @iter: iterator over a certain configuration
1138 *
1139 * Make @iter point to the next item of a certain configuration. It's an
1140 * automatically recycling iterator. When it reaches the end, false is
1141 * returned; then if user wants to iterate again, it's sufficient to call this
1142 * function once more.
1143 *
1144 * Returns: true if next position of @iter is valid or false if its end is
1145 * reached.
1146 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001147KMOD_EXPORT bool kmod_config_iter_next(struct kmod_config_iter *iter)
1148{
1149 if (iter == NULL)
1150 return false;
1151
1152 if (iter->curr == NULL) {
1153 iter->curr = iter->list;
1154 return iter->curr != NULL;
1155 }
1156
1157 iter->curr = kmod_list_next(iter->list, iter->curr);
1158
1159 return iter->curr != NULL;
1160}
1161
Lucas De Marchi2f47c7f2012-01-14 12:09:34 -02001162/**
1163 * kmod_config_iter_free_iter:
1164 * @iter: iterator over a certain configuration
1165 *
1166 * Free resources used by the iterator.
1167 */
Lucas De Marchi00178622012-01-13 02:24:18 -02001168KMOD_EXPORT void kmod_config_iter_free_iter(struct kmod_config_iter *iter)
1169{
Lucas De Marchi6b04ef32012-01-13 10:49:31 -02001170 free(iter->data);
Lucas De Marchi00178622012-01-13 02:24:18 -02001171 free(iter);
1172}