17c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi/*
27c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * libkmod - interface to kernel module operations
37c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi *
4e6b0e49b4ea7937a98b16f23d621244ee1a3e588Lucas De Marchi * Copyright (C) 2011-2013  ProFUSION embedded systems
5342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi * Copyright (C) 2013  Intel Corporation. All rights reserved.
67c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi *
77c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * This library is free software; you can redistribute it and/or
87c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * modify it under the terms of the GNU Lesser General Public
9cb451f35d9fe25ec1dee0628f8af23f022358f6bLucas De Marchi * License as published by the Free Software Foundation; either
10cb451f35d9fe25ec1dee0628f8af23f022358f6bLucas De Marchi * version 2.1 of the License, or (at your option) any later version.
117c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi *
127c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * This library is distributed in the hope that it will be useful,
137c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * but WITHOUT ANY WARRANTY; without even the implied warranty of
147c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
157c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * Lesser General Public License for more details.
167c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi *
177c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi * You should have received a copy of the GNU Lesser General Public
18dea2dfee9b301da84dbb09cf510b8ebf2ef28fffLucas De Marchi * License along with this library; if not, see <http://www.gnu.org/licenses/>.
197c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi */
207c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
21c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <ctype.h>
22c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <dirent.h>
23c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <errno.h>
24c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <stdarg.h>
25c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <stddef.h>
267c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi#include <stdio.h>
277c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi#include <stdlib.h>
287c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi#include <string.h>
29c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <unistd.h>
307c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi#include <sys/stat.h>
317c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi#include <sys/types.h>
327c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
3396573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi#include <shared/util.h>
3496573a02208abebe4a884c0bbd0d6ecde9047f37Lucas De Marchi
357c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi#include "libkmod.h"
3683b855a6ed7028173e231eab0a39c929a962ddf5Lucas De Marchi#include "libkmod-internal.h"
377c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
387c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchistruct kmod_alias {
397c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	char *name;
4043c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri	char modname[];
417c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi};
427c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
43615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchistruct kmod_options {
44615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	char *options;
45615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	char modname[];
46615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi};
47615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
48a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchistruct kmod_command {
49a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	char *command;
50a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	char modname[];
51a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi};
52a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
531c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieristruct kmod_softdep {
541c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	char *name;
551c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	const char **pre;
561c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	const char **post;
571c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	unsigned int n_pre;
581c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	unsigned int n_post;
591c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri};
601c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
61c1c9c446287fa979bf09deca05b8e2c75216b76eLucas De Marchiconst char *kmod_blacklist_get_modname(const struct kmod_list *l)
62c1c9c446287fa979bf09deca05b8e2c75216b76eLucas De Marchi{
63c1c9c446287fa979bf09deca05b8e2c75216b76eLucas De Marchi	return l->data;
64c1c9c446287fa979bf09deca05b8e2c75216b76eLucas De Marchi}
65c1c9c446287fa979bf09deca05b8e2c75216b76eLucas De Marchi
66b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchiconst char *kmod_alias_get_name(const struct kmod_list *l) {
671ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut Barbieri	const struct kmod_alias *alias = l->data;
68b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchi	return alias->name;
69b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchi}
70b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchi
71b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchiconst char *kmod_alias_get_modname(const struct kmod_list *l) {
721ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut Barbieri	const struct kmod_alias *alias = l->data;
73b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchi	return alias->modname;
74b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchi}
75b0ef19f7f5837550114c2923984d4d0f76a0756aLucas De Marchi
76bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbiericonst char *kmod_option_get_options(const struct kmod_list *l) {
77bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	const struct kmod_options *alias = l->data;
78bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	return alias->options;
79bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri}
80bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri
81bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbiericonst char *kmod_option_get_modname(const struct kmod_list *l) {
82bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	const struct kmod_options *alias = l->data;
83bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	return alias->modname;
84bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri}
85bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri
86bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbiericonst char *kmod_command_get_command(const struct kmod_list *l) {
87bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	const struct kmod_command *alias = l->data;
88bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	return alias->command;
89bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri}
90bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri
91bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbiericonst char *kmod_command_get_modname(const struct kmod_list *l) {
92bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	const struct kmod_command *alias = l->data;
93bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri	return alias->modname;
94bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri}
95bd3f5535268836aa697f84fa6946e4b0fc22df0bGustavo Sverzut Barbieri
961c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbiericonst char *kmod_softdep_get_name(const struct kmod_list *l) {
971c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	const struct kmod_softdep *dep = l->data;
981c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	return dep->name;
991c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri}
1001c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
1011c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbiericonst char * const *kmod_softdep_get_pre(const struct kmod_list *l, unsigned int *count) {
1021c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	const struct kmod_softdep *dep = l->data;
1031c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	*count = dep->n_pre;
1041c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	return dep->pre;
1051c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri}
1061c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
1071c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbiericonst char * const *kmod_softdep_get_post(const struct kmod_list *l, unsigned int *count) {
1081c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	const struct kmod_softdep *dep = l->data;
1091c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	*count = dep->n_post;
1101c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	return dep->post;
1111c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri}
1121c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
113a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchistatic int kmod_config_add_command(struct kmod_config *config,
114a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi						const char *modname,
115a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi						const char *command,
116a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi						const char *command_name,
117a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi						struct kmod_list **list)
118a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi{
119342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	_cleanup_free_ struct kmod_command *cmd;
120a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	struct kmod_list *l;
121a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	size_t modnamelen = strlen(modname) + 1;
122a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	size_t commandlen = strlen(command) + 1;
123a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
124e5a7f6ac79d6d5006323a2e9dfd645bef478da11Lucas De Marchi	DBG(config->ctx, "modname='%s' cmd='%s %s'\n", modname, command_name,
125a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi								command);
126a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
127a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	cmd = malloc(sizeof(*cmd) + modnamelen + commandlen);
128342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	if (!cmd)
129342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
130a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
131a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	cmd->command = sizeof(*cmd) + modnamelen + (char *)cmd;
132a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	memcpy(cmd->modname, modname, modnamelen);
133a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	memcpy(cmd->command, command, commandlen);
134a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
135a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	l = kmod_list_append(*list, cmd);
136342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	if (!l)
137342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
138a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
139a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	*list = l;
140342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	cmd = NULL;
141a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	return 0;
142a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi}
143a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
144a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchistatic void kmod_config_free_command(struct kmod_config *config,
145a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi					struct kmod_list *l,
146a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi					struct kmod_list **list)
147a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi{
148a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	struct kmod_command *cmd = l->data;
149a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
150a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	free(cmd);
151a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	*list = kmod_list_remove(l);
152a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi}
153a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
154615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchistatic int kmod_config_add_options(struct kmod_config *config,
155615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi				const char *modname, const char *options)
156615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi{
157342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	_cleanup_free_ struct kmod_options *opt;
158615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	struct kmod_list *list;
159615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	size_t modnamelen = strlen(modname) + 1;
160615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	size_t optionslen = strlen(options) + 1;
161615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
16223c0d012793bf50af18357abb4d10468e586e99aLucas De Marchi	DBG(config->ctx, "modname='%s' options='%s'\n", modname, options);
163615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
164615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	opt = malloc(sizeof(*opt) + modnamelen + optionslen);
165342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	if (!opt)
166342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
167615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
168615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	opt->options = sizeof(*opt) + modnamelen + (char *)opt;
169615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
170615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	memcpy(opt->modname, modname, modnamelen);
171615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	memcpy(opt->options, options, optionslen);
172615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	strchr_replace(opt->options, '\t', ' ');
173615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
174615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	list = kmod_list_append(config->options, opt);
175342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	if (!list)
176342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
177615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
178342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	opt = NULL;
179615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	config->options = list;
180615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	return 0;
181615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi}
182615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
183c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchistatic void kmod_config_free_options(struct kmod_config *config,
184c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi							struct kmod_list *l)
185615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi{
186615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	struct kmod_options *opt = l->data;
187615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
188615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	free(opt);
189615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
190615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	config->options = kmod_list_remove(l);
191615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi}
192615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
193d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieristatic int kmod_config_add_alias(struct kmod_config *config,
194c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi					const char *name, const char *modname)
1957c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
196342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	_cleanup_free_ struct kmod_alias *alias;
197d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	struct kmod_list *list;
19843c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri	size_t namelen = strlen(name) + 1, modnamelen = strlen(modname) + 1;
1997c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
200d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	DBG(config->ctx, "name=%s modname=%s\n", name, modname);
2017c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
20243c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri	alias = malloc(sizeof(*alias) + namelen + modnamelen);
203d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	if (!alias)
204342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
20528c175edd10eb778c706fb133a40150cf1a58054Lucas De Marchi
20643c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri	alias->name = sizeof(*alias) + modnamelen + (char *)alias;
20743c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri
20843c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri	memcpy(alias->modname, modname, modnamelen);
20943c29d10ff8dbe1e73bcea95b1cbb7b27547f828Gustavo Sverzut Barbieri	memcpy(alias->name, name, namelen);
2107c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
211d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	list = kmod_list_append(config->aliases, alias);
212d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	if (!list)
213342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
21428c175edd10eb778c706fb133a40150cf1a58054Lucas De Marchi
215342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	alias = NULL;
216d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	config->aliases = list;
217d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	return 0;
2187c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
2197c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
220c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchistatic void kmod_config_free_alias(struct kmod_config *config,
221c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi							struct kmod_list *l)
2227c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
2237c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	struct kmod_alias *alias = l->data;
2247c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
2257c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	free(alias);
2267c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
227d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	config->aliases = kmod_list_remove(l);
2287c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
2297c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
230d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieristatic int kmod_config_add_blacklist(struct kmod_config *config,
231c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi							const char *modname)
23281cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi{
233342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	_cleanup_free_ char *p;
234d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	struct kmod_list *list;
23581cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
236d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	DBG(config->ctx, "modname=%s\n", modname);
23781cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
23881cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi	p = strdup(modname);
239d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	if (!p)
240342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
241d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri
242d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	list = kmod_list_append(config->blacklists, p);
243d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	if (!list)
244342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi		return -ENOMEM;
245342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi
246342e9cea262578ca847678692b2cc73d659434fdLucas De Marchi	p = NULL;
247d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	config->blacklists = list;
248d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	return 0;
24981cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi}
25081cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
251d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieristatic void kmod_config_free_blacklist(struct kmod_config *config,
25281cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi							struct kmod_list *l)
25381cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi{
25481cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi	free(l->data);
255d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	config->blacklists = kmod_list_remove(l);
25681cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi}
25781cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
2581c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieristatic int kmod_config_add_softdep(struct kmod_config *config,
2591c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri							const char *modname,
2601c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri							const char *line)
2611c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri{
2621c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	struct kmod_list *list;
2631c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	struct kmod_softdep *dep;
2641c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	const char *s, *p;
2651c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	char *itr;
2661c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	unsigned int n_pre = 0, n_post = 0;
2671c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	size_t modnamelen = strlen(modname) + 1;
2681c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	size_t buflen = 0;
2691c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	bool was_space = false;
2701c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	enum { S_NONE, S_PRE, S_POST } mode = S_NONE;
2711c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
2721c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	DBG(config->ctx, "modname=%s\n", modname);
2731c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
2741c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	/* analyze and count */
2751c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	for (p = s = line; ; s++) {
2761c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		size_t plen;
2771c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
2781c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		if (*s != '\0') {
2791c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (!isspace(*s)) {
2801c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				was_space = false;
2811c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				continue;
2821c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			}
2831c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
2841c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (was_space) {
2851c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				p = s + 1;
2861c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				continue;
2871c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			}
2881c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			was_space = true;
2891c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
2901c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (p >= s)
2911c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				continue;
2921c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		}
2931c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		plen = s - p;
2941c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
2951c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		if (plen == sizeof("pre:") - 1 &&
2961c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				memcmp(p, "pre:", sizeof("pre:") - 1) == 0)
2971c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			mode = S_PRE;
2981c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		else if (plen == sizeof("post:") - 1 &&
2991c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				memcmp(p, "post:", sizeof("post:") - 1) == 0)
3001c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			mode = S_POST;
3011c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		else if (*s != '\0' || (*s == '\0' && !was_space)) {
3021c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (mode == S_PRE) {
3031c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				buflen += plen + 1;
3041c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				n_pre++;
3051c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			} else if (mode == S_POST) {
3061c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				buflen += plen + 1;
3071c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				n_post++;
3081c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			}
3091c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		}
3101c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		p = s + 1;
3111c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		if (*s == '\0')
3121c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			break;
3131c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	}
3141c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3151c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	DBG(config->ctx, "%u pre, %u post\n", n_pre, n_post);
3161c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3171c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	dep = malloc(sizeof(struct kmod_softdep) + modnamelen +
3181c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		     n_pre * sizeof(const char *) +
3191c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		     n_post * sizeof(const char *) +
3201c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		     buflen);
3211c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	if (dep == NULL) {
3221c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		ERR(config->ctx, "out-of-memory modname=%s\n", modname);
3231c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		return -ENOMEM;
3241c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	}
3251c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	dep->n_pre = n_pre;
3261c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	dep->n_post = n_post;
3271c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	dep->pre = (const char **)((char *)dep + sizeof(struct kmod_softdep));
3281c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	dep->post = dep->pre + n_pre;
3291c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	dep->name = (char *)(dep->post + n_post);
3301c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3311c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	memcpy(dep->name, modname, modnamelen);
3321c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3331c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	/* copy strings */
3341c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	itr = dep->name + modnamelen;
3351c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	n_pre = 0;
3361c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	n_post = 0;
3371c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	mode = S_NONE;
3381c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	for (p = s = line; ; s++) {
3391c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		size_t plen;
3401c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3411c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		if (*s != '\0') {
3421c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (!isspace(*s)) {
3431c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				was_space = false;
3441c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				continue;
3451c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			}
3461c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3471c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (was_space) {
3481c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				p = s + 1;
3491c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				continue;
3501c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			}
3511c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			was_space = true;
3521c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3531c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (p >= s)
3541c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				continue;
3551c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		}
3561c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		plen = s - p;
3571c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3581c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		if (plen == sizeof("pre:") - 1 &&
3591c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				memcmp(p, "pre:", sizeof("pre:") - 1) == 0)
3601c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			mode = S_PRE;
3611c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		else if (plen == sizeof("post:") - 1 &&
3621c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				memcmp(p, "post:", sizeof("post:") - 1) == 0)
3631c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			mode = S_POST;
3641c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		else if (*s != '\0' || (*s == '\0' && !was_space)) {
3651c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			if (mode == S_PRE) {
3661c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				dep->pre[n_pre] = itr;
3671c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				memcpy(itr, p, plen);
3681c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				itr[plen] = '\0';
3691c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				itr += plen + 1;
3701c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				n_pre++;
3711c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			} else if (mode == S_POST) {
3721c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				dep->post[n_post] = itr;
3731c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				memcpy(itr, p, plen);
3741c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				itr[plen] = '\0';
3751c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				itr += plen + 1;
3761c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				n_post++;
3771c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			}
3781c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		}
3791c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		p = s + 1;
3801c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		if (*s == '\0')
3811c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			break;
3821c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	}
3831c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3841c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	list = kmod_list_append(config->softdeps, dep);
3851c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	if (list == NULL) {
3861c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		free(dep);
3871c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		return -ENOMEM;
3881c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	}
3891c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	config->softdeps = list;
3901c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3911c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	return 0;
3921c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri}
3931c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
3946b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchistatic char *softdep_to_char(struct kmod_softdep *dep) {
3956b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	const size_t sz_preprefix = sizeof("pre: ") - 1;
3966b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	const size_t sz_postprefix = sizeof("post: ") - 1;
3976b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	size_t sz = 1; /* at least '\0' */
3986b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	size_t sz_pre, sz_post;
3996b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	const char *start, *end;
4006b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	char *s, *itr;
4016b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4026b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	/*
4036b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	 * Rely on the fact that dep->pre[] and dep->post[] are strv's that
4046b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	 * point to a contiguous buffer
4056b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	 */
4066b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	if (dep->n_pre > 0) {
4076b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		start = dep->pre[0];
4086b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		end = dep->pre[dep->n_pre - 1]
4096b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi					+ strlen(dep->pre[dep->n_pre - 1]);
4106b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		sz_pre = end - start;
4116b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		sz += sz_pre + sz_preprefix;
4126b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	} else
4136b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		sz_pre = 0;
4146b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4156b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	if (dep->n_post > 0) {
4166b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		start = dep->post[0];
4176b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		end = dep->post[dep->n_post - 1]
4186b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi					+ strlen(dep->post[dep->n_post - 1]);
4196b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		sz_post = end - start;
4206b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		sz += sz_post + sz_postprefix;
4216b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	} else
4226b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		sz_post = 0;
4236b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4246b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	itr = s = malloc(sz);
4256b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	if (s == NULL)
4266b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		return NULL;
4276b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4286b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	if (sz_pre) {
4296b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		char *p;
4306b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4316b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		memcpy(itr, "pre: ", sz_preprefix);
4326b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		itr += sz_preprefix;
4336b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4346b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		/* include last '\0' */
4356b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		memcpy(itr, dep->pre[0], sz_pre + 1);
4366b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		for (p = itr; p < itr + sz_pre; p++) {
4376b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi			if (*p == '\0')
4386b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi				*p = ' ';
4396b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		}
4406b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		itr = p;
4416b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	}
4426b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4436b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	if (sz_post) {
4446b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		char *p;
4456b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4466b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		memcpy(itr, "post: ", sz_postprefix);
4476b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		itr += sz_postprefix;
4486b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4496b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		/* include last '\0' */
4506b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		memcpy(itr, dep->post[0], sz_post + 1);
4516b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		for (p = itr; p < itr + sz_post; p++) {
4526b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi			if (*p == '\0')
4536b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi				*p = ' ';
4546b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		}
4556b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		itr = p;
4566b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	}
4576b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4586b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	*itr = '\0';
4596b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4606b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	return s;
4616b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi}
4626b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
4631c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieristatic void kmod_config_free_softdep(struct kmod_config *config,
4641c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri							struct kmod_list *l)
4651c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri{
4661c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	free(l->data);
4671c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	config->softdeps = kmod_list_remove(l);
4681c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri}
4691c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
4701684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchistatic void kcmdline_parse_result(struct kmod_config *config, char *modname,
4711684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi						char *param, char *value)
4721684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi{
473493dc650d687a5a3acec37ea11d0d1d073b83d5eLucas De Marchi	if (modname == NULL || param == NULL)
4741684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		return;
4751684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
4761684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	DBG(config->ctx, "%s %s\n", modname, param);
4771684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
4781684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	if (streq(modname, "modprobe") && !strncmp(param, "blacklist=", 10)) {
4791684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		for (;;) {
4801684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			char *t = strsep(&value, ",");
4811684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			if (t == NULL)
4821684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi				break;
4831684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
4841684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			kmod_config_add_blacklist(config, t);
4851684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		}
4861684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	} else {
48752c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		if (underscores(modname) < 0) {
48852c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			ERR(config->ctx, "Ignoring bad option on kernel command line while parsing module name: '%s'\n",
48952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			    modname);
49052c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		}
49152c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi		kmod_config_add_options(config, modname, param);
4921684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	}
4931684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi}
4941684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
4951684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchistatic int kmod_config_parse_kcmdline(struct kmod_config *config)
4961684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi{
4971684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	char buf[KCMD_LINE_SIZE];
4981684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	int fd, err;
4998df21177fba3f556d1a3e75d2648c50dfcf09ad0Lucas De Marchi	char *p, *modname,  *param = NULL, *value = NULL;
5008df21177fba3f556d1a3e75d2648c50dfcf09ad0Lucas De Marchi	bool is_quoted = false, is_module = true;
5011684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
50279e5ea91e04e96bdfde63b02c6859128e9b0a8adCristian Rodríguez	fd = open("/proc/cmdline", O_RDONLY|O_CLOEXEC);
503dd1cf10fc468b64c787ace4eae93f159032580d0Lucas De Marchi	if (fd < 0) {
504dd1cf10fc468b64c787ace4eae93f159032580d0Lucas De Marchi		err = -errno;
505dd1cf10fc468b64c787ace4eae93f159032580d0Lucas De Marchi		DBG(config->ctx, "could not open '/proc/cmdline' for reading: %m\n");
506dd1cf10fc468b64c787ace4eae93f159032580d0Lucas De Marchi		return err;
507dd1cf10fc468b64c787ace4eae93f159032580d0Lucas De Marchi	}
508dd1cf10fc468b64c787ace4eae93f159032580d0Lucas De Marchi
5091684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	err = read_str_safe(fd, buf, sizeof(buf));
5101684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	close(fd);
5111684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	if (err < 0) {
5121684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		ERR(config->ctx, "could not read from '/proc/cmdline': %s\n",
5131684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi							strerror(-err));
5141684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		return err;
5151684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	}
5161684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
5171684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	for (p = buf, modname = buf; *p != '\0' && *p != '\n'; p++) {
518f27a2b12748b55abdbdeba6ec3976033bd257947James Minor		if (*p == '"') {
519f27a2b12748b55abdbdeba6ec3976033bd257947James Minor			is_quoted = !is_quoted;
52031dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi
52131dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi			if (is_quoted) {
52231dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				/* don't consider a module until closing quotes */
52331dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				is_module = false;
52431dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi			} else if (param != NULL && value != NULL) {
52531dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				/*
52631dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				 * If we are indeed expecting a value and
52731dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				 * closing quotes, then this can be considered
52831dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				 * a valid option for a module
52931dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				 */
53031dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi				is_module = true;
53131dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi			}
53231dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi
533f27a2b12748b55abdbdeba6ec3976033bd257947James Minor			continue;
534f27a2b12748b55abdbdeba6ec3976033bd257947James Minor		}
535f27a2b12748b55abdbdeba6ec3976033bd257947James Minor		if (is_quoted)
536f27a2b12748b55abdbdeba6ec3976033bd257947James Minor			continue;
53731dd40a6b8fd66127496fc0772b6dbe0a3e5b823Lucas De Marchi
5381684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		switch (*p) {
5391684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		case ' ':
5401684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			*p = '\0';
541aa878540e6f3825cd5cc86d0771e203a6da6231aMichal Marek			if (is_module)
542aa878540e6f3825cd5cc86d0771e203a6da6231aMichal Marek				kcmdline_parse_result(config, modname, param, value);
5431684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			param = value = NULL;
5441684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			modname = p + 1;
5458df21177fba3f556d1a3e75d2648c50dfcf09ad0Lucas De Marchi			is_module = true;
5461684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			break;
5471684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		case '.':
54866f3228d17d66d7e2dd484427259290fbc82b2f0Lucas De Marchi			if (param == NULL) {
54966f3228d17d66d7e2dd484427259290fbc82b2f0Lucas De Marchi				*p = '\0';
55066f3228d17d66d7e2dd484427259290fbc82b2f0Lucas De Marchi				param = p + 1;
55166f3228d17d66d7e2dd484427259290fbc82b2f0Lucas De Marchi			}
5521684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			break;
5531684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		case '=':
554135bffd652cf3afbbb9b9639732cc272e74b6ef8Lucas De Marchi			if (param != NULL)
555135bffd652cf3afbbb9b9639732cc272e74b6ef8Lucas De Marchi				value = p + 1;
556aa878540e6f3825cd5cc86d0771e203a6da6231aMichal Marek			else
5578df21177fba3f556d1a3e75d2648c50dfcf09ad0Lucas De Marchi				is_module = false;
5581684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi			break;
5591684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi		}
5601684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	}
5611684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
5621684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	*p = '\0';
563aa878540e6f3825cd5cc86d0771e203a6da6231aMichal Marek	if (is_module)
564aa878540e6f3825cd5cc86d0771e203a6da6231aMichal Marek		kcmdline_parse_result(config, modname, param, value);
5651684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
5661684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	return 0;
5671684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi}
5681684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
569b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi/*
570b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi * Take an fd and own it. It will be closed on return. filename is used only
571b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi * for debug messages
572b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi */
573b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchistatic int kmod_config_parse(struct kmod_config *config, int fd,
574b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi							const char *filename)
5757c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
576d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	struct kmod_ctx *ctx = config->ctx;
5777c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	char *line;
5787c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	FILE *fp;
579759214fad036866c55b70e6fa1437f19fc08f255Lucas De Marchi	unsigned int linenum = 0;
580b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	int err;
5817c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
582b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	fp = fdopen(fd, "r");
583b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	if (fp == NULL) {
584b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi		err = -errno;
585050db08c57c10cb964d337c5668c4dce309b8d41Lucas De Marchi		ERR(config->ctx, "fd %d: %m\n", fd);
586b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi		close(fd);
587b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi		return err;
588b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	}
5897c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
590aafd38359adfd93b1f8c1e84b8bd7bc9e1b0b6cfLucas De Marchi	while ((line = freadline_wrapped(fp, &linenum)) != NULL) {
591c11e62bfd425fe4bcbb1729215bf18f16f97f768Lucas De Marchi		char *cmd, *saveptr;
5927c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
5937c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi		if (line[0] == '\0' || line[0] == '#')
5947c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi			goto done_next;
5957c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
596c11e62bfd425fe4bcbb1729215bf18f16f97f768Lucas De Marchi		cmd = strtok_r(line, "\t ", &saveptr);
5977c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi		if (cmd == NULL)
5987c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi			goto done_next;
5997c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
600877e80cd934951c02b437fd81c5a2609c20176beLucas De Marchi		if (streq(cmd, "alias")) {
601c11e62bfd425fe4bcbb1729215bf18f16f97f768Lucas De Marchi			char *alias = strtok_r(NULL, "\t ", &saveptr);
602c11e62bfd425fe4bcbb1729215bf18f16f97f768Lucas De Marchi			char *modname = strtok_r(NULL, "\t ", &saveptr);
6037c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
60452c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (underscores(alias) < 0 || underscores(modname) < 0)
6057c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi				goto syntax_error;
6067c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
60752c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			kmod_config_add_alias(config, alias, modname);
608877e80cd934951c02b437fd81c5a2609c20176beLucas De Marchi		} else if (streq(cmd, "blacklist")) {
609c11e62bfd425fe4bcbb1729215bf18f16f97f768Lucas De Marchi			char *modname = strtok_r(NULL, "\t ", &saveptr);
61081cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
61152c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (underscores(modname) < 0)
61281cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi				goto syntax_error;
61381cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
61452c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			kmod_config_add_blacklist(config, modname);
615615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi		} else if (streq(cmd, "options")) {
616615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi			char *modname = strtok_r(NULL, "\t ", &saveptr);
61783121fdea6750b80011587169fa5fd943f755794Lucas De Marchi			char *options = strtok_r(NULL, "\0", &saveptr);
618615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
61952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (underscores(modname) < 0 || options == NULL)
620615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi				goto syntax_error;
621615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
62252c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			kmod_config_add_options(config, modname, options);
62340ee8dadca79b97f830ba9ee04130ba0f46e390bLeandro Pereira		} else if (streq(cmd, "install")) {
624a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi			char *modname = strtok_r(NULL, "\t ", &saveptr);
62583121fdea6750b80011587169fa5fd943f755794Lucas De Marchi			char *installcmd = strtok_r(NULL, "\0", &saveptr);
626a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
62752c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (underscores(modname) < 0 || installcmd == NULL)
628a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi				goto syntax_error;
629a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
63052c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			kmod_config_add_command(config, modname, installcmd,
631a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi					cmd, &config->install_commands);
63240ee8dadca79b97f830ba9ee04130ba0f46e390bLeandro Pereira		} else if (streq(cmd, "remove")) {
633a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi			char *modname = strtok_r(NULL, "\t ", &saveptr);
63483121fdea6750b80011587169fa5fd943f755794Lucas De Marchi			char *removecmd = strtok_r(NULL, "\0", &saveptr);
635a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
63652c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (underscores(modname) < 0 || removecmd == NULL)
637a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi				goto syntax_error;
638a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
63952c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			kmod_config_add_command(config, modname, removecmd,
640a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi					cmd, &config->remove_commands);
64140ee8dadca79b97f830ba9ee04130ba0f46e390bLeandro Pereira		} else if (streq(cmd, "softdep")) {
6421c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri			char *modname = strtok_r(NULL, "\t ", &saveptr);
64383121fdea6750b80011587169fa5fd943f755794Lucas De Marchi			char *softdeps = strtok_r(NULL, "\0", &saveptr);
6441c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
64552c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			if (underscores(modname) < 0 || softdeps == NULL)
6461c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri				goto syntax_error;
6471c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
64852c9c9905683c781e611a5bf3c61fcdc22ab5429Lucas De Marchi			kmod_config_add_softdep(config, modname, softdeps);
649615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi		} else if (streq(cmd, "include")
650877e80cd934951c02b437fd81c5a2609c20176beLucas De Marchi				|| streq(cmd, "config")) {
6510ad5dd083750edcd56adf6f1e88445494c57dc51Lucas De Marchi			ERR(ctx, "%s: command %s is deprecated and not parsed anymore\n",
65281cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi								filename, cmd);
6537c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi		} else {
6547c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchisyntax_error:
6557c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi			ERR(ctx, "%s line %u: ignoring bad line starting with '%s'\n",
6567c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi						filename, linenum, cmd);
6577c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi		}
6587c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
6597c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchidone_next:
6607c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi		free(line);
6617c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	}
6627c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
6637c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	fclose(fp);
6647c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
6657c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	return 0;
6667c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
6677c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
668d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbierivoid kmod_config_free(struct kmod_config *config)
6697c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
6707c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	while (config->aliases)
671d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri		kmod_config_free_alias(config, config->aliases);
67281cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi
67381cf2060e067240ad8c4b9493e1fc1df3d12c956Lucas De Marchi	while (config->blacklists)
674d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri		kmod_config_free_blacklist(config, config->blacklists);
675d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri
676615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi	while (config->options)
677615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi		kmod_config_free_options(config, config->options);
678615c42be5cf756ab246ee520e3371940f1b04e02Lucas De Marchi
679a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	while (config->install_commands) {
680a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi		kmod_config_free_command(config, config->install_commands,
681a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi						&config->install_commands);
682a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	}
683a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
684a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	while (config->remove_commands) {
685a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi		kmod_config_free_command(config, config->remove_commands,
686a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi						&config->remove_commands);
687a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi	}
688a5cce6d6ef6e3b521f903f52066133ddf2ccd70bLucas De Marchi
6891c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri	while (config->softdeps)
6901c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri		kmod_config_free_softdep(config, config->softdeps);
6911c52260048792561160a75a2ce62217e98cd381aGustavo Sverzut Barbieri
692b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	for (; config->paths != NULL;
693b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi				config->paths = kmod_list_remove(config->paths))
694b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		free(config->paths->data);
695b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
696d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	free(config);
6977c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
6987c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
69998c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchistatic bool conf_files_filter_out(struct kmod_ctx *ctx, DIR *d,
70098c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi					const char *path, const char *fn)
7017c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
7027c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	size_t len = strlen(fn);
70398c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi	struct stat st;
7047c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
7057c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	if (fn[0] == '.')
7068f767e2dfa5b391b074b51f2abbc6d3562f424a2Lucas De Marchi		return true;
7077c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
708877e80cd934951c02b437fd81c5a2609c20176beLucas De Marchi	if (len < 6 || (!streq(&fn[len - 5], ".conf")
7099070b117ecef9a53e5224203952fc34256697fb7Dave Reisner				&& !streq(&fn[len - 6], ".alias")))
7108f767e2dfa5b391b074b51f2abbc6d3562f424a2Lucas De Marchi		return true;
7117c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
71298c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi	fstatat(dirfd(d), fn, &st, 0);
71398c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi
71498c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi	if (S_ISDIR(st.st_mode)) {
71598c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi		ERR(ctx, "Directories inside directories are not supported: "
71698c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi							"%s/%s\n", path, fn);
7178f767e2dfa5b391b074b51f2abbc6d3562f424a2Lucas De Marchi		return true;
71898c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi	}
71998c80f44c96238b50678a9fc419a5b41a5598859Lucas De Marchi
7208f767e2dfa5b391b074b51f2abbc6d3562f424a2Lucas De Marchi	return false;
7217c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
7227c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
7237fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchistruct conf_file {
7247fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	const char *path;
7257fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	bool is_single;
7267fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	char name[];
7277fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi};
7287fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7297fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchistatic int conf_files_insert_sorted(struct kmod_ctx *ctx,
7307fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi					struct kmod_list **list,
7317fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi					const char *path, const char *name)
7327fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi{
7337fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	struct kmod_list *lpos, *tmp;
7347fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	struct conf_file *cf;
7357fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	size_t namelen;
7367fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	int cmp = -1;
7377fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	bool is_single = false;
7387fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7397fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (name == NULL) {
7407fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		name = basename(path);
7417fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		is_single = true;
7427fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
7437fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7447fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	kmod_list_foreach(lpos, *list) {
7457fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		cf = lpos->data;
7467fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7477fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		if ((cmp = strcmp(name, cf->name)) <= 0)
7487fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi			break;
7497fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
7507fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7517fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (cmp == 0) {
7527fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		DBG(ctx, "Ignoring duplicate config file: %s/%s\n", path,
7537fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi									name);
7547fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		return -EEXIST;
7557fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
7567fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7577fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	namelen = strlen(name);
7587fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	cf = malloc(sizeof(*cf) + namelen + 1);
7597fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (cf == NULL)
7607fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		return -ENOMEM;
7617fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7627fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	memcpy(cf->name, name, namelen + 1);
7637fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	cf->path = path;
7647fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	cf->is_single = is_single;
7657fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7667fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (lpos == NULL)
7677fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		tmp = kmod_list_append(*list, cf);
7687fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	else if (lpos == *list)
7697fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		tmp = kmod_list_prepend(*list, cf);
7707fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	else
7717fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		tmp = kmod_list_insert_before(lpos, cf);
7727fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7737fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (tmp == NULL) {
7747fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		free(cf);
7757fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		return -ENOMEM;
7767fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
7777fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7787fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (lpos == NULL || lpos == *list)
7797fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		*list = tmp;
7807fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7817fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	return 0;
7827fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi}
7837fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
7844782396cc464feb84a1552379e1909a9446178ccLucas De Marchi/*
7857fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi * Insert configuration files in @list, ignoring duplicates
7864782396cc464feb84a1552379e1909a9446178ccLucas De Marchi */
7877fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchistatic int conf_files_list(struct kmod_ctx *ctx, struct kmod_list **list,
788b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi						const char *path,
789b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi						unsigned long long *path_stamp)
7907c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
7917c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	DIR *d;
7927c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	int err;
7937fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	struct stat st;
7947e0385c47ae7c313a59de3ea431af7b5d18807d7Lucas De Marchi	struct dirent *dent;
7957c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
7967fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	if (stat(path, &st) != 0) {
7977fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		err = -errno;
7987fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		DBG(ctx, "could not stat '%s': %m\n", path);
7997fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		return err;
8007fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
8017fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi
8026068aaaea8e7cdc6039e6fd7a1aeab9db9d0225bLucas De Marchi	*path_stamp = stat_mstamp(&st);
803b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
804519d27de5a209e3b64453e982feb6882ffd839c8Michal Marek	if (!S_ISDIR(st.st_mode)) {
8057fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		conf_files_insert_sorted(ctx, list, path, NULL);
8067fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		return 0;
8077fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
8081c250ec1504150e5be09f2c4a58f9282bf937f86Lucas De Marchi
8097c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	d = opendir(path);
8107c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	if (d == NULL) {
811dfa96f154529a666bee177f4ac44e0d3a9811ad5Gustavo Sverzut Barbieri		ERR(ctx, "opendir(%s): %m\n", path);
8127fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		return -EINVAL;
8137c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	}
8147c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8157e0385c47ae7c313a59de3ea431af7b5d18807d7Lucas De Marchi	for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
8167e0385c47ae7c313a59de3ea431af7b5d18807d7Lucas De Marchi		if (conf_files_filter_out(ctx, d, path, dent->d_name))
8177c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi			continue;
8187c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8197e0385c47ae7c313a59de3ea431af7b5d18807d7Lucas De Marchi		conf_files_insert_sorted(ctx, list, path, dent->d_name);
820b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	}
8217c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8227fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	closedir(d);
8237fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	return 0;
8247c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
8257c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
826c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchiint kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config,
827c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi					const char * const *config_paths)
8287c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi{
829d13e606ff6b064b9939169f1408fc5bd8ab2c1caGustavo Sverzut Barbieri	struct kmod_config *config;
8307fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	struct kmod_list *list = NULL;
831b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	struct kmod_list *path_list = NULL;
832b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	size_t i;
8337c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8348240333b257e96e7dc2ac2522f8bb7fb2158fafcTom Gundersen	conf_files_insert_sorted(ctx, &list, kmod_get_dirname(ctx), "modules.softdep");
8358240333b257e96e7dc2ac2522f8bb7fb2158fafcTom Gundersen
836cb8d4d3e999b1213549fc41618e86bd4ac2f4814Gustavo Sverzut Barbieri	for (i = 0; config_paths[i] != NULL; i++) {
837cb8d4d3e999b1213549fc41618e86bd4ac2f4814Gustavo Sverzut Barbieri		const char *path = config_paths[i];
838b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		unsigned long long path_stamp = 0;
839b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		size_t pathlen;
840b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		struct kmod_list *tmp;
841b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		struct kmod_config_path *cf;
842b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
843b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		if (conf_files_list(ctx, &list, path, &path_stamp) < 0)
844b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi			continue;
845b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
846b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		pathlen = strlen(path) + 1;
847b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		cf = malloc(sizeof(*cf) + pathlen);
848b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		if (cf == NULL)
849b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi			goto oom;
8507c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
851b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		cf->stamp = path_stamp;
852b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		memcpy(cf->path, path, pathlen);
853b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
854b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		tmp = kmod_list_append(path_list, cf);
855b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		if (tmp == NULL)
856b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi			goto oom;
857b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		path_list = tmp;
8587fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	}
859cb8d4d3e999b1213549fc41618e86bd4ac2f4814Gustavo Sverzut Barbieri
860b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	*p_config = config = calloc(1, sizeof(struct kmod_config));
861b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	if (config == NULL)
862b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		goto oom;
863b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
864b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	config->paths = path_list;
86529b69c0b98bdf43907206bfcdaadadcb4a1ea195Lucas De Marchi	config->ctx = ctx;
866b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
8677fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi	for (; list != NULL; list = kmod_list_remove(list)) {
86853d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi		char buf[PATH_MAX];
86953d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi		const char *fn = buf;
8707fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		struct conf_file *cf = list->data;
8717fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		int fd;
872cb8d4d3e999b1213549fc41618e86bd4ac2f4814Gustavo Sverzut Barbieri
87353d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi		if (cf->is_single) {
87453d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi			fn = cf->path;
87553d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi		} else if (snprintf(buf, sizeof(buf), "%s/%s",
87653d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi				    cf->path, cf->name) >= (int)sizeof(buf)) {
87753d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi			ERR(ctx, "Error parsing %s/%s: path too long\n",
87853d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi			    cf->path, cf->name);
87953d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi			free(cf);
88053d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi			continue;
88153d3a99cccf08016eff0351884e7e86a658dffd6Lucas De Marchi		}
8827c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8837fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		fd = open(fn, O_RDONLY|O_CLOEXEC);
8847fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		DBG(ctx, "parsing file '%s' fd=%d\n", fn, fd);
8857c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8867fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		if (fd >= 0)
8877fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi			kmod_config_parse(config, fd, fn);
8887c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8897fe5f7abceb4a22462cf00354f4cef95e20d74c7Lucas De Marchi		free(cf);
8907c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi	}
8917c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi
8921684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi	kmod_config_parse_kcmdline(config);
8931684e4402c1c2ede6c4faf06e6ac1bc0ff284fc8Lucas De Marchi
894b7b7ac298f53db53bebbfeff9dae3e8e4f47724aLucas De Marchi	return 0;
895b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
896b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchioom:
897b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	for (; list != NULL; list = kmod_list_remove(list))
898b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		free(list->data);
899b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
900b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	for (; path_list != NULL; path_list = kmod_list_remove(path_list))
901b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi		free(path_list->data);
902b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi
903b6a4dfb1b4c02a1094e022bc3553250949f73ca9Lucas De Marchi	return -ENOMEM;
9047c2ab358fd1b05be52a3a1d23fe74c7d101a69f9Lucas De Marchi}
9050017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9060017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi/**********************************************************************
9070017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi * struct kmod_config_iter functions
9080017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi **********************************************************************/
9090017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9100017862911984aac14794d0a84872dcb103e5a93Lucas De Marchienum config_type {
9110017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	CONFIG_TYPE_BLACKLIST = 0,
9120017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	CONFIG_TYPE_INSTALL,
9130017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	CONFIG_TYPE_REMOVE,
9140017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	CONFIG_TYPE_ALIAS,
9150017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	CONFIG_TYPE_OPTION,
9160017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	CONFIG_TYPE_SOFTDEP,
9170017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi};
9180017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9190017862911984aac14794d0a84872dcb103e5a93Lucas De Marchistruct kmod_config_iter {
9200017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	enum config_type type;
9216b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	bool intermediate;
9220017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	const struct kmod_list *list;
9230017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	const struct kmod_list *curr;
9246b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	void *data;
9250017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	const char *(*get_key)(const struct kmod_list *l);
9260017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	const char *(*get_value)(const struct kmod_list *l);
9270017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi};
9280017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9296b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchistatic const char *softdep_get_plain_softdep(const struct kmod_list *l)
9306b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi{
9316b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	char *s = softdep_to_char(l->data);
9326b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	return s;
9336b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi}
9346b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
9350017862911984aac14794d0a84872dcb103e5a93Lucas De Marchistatic struct kmod_config_iter *kmod_config_iter_new(const struct kmod_ctx* ctx,
9360017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi							enum config_type type)
9370017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
9380017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	struct kmod_config_iter *iter = calloc(1, sizeof(*iter));
939e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi	const struct kmod_config *config = kmod_get_config(ctx);
9400017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9410017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (iter == NULL)
9420017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;
9430017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9440017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	iter->type = type;
9450017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9460017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	switch (type) {
9470017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	case CONFIG_TYPE_BLACKLIST:
948e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi		iter->list = config->blacklists;
9490017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_key = kmod_blacklist_get_modname;
9500017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		break;
9510017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	case CONFIG_TYPE_INSTALL:
952e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi		iter->list = config->install_commands;
9530017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_key = kmod_command_get_modname;
9540017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_value = kmod_command_get_command;
9550017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		break;
9560017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	case CONFIG_TYPE_REMOVE:
957e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi		iter->list = config->remove_commands;
9580017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_key = kmod_command_get_modname;
9590017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_value = kmod_command_get_command;
9600017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		break;
9610017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	case CONFIG_TYPE_ALIAS:
962e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi		iter->list = config->aliases;
9630017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_key = kmod_alias_get_name;
9640017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_value = kmod_alias_get_modname;
9650017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		break;
9660017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	case CONFIG_TYPE_OPTION:
967e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi		iter->list = config->options;
9680017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_key = kmod_option_get_modname;
9690017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_value = kmod_option_get_options;
9700017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		break;
9710017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	case CONFIG_TYPE_SOFTDEP:
972e7fc2c868e240b280f593934278cc719e33e90f7Lucas De Marchi		iter->list = config->softdeps;
9730017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->get_key = kmod_softdep_get_name;
9746b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		iter->get_value = softdep_get_plain_softdep;
9756b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		iter->intermediate = true;
9760017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		break;
9770017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	}
9780017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9790017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return iter;
9800017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
9810017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
9822f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
9832f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * SECTION:libkmod-config
9842f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @short_description: retrieve current libkmod configuration
9852f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
9862f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi
9872f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
9882f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_get_blacklists:
9892f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @ctx: kmod library context
9902f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
9912f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Retrieve an iterator to deal with the blacklist maintained inside the
9922f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
9932f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
9942f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * be made to initialize the iterator and check if it's valid.
9952f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
996883d8c42c7af5fe1c60868dde973acf76389b759Lucas De Marchi * Returns: a new iterator over the blacklists or NULL on failure. Free it
9972f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * with kmod_config_iter_free_iter().
9982f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
9990017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT struct kmod_config_iter *kmod_config_get_blacklists(const struct kmod_ctx *ctx)
10000017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
10010017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (ctx == NULL)
10020017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;;
10030017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10040017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return kmod_config_iter_new(ctx, CONFIG_TYPE_BLACKLIST);
10050017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
10060017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10072f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
10082f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_get_install_commands:
10092f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @ctx: kmod library context
10102f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
10112f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Retrieve an iterator to deal with the install commands maintained inside the
10122f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
10132f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
10142f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * be made to initialize the iterator and check if it's valid.
10152f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
1016883d8c42c7af5fe1c60868dde973acf76389b759Lucas De Marchi * Returns: a new iterator over the install commands or NULL on failure. Free
10172f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * it with kmod_config_iter_free_iter().
10182f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
10190017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT struct kmod_config_iter *kmod_config_get_install_commands(const struct kmod_ctx *ctx)
10200017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
10210017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (ctx == NULL)
10220017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;;
10230017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10240017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return kmod_config_iter_new(ctx, CONFIG_TYPE_INSTALL);
10250017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
10260017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10272f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
10282f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_get_remove_commands:
10292f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @ctx: kmod library context
10302f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
10312f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Retrieve an iterator to deal with the remove commands maintained inside the
10322f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
10332f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
10342f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * be made to initialize the iterator and check if it's valid.
10352f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
1036883d8c42c7af5fe1c60868dde973acf76389b759Lucas De Marchi * Returns: a new iterator over the remove commands or NULL on failure. Free
10372f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * it with kmod_config_iter_free_iter().
10382f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
10390017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT struct kmod_config_iter *kmod_config_get_remove_commands(const struct kmod_ctx *ctx)
10400017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
10410017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (ctx == NULL)
10420017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;;
10430017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10440017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return kmod_config_iter_new(ctx, CONFIG_TYPE_REMOVE);
10450017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
10460017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10472f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
10482f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_get_aliases:
10492f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @ctx: kmod library context
10502f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
10512f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Retrieve an iterator to deal with the aliases maintained inside the
10522f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
10532f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
10542f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * be made to initialize the iterator and check if it's valid.
10552f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
1056883d8c42c7af5fe1c60868dde973acf76389b759Lucas De Marchi * Returns: a new iterator over the aliases or NULL on failure. Free it with
10572f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_free_iter().
10582f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
10590017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT struct kmod_config_iter *kmod_config_get_aliases(const struct kmod_ctx *ctx)
10600017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
10610017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (ctx == NULL)
10620017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;;
10630017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10640017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return kmod_config_iter_new(ctx, CONFIG_TYPE_ALIAS);
10650017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
10660017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10672f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
10682f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_get_options:
10692f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @ctx: kmod library context
10702f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
10712f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Retrieve an iterator to deal with the options maintained inside the
10722f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
10732f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
10742f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * be made to initialize the iterator and check if it's valid.
10752f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
1076883d8c42c7af5fe1c60868dde973acf76389b759Lucas De Marchi * Returns: a new iterator over the options or NULL on failure. Free it with
10772f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_free_iter().
10782f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
10790017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT struct kmod_config_iter *kmod_config_get_options(const struct kmod_ctx *ctx)
10800017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
10810017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (ctx == NULL)
10820017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;;
10830017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10840017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return kmod_config_iter_new(ctx, CONFIG_TYPE_OPTION);
10850017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
10860017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
10872f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
10882f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_get_softdeps:
10892f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @ctx: kmod library context
10902f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
10912f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Retrieve an iterator to deal with the softdeps maintained inside the
10922f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * library. See kmod_config_iter_get_key(), kmod_config_iter_get_value() and
10932f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next(). At least one call to kmod_config_iter_next() must
10942f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * be made to initialize the iterator and check if it's valid.
10952f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
1096883d8c42c7af5fe1c60868dde973acf76389b759Lucas De Marchi * Returns: a new iterator over the softdeps or NULL on failure. Free it with
10972f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_free_iter().
10982f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
10990017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT struct kmod_config_iter *kmod_config_get_softdeps(const struct kmod_ctx *ctx)
11000017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
11010017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (ctx == NULL)
11020017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;;
11030017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11040017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return kmod_config_iter_new(ctx, CONFIG_TYPE_SOFTDEP);
11050017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
11060017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11072f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
11082f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_get_key:
11092f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @iter: iterator over a certain configuration
11102f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11112f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * When using a new allocated iterator, user must perform a call to
11122f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next() to initialize iterator's position and check if it's
11132f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * valid.
11142f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11152f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Returns: the key of the current configuration pointed by @iter.
11162f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
11170017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT const char *kmod_config_iter_get_key(const struct kmod_config_iter *iter)
11180017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
11190017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (iter == NULL || iter->curr == NULL)
11200017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;
11210017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11220017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return iter->get_key(iter->curr);
11230017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
11240017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11252f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
11262f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_get_value:
11272f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @iter: iterator over a certain configuration
11282f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11292f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * When using a new allocated iterator, user must perform a call to
11302f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next() to initialize iterator's position and check if it's
11312f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * valid.
11322f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11332f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Returns: the value of the current configuration pointed by @iter.
11342f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
11350017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT const char *kmod_config_iter_get_value(const struct kmod_config_iter *iter)
11360017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
11376b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	const char *s;
11386b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
11390017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (iter == NULL || iter->curr == NULL)
11400017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;
11410017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11420017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (iter->get_value == NULL)
11430017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return NULL;
11440017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11456b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	if (iter->intermediate) {
11466b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		struct kmod_config_iter *i = (struct kmod_config_iter *)iter;
11476b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
11486b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		free(i->data);
11496b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		s = i->data = (void *) iter->get_value(iter->curr);
11506b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	} else
11516b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi		s = iter->get_value(iter->curr);
11526b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi
11536b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	return s;
11540017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
11550017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11562f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
11572f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_next:
11582f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @iter: iterator over a certain configuration
11592f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11602f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Make @iter point to the next item of a certain configuration. It's an
11612f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * automatically recycling iterator. When it reaches the end, false is
11622f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * returned; then if user wants to iterate again, it's sufficient to call this
11632f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * function once more.
11642f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11652f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Returns: true if next position of @iter is valid or false if its end is
11662f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * reached.
11672f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
11680017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT bool kmod_config_iter_next(struct kmod_config_iter *iter)
11690017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
11700017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (iter == NULL)
11710017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return false;
11720017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11730017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	if (iter->curr == NULL) {
11740017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		iter->curr = iter->list;
11750017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi		return iter->curr != NULL;
11760017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	}
11770017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11780017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	iter->curr = kmod_list_next(iter->list, iter->curr);
11790017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11800017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	return iter->curr != NULL;
11810017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
11820017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi
11832f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi/**
11842f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * kmod_config_iter_free_iter:
11852f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * @iter: iterator over a certain configuration
11862f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi *
11872f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi * Free resources used by the iterator.
11882f47c7fae9be6d786eabf89ee4dc6585e779b641Lucas De Marchi */
11890017862911984aac14794d0a84872dcb103e5a93Lucas De MarchiKMOD_EXPORT void kmod_config_iter_free_iter(struct kmod_config_iter *iter)
11900017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi{
11916b04ef324ab2fe3fd11051bcdd63c51751ecb309Lucas De Marchi	free(iter->data);
11920017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi	free(iter);
11930017862911984aac14794d0a84872dcb103e5a93Lucas De Marchi}
1194