]>
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"
35 static const char *config_files
[] = {
56 const char *kmod_alias_get_name(const struct kmod_list
*l
) {
57 const struct kmod_alias
*alias
= l
->data
;
61 const char *kmod_alias_get_modname(const struct kmod_list
*l
) {
62 const struct kmod_alias
*alias
= l
->data
;
63 return alias
->modname
;
66 static int kmod_config_add_command(struct kmod_config
*config
,
69 const char *command_name
,
70 struct kmod_list
**list
)
72 struct kmod_command
*cmd
;
74 size_t modnamelen
= strlen(modname
) + 1;
75 size_t commandlen
= strlen(command
) + 1;
77 DBG(config
->ctx
, "modname'%s' cmd='%s %s'\n", modname
, command_name
,
80 cmd
= malloc(sizeof(*cmd
) + modnamelen
+ commandlen
);
84 cmd
->command
= sizeof(*cmd
) + modnamelen
+ (char *)cmd
;
85 memcpy(cmd
->modname
, modname
, modnamelen
);
86 memcpy(cmd
->command
, command
, commandlen
);
88 l
= kmod_list_append(*list
, cmd
);
98 ERR(config
->ctx
, "out-of-memory\n");
102 static void kmod_config_free_command(struct kmod_config
*config
,
104 struct kmod_list
**list
)
106 struct kmod_command
*cmd
= l
->data
;
109 *list
= kmod_list_remove(l
);
112 static int kmod_config_add_options(struct kmod_config
*config
,
113 const char *modname
, const char *options
)
115 struct kmod_options
*opt
;
116 struct kmod_list
*list
;
117 size_t modnamelen
= strlen(modname
) + 1;
118 size_t optionslen
= strlen(options
) + 1;
120 DBG(config
->ctx
, "modname'%s' options='%s'\n", modname
, options
);
122 opt
= malloc(sizeof(*opt
) + modnamelen
+ optionslen
);
126 opt
->options
= sizeof(*opt
) + modnamelen
+ (char *)opt
;
128 memcpy(opt
->modname
, modname
, modnamelen
);
129 memcpy(opt
->options
, options
, optionslen
);
130 strchr_replace(opt
->options
, '\t', ' ');
132 list
= kmod_list_append(config
->options
, opt
);
136 config
->options
= list
;
142 ERR(config
->ctx
, "out-of-memory\n");
146 static void kmod_config_free_options(struct kmod_config
*config
, struct kmod_list
*l
)
148 struct kmod_options
*opt
= l
->data
;
152 config
->options
= kmod_list_remove(l
);
155 static int kmod_config_add_alias(struct kmod_config
*config
,
156 const char *name
, const char *modname
)
158 struct kmod_alias
*alias
;
159 struct kmod_list
*list
;
160 size_t namelen
= strlen(name
) + 1, modnamelen
= strlen(modname
) + 1;
162 DBG(config
->ctx
, "name=%s modname=%s\n", name
, modname
);
164 alias
= malloc(sizeof(*alias
) + namelen
+ modnamelen
);
167 alias
->name
= sizeof(*alias
) + modnamelen
+ (char *)alias
;
169 memcpy(alias
->modname
, modname
, modnamelen
);
170 memcpy(alias
->name
, name
, namelen
);
172 list
= kmod_list_append(config
->aliases
, alias
);
175 config
->aliases
= list
;
181 ERR(config
->ctx
, "out-of-memory name=%s modname=%s\n", name
, modname
);
185 static void kmod_config_free_alias(struct kmod_config
*config
, struct kmod_list
*l
)
187 struct kmod_alias
*alias
= l
->data
;
191 config
->aliases
= kmod_list_remove(l
);
194 static int kmod_config_add_blacklist(struct kmod_config
*config
,
198 struct kmod_list
*list
;
200 DBG(config
->ctx
, "modname=%s\n", modname
);
206 list
= kmod_list_append(config
->blacklists
, p
);
209 config
->blacklists
= list
;
215 ERR(config
->ctx
, "out-of-memory modname=%s\n", modname
);
219 static void kmod_config_free_blacklist(struct kmod_config
*config
,
223 config
->blacklists
= kmod_list_remove(l
);
227 * Take an fd and own it. It will be closed on return. filename is used only
230 static int kmod_config_parse(struct kmod_config
*config
, int fd
,
231 const char *filename
)
233 struct kmod_ctx
*ctx
= config
->ctx
;
236 unsigned int linenum
;
239 fp
= fdopen(fd
, "r");
242 ERR(config
->ctx
, "fd %d: %m", fd
);
247 while ((line
= getline_wrapped(fp
, &linenum
)) != NULL
) {
250 if (line
[0] == '\0' || line
[0] == '#')
253 cmd
= strtok_r(line
, "\t ", &saveptr
);
257 if (streq(cmd
, "alias")) {
258 char *alias
= strtok_r(NULL
, "\t ", &saveptr
);
259 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
261 if (alias
== NULL
|| modname
== NULL
)
264 kmod_config_add_alias(config
,
265 underscores(ctx
, alias
),
266 underscores(ctx
, modname
));
267 } else if (streq(cmd
, "blacklist")) {
268 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
273 kmod_config_add_blacklist(config
,
274 underscores(ctx
, modname
));
275 } else if (streq(cmd
, "options")) {
276 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
281 kmod_config_add_options(config
,
282 underscores(ctx
, modname
),
283 strtok_r(NULL
, "\0", &saveptr
));
284 } else if streq(cmd
, "install") {
285 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
290 kmod_config_add_command(config
,
291 underscores(ctx
, modname
),
292 strtok_r(NULL
, "\0", &saveptr
),
293 cmd
, &config
->install_commands
);
294 } else if streq(cmd
, "remove") {
295 char *modname
= strtok_r(NULL
, "\t ", &saveptr
);
300 kmod_config_add_command(config
,
301 underscores(ctx
, modname
),
302 strtok_r(NULL
, "\0", &saveptr
),
303 cmd
, &config
->remove_commands
);
304 } else if (streq(cmd
, "include")
305 || streq(cmd
, "softdep")
306 || streq(cmd
, "config")) {
307 INFO(ctx
, "%s: command %s not implemented yet\n",
311 ERR(ctx
, "%s line %u: ignoring bad line starting with '%s'\n",
312 filename
, linenum
, cmd
);
324 void kmod_config_free(struct kmod_config
*config
)
326 while (config
->aliases
)
327 kmod_config_free_alias(config
, config
->aliases
);
329 while (config
->blacklists
)
330 kmod_config_free_blacklist(config
, config
->blacklists
);
332 while (config
->options
)
333 kmod_config_free_options(config
, config
->options
);
335 while (config
->install_commands
) {
336 kmod_config_free_command(config
, config
->install_commands
,
337 &config
->install_commands
);
340 while (config
->remove_commands
) {
341 kmod_config_free_command(config
, config
->remove_commands
,
342 &config
->remove_commands
);
348 static bool conf_files_filter_out(struct kmod_ctx
*ctx
, const char *path
,
351 size_t len
= strlen(fn
);
356 if (len
< 6 || (!streq(&fn
[len
- 5], ".conf")
357 && !streq(&fn
[len
- 6], ".alias"))) {
358 INFO(ctx
, "All config files need .conf: %s/%s, "
359 "it will be ignored in a future release\n",
367 static DIR *conf_files_list(struct kmod_ctx
*ctx
, struct kmod_list
**list
,
374 if (stat(path
, &st
) < 0)
377 if (!S_ISDIR(st
.st_mode
)) {
378 *list
= kmod_list_append(*list
, path
);
390 struct dirent ent
, *entp
;
391 struct kmod_list
*l
, *tmp
;
394 err
= readdir_r(d
, &ent
, &entp
);
396 ERR(ctx
, "reading entry %s\n", strerror(-err
));
403 if (conf_files_filter_out(ctx
, path
, entp
->d_name
) == 1)
407 kmod_list_foreach(l
, *list
) {
408 if (strcmp(entp
->d_name
, l
->data
) < 0)
412 dname
= strdup(entp
->d_name
);
417 tmp
= kmod_list_append(*list
, dname
);
419 tmp
= kmod_list_prepend(*list
, dname
);
421 tmp
= kmod_list_insert_before(l
, dname
);
426 if (l
== NULL
|| l
== *list
)
433 ERR(ctx
, "out of memory while scanning '%s'\n", path
);
435 for (; *list
!= NULL
; *list
= kmod_list_remove(*list
))
441 int kmod_config_new(struct kmod_ctx
*ctx
, struct kmod_config
**p_config
)
443 struct kmod_config
*config
;
446 *p_config
= config
= calloc(1, sizeof(struct kmod_config
));
452 for (i
= 0; i
< ARRAY_SIZE(config_files
); i
++) {
453 struct kmod_list
*list
= NULL
;
457 d
= conf_files_list(ctx
, &list
, config_files
[i
]);
459 /* there's no entry */
463 /* there's only one entry, and it's a file */
465 DBG(ctx
, "parsing file '%s'\n", config_files
[i
]);
466 list
= kmod_list_remove(list
);
467 fd
= open(config_files
[i
], O_RDONLY
);
469 kmod_config_parse(config
, fd
, config_files
[i
]);
474 /* treat all the entries in that dir */
475 for (; list
!= NULL
; list
= kmod_list_remove(list
)) {
476 DBG(ctx
, "parsing file '%s/%s'\n", config_files
[i
],
477 (char *) list
->data
);
478 fd
= openat(dirfd(d
), list
->data
, O_RDONLY
);
480 kmod_config_parse(config
, fd
, list
->data
);