]> git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-config.c
Clean 'unused variable' warnings
[thirdparty/kmod.git] / libkmod / libkmod-config.c
1 /*
2 * libkmod - interface to kernel module operations
3 *
4 * Copyright (C) 2011 ProFUSION embedded systems
5 *
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.
9 *
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.
14 *
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
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stddef.h>
23 #include <stdarg.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <dirent.h>
31
32 #include "libkmod.h"
33 #include "libkmod-private.h"
34
35 static const char *config_files[] = {
36 "/run/modprobe.d",
37 "/etc/modprobe.d",
38 "/usr/local/lib/modprobe",
39 "/lib/modprobe.d",
40 };
41
42 struct kmod_alias {
43 char *name;
44 char *modname;
45 };
46
47 const char *kmod_alias_get_name(const struct kmod_list *l) {
48 struct kmod_alias *alias = l->data;
49 return alias->name;
50 }
51
52 const char *kmod_alias_get_modname(const struct kmod_list *l) {
53 struct kmod_alias *alias = l->data;
54 return alias->modname;
55 }
56
57 static struct kmod_list *add_alias(struct kmod_ctx *ctx,
58 struct kmod_list *aliases,
59 const char *name, const char *modname)
60 {
61 struct kmod_alias *alias;
62
63 DBG(ctx, "name=%s modname=%s\n", name, modname);
64
65 alias = malloc(sizeof(*alias));
66 alias->name = strdup(name);
67 alias->modname = strdup(modname);
68
69 return kmod_list_append(aliases, alias);
70 }
71
72 static struct kmod_list *free_alias(struct kmod_ctx *ctx, struct kmod_list *l)
73 {
74 struct kmod_alias *alias = l->data;
75
76 free(alias->modname);
77 free(alias->name);
78 free(alias);
79
80 return kmod_list_remove(l);
81 }
82
83 static struct kmod_list *add_blacklist(struct kmod_ctx *ctx,
84 struct kmod_list *blacklist,
85 const char *modname)
86 {
87 char *p;
88
89 DBG(ctx, "modname=%s\n", modname);
90
91 p = strdup(modname);
92
93 return kmod_list_append(blacklist, p);
94 }
95
96 static struct kmod_list *free_blacklist(struct kmod_ctx *ctx,
97 struct kmod_list *l)
98 {
99 free(l->data);
100 return kmod_list_remove(l);
101 }
102
103
104 int kmod_parse_config_file(struct kmod_ctx *ctx, const char *filename,
105 struct kmod_config *config)
106 {
107 char *line;
108 FILE *fp;
109 unsigned int linenum;
110
111 DBG(ctx, "%s\n", filename);
112
113 fp = fopen(filename, "r");
114 if (fp == NULL)
115 return errno;
116
117 while ((line = getline_wrapped(fp, &linenum)) != NULL) {
118 char *cmd, *saveptr;
119
120 if (line[0] == '\0' || line[0] == '#')
121 goto done_next;
122
123 cmd = strtok_r(line, "\t ", &saveptr);
124 if (cmd == NULL)
125 goto done_next;
126
127 if (!strcmp(cmd, "alias")) {
128 char *alias = strtok_r(NULL, "\t ", &saveptr);
129 char *modname = strtok_r(NULL, "\t ", &saveptr);
130
131 if (alias == NULL || modname == NULL)
132 goto syntax_error;
133
134 config->aliases = add_alias(ctx, config->aliases,
135 underscores(ctx, alias),
136 underscores(ctx, modname));
137 } else if (!strcmp(cmd, "blacklist")) {
138 char *modname = strtok_r(NULL, "\t ", &saveptr);
139
140 if (modname == NULL)
141 goto syntax_error;
142
143 config->blacklists = add_blacklist(ctx,
144 config->blacklists,
145 underscores(ctx, modname));
146 } else if (!strcmp(cmd, "include") || !strcmp(cmd, "options")
147 || !strcmp(cmd, "install")
148 || !strcmp(cmd, "remove")
149 || !strcmp(cmd, "softdep")
150 || !strcmp(cmd, "config")) {
151 INFO(ctx, "%s: command %s not implemented yet\n",
152 filename, cmd);
153 } else {
154 syntax_error:
155 ERR(ctx, "%s line %u: ignoring bad line starting with '%s'\n",
156 filename, linenum, cmd);
157 }
158
159 done_next:
160 free(line);
161 }
162
163 fclose(fp);
164
165 return 0;
166 }
167
168 void kmod_free_config(struct kmod_ctx *ctx, struct kmod_config *config)
169 {
170 while (config->aliases)
171 config->aliases = free_alias(ctx, config->aliases);
172
173 while (config->blacklists)
174 config->blacklists = free_blacklist(ctx, config->blacklists);
175 }
176
177 static bool conf_files_filter(struct kmod_ctx *ctx, const char *path,
178 const char *fn)
179 {
180 size_t len = strlen(fn);
181
182 if (fn[0] == '.')
183 return 1;
184
185 if (len < 6 || (strcmp(&fn[len - 5], ".conf") != 0
186 && strcmp(&fn[len - 6], ".alias"))) {
187 INFO(ctx, "All config files need .conf: %s/%s, "
188 "it will be ignored in a future release\n",
189 path, fn);
190 return 1;
191 }
192
193 return 0;
194 }
195
196 static int conf_files_list(struct kmod_ctx *ctx, struct kmod_list **list,
197 const char *path, size_t *n)
198 {
199 struct stat st;
200 DIR *d;
201 int err;
202
203 if (stat(path, &st) < 0)
204 return -ENOENT;
205
206 if (!S_ISDIR(st.st_mode)) {
207 *list = kmod_list_append(*list, (void *)path);
208 *n += 1;
209 return 0;
210 }
211
212 d = opendir(path);
213 if (d == NULL) {
214 err = errno;
215 ERR(ctx, "%m\n");
216 return -errno;
217 }
218
219 for (;;) {
220 struct dirent ent, *entp;
221 char *p;
222
223 err = readdir_r(d, &ent, &entp);
224 if (err != 0) {
225 err = -err;
226 goto finish;
227 }
228
229 if (entp == NULL)
230 break;
231
232 if (conf_files_filter(ctx, path, entp->d_name) == 1)
233 continue;
234
235 if (asprintf(&p, "%s/%s", path, entp->d_name) < 0) {
236 err = -ENOMEM;
237 goto finish;
238 }
239
240 DBG(ctx, "%s\n", p);
241
242 *list = kmod_list_append(*list, p);
243 *n += 1;
244 }
245
246 finish:
247 closedir(d);
248 return err;
249 }
250
251 static int base_cmp(const void *a, const void *b)
252 {
253 const char *s1, *s2;
254
255 s1 = *(char * const *)a;
256 s2 = *(char * const *)b;
257
258 return strcmp(basename(s1), basename(s2));
259 }
260
261 int kmod_parse_config(struct kmod_ctx *ctx, struct kmod_config *config)
262 {
263
264 size_t i, n = 0;
265 char **files = NULL;
266 int err = 0;
267 struct kmod_list *list = NULL, *l;
268
269 for (i = 0; i < ARRAY_SIZE(config_files); i++)
270 conf_files_list(ctx, &list, config_files[i], &n);
271
272 files = malloc(sizeof(char *) * n);
273 if (files == NULL) {
274 err = -ENOMEM;
275 goto finish;
276 }
277
278 i = 0;
279 kmod_list_foreach(l, list) {
280 files[i] = l->data;
281 i++;
282 }
283
284 qsort(files, n, sizeof(char *), base_cmp);
285
286 for (i = 0; i < n; i++)
287 kmod_parse_config_file(ctx, files[i], config);
288
289 finish:
290 free(files);
291
292 while (list) {
293 free(list->data);
294 list = kmod_list_remove(list);
295 }
296
297 return err;
298 }