]>
git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-config.c
2 * libkmod - interface to kernel module operations
4 * Copyright (C) 2011 ProFUSION embedded systems
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation version 2.1.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <sys/types.h>
33 #include "libkmod-private.h"
50 const char *kmod_alias_get_name(const struct kmod_list
*l
) {
51 const struct kmod_alias
*alias
= l
->data
;
55 const char *kmod_alias_get_modname(const struct kmod_list
*l
) {
56 const struct kmod_alias
*alias
= l
->data
;
57 return alias
->modname
;
60 const char *kmod_option_get_options(const struct kmod_list
*l
) {
61 const struct kmod_options
*alias
= l
->data
;
62 return alias
->options
;
65 const char *kmod_option_get_modname(const struct kmod_list
*l
) {
66 const struct kmod_options
*alias
= l
->data
;
67 return alias
->modname
;
70 const char *kmod_command_get_command(const struct kmod_list
*l
) {
71 const struct kmod_command
*alias
= l
->data
;
72 return alias
->command
;
75 const char *kmod_command_get_modname(const struct kmod_list
*l
) {
76 const struct kmod_command
*alias
= l
->data
;
77 return alias
->modname
;
80 static int kmod_config_add_command(struct kmod_config
*config
,
83 const char *command_name
,
84 struct kmod_list
**list
)
86 struct kmod_command
*cmd
;
88 size_t modnamelen
= strlen(modname
) + 1;
89 size_t commandlen
= strlen(command
) + 1;
91 DBG(config
->ctx
, "modname'%s' cmd='%s %s'\n", modname
, command_name
,
94 cmd
= malloc(sizeof(*cmd
) + modnamelen
+ commandlen
);
98 cmd
->command
= sizeof(*cmd
) + modnamelen
+ (char *)cmd
;
99 memcpy(cmd
->modname
, modname
, modnamelen
);
100 memcpy(cmd
->command
, command
, commandlen
);
102 l
= kmod_list_append(*list
, cmd
);
112 ERR(config
->ctx
, "out-of-memory\n");
116 static void kmod_config_free_command(struct kmod_config
*config
,
118 struct kmod_list
**list
)
120 struct kmod_command
*cmd
= l
->data
;
123 *list
= kmod_list_remove(l
);
126 static int kmod_config_add_options(struct kmod_config
*config
,
127 const char *modname
, const char *options
)
129 struct kmod_options
*opt
;
130 struct kmod_list
*list
;
131 size_t modnamelen
= strlen(modname
) + 1;
132 size_t optionslen
= strlen(options
) + 1;
134 DBG(config
->ctx
, "modname'%s' options='%s'\n", modname
, options
);
136 opt
= malloc(sizeof(*opt
) + modnamelen
+ optionslen
);
140 opt
->options
= sizeof(*opt
) + modnamelen
+ (char *)opt
;
142 memcpy(opt
->modname
, modname
, modnamelen
);
143 memcpy(opt
->options
, options
, optionslen
);
144 strchr_replace(opt
->options
, '\t', ' ');
146 list
= kmod_list_append(config
->options
, opt
);
150 config
->options
= list
;
156 ERR(config
->ctx
, "out-of-memory\n");
160 static void kmod_config_free_options(struct kmod_config
*config
,
163 struct kmod_options
*opt
= l
->data
;
167 config
->options
= kmod_list_remove(l
);
170 static int kmod_config_add_alias(struct kmod_config
*config
,
171 const char *name
, const char *modname
)
173 struct kmod_alias
*alias
;
174 struct kmod_list
*list
;
175 size_t namelen
= strlen(name
) + 1, modnamelen
= strlen(modname
) + 1;
177 DBG(config
->ctx
, "name=%s modname=%s\n", name
, modname
);
179 alias
= malloc(sizeof(*alias
) + namelen
+ modnamelen
);
183 alias
->name
= sizeof(*alias
) + modnamelen
+ (char *)alias
;
185 memcpy(alias
->modname
, modname
, modnamelen
);
186 memcpy(alias
->name
, name
, namelen
);
188 list
= kmod_list_append(config
->aliases
, alias
);
192 config
->aliases
= list
;
198 ERR(config
->ctx
, "out-of-memory name=%s modname=%s\n", name
, modname
);
202 static void kmod_config_free_alias(struct kmod_config
*config
,
205 struct kmod_alias
*alias
= l
->data
;
209 config
->aliases
= kmod_list_remove(l
);
212 static int kmod_config_add_blacklist(struct kmod_config
*config
,
216 struct kmod_list
*list
;
218 DBG(config
->ctx
, "modname=%s\n", modname
);
224 list
= kmod_list_append(config
->blacklists
, p
);
227 config
->blacklists
= list
;
233 ERR(config
->ctx
, "out-of-memory modname=%s\n", modname
);
237 static void kmod_config_free_blacklist(struct kmod_config
*config
,
241 config
->blacklists
= kmod_list_remove(l
);
245 * Take an fd and own it. It will be closed on return. filename is used only
248 static int kmod_config_parse(struct kmod_config
*config
, int fd
,
249 const char *filename
)
251 struct kmod_ctx
*ctx
= config
->ctx
;
254 unsigned int linenum
;
257 fp
= fdopen(fd
, "r");
260 ERR(config
->ctx
, "fd %d: %m", fd
);
265 while ((line
= getline_wrapped(fp
, &linenum
)) != NULL
) {
268 if (line
[0] == '\0' || line
[0] == '#')
271 cmd
= strtok_r(line
, "\t ", &saveptr
);
275 if (streq(cmd
, "alias")) {
276 char *alias
= strtok_r(NULL
, "\t ", &saveptr
);
277 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
279 if (alias
== NULL
|| modname
== NULL
)
282 kmod_config_add_alias(config
,
283 underscores(ctx
, alias
),
284 underscores(ctx
, modname
));
285 } else if (streq(cmd
, "blacklist")) {
286 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
291 kmod_config_add_blacklist(config
,
292 underscores(ctx
, modname
));
293 } else if (streq(cmd
, "options")) {
294 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
299 kmod_config_add_options(config
,
300 underscores(ctx
, modname
),
301 strtok_r(NULL
, "\0", &saveptr
));
302 } else if streq(cmd
, "install") {
303 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
308 kmod_config_add_command(config
,
309 underscores(ctx
, modname
),
310 strtok_r(NULL
, "\0", &saveptr
),
311 cmd
, &config
->install_commands
);
312 } else if streq(cmd
, "remove") {
313 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
318 kmod_config_add_command(config
,
319 underscores(ctx
, modname
),
320 strtok_r(NULL
, "\0", &saveptr
),
321 cmd
, &config
->remove_commands
);
322 } else if (streq(cmd
, "include")
323 || streq(cmd
, "softdep")
324 || streq(cmd
, "config")) {
325 INFO(ctx
, "%s: command %s not implemented yet\n",
329 ERR(ctx
, "%s line %u: ignoring bad line starting with '%s'\n",
330 filename
, linenum
, cmd
);
342 void kmod_config_free(struct kmod_config
*config
)
344 while (config
->aliases
)
345 kmod_config_free_alias(config
, config
->aliases
);
347 while (config
->blacklists
)
348 kmod_config_free_blacklist(config
, config
->blacklists
);
350 while (config
->options
)
351 kmod_config_free_options(config
, config
->options
);
353 while (config
->install_commands
) {
354 kmod_config_free_command(config
, config
->install_commands
,
355 &config
->install_commands
);
358 while (config
->remove_commands
) {
359 kmod_config_free_command(config
, config
->remove_commands
,
360 &config
->remove_commands
);
366 static bool conf_files_filter_out(struct kmod_ctx
*ctx
, const char *path
,
369 size_t len
= strlen(fn
);
374 if (len
< 6 || (!streq(&fn
[len
- 5], ".conf")
375 && !streq(&fn
[len
- 6], ".alias"))) {
376 INFO(ctx
, "All config files need .conf: %s/%s, "
377 "it will be ignored in a future release\n",
386 * Iterate over a directory (given by @path) and save the list of
387 * configuration files in @list.
389 static DIR *conf_files_list(struct kmod_ctx
*ctx
, struct kmod_list
**list
,
405 struct dirent ent
, *entp
;
406 struct kmod_list
*l
, *tmp
;
409 err
= readdir_r(d
, &ent
, &entp
);
411 ERR(ctx
, "reading entry %s\n", strerror(-err
));
418 if (conf_files_filter_out(ctx
, path
, entp
->d_name
) == 1)
422 kmod_list_foreach(l
, *list
) {
423 if (strcmp(entp
->d_name
, l
->data
) < 0)
427 dname
= strdup(entp
->d_name
);
432 tmp
= kmod_list_append(*list
, dname
);
434 tmp
= kmod_list_prepend(*list
, dname
);
436 tmp
= kmod_list_insert_before(l
, dname
);
441 if (l
== NULL
|| l
== *list
)
448 ERR(ctx
, "out of memory while scanning '%s'\n", path
);
450 for (; *list
!= NULL
; *list
= kmod_list_remove(*list
))
456 int kmod_config_new(struct kmod_ctx
*ctx
, struct kmod_config
**p_config
,
457 const char * const *config_paths
)
459 struct kmod_config
*config
;
462 *p_config
= config
= calloc(1, sizeof(struct kmod_config
));
468 for (i
= 0; config_paths
[i
] != NULL
; i
++) {
469 const char *path
= config_paths
[i
];
470 struct kmod_list
*list
;
474 if (stat(path
, &st
) != 0) {
475 DBG(ctx
, "could not load '%s': %s\n",
476 path
, strerror(errno
));
480 if (S_ISREG(st
.st_mode
)) {
481 int fd
= open(path
, O_RDONLY
);
482 DBG(ctx
, "parsing file '%s': %d\n", path
, fd
);
484 kmod_config_parse(config
, fd
, path
);
486 } else if (!S_ISDIR(st
.st_mode
)) {
487 ERR(ctx
, "unsupported file mode %s: %#x\n",
492 d
= conf_files_list(ctx
, &list
, path
);
494 for (; list
!= NULL
; list
= kmod_list_remove(list
)) {
495 int fd
= openat(dirfd(d
), list
->data
, O_RDONLY
);
496 DBG(ctx
, "parsing file '%s/%s': %d\n", path
,
497 (const char *) list
->data
, fd
);
499 kmod_config_parse(config
, fd
, list
->data
);