xref: /aosp_15_r20/external/kmod/libkmod/libkmod-config.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker  * libkmod - interface to kernel module operations
3*cc4ad7daSAndroid Build Coastguard Worker  *
4*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2011-2013  ProFUSION embedded systems
5*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2013  Intel Corporation. All rights reserved.
6*cc4ad7daSAndroid Build Coastguard Worker  *
7*cc4ad7daSAndroid Build Coastguard Worker  * This library is free software; you can redistribute it and/or
8*cc4ad7daSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
9*cc4ad7daSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
10*cc4ad7daSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
11*cc4ad7daSAndroid Build Coastguard Worker  *
12*cc4ad7daSAndroid Build Coastguard Worker  * This library is distributed in the hope that it will be useful,
13*cc4ad7daSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*cc4ad7daSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*cc4ad7daSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
16*cc4ad7daSAndroid Build Coastguard Worker  *
17*cc4ad7daSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
18*cc4ad7daSAndroid Build Coastguard Worker  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19*cc4ad7daSAndroid Build Coastguard Worker  */
20*cc4ad7daSAndroid Build Coastguard Worker 
21*cc4ad7daSAndroid Build Coastguard Worker #include <ctype.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stddef.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
32*cc4ad7daSAndroid Build Coastguard Worker 
33*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
34*cc4ad7daSAndroid Build Coastguard Worker 
35*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod.h"
36*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod-internal.h"
37*cc4ad7daSAndroid Build Coastguard Worker 
38*cc4ad7daSAndroid Build Coastguard Worker struct kmod_alias {
39*cc4ad7daSAndroid Build Coastguard Worker 	char *name;
40*cc4ad7daSAndroid Build Coastguard Worker 	char modname[];
41*cc4ad7daSAndroid Build Coastguard Worker };
42*cc4ad7daSAndroid Build Coastguard Worker 
43*cc4ad7daSAndroid Build Coastguard Worker struct kmod_options {
44*cc4ad7daSAndroid Build Coastguard Worker 	char *options;
45*cc4ad7daSAndroid Build Coastguard Worker 	char modname[];
46*cc4ad7daSAndroid Build Coastguard Worker };
47*cc4ad7daSAndroid Build Coastguard Worker 
48*cc4ad7daSAndroid Build Coastguard Worker struct kmod_command {
49*cc4ad7daSAndroid Build Coastguard Worker 	char *command;
50*cc4ad7daSAndroid Build Coastguard Worker 	char modname[];
51*cc4ad7daSAndroid Build Coastguard Worker };
52*cc4ad7daSAndroid Build Coastguard Worker 
53*cc4ad7daSAndroid Build Coastguard Worker struct kmod_softdep {
54*cc4ad7daSAndroid Build Coastguard Worker 	char *name;
55*cc4ad7daSAndroid Build Coastguard Worker 	const char **pre;
56*cc4ad7daSAndroid Build Coastguard Worker 	const char **post;
57*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int n_pre;
58*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int n_post;
59*cc4ad7daSAndroid Build Coastguard Worker };
60*cc4ad7daSAndroid Build Coastguard Worker 
kmod_blacklist_get_modname(const struct kmod_list * l)61*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_blacklist_get_modname(const struct kmod_list *l)
62*cc4ad7daSAndroid Build Coastguard Worker {
63*cc4ad7daSAndroid Build Coastguard Worker 	return l->data;
64*cc4ad7daSAndroid Build Coastguard Worker }
65*cc4ad7daSAndroid Build Coastguard Worker 
kmod_alias_get_name(const struct kmod_list * l)66*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_alias_get_name(const struct kmod_list *l) {
67*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_alias *alias = l->data;
68*cc4ad7daSAndroid Build Coastguard Worker 	return alias->name;
69*cc4ad7daSAndroid Build Coastguard Worker }
70*cc4ad7daSAndroid Build Coastguard Worker 
kmod_alias_get_modname(const struct kmod_list * l)71*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_alias_get_modname(const struct kmod_list *l) {
72*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_alias *alias = l->data;
73*cc4ad7daSAndroid Build Coastguard Worker 	return alias->modname;
74*cc4ad7daSAndroid Build Coastguard Worker }
75*cc4ad7daSAndroid Build Coastguard Worker 
kmod_option_get_options(const struct kmod_list * l)76*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_option_get_options(const struct kmod_list *l) {
77*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_options *alias = l->data;
78*cc4ad7daSAndroid Build Coastguard Worker 	return alias->options;
79*cc4ad7daSAndroid Build Coastguard Worker }
80*cc4ad7daSAndroid Build Coastguard Worker 
kmod_option_get_modname(const struct kmod_list * l)81*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_option_get_modname(const struct kmod_list *l) {
82*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_options *alias = l->data;
83*cc4ad7daSAndroid Build Coastguard Worker 	return alias->modname;
84*cc4ad7daSAndroid Build Coastguard Worker }
85*cc4ad7daSAndroid Build Coastguard Worker 
kmod_command_get_command(const struct kmod_list * l)86*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_command_get_command(const struct kmod_list *l) {
87*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_command *alias = l->data;
88*cc4ad7daSAndroid Build Coastguard Worker 	return alias->command;
89*cc4ad7daSAndroid Build Coastguard Worker }
90*cc4ad7daSAndroid Build Coastguard Worker 
kmod_command_get_modname(const struct kmod_list * l)91*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_command_get_modname(const struct kmod_list *l) {
92*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_command *alias = l->data;
93*cc4ad7daSAndroid Build Coastguard Worker 	return alias->modname;
94*cc4ad7daSAndroid Build Coastguard Worker }
95*cc4ad7daSAndroid Build Coastguard Worker 
kmod_softdep_get_name(const struct kmod_list * l)96*cc4ad7daSAndroid Build Coastguard Worker const char *kmod_softdep_get_name(const struct kmod_list *l) {
97*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_softdep *dep = l->data;
98*cc4ad7daSAndroid Build Coastguard Worker 	return dep->name;
99*cc4ad7daSAndroid Build Coastguard Worker }
100*cc4ad7daSAndroid Build Coastguard Worker 
kmod_softdep_get_pre(const struct kmod_list * l,unsigned int * count)101*cc4ad7daSAndroid Build Coastguard Worker const char * const *kmod_softdep_get_pre(const struct kmod_list *l, unsigned int *count) {
102*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_softdep *dep = l->data;
103*cc4ad7daSAndroid Build Coastguard Worker 	*count = dep->n_pre;
104*cc4ad7daSAndroid Build Coastguard Worker 	return dep->pre;
105*cc4ad7daSAndroid Build Coastguard Worker }
106*cc4ad7daSAndroid Build Coastguard Worker 
kmod_softdep_get_post(const struct kmod_list * l,unsigned int * count)107*cc4ad7daSAndroid Build Coastguard Worker const char * const *kmod_softdep_get_post(const struct kmod_list *l, unsigned int *count) {
108*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_softdep *dep = l->data;
109*cc4ad7daSAndroid Build Coastguard Worker 	*count = dep->n_post;
110*cc4ad7daSAndroid Build Coastguard Worker 	return dep->post;
111*cc4ad7daSAndroid Build Coastguard Worker }
112*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_add_command(struct kmod_config * config,const char * modname,const char * command,const char * command_name,struct kmod_list ** list)113*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_add_command(struct kmod_config *config,
114*cc4ad7daSAndroid Build Coastguard Worker 						const char *modname,
115*cc4ad7daSAndroid Build Coastguard Worker 						const char *command,
116*cc4ad7daSAndroid Build Coastguard Worker 						const char *command_name,
117*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
118*cc4ad7daSAndroid Build Coastguard Worker {
119*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ struct kmod_command *cmd;
120*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l;
121*cc4ad7daSAndroid Build Coastguard Worker 	size_t modnamelen = strlen(modname) + 1;
122*cc4ad7daSAndroid Build Coastguard Worker 	size_t commandlen = strlen(command) + 1;
123*cc4ad7daSAndroid Build Coastguard Worker 
124*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "modname='%s' cmd='%s %s'\n", modname, command_name,
125*cc4ad7daSAndroid Build Coastguard Worker 								command);
126*cc4ad7daSAndroid Build Coastguard Worker 
127*cc4ad7daSAndroid Build Coastguard Worker 	cmd = malloc(sizeof(*cmd) + modnamelen + commandlen);
128*cc4ad7daSAndroid Build Coastguard Worker 	if (!cmd)
129*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
130*cc4ad7daSAndroid Build Coastguard Worker 
131*cc4ad7daSAndroid Build Coastguard Worker 	cmd->command = sizeof(*cmd) + modnamelen + (char *)cmd;
132*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(cmd->modname, modname, modnamelen);
133*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(cmd->command, command, commandlen);
134*cc4ad7daSAndroid Build Coastguard Worker 
135*cc4ad7daSAndroid Build Coastguard Worker 	l = kmod_list_append(*list, cmd);
136*cc4ad7daSAndroid Build Coastguard Worker 	if (!l)
137*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
138*cc4ad7daSAndroid Build Coastguard Worker 
139*cc4ad7daSAndroid Build Coastguard Worker 	*list = l;
140*cc4ad7daSAndroid Build Coastguard Worker 	cmd = NULL;
141*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
142*cc4ad7daSAndroid Build Coastguard Worker }
143*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_free_command(struct kmod_config * config,struct kmod_list * l,struct kmod_list ** list)144*cc4ad7daSAndroid Build Coastguard Worker static void kmod_config_free_command(struct kmod_config *config,
145*cc4ad7daSAndroid Build Coastguard Worker 					struct kmod_list *l,
146*cc4ad7daSAndroid Build Coastguard Worker 					struct kmod_list **list)
147*cc4ad7daSAndroid Build Coastguard Worker {
148*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_command *cmd = l->data;
149*cc4ad7daSAndroid Build Coastguard Worker 
150*cc4ad7daSAndroid Build Coastguard Worker 	free(cmd);
151*cc4ad7daSAndroid Build Coastguard Worker 	*list = kmod_list_remove(l);
152*cc4ad7daSAndroid Build Coastguard Worker }
153*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_add_options(struct kmod_config * config,const char * modname,const char * options)154*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_add_options(struct kmod_config *config,
155*cc4ad7daSAndroid Build Coastguard Worker 				const char *modname, const char *options)
156*cc4ad7daSAndroid Build Coastguard Worker {
157*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ struct kmod_options *opt;
158*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list;
159*cc4ad7daSAndroid Build Coastguard Worker 	size_t modnamelen = strlen(modname) + 1;
160*cc4ad7daSAndroid Build Coastguard Worker 	size_t optionslen = strlen(options) + 1;
161*cc4ad7daSAndroid Build Coastguard Worker 
162*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "modname='%s' options='%s'\n", modname, options);
163*cc4ad7daSAndroid Build Coastguard Worker 
164*cc4ad7daSAndroid Build Coastguard Worker 	opt = malloc(sizeof(*opt) + modnamelen + optionslen);
165*cc4ad7daSAndroid Build Coastguard Worker 	if (!opt)
166*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
167*cc4ad7daSAndroid Build Coastguard Worker 
168*cc4ad7daSAndroid Build Coastguard Worker 	opt->options = sizeof(*opt) + modnamelen + (char *)opt;
169*cc4ad7daSAndroid Build Coastguard Worker 
170*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(opt->modname, modname, modnamelen);
171*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(opt->options, options, optionslen);
172*cc4ad7daSAndroid Build Coastguard Worker 	strchr_replace(opt->options, '\t', ' ');
173*cc4ad7daSAndroid Build Coastguard Worker 
174*cc4ad7daSAndroid Build Coastguard Worker 	list = kmod_list_append(config->options, opt);
175*cc4ad7daSAndroid Build Coastguard Worker 	if (!list)
176*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
177*cc4ad7daSAndroid Build Coastguard Worker 
178*cc4ad7daSAndroid Build Coastguard Worker 	opt = NULL;
179*cc4ad7daSAndroid Build Coastguard Worker 	config->options = list;
180*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
181*cc4ad7daSAndroid Build Coastguard Worker }
182*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_free_options(struct kmod_config * config,struct kmod_list * l)183*cc4ad7daSAndroid Build Coastguard Worker static void kmod_config_free_options(struct kmod_config *config,
184*cc4ad7daSAndroid Build Coastguard Worker 							struct kmod_list *l)
185*cc4ad7daSAndroid Build Coastguard Worker {
186*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_options *opt = l->data;
187*cc4ad7daSAndroid Build Coastguard Worker 
188*cc4ad7daSAndroid Build Coastguard Worker 	free(opt);
189*cc4ad7daSAndroid Build Coastguard Worker 
190*cc4ad7daSAndroid Build Coastguard Worker 	config->options = kmod_list_remove(l);
191*cc4ad7daSAndroid Build Coastguard Worker }
192*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_add_alias(struct kmod_config * config,const char * name,const char * modname)193*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_add_alias(struct kmod_config *config,
194*cc4ad7daSAndroid Build Coastguard Worker 					const char *name, const char *modname)
195*cc4ad7daSAndroid Build Coastguard Worker {
196*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ struct kmod_alias *alias;
197*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list;
198*cc4ad7daSAndroid Build Coastguard Worker 	size_t namelen = strlen(name) + 1, modnamelen = strlen(modname) + 1;
199*cc4ad7daSAndroid Build Coastguard Worker 
200*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "name=%s modname=%s\n", name, modname);
201*cc4ad7daSAndroid Build Coastguard Worker 
202*cc4ad7daSAndroid Build Coastguard Worker 	alias = malloc(sizeof(*alias) + namelen + modnamelen);
203*cc4ad7daSAndroid Build Coastguard Worker 	if (!alias)
204*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
205*cc4ad7daSAndroid Build Coastguard Worker 
206*cc4ad7daSAndroid Build Coastguard Worker 	alias->name = sizeof(*alias) + modnamelen + (char *)alias;
207*cc4ad7daSAndroid Build Coastguard Worker 
208*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(alias->modname, modname, modnamelen);
209*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(alias->name, name, namelen);
210*cc4ad7daSAndroid Build Coastguard Worker 
211*cc4ad7daSAndroid Build Coastguard Worker 	list = kmod_list_append(config->aliases, alias);
212*cc4ad7daSAndroid Build Coastguard Worker 	if (!list)
213*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
214*cc4ad7daSAndroid Build Coastguard Worker 
215*cc4ad7daSAndroid Build Coastguard Worker 	alias = NULL;
216*cc4ad7daSAndroid Build Coastguard Worker 	config->aliases = list;
217*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
218*cc4ad7daSAndroid Build Coastguard Worker }
219*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_free_alias(struct kmod_config * config,struct kmod_list * l)220*cc4ad7daSAndroid Build Coastguard Worker static void kmod_config_free_alias(struct kmod_config *config,
221*cc4ad7daSAndroid Build Coastguard Worker 							struct kmod_list *l)
222*cc4ad7daSAndroid Build Coastguard Worker {
223*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_alias *alias = l->data;
224*cc4ad7daSAndroid Build Coastguard Worker 
225*cc4ad7daSAndroid Build Coastguard Worker 	free(alias);
226*cc4ad7daSAndroid Build Coastguard Worker 
227*cc4ad7daSAndroid Build Coastguard Worker 	config->aliases = kmod_list_remove(l);
228*cc4ad7daSAndroid Build Coastguard Worker }
229*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_add_blacklist(struct kmod_config * config,const char * modname)230*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_add_blacklist(struct kmod_config *config,
231*cc4ad7daSAndroid Build Coastguard Worker 							const char *modname)
232*cc4ad7daSAndroid Build Coastguard Worker {
233*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ char *p;
234*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list;
235*cc4ad7daSAndroid Build Coastguard Worker 
236*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "modname=%s\n", modname);
237*cc4ad7daSAndroid Build Coastguard Worker 
238*cc4ad7daSAndroid Build Coastguard Worker 	p = strdup(modname);
239*cc4ad7daSAndroid Build Coastguard Worker 	if (!p)
240*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
241*cc4ad7daSAndroid Build Coastguard Worker 
242*cc4ad7daSAndroid Build Coastguard Worker 	list = kmod_list_append(config->blacklists, p);
243*cc4ad7daSAndroid Build Coastguard Worker 	if (!list)
244*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
245*cc4ad7daSAndroid Build Coastguard Worker 
246*cc4ad7daSAndroid Build Coastguard Worker 	p = NULL;
247*cc4ad7daSAndroid Build Coastguard Worker 	config->blacklists = list;
248*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
249*cc4ad7daSAndroid Build Coastguard Worker }
250*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_free_blacklist(struct kmod_config * config,struct kmod_list * l)251*cc4ad7daSAndroid Build Coastguard Worker static void kmod_config_free_blacklist(struct kmod_config *config,
252*cc4ad7daSAndroid Build Coastguard Worker 							struct kmod_list *l)
253*cc4ad7daSAndroid Build Coastguard Worker {
254*cc4ad7daSAndroid Build Coastguard Worker 	free(l->data);
255*cc4ad7daSAndroid Build Coastguard Worker 	config->blacklists = kmod_list_remove(l);
256*cc4ad7daSAndroid Build Coastguard Worker }
257*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_add_softdep(struct kmod_config * config,const char * modname,const char * line)258*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_add_softdep(struct kmod_config *config,
259*cc4ad7daSAndroid Build Coastguard Worker 							const char *modname,
260*cc4ad7daSAndroid Build Coastguard Worker 							const char *line)
261*cc4ad7daSAndroid Build Coastguard Worker {
262*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list;
263*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_softdep *dep;
264*cc4ad7daSAndroid Build Coastguard Worker 	const char *s, *p;
265*cc4ad7daSAndroid Build Coastguard Worker 	char *itr;
266*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int n_pre = 0, n_post = 0;
267*cc4ad7daSAndroid Build Coastguard Worker 	size_t modnamelen = strlen(modname) + 1;
268*cc4ad7daSAndroid Build Coastguard Worker 	size_t buflen = 0;
269*cc4ad7daSAndroid Build Coastguard Worker 	bool was_space = false;
270*cc4ad7daSAndroid Build Coastguard Worker 	enum { S_NONE, S_PRE, S_POST } mode = S_NONE;
271*cc4ad7daSAndroid Build Coastguard Worker 
272*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "modname=%s\n", modname);
273*cc4ad7daSAndroid Build Coastguard Worker 
274*cc4ad7daSAndroid Build Coastguard Worker 	/* analyze and count */
275*cc4ad7daSAndroid Build Coastguard Worker 	for (p = s = line; ; s++) {
276*cc4ad7daSAndroid Build Coastguard Worker 		size_t plen;
277*cc4ad7daSAndroid Build Coastguard Worker 
278*cc4ad7daSAndroid Build Coastguard Worker 		if (*s != '\0') {
279*cc4ad7daSAndroid Build Coastguard Worker 			if (!isspace(*s)) {
280*cc4ad7daSAndroid Build Coastguard Worker 				was_space = false;
281*cc4ad7daSAndroid Build Coastguard Worker 				continue;
282*cc4ad7daSAndroid Build Coastguard Worker 			}
283*cc4ad7daSAndroid Build Coastguard Worker 
284*cc4ad7daSAndroid Build Coastguard Worker 			if (was_space) {
285*cc4ad7daSAndroid Build Coastguard Worker 				p = s + 1;
286*cc4ad7daSAndroid Build Coastguard Worker 				continue;
287*cc4ad7daSAndroid Build Coastguard Worker 			}
288*cc4ad7daSAndroid Build Coastguard Worker 			was_space = true;
289*cc4ad7daSAndroid Build Coastguard Worker 
290*cc4ad7daSAndroid Build Coastguard Worker 			if (p >= s)
291*cc4ad7daSAndroid Build Coastguard Worker 				continue;
292*cc4ad7daSAndroid Build Coastguard Worker 		}
293*cc4ad7daSAndroid Build Coastguard Worker 		plen = s - p;
294*cc4ad7daSAndroid Build Coastguard Worker 
295*cc4ad7daSAndroid Build Coastguard Worker 		if (plen == sizeof("pre:") - 1 &&
296*cc4ad7daSAndroid Build Coastguard Worker 				memcmp(p, "pre:", sizeof("pre:") - 1) == 0)
297*cc4ad7daSAndroid Build Coastguard Worker 			mode = S_PRE;
298*cc4ad7daSAndroid Build Coastguard Worker 		else if (plen == sizeof("post:") - 1 &&
299*cc4ad7daSAndroid Build Coastguard Worker 				memcmp(p, "post:", sizeof("post:") - 1) == 0)
300*cc4ad7daSAndroid Build Coastguard Worker 			mode = S_POST;
301*cc4ad7daSAndroid Build Coastguard Worker 		else if (*s != '\0' || (*s == '\0' && !was_space)) {
302*cc4ad7daSAndroid Build Coastguard Worker 			if (mode == S_PRE) {
303*cc4ad7daSAndroid Build Coastguard Worker 				buflen += plen + 1;
304*cc4ad7daSAndroid Build Coastguard Worker 				n_pre++;
305*cc4ad7daSAndroid Build Coastguard Worker 			} else if (mode == S_POST) {
306*cc4ad7daSAndroid Build Coastguard Worker 				buflen += plen + 1;
307*cc4ad7daSAndroid Build Coastguard Worker 				n_post++;
308*cc4ad7daSAndroid Build Coastguard Worker 			}
309*cc4ad7daSAndroid Build Coastguard Worker 		}
310*cc4ad7daSAndroid Build Coastguard Worker 		p = s + 1;
311*cc4ad7daSAndroid Build Coastguard Worker 		if (*s == '\0')
312*cc4ad7daSAndroid Build Coastguard Worker 			break;
313*cc4ad7daSAndroid Build Coastguard Worker 	}
314*cc4ad7daSAndroid Build Coastguard Worker 
315*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "%u pre, %u post\n", n_pre, n_post);
316*cc4ad7daSAndroid Build Coastguard Worker 
317*cc4ad7daSAndroid Build Coastguard Worker 	dep = malloc(sizeof(struct kmod_softdep) + modnamelen +
318*cc4ad7daSAndroid Build Coastguard Worker 		     n_pre * sizeof(const char *) +
319*cc4ad7daSAndroid Build Coastguard Worker 		     n_post * sizeof(const char *) +
320*cc4ad7daSAndroid Build Coastguard Worker 		     buflen);
321*cc4ad7daSAndroid Build Coastguard Worker 	if (dep == NULL) {
322*cc4ad7daSAndroid Build Coastguard Worker 		ERR(config->ctx, "out-of-memory modname=%s\n", modname);
323*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
324*cc4ad7daSAndroid Build Coastguard Worker 	}
325*cc4ad7daSAndroid Build Coastguard Worker 	dep->n_pre = n_pre;
326*cc4ad7daSAndroid Build Coastguard Worker 	dep->n_post = n_post;
327*cc4ad7daSAndroid Build Coastguard Worker 	dep->pre = (const char **)((char *)dep + sizeof(struct kmod_softdep));
328*cc4ad7daSAndroid Build Coastguard Worker 	dep->post = dep->pre + n_pre;
329*cc4ad7daSAndroid Build Coastguard Worker 	dep->name = (char *)(dep->post + n_post);
330*cc4ad7daSAndroid Build Coastguard Worker 
331*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(dep->name, modname, modnamelen);
332*cc4ad7daSAndroid Build Coastguard Worker 
333*cc4ad7daSAndroid Build Coastguard Worker 	/* copy strings */
334*cc4ad7daSAndroid Build Coastguard Worker 	itr = dep->name + modnamelen;
335*cc4ad7daSAndroid Build Coastguard Worker 	n_pre = 0;
336*cc4ad7daSAndroid Build Coastguard Worker 	n_post = 0;
337*cc4ad7daSAndroid Build Coastguard Worker 	mode = S_NONE;
338*cc4ad7daSAndroid Build Coastguard Worker 	was_space = false;
339*cc4ad7daSAndroid Build Coastguard Worker 	for (p = s = line; ; s++) {
340*cc4ad7daSAndroid Build Coastguard Worker 		size_t plen;
341*cc4ad7daSAndroid Build Coastguard Worker 
342*cc4ad7daSAndroid Build Coastguard Worker 		if (*s != '\0') {
343*cc4ad7daSAndroid Build Coastguard Worker 			if (!isspace(*s)) {
344*cc4ad7daSAndroid Build Coastguard Worker 				was_space = false;
345*cc4ad7daSAndroid Build Coastguard Worker 				continue;
346*cc4ad7daSAndroid Build Coastguard Worker 			}
347*cc4ad7daSAndroid Build Coastguard Worker 
348*cc4ad7daSAndroid Build Coastguard Worker 			if (was_space) {
349*cc4ad7daSAndroid Build Coastguard Worker 				p = s + 1;
350*cc4ad7daSAndroid Build Coastguard Worker 				continue;
351*cc4ad7daSAndroid Build Coastguard Worker 			}
352*cc4ad7daSAndroid Build Coastguard Worker 			was_space = true;
353*cc4ad7daSAndroid Build Coastguard Worker 
354*cc4ad7daSAndroid Build Coastguard Worker 			if (p >= s)
355*cc4ad7daSAndroid Build Coastguard Worker 				continue;
356*cc4ad7daSAndroid Build Coastguard Worker 		}
357*cc4ad7daSAndroid Build Coastguard Worker 		plen = s - p;
358*cc4ad7daSAndroid Build Coastguard Worker 
359*cc4ad7daSAndroid Build Coastguard Worker 		if (plen == sizeof("pre:") - 1 &&
360*cc4ad7daSAndroid Build Coastguard Worker 				memcmp(p, "pre:", sizeof("pre:") - 1) == 0)
361*cc4ad7daSAndroid Build Coastguard Worker 			mode = S_PRE;
362*cc4ad7daSAndroid Build Coastguard Worker 		else if (plen == sizeof("post:") - 1 &&
363*cc4ad7daSAndroid Build Coastguard Worker 				memcmp(p, "post:", sizeof("post:") - 1) == 0)
364*cc4ad7daSAndroid Build Coastguard Worker 			mode = S_POST;
365*cc4ad7daSAndroid Build Coastguard Worker 		else if (*s != '\0' || (*s == '\0' && !was_space)) {
366*cc4ad7daSAndroid Build Coastguard Worker 			if (mode == S_PRE) {
367*cc4ad7daSAndroid Build Coastguard Worker 				dep->pre[n_pre] = itr;
368*cc4ad7daSAndroid Build Coastguard Worker 				memcpy(itr, p, plen);
369*cc4ad7daSAndroid Build Coastguard Worker 				itr[plen] = '\0';
370*cc4ad7daSAndroid Build Coastguard Worker 				itr += plen + 1;
371*cc4ad7daSAndroid Build Coastguard Worker 				n_pre++;
372*cc4ad7daSAndroid Build Coastguard Worker 			} else if (mode == S_POST) {
373*cc4ad7daSAndroid Build Coastguard Worker 				dep->post[n_post] = itr;
374*cc4ad7daSAndroid Build Coastguard Worker 				memcpy(itr, p, plen);
375*cc4ad7daSAndroid Build Coastguard Worker 				itr[plen] = '\0';
376*cc4ad7daSAndroid Build Coastguard Worker 				itr += plen + 1;
377*cc4ad7daSAndroid Build Coastguard Worker 				n_post++;
378*cc4ad7daSAndroid Build Coastguard Worker 			}
379*cc4ad7daSAndroid Build Coastguard Worker 		}
380*cc4ad7daSAndroid Build Coastguard Worker 		p = s + 1;
381*cc4ad7daSAndroid Build Coastguard Worker 		if (*s == '\0')
382*cc4ad7daSAndroid Build Coastguard Worker 			break;
383*cc4ad7daSAndroid Build Coastguard Worker 	}
384*cc4ad7daSAndroid Build Coastguard Worker 
385*cc4ad7daSAndroid Build Coastguard Worker 	list = kmod_list_append(config->softdeps, dep);
386*cc4ad7daSAndroid Build Coastguard Worker 	if (list == NULL) {
387*cc4ad7daSAndroid Build Coastguard Worker 		free(dep);
388*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
389*cc4ad7daSAndroid Build Coastguard Worker 	}
390*cc4ad7daSAndroid Build Coastguard Worker 	config->softdeps = list;
391*cc4ad7daSAndroid Build Coastguard Worker 
392*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
393*cc4ad7daSAndroid Build Coastguard Worker }
394*cc4ad7daSAndroid Build Coastguard Worker 
softdep_to_char(struct kmod_softdep * dep)395*cc4ad7daSAndroid Build Coastguard Worker static char *softdep_to_char(struct kmod_softdep *dep) {
396*cc4ad7daSAndroid Build Coastguard Worker 	const size_t sz_preprefix = sizeof("pre: ") - 1;
397*cc4ad7daSAndroid Build Coastguard Worker 	const size_t sz_postprefix = sizeof("post: ") - 1;
398*cc4ad7daSAndroid Build Coastguard Worker 	size_t sz = 1; /* at least '\0' */
399*cc4ad7daSAndroid Build Coastguard Worker 	size_t sz_pre, sz_post;
400*cc4ad7daSAndroid Build Coastguard Worker 	const char *start, *end;
401*cc4ad7daSAndroid Build Coastguard Worker 	char *s, *itr;
402*cc4ad7daSAndroid Build Coastguard Worker 
403*cc4ad7daSAndroid Build Coastguard Worker 	/*
404*cc4ad7daSAndroid Build Coastguard Worker 	 * Rely on the fact that dep->pre[] and dep->post[] are strv's that
405*cc4ad7daSAndroid Build Coastguard Worker 	 * point to a contiguous buffer
406*cc4ad7daSAndroid Build Coastguard Worker 	 */
407*cc4ad7daSAndroid Build Coastguard Worker 	if (dep->n_pre > 0) {
408*cc4ad7daSAndroid Build Coastguard Worker 		start = dep->pre[0];
409*cc4ad7daSAndroid Build Coastguard Worker 		end = dep->pre[dep->n_pre - 1]
410*cc4ad7daSAndroid Build Coastguard Worker 					+ strlen(dep->pre[dep->n_pre - 1]);
411*cc4ad7daSAndroid Build Coastguard Worker 		sz_pre = end - start;
412*cc4ad7daSAndroid Build Coastguard Worker 		sz += sz_pre + sz_preprefix;
413*cc4ad7daSAndroid Build Coastguard Worker 	} else
414*cc4ad7daSAndroid Build Coastguard Worker 		sz_pre = 0;
415*cc4ad7daSAndroid Build Coastguard Worker 
416*cc4ad7daSAndroid Build Coastguard Worker 	if (dep->n_post > 0) {
417*cc4ad7daSAndroid Build Coastguard Worker 		start = dep->post[0];
418*cc4ad7daSAndroid Build Coastguard Worker 		end = dep->post[dep->n_post - 1]
419*cc4ad7daSAndroid Build Coastguard Worker 					+ strlen(dep->post[dep->n_post - 1]);
420*cc4ad7daSAndroid Build Coastguard Worker 		sz_post = end - start;
421*cc4ad7daSAndroid Build Coastguard Worker 		sz += sz_post + sz_postprefix;
422*cc4ad7daSAndroid Build Coastguard Worker 	} else
423*cc4ad7daSAndroid Build Coastguard Worker 		sz_post = 0;
424*cc4ad7daSAndroid Build Coastguard Worker 
425*cc4ad7daSAndroid Build Coastguard Worker 	itr = s = malloc(sz);
426*cc4ad7daSAndroid Build Coastguard Worker 	if (s == NULL)
427*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
428*cc4ad7daSAndroid Build Coastguard Worker 
429*cc4ad7daSAndroid Build Coastguard Worker 	if (sz_pre) {
430*cc4ad7daSAndroid Build Coastguard Worker 		char *p;
431*cc4ad7daSAndroid Build Coastguard Worker 
432*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(itr, "pre: ", sz_preprefix);
433*cc4ad7daSAndroid Build Coastguard Worker 		itr += sz_preprefix;
434*cc4ad7daSAndroid Build Coastguard Worker 
435*cc4ad7daSAndroid Build Coastguard Worker 		/* include last '\0' */
436*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(itr, dep->pre[0], sz_pre + 1);
437*cc4ad7daSAndroid Build Coastguard Worker 		for (p = itr; p < itr + sz_pre; p++) {
438*cc4ad7daSAndroid Build Coastguard Worker 			if (*p == '\0')
439*cc4ad7daSAndroid Build Coastguard Worker 				*p = ' ';
440*cc4ad7daSAndroid Build Coastguard Worker 		}
441*cc4ad7daSAndroid Build Coastguard Worker 		itr = p;
442*cc4ad7daSAndroid Build Coastguard Worker 	}
443*cc4ad7daSAndroid Build Coastguard Worker 
444*cc4ad7daSAndroid Build Coastguard Worker 	if (sz_post) {
445*cc4ad7daSAndroid Build Coastguard Worker 		char *p;
446*cc4ad7daSAndroid Build Coastguard Worker 
447*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(itr, "post: ", sz_postprefix);
448*cc4ad7daSAndroid Build Coastguard Worker 		itr += sz_postprefix;
449*cc4ad7daSAndroid Build Coastguard Worker 
450*cc4ad7daSAndroid Build Coastguard Worker 		/* include last '\0' */
451*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(itr, dep->post[0], sz_post + 1);
452*cc4ad7daSAndroid Build Coastguard Worker 		for (p = itr; p < itr + sz_post; p++) {
453*cc4ad7daSAndroid Build Coastguard Worker 			if (*p == '\0')
454*cc4ad7daSAndroid Build Coastguard Worker 				*p = ' ';
455*cc4ad7daSAndroid Build Coastguard Worker 		}
456*cc4ad7daSAndroid Build Coastguard Worker 		itr = p;
457*cc4ad7daSAndroid Build Coastguard Worker 	}
458*cc4ad7daSAndroid Build Coastguard Worker 
459*cc4ad7daSAndroid Build Coastguard Worker 	*itr = '\0';
460*cc4ad7daSAndroid Build Coastguard Worker 
461*cc4ad7daSAndroid Build Coastguard Worker 	return s;
462*cc4ad7daSAndroid Build Coastguard Worker }
463*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_free_softdep(struct kmod_config * config,struct kmod_list * l)464*cc4ad7daSAndroid Build Coastguard Worker static void kmod_config_free_softdep(struct kmod_config *config,
465*cc4ad7daSAndroid Build Coastguard Worker 							struct kmod_list *l)
466*cc4ad7daSAndroid Build Coastguard Worker {
467*cc4ad7daSAndroid Build Coastguard Worker 	free(l->data);
468*cc4ad7daSAndroid Build Coastguard Worker 	config->softdeps = kmod_list_remove(l);
469*cc4ad7daSAndroid Build Coastguard Worker }
470*cc4ad7daSAndroid Build Coastguard Worker 
kcmdline_parse_result(struct kmod_config * config,char * modname,char * param,char * value)471*cc4ad7daSAndroid Build Coastguard Worker static void kcmdline_parse_result(struct kmod_config *config, char *modname,
472*cc4ad7daSAndroid Build Coastguard Worker 						char *param, char *value)
473*cc4ad7daSAndroid Build Coastguard Worker {
474*cc4ad7daSAndroid Build Coastguard Worker 	if (modname == NULL || param == NULL)
475*cc4ad7daSAndroid Build Coastguard Worker 		return;
476*cc4ad7daSAndroid Build Coastguard Worker 
477*cc4ad7daSAndroid Build Coastguard Worker 	DBG(config->ctx, "%s %s\n", modname, param);
478*cc4ad7daSAndroid Build Coastguard Worker 
479*cc4ad7daSAndroid Build Coastguard Worker 	if (streq(modname, "modprobe") && !strncmp(param, "blacklist=", 10)) {
480*cc4ad7daSAndroid Build Coastguard Worker 		for (;;) {
481*cc4ad7daSAndroid Build Coastguard Worker 			char *t = strsep(&value, ",");
482*cc4ad7daSAndroid Build Coastguard Worker 			if (t == NULL)
483*cc4ad7daSAndroid Build Coastguard Worker 				break;
484*cc4ad7daSAndroid Build Coastguard Worker 
485*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_blacklist(config, t);
486*cc4ad7daSAndroid Build Coastguard Worker 		}
487*cc4ad7daSAndroid Build Coastguard Worker 	} else {
488*cc4ad7daSAndroid Build Coastguard Worker 		if (underscores(modname) < 0) {
489*cc4ad7daSAndroid Build Coastguard Worker 			ERR(config->ctx, "Ignoring bad option on kernel command line while parsing module name: '%s'\n",
490*cc4ad7daSAndroid Build Coastguard Worker 			    modname);
491*cc4ad7daSAndroid Build Coastguard Worker 		} else {
492*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_options(config, modname, param);
493*cc4ad7daSAndroid Build Coastguard Worker 		}
494*cc4ad7daSAndroid Build Coastguard Worker 	}
495*cc4ad7daSAndroid Build Coastguard Worker }
496*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_parse_kcmdline(struct kmod_config * config)497*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_parse_kcmdline(struct kmod_config *config)
498*cc4ad7daSAndroid Build Coastguard Worker {
499*cc4ad7daSAndroid Build Coastguard Worker 	char buf[KCMD_LINE_SIZE];
500*cc4ad7daSAndroid Build Coastguard Worker 	int fd, err;
501*cc4ad7daSAndroid Build Coastguard Worker 	char *p, *p_quote_start, *modname,  *param = NULL, *value = NULL;
502*cc4ad7daSAndroid Build Coastguard Worker 	bool is_quoted = false, iter = true;
503*cc4ad7daSAndroid Build Coastguard Worker 	enum state {
504*cc4ad7daSAndroid Build Coastguard Worker 		STATE_IGNORE,
505*cc4ad7daSAndroid Build Coastguard Worker 		STATE_MODNAME,
506*cc4ad7daSAndroid Build Coastguard Worker 		STATE_PARAM,
507*cc4ad7daSAndroid Build Coastguard Worker 		STATE_VALUE,
508*cc4ad7daSAndroid Build Coastguard Worker 		STATE_COMPLETE,
509*cc4ad7daSAndroid Build Coastguard Worker 	} state;
510*cc4ad7daSAndroid Build Coastguard Worker 
511*cc4ad7daSAndroid Build Coastguard Worker 	fd = open("/proc/cmdline", O_RDONLY|O_CLOEXEC);
512*cc4ad7daSAndroid Build Coastguard Worker 	if (fd < 0) {
513*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
514*cc4ad7daSAndroid Build Coastguard Worker 		DBG(config->ctx, "could not open '/proc/cmdline' for reading: %m\n");
515*cc4ad7daSAndroid Build Coastguard Worker 		return err;
516*cc4ad7daSAndroid Build Coastguard Worker 	}
517*cc4ad7daSAndroid Build Coastguard Worker 
518*cc4ad7daSAndroid Build Coastguard Worker 	err = read_str_safe(fd, buf, sizeof(buf));
519*cc4ad7daSAndroid Build Coastguard Worker 	close(fd);
520*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
521*cc4ad7daSAndroid Build Coastguard Worker 		ERR(config->ctx, "could not read from '/proc/cmdline': %s\n",
522*cc4ad7daSAndroid Build Coastguard Worker 							strerror(-err));
523*cc4ad7daSAndroid Build Coastguard Worker 		return err;
524*cc4ad7daSAndroid Build Coastguard Worker 	}
525*cc4ad7daSAndroid Build Coastguard Worker 
526*cc4ad7daSAndroid Build Coastguard Worker 	state = STATE_MODNAME;
527*cc4ad7daSAndroid Build Coastguard Worker 	p_quote_start = NULL;
528*cc4ad7daSAndroid Build Coastguard Worker 	for (p = buf, modname = buf; iter; p++) {
529*cc4ad7daSAndroid Build Coastguard Worker 		switch (*p) {
530*cc4ad7daSAndroid Build Coastguard Worker 		case '"':
531*cc4ad7daSAndroid Build Coastguard Worker 			is_quoted = !is_quoted;
532*cc4ad7daSAndroid Build Coastguard Worker 
533*cc4ad7daSAndroid Build Coastguard Worker 			/*
534*cc4ad7daSAndroid Build Coastguard Worker 			 * only allow starting quote as first char when looking
535*cc4ad7daSAndroid Build Coastguard Worker 			 * for a modname: anything else is considered ill-formed
536*cc4ad7daSAndroid Build Coastguard Worker 			 */
537*cc4ad7daSAndroid Build Coastguard Worker 			if (is_quoted && state == STATE_MODNAME && p == modname) {
538*cc4ad7daSAndroid Build Coastguard Worker 				p_quote_start = p;
539*cc4ad7daSAndroid Build Coastguard Worker 				modname = p + 1;
540*cc4ad7daSAndroid Build Coastguard Worker 			} else if (state != STATE_VALUE) {
541*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_IGNORE;
542*cc4ad7daSAndroid Build Coastguard Worker 			}
543*cc4ad7daSAndroid Build Coastguard Worker 
544*cc4ad7daSAndroid Build Coastguard Worker 			break;
545*cc4ad7daSAndroid Build Coastguard Worker 		case '\0':
546*cc4ad7daSAndroid Build Coastguard Worker 			iter = false;
547*cc4ad7daSAndroid Build Coastguard Worker 			/* fall-through */
548*cc4ad7daSAndroid Build Coastguard Worker 		case ' ':
549*cc4ad7daSAndroid Build Coastguard Worker 		case '\n':
550*cc4ad7daSAndroid Build Coastguard Worker 		case '\t':
551*cc4ad7daSAndroid Build Coastguard Worker 		case '\v':
552*cc4ad7daSAndroid Build Coastguard Worker 		case '\f':
553*cc4ad7daSAndroid Build Coastguard Worker 		case '\r':
554*cc4ad7daSAndroid Build Coastguard Worker 			if (is_quoted && state == STATE_VALUE) {
555*cc4ad7daSAndroid Build Coastguard Worker 				/* no state change*/;
556*cc4ad7daSAndroid Build Coastguard Worker 			} else if (is_quoted) {
557*cc4ad7daSAndroid Build Coastguard Worker 				/* spaces are only allowed in the value part */
558*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_IGNORE;
559*cc4ad7daSAndroid Build Coastguard Worker 			} else if (state == STATE_VALUE || state == STATE_PARAM) {
560*cc4ad7daSAndroid Build Coastguard Worker 				*p = '\0';
561*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_COMPLETE;
562*cc4ad7daSAndroid Build Coastguard Worker 			} else {
563*cc4ad7daSAndroid Build Coastguard Worker 				/*
564*cc4ad7daSAndroid Build Coastguard Worker 				 * go to next option, ignoring any possible
565*cc4ad7daSAndroid Build Coastguard Worker 				 * partial match we have
566*cc4ad7daSAndroid Build Coastguard Worker 				 */
567*cc4ad7daSAndroid Build Coastguard Worker 				modname = p + 1;
568*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_MODNAME;
569*cc4ad7daSAndroid Build Coastguard Worker 				p_quote_start = NULL;
570*cc4ad7daSAndroid Build Coastguard Worker 			}
571*cc4ad7daSAndroid Build Coastguard Worker 			break;
572*cc4ad7daSAndroid Build Coastguard Worker 		case '.':
573*cc4ad7daSAndroid Build Coastguard Worker 			if (state == STATE_MODNAME) {
574*cc4ad7daSAndroid Build Coastguard Worker 				*p = '\0';
575*cc4ad7daSAndroid Build Coastguard Worker 				param = p + 1;
576*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_PARAM;
577*cc4ad7daSAndroid Build Coastguard Worker 			} else if (state == STATE_PARAM) {
578*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_IGNORE;
579*cc4ad7daSAndroid Build Coastguard Worker 			}
580*cc4ad7daSAndroid Build Coastguard Worker 			break;
581*cc4ad7daSAndroid Build Coastguard Worker 		case '=':
582*cc4ad7daSAndroid Build Coastguard Worker 			if (state == STATE_PARAM) {
583*cc4ad7daSAndroid Build Coastguard Worker 				/*
584*cc4ad7daSAndroid Build Coastguard Worker 				 * Don't set *p to '\0': the value var shadows
585*cc4ad7daSAndroid Build Coastguard Worker 				 * param
586*cc4ad7daSAndroid Build Coastguard Worker 				 */
587*cc4ad7daSAndroid Build Coastguard Worker 				value = p + 1;
588*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_VALUE;
589*cc4ad7daSAndroid Build Coastguard Worker 			} else if (state == STATE_MODNAME) {
590*cc4ad7daSAndroid Build Coastguard Worker 				state = STATE_IGNORE;
591*cc4ad7daSAndroid Build Coastguard Worker 			}
592*cc4ad7daSAndroid Build Coastguard Worker 			break;
593*cc4ad7daSAndroid Build Coastguard Worker 		}
594*cc4ad7daSAndroid Build Coastguard Worker 
595*cc4ad7daSAndroid Build Coastguard Worker 		if (state == STATE_COMPLETE) {
596*cc4ad7daSAndroid Build Coastguard Worker 			/*
597*cc4ad7daSAndroid Build Coastguard Worker 			 * We may need to re-quote to unmangle what the
598*cc4ad7daSAndroid Build Coastguard Worker 			 * bootloader passed. Example: grub passes the option as
599*cc4ad7daSAndroid Build Coastguard Worker 			 * "parport.dyndbg=file drivers/parport/ieee1284_ops.c +mpf"
600*cc4ad7daSAndroid Build Coastguard Worker 			 * instead of
601*cc4ad7daSAndroid Build Coastguard Worker 			 * parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf"
602*cc4ad7daSAndroid Build Coastguard Worker 			 */
603*cc4ad7daSAndroid Build Coastguard Worker 			if (p_quote_start && p_quote_start < modname) {
604*cc4ad7daSAndroid Build Coastguard Worker 				/*
605*cc4ad7daSAndroid Build Coastguard Worker 				 * p_quote_start
606*cc4ad7daSAndroid Build Coastguard Worker 				 * |
607*cc4ad7daSAndroid Build Coastguard Worker 				 * |modname  param  value
608*cc4ad7daSAndroid Build Coastguard Worker 				 * ||        |      |
609*cc4ad7daSAndroid Build Coastguard Worker 				 * vv        v      v
610*cc4ad7daSAndroid Build Coastguard Worker 				 * "parport\0dyndbg=file drivers/parport/ieee1284_ops.c +mpf" */
611*cc4ad7daSAndroid Build Coastguard Worker 				memmove(p_quote_start, modname, value - modname);
612*cc4ad7daSAndroid Build Coastguard Worker 				value--; modname--; param--;
613*cc4ad7daSAndroid Build Coastguard Worker 				*value = '"';
614*cc4ad7daSAndroid Build Coastguard Worker 			}
615*cc4ad7daSAndroid Build Coastguard Worker 			kcmdline_parse_result(config, modname, param, value);
616*cc4ad7daSAndroid Build Coastguard Worker 			/* start over on next iteration */
617*cc4ad7daSAndroid Build Coastguard Worker 			modname = p + 1;
618*cc4ad7daSAndroid Build Coastguard Worker 			state = STATE_MODNAME;
619*cc4ad7daSAndroid Build Coastguard Worker 			p_quote_start = NULL;
620*cc4ad7daSAndroid Build Coastguard Worker 		}
621*cc4ad7daSAndroid Build Coastguard Worker 	}
622*cc4ad7daSAndroid Build Coastguard Worker 
623*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
624*cc4ad7daSAndroid Build Coastguard Worker }
625*cc4ad7daSAndroid Build Coastguard Worker 
626*cc4ad7daSAndroid Build Coastguard Worker /*
627*cc4ad7daSAndroid Build Coastguard Worker  * Take an fd and own it. It will be closed on return. filename is used only
628*cc4ad7daSAndroid Build Coastguard Worker  * for debug messages
629*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_parse(struct kmod_config * config,int fd,const char * filename)630*cc4ad7daSAndroid Build Coastguard Worker static int kmod_config_parse(struct kmod_config *config, int fd,
631*cc4ad7daSAndroid Build Coastguard Worker 							const char *filename)
632*cc4ad7daSAndroid Build Coastguard Worker {
633*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_ctx *ctx = config->ctx;
634*cc4ad7daSAndroid Build Coastguard Worker 	char *line;
635*cc4ad7daSAndroid Build Coastguard Worker 	FILE *fp;
636*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int linenum = 0;
637*cc4ad7daSAndroid Build Coastguard Worker 	int err;
638*cc4ad7daSAndroid Build Coastguard Worker 
639*cc4ad7daSAndroid Build Coastguard Worker 	fp = fdopen(fd, "r");
640*cc4ad7daSAndroid Build Coastguard Worker 	if (fp == NULL) {
641*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
642*cc4ad7daSAndroid Build Coastguard Worker 		ERR(config->ctx, "fd %d: %m\n", fd);
643*cc4ad7daSAndroid Build Coastguard Worker 		close(fd);
644*cc4ad7daSAndroid Build Coastguard Worker 		return err;
645*cc4ad7daSAndroid Build Coastguard Worker 	}
646*cc4ad7daSAndroid Build Coastguard Worker 
647*cc4ad7daSAndroid Build Coastguard Worker 	while ((line = freadline_wrapped(fp, &linenum)) != NULL) {
648*cc4ad7daSAndroid Build Coastguard Worker 		char *cmd, *saveptr;
649*cc4ad7daSAndroid Build Coastguard Worker 
650*cc4ad7daSAndroid Build Coastguard Worker 		if (line[0] == '\0' || line[0] == '#')
651*cc4ad7daSAndroid Build Coastguard Worker 			goto done_next;
652*cc4ad7daSAndroid Build Coastguard Worker 
653*cc4ad7daSAndroid Build Coastguard Worker 		cmd = strtok_r(line, "\t ", &saveptr);
654*cc4ad7daSAndroid Build Coastguard Worker 		if (cmd == NULL)
655*cc4ad7daSAndroid Build Coastguard Worker 			goto done_next;
656*cc4ad7daSAndroid Build Coastguard Worker 
657*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(cmd, "alias")) {
658*cc4ad7daSAndroid Build Coastguard Worker 			char *alias = strtok_r(NULL, "\t ", &saveptr);
659*cc4ad7daSAndroid Build Coastguard Worker 			char *modname = strtok_r(NULL, "\t ", &saveptr);
660*cc4ad7daSAndroid Build Coastguard Worker 
661*cc4ad7daSAndroid Build Coastguard Worker 			if (underscores(alias) < 0 || underscores(modname) < 0)
662*cc4ad7daSAndroid Build Coastguard Worker 				goto syntax_error;
663*cc4ad7daSAndroid Build Coastguard Worker 
664*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_alias(config, alias, modname);
665*cc4ad7daSAndroid Build Coastguard Worker 		} else if (streq(cmd, "blacklist")) {
666*cc4ad7daSAndroid Build Coastguard Worker 			char *modname = strtok_r(NULL, "\t ", &saveptr);
667*cc4ad7daSAndroid Build Coastguard Worker 
668*cc4ad7daSAndroid Build Coastguard Worker 			if (underscores(modname) < 0)
669*cc4ad7daSAndroid Build Coastguard Worker 				goto syntax_error;
670*cc4ad7daSAndroid Build Coastguard Worker 
671*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_blacklist(config, modname);
672*cc4ad7daSAndroid Build Coastguard Worker 		} else if (streq(cmd, "options")) {
673*cc4ad7daSAndroid Build Coastguard Worker 			char *modname = strtok_r(NULL, "\t ", &saveptr);
674*cc4ad7daSAndroid Build Coastguard Worker 			char *options = strtok_r(NULL, "\0", &saveptr);
675*cc4ad7daSAndroid Build Coastguard Worker 
676*cc4ad7daSAndroid Build Coastguard Worker 			if (underscores(modname) < 0 || options == NULL)
677*cc4ad7daSAndroid Build Coastguard Worker 				goto syntax_error;
678*cc4ad7daSAndroid Build Coastguard Worker 
679*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_options(config, modname, options);
680*cc4ad7daSAndroid Build Coastguard Worker 		} else if (streq(cmd, "install")) {
681*cc4ad7daSAndroid Build Coastguard Worker 			char *modname = strtok_r(NULL, "\t ", &saveptr);
682*cc4ad7daSAndroid Build Coastguard Worker 			char *installcmd = strtok_r(NULL, "\0", &saveptr);
683*cc4ad7daSAndroid Build Coastguard Worker 
684*cc4ad7daSAndroid Build Coastguard Worker 			if (underscores(modname) < 0 || installcmd == NULL)
685*cc4ad7daSAndroid Build Coastguard Worker 				goto syntax_error;
686*cc4ad7daSAndroid Build Coastguard Worker 
687*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_command(config, modname, installcmd,
688*cc4ad7daSAndroid Build Coastguard Worker 					cmd, &config->install_commands);
689*cc4ad7daSAndroid Build Coastguard Worker 		} else if (streq(cmd, "remove")) {
690*cc4ad7daSAndroid Build Coastguard Worker 			char *modname = strtok_r(NULL, "\t ", &saveptr);
691*cc4ad7daSAndroid Build Coastguard Worker 			char *removecmd = strtok_r(NULL, "\0", &saveptr);
692*cc4ad7daSAndroid Build Coastguard Worker 
693*cc4ad7daSAndroid Build Coastguard Worker 			if (underscores(modname) < 0 || removecmd == NULL)
694*cc4ad7daSAndroid Build Coastguard Worker 				goto syntax_error;
695*cc4ad7daSAndroid Build Coastguard Worker 
696*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_command(config, modname, removecmd,
697*cc4ad7daSAndroid Build Coastguard Worker 					cmd, &config->remove_commands);
698*cc4ad7daSAndroid Build Coastguard Worker 		} else if (streq(cmd, "softdep")) {
699*cc4ad7daSAndroid Build Coastguard Worker 			char *modname = strtok_r(NULL, "\t ", &saveptr);
700*cc4ad7daSAndroid Build Coastguard Worker 			char *softdeps = strtok_r(NULL, "\0", &saveptr);
701*cc4ad7daSAndroid Build Coastguard Worker 
702*cc4ad7daSAndroid Build Coastguard Worker 			if (underscores(modname) < 0 || softdeps == NULL)
703*cc4ad7daSAndroid Build Coastguard Worker 				goto syntax_error;
704*cc4ad7daSAndroid Build Coastguard Worker 
705*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_add_softdep(config, modname, softdeps);
706*cc4ad7daSAndroid Build Coastguard Worker 		} else if (streq(cmd, "include")
707*cc4ad7daSAndroid Build Coastguard Worker 				|| streq(cmd, "config")) {
708*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "%s: command %s is deprecated and not parsed anymore\n",
709*cc4ad7daSAndroid Build Coastguard Worker 								filename, cmd);
710*cc4ad7daSAndroid Build Coastguard Worker 		} else {
711*cc4ad7daSAndroid Build Coastguard Worker syntax_error:
712*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "%s line %u: ignoring bad line starting with '%s'\n",
713*cc4ad7daSAndroid Build Coastguard Worker 						filename, linenum, cmd);
714*cc4ad7daSAndroid Build Coastguard Worker 		}
715*cc4ad7daSAndroid Build Coastguard Worker 
716*cc4ad7daSAndroid Build Coastguard Worker done_next:
717*cc4ad7daSAndroid Build Coastguard Worker 		free(line);
718*cc4ad7daSAndroid Build Coastguard Worker 	}
719*cc4ad7daSAndroid Build Coastguard Worker 
720*cc4ad7daSAndroid Build Coastguard Worker 	fclose(fp);
721*cc4ad7daSAndroid Build Coastguard Worker 
722*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
723*cc4ad7daSAndroid Build Coastguard Worker }
724*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_free(struct kmod_config * config)725*cc4ad7daSAndroid Build Coastguard Worker void kmod_config_free(struct kmod_config *config)
726*cc4ad7daSAndroid Build Coastguard Worker {
727*cc4ad7daSAndroid Build Coastguard Worker 	while (config->aliases)
728*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free_alias(config, config->aliases);
729*cc4ad7daSAndroid Build Coastguard Worker 
730*cc4ad7daSAndroid Build Coastguard Worker 	while (config->blacklists)
731*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free_blacklist(config, config->blacklists);
732*cc4ad7daSAndroid Build Coastguard Worker 
733*cc4ad7daSAndroid Build Coastguard Worker 	while (config->options)
734*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free_options(config, config->options);
735*cc4ad7daSAndroid Build Coastguard Worker 
736*cc4ad7daSAndroid Build Coastguard Worker 	while (config->install_commands) {
737*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free_command(config, config->install_commands,
738*cc4ad7daSAndroid Build Coastguard Worker 						&config->install_commands);
739*cc4ad7daSAndroid Build Coastguard Worker 	}
740*cc4ad7daSAndroid Build Coastguard Worker 
741*cc4ad7daSAndroid Build Coastguard Worker 	while (config->remove_commands) {
742*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free_command(config, config->remove_commands,
743*cc4ad7daSAndroid Build Coastguard Worker 						&config->remove_commands);
744*cc4ad7daSAndroid Build Coastguard Worker 	}
745*cc4ad7daSAndroid Build Coastguard Worker 
746*cc4ad7daSAndroid Build Coastguard Worker 	while (config->softdeps)
747*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free_softdep(config, config->softdeps);
748*cc4ad7daSAndroid Build Coastguard Worker 
749*cc4ad7daSAndroid Build Coastguard Worker 	for (; config->paths != NULL;
750*cc4ad7daSAndroid Build Coastguard Worker 				config->paths = kmod_list_remove(config->paths))
751*cc4ad7daSAndroid Build Coastguard Worker 		free(config->paths->data);
752*cc4ad7daSAndroid Build Coastguard Worker 
753*cc4ad7daSAndroid Build Coastguard Worker 	free(config);
754*cc4ad7daSAndroid Build Coastguard Worker }
755*cc4ad7daSAndroid Build Coastguard Worker 
conf_files_filter_out(struct kmod_ctx * ctx,DIR * d,const char * path,const char * fn)756*cc4ad7daSAndroid Build Coastguard Worker static bool conf_files_filter_out(struct kmod_ctx *ctx, DIR *d,
757*cc4ad7daSAndroid Build Coastguard Worker 					const char *path, const char *fn)
758*cc4ad7daSAndroid Build Coastguard Worker {
759*cc4ad7daSAndroid Build Coastguard Worker 	size_t len = strlen(fn);
760*cc4ad7daSAndroid Build Coastguard Worker 	struct stat st;
761*cc4ad7daSAndroid Build Coastguard Worker 
762*cc4ad7daSAndroid Build Coastguard Worker 	if (fn[0] == '.')
763*cc4ad7daSAndroid Build Coastguard Worker 		return true;
764*cc4ad7daSAndroid Build Coastguard Worker 
765*cc4ad7daSAndroid Build Coastguard Worker 	if (len < 6 || (!streq(&fn[len - 5], ".conf")
766*cc4ad7daSAndroid Build Coastguard Worker 				&& !streq(&fn[len - 6], ".alias")))
767*cc4ad7daSAndroid Build Coastguard Worker 		return true;
768*cc4ad7daSAndroid Build Coastguard Worker 
769*cc4ad7daSAndroid Build Coastguard Worker 	fstatat(dirfd(d), fn, &st, 0);
770*cc4ad7daSAndroid Build Coastguard Worker 
771*cc4ad7daSAndroid Build Coastguard Worker 	if (S_ISDIR(st.st_mode)) {
772*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "Directories inside directories are not supported: "
773*cc4ad7daSAndroid Build Coastguard Worker 							"%s/%s\n", path, fn);
774*cc4ad7daSAndroid Build Coastguard Worker 		return true;
775*cc4ad7daSAndroid Build Coastguard Worker 	}
776*cc4ad7daSAndroid Build Coastguard Worker 
777*cc4ad7daSAndroid Build Coastguard Worker 	return false;
778*cc4ad7daSAndroid Build Coastguard Worker }
779*cc4ad7daSAndroid Build Coastguard Worker 
780*cc4ad7daSAndroid Build Coastguard Worker struct conf_file {
781*cc4ad7daSAndroid Build Coastguard Worker 	const char *path;
782*cc4ad7daSAndroid Build Coastguard Worker 	bool is_single;
783*cc4ad7daSAndroid Build Coastguard Worker 	char name[];
784*cc4ad7daSAndroid Build Coastguard Worker };
785*cc4ad7daSAndroid Build Coastguard Worker 
conf_files_insert_sorted(struct kmod_ctx * ctx,struct kmod_list ** list,const char * path,const char * name)786*cc4ad7daSAndroid Build Coastguard Worker static int conf_files_insert_sorted(struct kmod_ctx *ctx,
787*cc4ad7daSAndroid Build Coastguard Worker 					struct kmod_list **list,
788*cc4ad7daSAndroid Build Coastguard Worker 					const char *path, const char *name)
789*cc4ad7daSAndroid Build Coastguard Worker {
790*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *lpos, *tmp;
791*cc4ad7daSAndroid Build Coastguard Worker 	struct conf_file *cf;
792*cc4ad7daSAndroid Build Coastguard Worker 	size_t namelen;
793*cc4ad7daSAndroid Build Coastguard Worker 	int cmp = -1;
794*cc4ad7daSAndroid Build Coastguard Worker 	bool is_single = false;
795*cc4ad7daSAndroid Build Coastguard Worker 
796*cc4ad7daSAndroid Build Coastguard Worker 	if (name == NULL) {
797*cc4ad7daSAndroid Build Coastguard Worker 		name = basename(path);
798*cc4ad7daSAndroid Build Coastguard Worker 		is_single = true;
799*cc4ad7daSAndroid Build Coastguard Worker 	}
800*cc4ad7daSAndroid Build Coastguard Worker 
801*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(lpos, *list) {
802*cc4ad7daSAndroid Build Coastguard Worker 		cf = lpos->data;
803*cc4ad7daSAndroid Build Coastguard Worker 
804*cc4ad7daSAndroid Build Coastguard Worker 		if ((cmp = strcmp(name, cf->name)) <= 0)
805*cc4ad7daSAndroid Build Coastguard Worker 			break;
806*cc4ad7daSAndroid Build Coastguard Worker 	}
807*cc4ad7daSAndroid Build Coastguard Worker 
808*cc4ad7daSAndroid Build Coastguard Worker 	if (cmp == 0) {
809*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "Ignoring duplicate config file: %s/%s\n", path,
810*cc4ad7daSAndroid Build Coastguard Worker 									name);
811*cc4ad7daSAndroid Build Coastguard Worker 		return -EEXIST;
812*cc4ad7daSAndroid Build Coastguard Worker 	}
813*cc4ad7daSAndroid Build Coastguard Worker 
814*cc4ad7daSAndroid Build Coastguard Worker 	namelen = strlen(name);
815*cc4ad7daSAndroid Build Coastguard Worker 	cf = malloc(sizeof(*cf) + namelen + 1);
816*cc4ad7daSAndroid Build Coastguard Worker 	if (cf == NULL)
817*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
818*cc4ad7daSAndroid Build Coastguard Worker 
819*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(cf->name, name, namelen + 1);
820*cc4ad7daSAndroid Build Coastguard Worker 	cf->path = path;
821*cc4ad7daSAndroid Build Coastguard Worker 	cf->is_single = is_single;
822*cc4ad7daSAndroid Build Coastguard Worker 
823*cc4ad7daSAndroid Build Coastguard Worker 	if (lpos == NULL)
824*cc4ad7daSAndroid Build Coastguard Worker 		tmp = kmod_list_append(*list, cf);
825*cc4ad7daSAndroid Build Coastguard Worker 	else if (lpos == *list)
826*cc4ad7daSAndroid Build Coastguard Worker 		tmp = kmod_list_prepend(*list, cf);
827*cc4ad7daSAndroid Build Coastguard Worker 	else
828*cc4ad7daSAndroid Build Coastguard Worker 		tmp = kmod_list_insert_before(lpos, cf);
829*cc4ad7daSAndroid Build Coastguard Worker 
830*cc4ad7daSAndroid Build Coastguard Worker 	if (tmp == NULL) {
831*cc4ad7daSAndroid Build Coastguard Worker 		free(cf);
832*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
833*cc4ad7daSAndroid Build Coastguard Worker 	}
834*cc4ad7daSAndroid Build Coastguard Worker 
835*cc4ad7daSAndroid Build Coastguard Worker 	if (lpos == NULL || lpos == *list)
836*cc4ad7daSAndroid Build Coastguard Worker 		*list = tmp;
837*cc4ad7daSAndroid Build Coastguard Worker 
838*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
839*cc4ad7daSAndroid Build Coastguard Worker }
840*cc4ad7daSAndroid Build Coastguard Worker 
841*cc4ad7daSAndroid Build Coastguard Worker /*
842*cc4ad7daSAndroid Build Coastguard Worker  * Insert configuration files in @list, ignoring duplicates
843*cc4ad7daSAndroid Build Coastguard Worker  */
conf_files_list(struct kmod_ctx * ctx,struct kmod_list ** list,const char * path,unsigned long long * path_stamp)844*cc4ad7daSAndroid Build Coastguard Worker static int conf_files_list(struct kmod_ctx *ctx, struct kmod_list **list,
845*cc4ad7daSAndroid Build Coastguard Worker 						const char *path,
846*cc4ad7daSAndroid Build Coastguard Worker 						unsigned long long *path_stamp)
847*cc4ad7daSAndroid Build Coastguard Worker {
848*cc4ad7daSAndroid Build Coastguard Worker 	DIR *d;
849*cc4ad7daSAndroid Build Coastguard Worker 	int err;
850*cc4ad7daSAndroid Build Coastguard Worker 	struct stat st;
851*cc4ad7daSAndroid Build Coastguard Worker 	struct dirent *dent;
852*cc4ad7daSAndroid Build Coastguard Worker 
853*cc4ad7daSAndroid Build Coastguard Worker 	if (stat(path, &st) != 0) {
854*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
855*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "could not stat '%s': %m\n", path);
856*cc4ad7daSAndroid Build Coastguard Worker 		return err;
857*cc4ad7daSAndroid Build Coastguard Worker 	}
858*cc4ad7daSAndroid Build Coastguard Worker 
859*cc4ad7daSAndroid Build Coastguard Worker 	*path_stamp = stat_mstamp(&st);
860*cc4ad7daSAndroid Build Coastguard Worker 
861*cc4ad7daSAndroid Build Coastguard Worker 	if (!S_ISDIR(st.st_mode)) {
862*cc4ad7daSAndroid Build Coastguard Worker 		conf_files_insert_sorted(ctx, list, path, NULL);
863*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
864*cc4ad7daSAndroid Build Coastguard Worker 	}
865*cc4ad7daSAndroid Build Coastguard Worker 
866*cc4ad7daSAndroid Build Coastguard Worker 	d = opendir(path);
867*cc4ad7daSAndroid Build Coastguard Worker 	if (d == NULL) {
868*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "opendir(%s): %m\n", path);
869*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
870*cc4ad7daSAndroid Build Coastguard Worker 	}
871*cc4ad7daSAndroid Build Coastguard Worker 
872*cc4ad7daSAndroid Build Coastguard Worker 	for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
873*cc4ad7daSAndroid Build Coastguard Worker 		if (conf_files_filter_out(ctx, d, path, dent->d_name))
874*cc4ad7daSAndroid Build Coastguard Worker 			continue;
875*cc4ad7daSAndroid Build Coastguard Worker 
876*cc4ad7daSAndroid Build Coastguard Worker 		conf_files_insert_sorted(ctx, list, path, dent->d_name);
877*cc4ad7daSAndroid Build Coastguard Worker 	}
878*cc4ad7daSAndroid Build Coastguard Worker 
879*cc4ad7daSAndroid Build Coastguard Worker 	closedir(d);
880*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
881*cc4ad7daSAndroid Build Coastguard Worker }
882*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_new(struct kmod_ctx * ctx,struct kmod_config ** p_config,const char * const * config_paths)883*cc4ad7daSAndroid Build Coastguard Worker int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config,
884*cc4ad7daSAndroid Build Coastguard Worker 					const char * const *config_paths)
885*cc4ad7daSAndroid Build Coastguard Worker {
886*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_config *config;
887*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list = NULL;
888*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *path_list = NULL;
889*cc4ad7daSAndroid Build Coastguard Worker 	size_t i;
890*cc4ad7daSAndroid Build Coastguard Worker 
891*cc4ad7daSAndroid Build Coastguard Worker 	conf_files_insert_sorted(ctx, &list, kmod_get_dirname(ctx), "modules.softdep");
892*cc4ad7daSAndroid Build Coastguard Worker 
893*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; config_paths[i] != NULL; i++) {
894*cc4ad7daSAndroid Build Coastguard Worker 		const char *path = config_paths[i];
895*cc4ad7daSAndroid Build Coastguard Worker 		unsigned long long path_stamp = 0;
896*cc4ad7daSAndroid Build Coastguard Worker 		size_t pathlen;
897*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *tmp;
898*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_config_path *cf;
899*cc4ad7daSAndroid Build Coastguard Worker 
900*cc4ad7daSAndroid Build Coastguard Worker 		if (conf_files_list(ctx, &list, path, &path_stamp) < 0)
901*cc4ad7daSAndroid Build Coastguard Worker 			continue;
902*cc4ad7daSAndroid Build Coastguard Worker 
903*cc4ad7daSAndroid Build Coastguard Worker 		pathlen = strlen(path) + 1;
904*cc4ad7daSAndroid Build Coastguard Worker 		cf = malloc(sizeof(*cf) + pathlen);
905*cc4ad7daSAndroid Build Coastguard Worker 		if (cf == NULL)
906*cc4ad7daSAndroid Build Coastguard Worker 			goto oom;
907*cc4ad7daSAndroid Build Coastguard Worker 
908*cc4ad7daSAndroid Build Coastguard Worker 		cf->stamp = path_stamp;
909*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(cf->path, path, pathlen);
910*cc4ad7daSAndroid Build Coastguard Worker 
911*cc4ad7daSAndroid Build Coastguard Worker 		tmp = kmod_list_append(path_list, cf);
912*cc4ad7daSAndroid Build Coastguard Worker 		if (tmp == NULL) {
913*cc4ad7daSAndroid Build Coastguard Worker 			free(cf);
914*cc4ad7daSAndroid Build Coastguard Worker 			goto oom;
915*cc4ad7daSAndroid Build Coastguard Worker 		}
916*cc4ad7daSAndroid Build Coastguard Worker 		path_list = tmp;
917*cc4ad7daSAndroid Build Coastguard Worker 	}
918*cc4ad7daSAndroid Build Coastguard Worker 
919*cc4ad7daSAndroid Build Coastguard Worker 	*p_config = config = calloc(1, sizeof(struct kmod_config));
920*cc4ad7daSAndroid Build Coastguard Worker 	if (config == NULL)
921*cc4ad7daSAndroid Build Coastguard Worker 		goto oom;
922*cc4ad7daSAndroid Build Coastguard Worker 
923*cc4ad7daSAndroid Build Coastguard Worker 	config->paths = path_list;
924*cc4ad7daSAndroid Build Coastguard Worker 	config->ctx = ctx;
925*cc4ad7daSAndroid Build Coastguard Worker 
926*cc4ad7daSAndroid Build Coastguard Worker 	for (; list != NULL; list = kmod_list_remove(list)) {
927*cc4ad7daSAndroid Build Coastguard Worker 		char buf[PATH_MAX];
928*cc4ad7daSAndroid Build Coastguard Worker 		const char *fn = buf;
929*cc4ad7daSAndroid Build Coastguard Worker 		struct conf_file *cf = list->data;
930*cc4ad7daSAndroid Build Coastguard Worker 		int fd;
931*cc4ad7daSAndroid Build Coastguard Worker 
932*cc4ad7daSAndroid Build Coastguard Worker 		if (cf->is_single) {
933*cc4ad7daSAndroid Build Coastguard Worker 			fn = cf->path;
934*cc4ad7daSAndroid Build Coastguard Worker 		} else if (snprintf(buf, sizeof(buf), "%s/%s",
935*cc4ad7daSAndroid Build Coastguard Worker 				    cf->path, cf->name) >= (int)sizeof(buf)) {
936*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "Error parsing %s/%s: path too long\n",
937*cc4ad7daSAndroid Build Coastguard Worker 			    cf->path, cf->name);
938*cc4ad7daSAndroid Build Coastguard Worker 			free(cf);
939*cc4ad7daSAndroid Build Coastguard Worker 			continue;
940*cc4ad7daSAndroid Build Coastguard Worker 		}
941*cc4ad7daSAndroid Build Coastguard Worker 
942*cc4ad7daSAndroid Build Coastguard Worker 		fd = open(fn, O_RDONLY|O_CLOEXEC);
943*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "parsing file '%s' fd=%d\n", fn, fd);
944*cc4ad7daSAndroid Build Coastguard Worker 
945*cc4ad7daSAndroid Build Coastguard Worker 		if (fd >= 0)
946*cc4ad7daSAndroid Build Coastguard Worker 			kmod_config_parse(config, fd, fn);
947*cc4ad7daSAndroid Build Coastguard Worker 
948*cc4ad7daSAndroid Build Coastguard Worker 		free(cf);
949*cc4ad7daSAndroid Build Coastguard Worker 	}
950*cc4ad7daSAndroid Build Coastguard Worker 
951*cc4ad7daSAndroid Build Coastguard Worker 	kmod_config_parse_kcmdline(config);
952*cc4ad7daSAndroid Build Coastguard Worker 
953*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
954*cc4ad7daSAndroid Build Coastguard Worker 
955*cc4ad7daSAndroid Build Coastguard Worker oom:
956*cc4ad7daSAndroid Build Coastguard Worker 	for (; list != NULL; list = kmod_list_remove(list))
957*cc4ad7daSAndroid Build Coastguard Worker 		free(list->data);
958*cc4ad7daSAndroid Build Coastguard Worker 
959*cc4ad7daSAndroid Build Coastguard Worker 	for (; path_list != NULL; path_list = kmod_list_remove(path_list))
960*cc4ad7daSAndroid Build Coastguard Worker 		free(path_list->data);
961*cc4ad7daSAndroid Build Coastguard Worker 
962*cc4ad7daSAndroid Build Coastguard Worker 	return -ENOMEM;
963*cc4ad7daSAndroid Build Coastguard Worker }
964*cc4ad7daSAndroid Build Coastguard Worker 
965*cc4ad7daSAndroid Build Coastguard Worker /**********************************************************************
966*cc4ad7daSAndroid Build Coastguard Worker  * struct kmod_config_iter functions
967*cc4ad7daSAndroid Build Coastguard Worker  **********************************************************************/
968*cc4ad7daSAndroid Build Coastguard Worker 
969*cc4ad7daSAndroid Build Coastguard Worker enum config_type {
970*cc4ad7daSAndroid Build Coastguard Worker 	CONFIG_TYPE_BLACKLIST = 0,
971*cc4ad7daSAndroid Build Coastguard Worker 	CONFIG_TYPE_INSTALL,
972*cc4ad7daSAndroid Build Coastguard Worker 	CONFIG_TYPE_REMOVE,
973*cc4ad7daSAndroid Build Coastguard Worker 	CONFIG_TYPE_ALIAS,
974*cc4ad7daSAndroid Build Coastguard Worker 	CONFIG_TYPE_OPTION,
975*cc4ad7daSAndroid Build Coastguard Worker 	CONFIG_TYPE_SOFTDEP,
976*cc4ad7daSAndroid Build Coastguard Worker };
977*cc4ad7daSAndroid Build Coastguard Worker 
978*cc4ad7daSAndroid Build Coastguard Worker struct kmod_config_iter {
979*cc4ad7daSAndroid Build Coastguard Worker 	enum config_type type;
980*cc4ad7daSAndroid Build Coastguard Worker 	bool intermediate;
981*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_list *list;
982*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_list *curr;
983*cc4ad7daSAndroid Build Coastguard Worker 	void *data;
984*cc4ad7daSAndroid Build Coastguard Worker 	const char *(*get_key)(const struct kmod_list *l);
985*cc4ad7daSAndroid Build Coastguard Worker 	const char *(*get_value)(const struct kmod_list *l);
986*cc4ad7daSAndroid Build Coastguard Worker };
987*cc4ad7daSAndroid Build Coastguard Worker 
softdep_get_plain_softdep(const struct kmod_list * l)988*cc4ad7daSAndroid Build Coastguard Worker static const char *softdep_get_plain_softdep(const struct kmod_list *l)
989*cc4ad7daSAndroid Build Coastguard Worker {
990*cc4ad7daSAndroid Build Coastguard Worker 	char *s = softdep_to_char(l->data);
991*cc4ad7daSAndroid Build Coastguard Worker 	return s;
992*cc4ad7daSAndroid Build Coastguard Worker }
993*cc4ad7daSAndroid Build Coastguard Worker 
kmod_config_iter_new(const struct kmod_ctx * ctx,enum config_type type)994*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_config_iter *kmod_config_iter_new(const struct kmod_ctx* ctx,
995*cc4ad7daSAndroid Build Coastguard Worker 							enum config_type type)
996*cc4ad7daSAndroid Build Coastguard Worker {
997*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_config_iter *iter = calloc(1, sizeof(*iter));
998*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_config *config = kmod_get_config(ctx);
999*cc4ad7daSAndroid Build Coastguard Worker 
1000*cc4ad7daSAndroid Build Coastguard Worker 	if (iter == NULL)
1001*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1002*cc4ad7daSAndroid Build Coastguard Worker 
1003*cc4ad7daSAndroid Build Coastguard Worker 	iter->type = type;
1004*cc4ad7daSAndroid Build Coastguard Worker 
1005*cc4ad7daSAndroid Build Coastguard Worker 	switch (type) {
1006*cc4ad7daSAndroid Build Coastguard Worker 	case CONFIG_TYPE_BLACKLIST:
1007*cc4ad7daSAndroid Build Coastguard Worker 		iter->list = config->blacklists;
1008*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_key = kmod_blacklist_get_modname;
1009*cc4ad7daSAndroid Build Coastguard Worker 		break;
1010*cc4ad7daSAndroid Build Coastguard Worker 	case CONFIG_TYPE_INSTALL:
1011*cc4ad7daSAndroid Build Coastguard Worker 		iter->list = config->install_commands;
1012*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_key = kmod_command_get_modname;
1013*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_value = kmod_command_get_command;
1014*cc4ad7daSAndroid Build Coastguard Worker 		break;
1015*cc4ad7daSAndroid Build Coastguard Worker 	case CONFIG_TYPE_REMOVE:
1016*cc4ad7daSAndroid Build Coastguard Worker 		iter->list = config->remove_commands;
1017*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_key = kmod_command_get_modname;
1018*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_value = kmod_command_get_command;
1019*cc4ad7daSAndroid Build Coastguard Worker 		break;
1020*cc4ad7daSAndroid Build Coastguard Worker 	case CONFIG_TYPE_ALIAS:
1021*cc4ad7daSAndroid Build Coastguard Worker 		iter->list = config->aliases;
1022*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_key = kmod_alias_get_name;
1023*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_value = kmod_alias_get_modname;
1024*cc4ad7daSAndroid Build Coastguard Worker 		break;
1025*cc4ad7daSAndroid Build Coastguard Worker 	case CONFIG_TYPE_OPTION:
1026*cc4ad7daSAndroid Build Coastguard Worker 		iter->list = config->options;
1027*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_key = kmod_option_get_modname;
1028*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_value = kmod_option_get_options;
1029*cc4ad7daSAndroid Build Coastguard Worker 		break;
1030*cc4ad7daSAndroid Build Coastguard Worker 	case CONFIG_TYPE_SOFTDEP:
1031*cc4ad7daSAndroid Build Coastguard Worker 		iter->list = config->softdeps;
1032*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_key = kmod_softdep_get_name;
1033*cc4ad7daSAndroid Build Coastguard Worker 		iter->get_value = softdep_get_plain_softdep;
1034*cc4ad7daSAndroid Build Coastguard Worker 		iter->intermediate = true;
1035*cc4ad7daSAndroid Build Coastguard Worker 		break;
1036*cc4ad7daSAndroid Build Coastguard Worker 	}
1037*cc4ad7daSAndroid Build Coastguard Worker 
1038*cc4ad7daSAndroid Build Coastguard Worker 	return iter;
1039*cc4ad7daSAndroid Build Coastguard Worker }
1040*cc4ad7daSAndroid Build Coastguard Worker 
1041*cc4ad7daSAndroid Build Coastguard Worker /**
1042*cc4ad7daSAndroid Build Coastguard Worker  * SECTION:libkmod-config
1043*cc4ad7daSAndroid Build Coastguard Worker  * @short_description: retrieve current libkmod configuration
1044*cc4ad7daSAndroid Build Coastguard Worker  */
1045*cc4ad7daSAndroid Build Coastguard Worker 
1046*cc4ad7daSAndroid Build Coastguard Worker /**
1047*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_get_blacklists:
1048*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1049*cc4ad7daSAndroid Build Coastguard Worker  *
1050*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve an iterator to deal with the blacklist maintained inside the
1051*cc4ad7daSAndroid Build Coastguard Worker  * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1052*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1053*cc4ad7daSAndroid Build Coastguard Worker  * be made to initialize the iterator and check if it's valid.
1054*cc4ad7daSAndroid Build Coastguard Worker  *
1055*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new iterator over the blacklists or NULL on failure. Free it
1056*cc4ad7daSAndroid Build Coastguard Worker  * with kmod_config_iter_free_iter().
1057*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_get_blacklists(const struct kmod_ctx * ctx)1058*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_config_iter *kmod_config_get_blacklists(const struct kmod_ctx *ctx)
1059*cc4ad7daSAndroid Build Coastguard Worker {
1060*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
1061*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;;
1062*cc4ad7daSAndroid Build Coastguard Worker 
1063*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_config_iter_new(ctx, CONFIG_TYPE_BLACKLIST);
1064*cc4ad7daSAndroid Build Coastguard Worker }
1065*cc4ad7daSAndroid Build Coastguard Worker 
1066*cc4ad7daSAndroid Build Coastguard Worker /**
1067*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_get_install_commands:
1068*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1069*cc4ad7daSAndroid Build Coastguard Worker  *
1070*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve an iterator to deal with the install commands maintained inside the
1071*cc4ad7daSAndroid Build Coastguard Worker  * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1072*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1073*cc4ad7daSAndroid Build Coastguard Worker  * be made to initialize the iterator and check if it's valid.
1074*cc4ad7daSAndroid Build Coastguard Worker  *
1075*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new iterator over the install commands or NULL on failure. Free
1076*cc4ad7daSAndroid Build Coastguard Worker  * it with kmod_config_iter_free_iter().
1077*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_get_install_commands(const struct kmod_ctx * ctx)1078*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_config_iter *kmod_config_get_install_commands(const struct kmod_ctx *ctx)
1079*cc4ad7daSAndroid Build Coastguard Worker {
1080*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
1081*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;;
1082*cc4ad7daSAndroid Build Coastguard Worker 
1083*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_config_iter_new(ctx, CONFIG_TYPE_INSTALL);
1084*cc4ad7daSAndroid Build Coastguard Worker }
1085*cc4ad7daSAndroid Build Coastguard Worker 
1086*cc4ad7daSAndroid Build Coastguard Worker /**
1087*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_get_remove_commands:
1088*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1089*cc4ad7daSAndroid Build Coastguard Worker  *
1090*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve an iterator to deal with the remove commands maintained inside the
1091*cc4ad7daSAndroid Build Coastguard Worker  * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1092*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1093*cc4ad7daSAndroid Build Coastguard Worker  * be made to initialize the iterator and check if it's valid.
1094*cc4ad7daSAndroid Build Coastguard Worker  *
1095*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new iterator over the remove commands or NULL on failure. Free
1096*cc4ad7daSAndroid Build Coastguard Worker  * it with kmod_config_iter_free_iter().
1097*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_get_remove_commands(const struct kmod_ctx * ctx)1098*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_config_iter *kmod_config_get_remove_commands(const struct kmod_ctx *ctx)
1099*cc4ad7daSAndroid Build Coastguard Worker {
1100*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
1101*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;;
1102*cc4ad7daSAndroid Build Coastguard Worker 
1103*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_config_iter_new(ctx, CONFIG_TYPE_REMOVE);
1104*cc4ad7daSAndroid Build Coastguard Worker }
1105*cc4ad7daSAndroid Build Coastguard Worker 
1106*cc4ad7daSAndroid Build Coastguard Worker /**
1107*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_get_aliases:
1108*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1109*cc4ad7daSAndroid Build Coastguard Worker  *
1110*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve an iterator to deal with the aliases maintained inside the
1111*cc4ad7daSAndroid Build Coastguard Worker  * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1112*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1113*cc4ad7daSAndroid Build Coastguard Worker  * be made to initialize the iterator and check if it's valid.
1114*cc4ad7daSAndroid Build Coastguard Worker  *
1115*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new iterator over the aliases or NULL on failure. Free it with
1116*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_free_iter().
1117*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_get_aliases(const struct kmod_ctx * ctx)1118*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_config_iter *kmod_config_get_aliases(const struct kmod_ctx *ctx)
1119*cc4ad7daSAndroid Build Coastguard Worker {
1120*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
1121*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;;
1122*cc4ad7daSAndroid Build Coastguard Worker 
1123*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_config_iter_new(ctx, CONFIG_TYPE_ALIAS);
1124*cc4ad7daSAndroid Build Coastguard Worker }
1125*cc4ad7daSAndroid Build Coastguard Worker 
1126*cc4ad7daSAndroid Build Coastguard Worker /**
1127*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_get_options:
1128*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1129*cc4ad7daSAndroid Build Coastguard Worker  *
1130*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve an iterator to deal with the options maintained inside the
1131*cc4ad7daSAndroid Build Coastguard Worker  * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1132*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1133*cc4ad7daSAndroid Build Coastguard Worker  * be made to initialize the iterator and check if it's valid.
1134*cc4ad7daSAndroid Build Coastguard Worker  *
1135*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new iterator over the options or NULL on failure. Free it with
1136*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_free_iter().
1137*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_get_options(const struct kmod_ctx * ctx)1138*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_config_iter *kmod_config_get_options(const struct kmod_ctx *ctx)
1139*cc4ad7daSAndroid Build Coastguard Worker {
1140*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
1141*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;;
1142*cc4ad7daSAndroid Build Coastguard Worker 
1143*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_config_iter_new(ctx, CONFIG_TYPE_OPTION);
1144*cc4ad7daSAndroid Build Coastguard Worker }
1145*cc4ad7daSAndroid Build Coastguard Worker 
1146*cc4ad7daSAndroid Build Coastguard Worker /**
1147*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_get_softdeps:
1148*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1149*cc4ad7daSAndroid Build Coastguard Worker  *
1150*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve an iterator to deal with the softdeps maintained inside the
1151*cc4ad7daSAndroid Build Coastguard Worker  * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
1152*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
1153*cc4ad7daSAndroid Build Coastguard Worker  * be made to initialize the iterator and check if it's valid.
1154*cc4ad7daSAndroid Build Coastguard Worker  *
1155*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new iterator over the softdeps or NULL on failure. Free it with
1156*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_free_iter().
1157*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_get_softdeps(const struct kmod_ctx * ctx)1158*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_config_iter *kmod_config_get_softdeps(const struct kmod_ctx *ctx)
1159*cc4ad7daSAndroid Build Coastguard Worker {
1160*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
1161*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;;
1162*cc4ad7daSAndroid Build Coastguard Worker 
1163*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_config_iter_new(ctx, CONFIG_TYPE_SOFTDEP);
1164*cc4ad7daSAndroid Build Coastguard Worker }
1165*cc4ad7daSAndroid Build Coastguard Worker 
1166*cc4ad7daSAndroid Build Coastguard Worker /**
1167*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_get_key:
1168*cc4ad7daSAndroid Build Coastguard Worker  * @iter: iterator over a certain configuration
1169*cc4ad7daSAndroid Build Coastguard Worker  *
1170*cc4ad7daSAndroid Build Coastguard Worker  * When using a new allocated iterator, user must perform a call to
1171*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next() to initialize iterator's position and check if it's
1172*cc4ad7daSAndroid Build Coastguard Worker  * valid.
1173*cc4ad7daSAndroid Build Coastguard Worker  *
1174*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the key of the current configuration pointed by @iter.
1175*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_iter_get_key(const struct kmod_config_iter * iter)1176*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_config_iter_get_key(const struct kmod_config_iter *iter)
1177*cc4ad7daSAndroid Build Coastguard Worker {
1178*cc4ad7daSAndroid Build Coastguard Worker 	if (iter == NULL || iter->curr == NULL)
1179*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1180*cc4ad7daSAndroid Build Coastguard Worker 
1181*cc4ad7daSAndroid Build Coastguard Worker 	return iter->get_key(iter->curr);
1182*cc4ad7daSAndroid Build Coastguard Worker }
1183*cc4ad7daSAndroid Build Coastguard Worker 
1184*cc4ad7daSAndroid Build Coastguard Worker /**
1185*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_get_value:
1186*cc4ad7daSAndroid Build Coastguard Worker  * @iter: iterator over a certain configuration
1187*cc4ad7daSAndroid Build Coastguard Worker  *
1188*cc4ad7daSAndroid Build Coastguard Worker  * When using a new allocated iterator, user must perform a call to
1189*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next() to initialize iterator's position and check if it's
1190*cc4ad7daSAndroid Build Coastguard Worker  * valid.
1191*cc4ad7daSAndroid Build Coastguard Worker  *
1192*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the value of the current configuration pointed by @iter.
1193*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_iter_get_value(const struct kmod_config_iter * iter)1194*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_config_iter_get_value(const struct kmod_config_iter *iter)
1195*cc4ad7daSAndroid Build Coastguard Worker {
1196*cc4ad7daSAndroid Build Coastguard Worker 	const char *s;
1197*cc4ad7daSAndroid Build Coastguard Worker 
1198*cc4ad7daSAndroid Build Coastguard Worker 	if (iter == NULL || iter->curr == NULL)
1199*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1200*cc4ad7daSAndroid Build Coastguard Worker 
1201*cc4ad7daSAndroid Build Coastguard Worker 	if (iter->get_value == NULL)
1202*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1203*cc4ad7daSAndroid Build Coastguard Worker 
1204*cc4ad7daSAndroid Build Coastguard Worker 	if (iter->intermediate) {
1205*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_config_iter *i = (struct kmod_config_iter *)iter;
1206*cc4ad7daSAndroid Build Coastguard Worker 
1207*cc4ad7daSAndroid Build Coastguard Worker 		free(i->data);
1208*cc4ad7daSAndroid Build Coastguard Worker 		s = i->data = (void *) iter->get_value(iter->curr);
1209*cc4ad7daSAndroid Build Coastguard Worker 	} else
1210*cc4ad7daSAndroid Build Coastguard Worker 		s = iter->get_value(iter->curr);
1211*cc4ad7daSAndroid Build Coastguard Worker 
1212*cc4ad7daSAndroid Build Coastguard Worker 	return s;
1213*cc4ad7daSAndroid Build Coastguard Worker }
1214*cc4ad7daSAndroid Build Coastguard Worker 
1215*cc4ad7daSAndroid Build Coastguard Worker /**
1216*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_next:
1217*cc4ad7daSAndroid Build Coastguard Worker  * @iter: iterator over a certain configuration
1218*cc4ad7daSAndroid Build Coastguard Worker  *
1219*cc4ad7daSAndroid Build Coastguard Worker  * Make @iter point to the next item of a certain configuration. It's an
1220*cc4ad7daSAndroid Build Coastguard Worker  * automatically recycling iterator. When it reaches the end, false is
1221*cc4ad7daSAndroid Build Coastguard Worker  * returned; then if user wants to iterate again, it's sufficient to call this
1222*cc4ad7daSAndroid Build Coastguard Worker  * function once more.
1223*cc4ad7daSAndroid Build Coastguard Worker  *
1224*cc4ad7daSAndroid Build Coastguard Worker  * Returns: true if next position of @iter is valid or false if its end is
1225*cc4ad7daSAndroid Build Coastguard Worker  * reached.
1226*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_iter_next(struct kmod_config_iter * iter)1227*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT bool kmod_config_iter_next(struct kmod_config_iter *iter)
1228*cc4ad7daSAndroid Build Coastguard Worker {
1229*cc4ad7daSAndroid Build Coastguard Worker 	if (iter == NULL)
1230*cc4ad7daSAndroid Build Coastguard Worker 		return false;
1231*cc4ad7daSAndroid Build Coastguard Worker 
1232*cc4ad7daSAndroid Build Coastguard Worker 	if (iter->curr == NULL) {
1233*cc4ad7daSAndroid Build Coastguard Worker 		iter->curr = iter->list;
1234*cc4ad7daSAndroid Build Coastguard Worker 		return iter->curr != NULL;
1235*cc4ad7daSAndroid Build Coastguard Worker 	}
1236*cc4ad7daSAndroid Build Coastguard Worker 
1237*cc4ad7daSAndroid Build Coastguard Worker 	iter->curr = kmod_list_next(iter->list, iter->curr);
1238*cc4ad7daSAndroid Build Coastguard Worker 
1239*cc4ad7daSAndroid Build Coastguard Worker 	return iter->curr != NULL;
1240*cc4ad7daSAndroid Build Coastguard Worker }
1241*cc4ad7daSAndroid Build Coastguard Worker 
1242*cc4ad7daSAndroid Build Coastguard Worker /**
1243*cc4ad7daSAndroid Build Coastguard Worker  * kmod_config_iter_free_iter:
1244*cc4ad7daSAndroid Build Coastguard Worker  * @iter: iterator over a certain configuration
1245*cc4ad7daSAndroid Build Coastguard Worker  *
1246*cc4ad7daSAndroid Build Coastguard Worker  * Free resources used by the iterator.
1247*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_config_iter_free_iter(struct kmod_config_iter * iter)1248*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_config_iter_free_iter(struct kmod_config_iter *iter)
1249*cc4ad7daSAndroid Build Coastguard Worker {
1250*cc4ad7daSAndroid Build Coastguard Worker 	free(iter->data);
1251*cc4ad7daSAndroid Build Coastguard Worker 	free(iter);
1252*cc4ad7daSAndroid Build Coastguard Worker }
1253