]>
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
, struct kmod_list
*l
)
162 struct kmod_options
*opt
= l
->data
;
166 config
->options
= kmod_list_remove(l
);
169 static int kmod_config_add_alias(struct kmod_config
*config
,
170 const char *name
, const char *modname
)
172 struct kmod_alias
*alias
;
173 struct kmod_list
*list
;
174 size_t namelen
= strlen(name
) + 1, modnamelen
= strlen(modname
) + 1;
176 DBG(config
->ctx
, "name=%s modname=%s\n", name
, modname
);
178 alias
= malloc(sizeof(*alias
) + namelen
+ modnamelen
);
181 alias
->name
= sizeof(*alias
) + modnamelen
+ (char *)alias
;
183 memcpy(alias
->modname
, modname
, modnamelen
);
184 memcpy(alias
->name
, name
, namelen
);
186 list
= kmod_list_append(config
->aliases
, alias
);
189 config
->aliases
= list
;
195 ERR(config
->ctx
, "out-of-memory name=%s modname=%s\n", name
, modname
);
199 static void kmod_config_free_alias(struct kmod_config
*config
, struct kmod_list
*l
)
201 struct kmod_alias
*alias
= l
->data
;
205 config
->aliases
= kmod_list_remove(l
);
208 static int kmod_config_add_blacklist(struct kmod_config
*config
,
212 struct kmod_list
*list
;
214 DBG(config
->ctx
, "modname=%s\n", modname
);
220 list
= kmod_list_append(config
->blacklists
, p
);
223 config
->blacklists
= list
;
229 ERR(config
->ctx
, "out-of-memory modname=%s\n", modname
);
233 static void kmod_config_free_blacklist(struct kmod_config
*config
,
237 config
->blacklists
= kmod_list_remove(l
);
241 * Take an fd and own it. It will be closed on return. filename is used only
244 static int kmod_config_parse(struct kmod_config
*config
, int fd
,
245 const char *filename
)
247 struct kmod_ctx
*ctx
= config
->ctx
;
250 unsigned int linenum
;
253 fp
= fdopen(fd
, "r");
256 ERR(config
->ctx
, "fd %d: %m", fd
);
261 while ((line
= getline_wrapped(fp
, &linenum
)) != NULL
) {
264 if (line
[0] == '\0' || line
[0] == '#')
267 cmd
= strtok_r(line
, "\t ", &saveptr
);
271 if (streq(cmd
, "alias")) {
272 char *alias
= strtok_r(NULL
, "\t ", &saveptr
);
273 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
275 if (alias
== NULL
|| modname
== NULL
)
278 kmod_config_add_alias(config
,
279 underscores(ctx
, alias
),
280 underscores(ctx
, modname
));
281 } else if (streq(cmd
, "blacklist")) {
282 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
287 kmod_config_add_blacklist(config
,
288 underscores(ctx
, modname
));
289 } else if (streq(cmd
, "options")) {
290 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
295 kmod_config_add_options(config
,
296 underscores(ctx
, modname
),
297 strtok_r(NULL
, "\0", &saveptr
));
298 } else if streq(cmd
, "install") {
299 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
304 kmod_config_add_command(config
,
305 underscores(ctx
, modname
),
306 strtok_r(NULL
, "\0", &saveptr
),
307 cmd
, &config
->install_commands
);
308 } else if streq(cmd
, "remove") {
309 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
314 kmod_config_add_command(config
,
315 underscores(ctx
, modname
),
316 strtok_r(NULL
, "\0", &saveptr
),
317 cmd
, &config
->remove_commands
);
318 } else if (streq(cmd
, "include")
319 || streq(cmd
, "softdep")
320 || streq(cmd
, "config")) {
321 INFO(ctx
, "%s: command %s not implemented yet\n",
325 ERR(ctx
, "%s line %u: ignoring bad line starting with '%s'\n",
326 filename
, linenum
, cmd
);
338 void kmod_config_free(struct kmod_config
*config
)
340 while (config
->aliases
)
341 kmod_config_free_alias(config
, config
->aliases
);
343 while (config
->blacklists
)
344 kmod_config_free_blacklist(config
, config
->blacklists
);
346 while (config
->options
)
347 kmod_config_free_options(config
, config
->options
);
349 while (config
->install_commands
) {
350 kmod_config_free_command(config
, config
->install_commands
,
351 &config
->install_commands
);
354 while (config
->remove_commands
) {
355 kmod_config_free_command(config
, config
->remove_commands
,
356 &config
->remove_commands
);
362 static bool conf_files_filter_out(struct kmod_ctx
*ctx
, const char *path
,
365 size_t len
= strlen(fn
);
370 if (len
< 6 || (!streq(&fn
[len
- 5], ".conf")
371 && !streq(&fn
[len
- 6], ".alias"))) {
372 INFO(ctx
, "All config files need .conf: %s/%s, "
373 "it will be ignored in a future release\n",
381 static DIR *conf_files_list(struct kmod_ctx
*ctx
, struct kmod_list
**list
,
388 if (stat(path
, &st
) < 0)
391 if (!S_ISDIR(st
.st_mode
)) {
392 *list
= kmod_list_append(*list
, path
);
404 struct dirent ent
, *entp
;
405 struct kmod_list
*l
, *tmp
;
408 err
= readdir_r(d
, &ent
, &entp
);
410 ERR(ctx
, "reading entry %s\n", strerror(-err
));
417 if (conf_files_filter_out(ctx
, path
, entp
->d_name
) == 1)
421 kmod_list_foreach(l
, *list
) {
422 if (strcmp(entp
->d_name
, l
->data
) < 0)
426 dname
= strdup(entp
->d_name
);
431 tmp
= kmod_list_append(*list
, dname
);
433 tmp
= kmod_list_prepend(*list
, dname
);
435 tmp
= kmod_list_insert_before(l
, dname
);
440 if (l
== NULL
|| l
== *list
)
447 ERR(ctx
, "out of memory while scanning '%s'\n", path
);
449 for (; *list
!= NULL
; *list
= kmod_list_remove(*list
))
455 int kmod_config_new(struct kmod_ctx
*ctx
, struct kmod_config
**p_config
, const char * const *config_paths
)
457 struct kmod_config
*config
;
460 *p_config
= config
= calloc(1, sizeof(struct kmod_config
));
466 for (i
= 0; config_paths
[i
] != NULL
; i
++) {
467 const char *path
= config_paths
[i
];
468 struct kmod_list
*list
= NULL
;
472 if (stat(path
, &st
) != 0) {
473 DBG(ctx
, "could not load '%s': %s\n",
474 path
, strerror(errno
));
478 if (S_ISREG(st
.st_mode
)) {
479 int fd
= open(path
, O_RDONLY
);
480 DBG(ctx
, "parsing file '%s': %d\n", path
, fd
);
482 kmod_config_parse(config
, fd
, path
);
484 } else if (!S_ISDIR(st
.st_mode
)) {
485 ERR(ctx
, "unsupported file mode %s: %#x\n",
490 d
= conf_files_list(ctx
, &list
, path
);
492 /* there's no entry */
496 ERR(ctx
, "returned list but no directory?\n");
499 kmod_list_remove(list
);
504 /* treat all the entries in that dir */
505 for (; list
!= NULL
; list
= kmod_list_remove(list
)) {
506 int fd
= openat(dirfd(d
), list
->data
, O_RDONLY
);
507 DBG(ctx
, "parsing file '%s/%s': %d\n", path
,
508 (const char *) list
->data
, fd
);
510 kmod_config_parse(config
, fd
, list
->data
);