xref: /aosp_15_r20/external/kmod/libkmod/libkmod-module.c (revision cc4ad7da8cefe208cb129ac2aa9a357c7c72deb2)
1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker  * libkmod - interface to kernel module operations
3*cc4ad7daSAndroid Build Coastguard Worker  *
4*cc4ad7daSAndroid Build Coastguard Worker  * Copyright (C) 2011-2013  ProFUSION embedded systems
5*cc4ad7daSAndroid Build Coastguard Worker  *
6*cc4ad7daSAndroid Build Coastguard Worker  * This library is free software; you can redistribute it and/or
7*cc4ad7daSAndroid Build Coastguard Worker  * modify it under the terms of the GNU Lesser General Public
8*cc4ad7daSAndroid Build Coastguard Worker  * License as published by the Free Software Foundation; either
9*cc4ad7daSAndroid Build Coastguard Worker  * version 2.1 of the License, or (at your option) any later version.
10*cc4ad7daSAndroid Build Coastguard Worker  *
11*cc4ad7daSAndroid Build Coastguard Worker  * This library is distributed in the hope that it will be useful,
12*cc4ad7daSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*cc4ad7daSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*cc4ad7daSAndroid Build Coastguard Worker  * Lesser General Public License for more details.
15*cc4ad7daSAndroid Build Coastguard Worker  *
16*cc4ad7daSAndroid Build Coastguard Worker  * You should have received a copy of the GNU Lesser General Public
17*cc4ad7daSAndroid Build Coastguard Worker  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18*cc4ad7daSAndroid Build Coastguard Worker  */
19*cc4ad7daSAndroid Build Coastguard Worker 
20*cc4ad7daSAndroid Build Coastguard Worker #include <assert.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <ctype.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <dirent.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <fnmatch.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <inttypes.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <stddef.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
33*cc4ad7daSAndroid Build Coastguard Worker #include <sys/mman.h>
34*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
35*cc4ad7daSAndroid Build Coastguard Worker #include <sys/syscall.h>
36*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
37*cc4ad7daSAndroid Build Coastguard Worker #include <sys/wait.h>
38*cc4ad7daSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_MODULE_H
39*cc4ad7daSAndroid Build Coastguard Worker #include <linux/module.h>
40*cc4ad7daSAndroid Build Coastguard Worker #endif
41*cc4ad7daSAndroid Build Coastguard Worker 
42*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
43*cc4ad7daSAndroid Build Coastguard Worker 
44*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod.h"
45*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod-internal.h"
46*cc4ad7daSAndroid Build Coastguard Worker 
47*cc4ad7daSAndroid Build Coastguard Worker /**
48*cc4ad7daSAndroid Build Coastguard Worker  * SECTION:libkmod-module
49*cc4ad7daSAndroid Build Coastguard Worker  * @short_description: operate on kernel modules
50*cc4ad7daSAndroid Build Coastguard Worker  */
51*cc4ad7daSAndroid Build Coastguard Worker 
52*cc4ad7daSAndroid Build Coastguard Worker enum kmod_module_builtin {
53*cc4ad7daSAndroid Build Coastguard Worker     KMOD_MODULE_BUILTIN_UNKNOWN,
54*cc4ad7daSAndroid Build Coastguard Worker     KMOD_MODULE_BUILTIN_NO,
55*cc4ad7daSAndroid Build Coastguard Worker     KMOD_MODULE_BUILTIN_YES,
56*cc4ad7daSAndroid Build Coastguard Worker };
57*cc4ad7daSAndroid Build Coastguard Worker 
58*cc4ad7daSAndroid Build Coastguard Worker /**
59*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module:
60*cc4ad7daSAndroid Build Coastguard Worker  *
61*cc4ad7daSAndroid Build Coastguard Worker  * Opaque object representing a module.
62*cc4ad7daSAndroid Build Coastguard Worker  */
63*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module {
64*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_ctx *ctx;
65*cc4ad7daSAndroid Build Coastguard Worker 	char *hashkey;
66*cc4ad7daSAndroid Build Coastguard Worker 	char *name;
67*cc4ad7daSAndroid Build Coastguard Worker 	char *path;
68*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *dep;
69*cc4ad7daSAndroid Build Coastguard Worker 	char *options;
70*cc4ad7daSAndroid Build Coastguard Worker 	const char *install_commands;	/* owned by kmod_config */
71*cc4ad7daSAndroid Build Coastguard Worker 	const char *remove_commands;	/* owned by kmod_config */
72*cc4ad7daSAndroid Build Coastguard Worker 	char *alias; /* only set if this module was created from an alias */
73*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_file *file;
74*cc4ad7daSAndroid Build Coastguard Worker 	int n_dep;
75*cc4ad7daSAndroid Build Coastguard Worker 	int refcount;
76*cc4ad7daSAndroid Build Coastguard Worker 	struct {
77*cc4ad7daSAndroid Build Coastguard Worker 		bool dep : 1;
78*cc4ad7daSAndroid Build Coastguard Worker 		bool options : 1;
79*cc4ad7daSAndroid Build Coastguard Worker 		bool install_commands : 1;
80*cc4ad7daSAndroid Build Coastguard Worker 		bool remove_commands : 1;
81*cc4ad7daSAndroid Build Coastguard Worker 	} init;
82*cc4ad7daSAndroid Build Coastguard Worker 
83*cc4ad7daSAndroid Build Coastguard Worker 	/*
84*cc4ad7daSAndroid Build Coastguard Worker 	 * mark if module is builtin, i.e. it's present on modules.builtin
85*cc4ad7daSAndroid Build Coastguard Worker 	 * file. This is set as soon as it is needed or as soon as we know
86*cc4ad7daSAndroid Build Coastguard Worker 	 * about it, i.e. the module was created from builtin lookup.
87*cc4ad7daSAndroid Build Coastguard Worker 	 */
88*cc4ad7daSAndroid Build Coastguard Worker 	enum kmod_module_builtin builtin;
89*cc4ad7daSAndroid Build Coastguard Worker 
90*cc4ad7daSAndroid Build Coastguard Worker 	/*
91*cc4ad7daSAndroid Build Coastguard Worker 	 * private field used by kmod_module_get_probe_list() to detect
92*cc4ad7daSAndroid Build Coastguard Worker 	 * dependency loops
93*cc4ad7daSAndroid Build Coastguard Worker 	 */
94*cc4ad7daSAndroid Build Coastguard Worker 	bool visited : 1;
95*cc4ad7daSAndroid Build Coastguard Worker 
96*cc4ad7daSAndroid Build Coastguard Worker 	/*
97*cc4ad7daSAndroid Build Coastguard Worker 	 * set by kmod_module_get_probe_list: indicates for probe_insert()
98*cc4ad7daSAndroid Build Coastguard Worker 	 * whether the module's command and softdep should be ignored
99*cc4ad7daSAndroid Build Coastguard Worker 	 */
100*cc4ad7daSAndroid Build Coastguard Worker 	bool ignorecmd : 1;
101*cc4ad7daSAndroid Build Coastguard Worker 
102*cc4ad7daSAndroid Build Coastguard Worker 	/*
103*cc4ad7daSAndroid Build Coastguard Worker 	 * set by kmod_module_get_probe_list: indicates whether this is the
104*cc4ad7daSAndroid Build Coastguard Worker 	 * module the user asked for or its dependency, or whether this
105*cc4ad7daSAndroid Build Coastguard Worker 	 * is a softdep only
106*cc4ad7daSAndroid Build Coastguard Worker 	 */
107*cc4ad7daSAndroid Build Coastguard Worker 	bool required : 1;
108*cc4ad7daSAndroid Build Coastguard Worker };
109*cc4ad7daSAndroid Build Coastguard Worker 
path_join(const char * path,size_t prefixlen,char buf[PATH_MAX])110*cc4ad7daSAndroid Build Coastguard Worker static inline const char *path_join(const char *path, size_t prefixlen,
111*cc4ad7daSAndroid Build Coastguard Worker 							char buf[PATH_MAX])
112*cc4ad7daSAndroid Build Coastguard Worker {
113*cc4ad7daSAndroid Build Coastguard Worker 	size_t pathlen;
114*cc4ad7daSAndroid Build Coastguard Worker 
115*cc4ad7daSAndroid Build Coastguard Worker 	if (path[0] == '/')
116*cc4ad7daSAndroid Build Coastguard Worker 		return path;
117*cc4ad7daSAndroid Build Coastguard Worker 
118*cc4ad7daSAndroid Build Coastguard Worker 	pathlen = strlen(path);
119*cc4ad7daSAndroid Build Coastguard Worker 	if (prefixlen + pathlen + 1 >= PATH_MAX)
120*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
121*cc4ad7daSAndroid Build Coastguard Worker 
122*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(buf + prefixlen, path, pathlen + 1);
123*cc4ad7daSAndroid Build Coastguard Worker 	return buf;
124*cc4ad7daSAndroid Build Coastguard Worker }
125*cc4ad7daSAndroid Build Coastguard Worker 
module_is_inkernel(struct kmod_module * mod)126*cc4ad7daSAndroid Build Coastguard Worker static inline bool module_is_inkernel(struct kmod_module *mod)
127*cc4ad7daSAndroid Build Coastguard Worker {
128*cc4ad7daSAndroid Build Coastguard Worker 	int state = kmod_module_get_initstate(mod);
129*cc4ad7daSAndroid Build Coastguard Worker 
130*cc4ad7daSAndroid Build Coastguard Worker 	if (state == KMOD_MODULE_LIVE ||
131*cc4ad7daSAndroid Build Coastguard Worker 			state == KMOD_MODULE_BUILTIN)
132*cc4ad7daSAndroid Build Coastguard Worker 		return true;
133*cc4ad7daSAndroid Build Coastguard Worker 
134*cc4ad7daSAndroid Build Coastguard Worker 	return false;
135*cc4ad7daSAndroid Build Coastguard Worker }
136*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_parse_depline(struct kmod_module * mod,char * line)137*cc4ad7daSAndroid Build Coastguard Worker int kmod_module_parse_depline(struct kmod_module *mod, char *line)
138*cc4ad7daSAndroid Build Coastguard Worker {
139*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_ctx *ctx = mod->ctx;
140*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list = NULL;
141*cc4ad7daSAndroid Build Coastguard Worker 	const char *dirname;
142*cc4ad7daSAndroid Build Coastguard Worker 	char buf[PATH_MAX];
143*cc4ad7daSAndroid Build Coastguard Worker 	char *p, *saveptr;
144*cc4ad7daSAndroid Build Coastguard Worker 	int err = 0, n = 0;
145*cc4ad7daSAndroid Build Coastguard Worker 	size_t dirnamelen;
146*cc4ad7daSAndroid Build Coastguard Worker 
147*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->init.dep)
148*cc4ad7daSAndroid Build Coastguard Worker 		return mod->n_dep;
149*cc4ad7daSAndroid Build Coastguard Worker 	assert(mod->dep == NULL);
150*cc4ad7daSAndroid Build Coastguard Worker 	mod->init.dep = true;
151*cc4ad7daSAndroid Build Coastguard Worker 
152*cc4ad7daSAndroid Build Coastguard Worker 	p = strchr(line, ':');
153*cc4ad7daSAndroid Build Coastguard Worker 	if (p == NULL)
154*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
155*cc4ad7daSAndroid Build Coastguard Worker 
156*cc4ad7daSAndroid Build Coastguard Worker 	*p = '\0';
157*cc4ad7daSAndroid Build Coastguard Worker 	dirname = kmod_get_dirname(mod->ctx);
158*cc4ad7daSAndroid Build Coastguard Worker 	dirnamelen = strlen(dirname);
159*cc4ad7daSAndroid Build Coastguard Worker 	if (dirnamelen + 2 >= PATH_MAX)
160*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
161*cc4ad7daSAndroid Build Coastguard Worker 
162*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(buf, dirname, dirnamelen);
163*cc4ad7daSAndroid Build Coastguard Worker 	buf[dirnamelen] = '/';
164*cc4ad7daSAndroid Build Coastguard Worker 	dirnamelen++;
165*cc4ad7daSAndroid Build Coastguard Worker 	buf[dirnamelen] = '\0';
166*cc4ad7daSAndroid Build Coastguard Worker 
167*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->path == NULL) {
168*cc4ad7daSAndroid Build Coastguard Worker 		const char *str = path_join(line, dirnamelen, buf);
169*cc4ad7daSAndroid Build Coastguard Worker 		if (str == NULL)
170*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
171*cc4ad7daSAndroid Build Coastguard Worker 		mod->path = strdup(str);
172*cc4ad7daSAndroid Build Coastguard Worker 		if (mod->path == NULL)
173*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
174*cc4ad7daSAndroid Build Coastguard Worker 	}
175*cc4ad7daSAndroid Build Coastguard Worker 
176*cc4ad7daSAndroid Build Coastguard Worker 	p++;
177*cc4ad7daSAndroid Build Coastguard Worker 	for (p = strtok_r(p, " \t", &saveptr); p != NULL;
178*cc4ad7daSAndroid Build Coastguard Worker 					p = strtok_r(NULL, " \t", &saveptr)) {
179*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *depmod = NULL;
180*cc4ad7daSAndroid Build Coastguard Worker 		const char *path;
181*cc4ad7daSAndroid Build Coastguard Worker 
182*cc4ad7daSAndroid Build Coastguard Worker 		path = path_join(p, dirnamelen, buf);
183*cc4ad7daSAndroid Build Coastguard Worker 		if (path == NULL) {
184*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "could not join path '%s' and '%s'.\n",
185*cc4ad7daSAndroid Build Coastguard Worker 			    dirname, p);
186*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
187*cc4ad7daSAndroid Build Coastguard Worker 		}
188*cc4ad7daSAndroid Build Coastguard Worker 
189*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new_from_path(ctx, path, &depmod);
190*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
191*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "ctx=%p path=%s error=%s\n",
192*cc4ad7daSAndroid Build Coastguard Worker 						ctx, path, strerror(-err));
193*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
194*cc4ad7daSAndroid Build Coastguard Worker 		}
195*cc4ad7daSAndroid Build Coastguard Worker 
196*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "add dep: %s\n", path);
197*cc4ad7daSAndroid Build Coastguard Worker 
198*cc4ad7daSAndroid Build Coastguard Worker 		list = kmod_list_prepend(list, depmod);
199*cc4ad7daSAndroid Build Coastguard Worker 		n++;
200*cc4ad7daSAndroid Build Coastguard Worker 	}
201*cc4ad7daSAndroid Build Coastguard Worker 
202*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "%d dependencies for %s\n", n, mod->name);
203*cc4ad7daSAndroid Build Coastguard Worker 
204*cc4ad7daSAndroid Build Coastguard Worker 	mod->dep = list;
205*cc4ad7daSAndroid Build Coastguard Worker 	mod->n_dep = n;
206*cc4ad7daSAndroid Build Coastguard Worker 	return n;
207*cc4ad7daSAndroid Build Coastguard Worker 
208*cc4ad7daSAndroid Build Coastguard Worker fail:
209*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(list);
210*cc4ad7daSAndroid Build Coastguard Worker 	mod->init.dep = false;
211*cc4ad7daSAndroid Build Coastguard Worker 	return err;
212*cc4ad7daSAndroid Build Coastguard Worker }
213*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_set_visited(struct kmod_module * mod,bool visited)214*cc4ad7daSAndroid Build Coastguard Worker void kmod_module_set_visited(struct kmod_module *mod, bool visited)
215*cc4ad7daSAndroid Build Coastguard Worker {
216*cc4ad7daSAndroid Build Coastguard Worker 	mod->visited = visited;
217*cc4ad7daSAndroid Build Coastguard Worker }
218*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_set_builtin(struct kmod_module * mod,bool builtin)219*cc4ad7daSAndroid Build Coastguard Worker void kmod_module_set_builtin(struct kmod_module *mod, bool builtin)
220*cc4ad7daSAndroid Build Coastguard Worker {
221*cc4ad7daSAndroid Build Coastguard Worker 	mod->builtin =
222*cc4ad7daSAndroid Build Coastguard Worker 		builtin ? KMOD_MODULE_BUILTIN_YES : KMOD_MODULE_BUILTIN_NO;
223*cc4ad7daSAndroid Build Coastguard Worker }
224*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_set_required(struct kmod_module * mod,bool required)225*cc4ad7daSAndroid Build Coastguard Worker void kmod_module_set_required(struct kmod_module *mod, bool required)
226*cc4ad7daSAndroid Build Coastguard Worker {
227*cc4ad7daSAndroid Build Coastguard Worker 	mod->required = required;
228*cc4ad7daSAndroid Build Coastguard Worker }
229*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_is_builtin(struct kmod_module * mod)230*cc4ad7daSAndroid Build Coastguard Worker bool kmod_module_is_builtin(struct kmod_module *mod)
231*cc4ad7daSAndroid Build Coastguard Worker {
232*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->builtin == KMOD_MODULE_BUILTIN_UNKNOWN) {
233*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_set_builtin(mod,
234*cc4ad7daSAndroid Build Coastguard Worker 					kmod_lookup_alias_is_builtin(mod->ctx, mod->name));
235*cc4ad7daSAndroid Build Coastguard Worker 	}
236*cc4ad7daSAndroid Build Coastguard Worker 
237*cc4ad7daSAndroid Build Coastguard Worker 	return mod->builtin == KMOD_MODULE_BUILTIN_YES;
238*cc4ad7daSAndroid Build Coastguard Worker }
239*cc4ad7daSAndroid Build Coastguard Worker /*
240*cc4ad7daSAndroid Build Coastguard Worker  * Memory layout with alias:
241*cc4ad7daSAndroid Build Coastguard Worker  *
242*cc4ad7daSAndroid Build Coastguard Worker  * struct kmod_module {
243*cc4ad7daSAndroid Build Coastguard Worker  *        hashkey -----.
244*cc4ad7daSAndroid Build Coastguard Worker  *        alias -----. |
245*cc4ad7daSAndroid Build Coastguard Worker  *        name ----. | |
246*cc4ad7daSAndroid Build Coastguard Worker  * }               | | |
247*cc4ad7daSAndroid Build Coastguard Worker  * name <----------' | |
248*cc4ad7daSAndroid Build Coastguard Worker  * alias <-----------' |
249*cc4ad7daSAndroid Build Coastguard Worker  * name\alias <--------'
250*cc4ad7daSAndroid Build Coastguard Worker  *
251*cc4ad7daSAndroid Build Coastguard Worker  * Memory layout without alias:
252*cc4ad7daSAndroid Build Coastguard Worker  *
253*cc4ad7daSAndroid Build Coastguard Worker  * struct kmod_module {
254*cc4ad7daSAndroid Build Coastguard Worker  *        hashkey ---.
255*cc4ad7daSAndroid Build Coastguard Worker  *        alias -----|----> NULL
256*cc4ad7daSAndroid Build Coastguard Worker  *        name ----. |
257*cc4ad7daSAndroid Build Coastguard Worker  * }               | |
258*cc4ad7daSAndroid Build Coastguard Worker  * name <----------'-'
259*cc4ad7daSAndroid Build Coastguard Worker  *
260*cc4ad7daSAndroid Build Coastguard Worker  * @key is "name\alias" or "name" (in which case alias == NULL)
261*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_new(struct kmod_ctx * ctx,const char * key,const char * name,size_t namelen,const char * alias,size_t aliaslen,struct kmod_module ** mod)262*cc4ad7daSAndroid Build Coastguard Worker static int kmod_module_new(struct kmod_ctx *ctx, const char *key,
263*cc4ad7daSAndroid Build Coastguard Worker 				const char *name, size_t namelen,
264*cc4ad7daSAndroid Build Coastguard Worker 				const char *alias, size_t aliaslen,
265*cc4ad7daSAndroid Build Coastguard Worker 				struct kmod_module **mod)
266*cc4ad7daSAndroid Build Coastguard Worker {
267*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module *m;
268*cc4ad7daSAndroid Build Coastguard Worker 	size_t keylen;
269*cc4ad7daSAndroid Build Coastguard Worker 
270*cc4ad7daSAndroid Build Coastguard Worker 	m = kmod_pool_get_module(ctx, key);
271*cc4ad7daSAndroid Build Coastguard Worker 	if (m != NULL) {
272*cc4ad7daSAndroid Build Coastguard Worker 		*mod = kmod_module_ref(m);
273*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
274*cc4ad7daSAndroid Build Coastguard Worker 	}
275*cc4ad7daSAndroid Build Coastguard Worker 
276*cc4ad7daSAndroid Build Coastguard Worker 	if (alias == NULL)
277*cc4ad7daSAndroid Build Coastguard Worker 		keylen = namelen;
278*cc4ad7daSAndroid Build Coastguard Worker 	else
279*cc4ad7daSAndroid Build Coastguard Worker 		keylen = namelen + aliaslen + 1;
280*cc4ad7daSAndroid Build Coastguard Worker 
281*cc4ad7daSAndroid Build Coastguard Worker 	m = malloc(sizeof(*m) + (alias == NULL ? 1 : 2) * (keylen + 1));
282*cc4ad7daSAndroid Build Coastguard Worker 	if (m == NULL)
283*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
284*cc4ad7daSAndroid Build Coastguard Worker 
285*cc4ad7daSAndroid Build Coastguard Worker 	memset(m, 0, sizeof(*m));
286*cc4ad7daSAndroid Build Coastguard Worker 
287*cc4ad7daSAndroid Build Coastguard Worker 	m->ctx = kmod_ref(ctx);
288*cc4ad7daSAndroid Build Coastguard Worker 	m->name = (char *)m + sizeof(*m);
289*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(m->name, key, keylen + 1);
290*cc4ad7daSAndroid Build Coastguard Worker 	if (alias == NULL) {
291*cc4ad7daSAndroid Build Coastguard Worker 		m->hashkey = m->name;
292*cc4ad7daSAndroid Build Coastguard Worker 		m->alias = NULL;
293*cc4ad7daSAndroid Build Coastguard Worker 	} else {
294*cc4ad7daSAndroid Build Coastguard Worker 		m->name[namelen] = '\0';
295*cc4ad7daSAndroid Build Coastguard Worker 		m->alias = m->name + namelen + 1;
296*cc4ad7daSAndroid Build Coastguard Worker 		m->hashkey = m->name + keylen + 1;
297*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(m->hashkey, key, keylen + 1);
298*cc4ad7daSAndroid Build Coastguard Worker 	}
299*cc4ad7daSAndroid Build Coastguard Worker 
300*cc4ad7daSAndroid Build Coastguard Worker 	m->refcount = 1;
301*cc4ad7daSAndroid Build Coastguard Worker 	kmod_pool_add_module(ctx, m, m->hashkey);
302*cc4ad7daSAndroid Build Coastguard Worker 	*mod = m;
303*cc4ad7daSAndroid Build Coastguard Worker 
304*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
305*cc4ad7daSAndroid Build Coastguard Worker }
306*cc4ad7daSAndroid Build Coastguard Worker 
307*cc4ad7daSAndroid Build Coastguard Worker /**
308*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_new_from_name:
309*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
310*cc4ad7daSAndroid Build Coastguard Worker  * @name: name of the module
311*cc4ad7daSAndroid Build Coastguard Worker  * @mod: where to save the created struct kmod_module
312*cc4ad7daSAndroid Build Coastguard Worker  *
313*cc4ad7daSAndroid Build Coastguard Worker  * Create a new struct kmod_module using the module name. @name can not be an
314*cc4ad7daSAndroid Build Coastguard Worker  * alias, file name or anything else; it must be a module name. There's no
315*cc4ad7daSAndroid Build Coastguard Worker  * check if the module exists in the system.
316*cc4ad7daSAndroid Build Coastguard Worker  *
317*cc4ad7daSAndroid Build Coastguard Worker  * This function is also used internally by many others that return a new
318*cc4ad7daSAndroid Build Coastguard Worker  * struct kmod_module or a new list of modules.
319*cc4ad7daSAndroid Build Coastguard Worker  *
320*cc4ad7daSAndroid Build Coastguard Worker  * The initial refcount is 1, and needs to be decremented to release the
321*cc4ad7daSAndroid Build Coastguard Worker  * resources of the kmod_module. Since libkmod keeps track of all
322*cc4ad7daSAndroid Build Coastguard Worker  * kmod_modules created, they are all released upon @ctx destruction too. Do
323*cc4ad7daSAndroid Build Coastguard Worker  * not unref @ctx before all the desired operations with the returned
324*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module are done.
325*cc4ad7daSAndroid Build Coastguard Worker  *
326*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise. It fails if name is not a valid
327*cc4ad7daSAndroid Build Coastguard Worker  * module name or if memory allocation failed.
328*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_new_from_name(struct kmod_ctx * ctx,const char * name,struct kmod_module ** mod)329*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
330*cc4ad7daSAndroid Build Coastguard Worker 						const char *name,
331*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_module **mod)
332*cc4ad7daSAndroid Build Coastguard Worker {
333*cc4ad7daSAndroid Build Coastguard Worker 	size_t namelen;
334*cc4ad7daSAndroid Build Coastguard Worker 	char name_norm[PATH_MAX];
335*cc4ad7daSAndroid Build Coastguard Worker 
336*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || name == NULL || mod == NULL)
337*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
338*cc4ad7daSAndroid Build Coastguard Worker 
339*cc4ad7daSAndroid Build Coastguard Worker 	modname_normalize(name, name_norm, &namelen);
340*cc4ad7daSAndroid Build Coastguard Worker 
341*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_module_new(ctx, name_norm, name_norm, namelen, NULL, 0, mod);
342*cc4ad7daSAndroid Build Coastguard Worker }
343*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_new_from_alias(struct kmod_ctx * ctx,const char * alias,const char * name,struct kmod_module ** mod)344*cc4ad7daSAndroid Build Coastguard Worker int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias,
345*cc4ad7daSAndroid Build Coastguard Worker 				const char *name, struct kmod_module **mod)
346*cc4ad7daSAndroid Build Coastguard Worker {
347*cc4ad7daSAndroid Build Coastguard Worker 	int err;
348*cc4ad7daSAndroid Build Coastguard Worker 	char key[PATH_MAX];
349*cc4ad7daSAndroid Build Coastguard Worker 	size_t namelen = strlen(name);
350*cc4ad7daSAndroid Build Coastguard Worker 	size_t aliaslen = strlen(alias);
351*cc4ad7daSAndroid Build Coastguard Worker 
352*cc4ad7daSAndroid Build Coastguard Worker 	if (namelen + aliaslen + 2 > PATH_MAX)
353*cc4ad7daSAndroid Build Coastguard Worker 		return -ENAMETOOLONG;
354*cc4ad7daSAndroid Build Coastguard Worker 
355*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(key, name, namelen);
356*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(key + namelen + 1, alias, aliaslen + 1);
357*cc4ad7daSAndroid Build Coastguard Worker 	key[namelen] = '\\';
358*cc4ad7daSAndroid Build Coastguard Worker 
359*cc4ad7daSAndroid Build Coastguard Worker 	err = kmod_module_new(ctx, key, name, namelen, alias, aliaslen, mod);
360*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
361*cc4ad7daSAndroid Build Coastguard Worker 		return err;
362*cc4ad7daSAndroid Build Coastguard Worker 
363*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
364*cc4ad7daSAndroid Build Coastguard Worker }
365*cc4ad7daSAndroid Build Coastguard Worker 
366*cc4ad7daSAndroid Build Coastguard Worker /**
367*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_new_from_path:
368*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
369*cc4ad7daSAndroid Build Coastguard Worker  * @path: path where to find the given module
370*cc4ad7daSAndroid Build Coastguard Worker  * @mod: where to save the created struct kmod_module
371*cc4ad7daSAndroid Build Coastguard Worker  *
372*cc4ad7daSAndroid Build Coastguard Worker  * Create a new struct kmod_module using the module path. @path must be an
373*cc4ad7daSAndroid Build Coastguard Worker  * existent file with in the filesystem and must be accessible to libkmod.
374*cc4ad7daSAndroid Build Coastguard Worker  *
375*cc4ad7daSAndroid Build Coastguard Worker  * The initial refcount is 1, and needs to be decremented to release the
376*cc4ad7daSAndroid Build Coastguard Worker  * resources of the kmod_module. Since libkmod keeps track of all
377*cc4ad7daSAndroid Build Coastguard Worker  * kmod_modules created, they are all released upon @ctx destruction too. Do
378*cc4ad7daSAndroid Build Coastguard Worker  * not unref @ctx before all the desired operations with the returned
379*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module are done.
380*cc4ad7daSAndroid Build Coastguard Worker  *
381*cc4ad7daSAndroid Build Coastguard Worker  * If @path is relative, it's treated as relative to the current working
382*cc4ad7daSAndroid Build Coastguard Worker  * directory. Otherwise, give an absolute path.
383*cc4ad7daSAndroid Build Coastguard Worker  *
384*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise. It fails if file does not exist, if
385*cc4ad7daSAndroid Build Coastguard Worker  * it's not a valid file for a kmod_module or if memory allocation failed.
386*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_new_from_path(struct kmod_ctx * ctx,const char * path,struct kmod_module ** mod)387*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
388*cc4ad7daSAndroid Build Coastguard Worker 						const char *path,
389*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_module **mod)
390*cc4ad7daSAndroid Build Coastguard Worker {
391*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module *m;
392*cc4ad7daSAndroid Build Coastguard Worker 	int err;
393*cc4ad7daSAndroid Build Coastguard Worker 	struct stat st;
394*cc4ad7daSAndroid Build Coastguard Worker 	char name[PATH_MAX];
395*cc4ad7daSAndroid Build Coastguard Worker 	char *abspath;
396*cc4ad7daSAndroid Build Coastguard Worker 	size_t namelen;
397*cc4ad7daSAndroid Build Coastguard Worker 
398*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || path == NULL || mod == NULL)
399*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
400*cc4ad7daSAndroid Build Coastguard Worker 
401*cc4ad7daSAndroid Build Coastguard Worker 	abspath = path_make_absolute_cwd(path);
402*cc4ad7daSAndroid Build Coastguard Worker 	if (abspath == NULL) {
403*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "no absolute path for %s\n", path);
404*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
405*cc4ad7daSAndroid Build Coastguard Worker 	}
406*cc4ad7daSAndroid Build Coastguard Worker 
407*cc4ad7daSAndroid Build Coastguard Worker 	err = stat(abspath, &st);
408*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
409*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
410*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "stat %s: %s\n", path, strerror(errno));
411*cc4ad7daSAndroid Build Coastguard Worker 		free(abspath);
412*cc4ad7daSAndroid Build Coastguard Worker 		return err;
413*cc4ad7daSAndroid Build Coastguard Worker 	}
414*cc4ad7daSAndroid Build Coastguard Worker 
415*cc4ad7daSAndroid Build Coastguard Worker 	if (path_to_modname(path, name, &namelen) == NULL) {
416*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "could not get modname from path %s\n", path);
417*cc4ad7daSAndroid Build Coastguard Worker 		free(abspath);
418*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
419*cc4ad7daSAndroid Build Coastguard Worker 	}
420*cc4ad7daSAndroid Build Coastguard Worker 
421*cc4ad7daSAndroid Build Coastguard Worker 	m = kmod_pool_get_module(ctx, name);
422*cc4ad7daSAndroid Build Coastguard Worker 	if (m != NULL) {
423*cc4ad7daSAndroid Build Coastguard Worker 		if (m->path == NULL)
424*cc4ad7daSAndroid Build Coastguard Worker 			m->path = abspath;
425*cc4ad7daSAndroid Build Coastguard Worker 		else if (streq(m->path, abspath))
426*cc4ad7daSAndroid Build Coastguard Worker 			free(abspath);
427*cc4ad7daSAndroid Build Coastguard Worker 		else {
428*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "kmod_module '%s' already exists with different path: new-path='%s' old-path='%s'\n",
429*cc4ad7daSAndroid Build Coastguard Worker 							name, abspath, m->path);
430*cc4ad7daSAndroid Build Coastguard Worker 			free(abspath);
431*cc4ad7daSAndroid Build Coastguard Worker 			return -EEXIST;
432*cc4ad7daSAndroid Build Coastguard Worker 		}
433*cc4ad7daSAndroid Build Coastguard Worker 
434*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_ref(m);
435*cc4ad7daSAndroid Build Coastguard Worker 	} else {
436*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m);
437*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
438*cc4ad7daSAndroid Build Coastguard Worker 			free(abspath);
439*cc4ad7daSAndroid Build Coastguard Worker 			return err;
440*cc4ad7daSAndroid Build Coastguard Worker 		}
441*cc4ad7daSAndroid Build Coastguard Worker 
442*cc4ad7daSAndroid Build Coastguard Worker 		m->path = abspath;
443*cc4ad7daSAndroid Build Coastguard Worker 	}
444*cc4ad7daSAndroid Build Coastguard Worker 
445*cc4ad7daSAndroid Build Coastguard Worker 	m->builtin = KMOD_MODULE_BUILTIN_NO;
446*cc4ad7daSAndroid Build Coastguard Worker 	*mod = m;
447*cc4ad7daSAndroid Build Coastguard Worker 
448*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
449*cc4ad7daSAndroid Build Coastguard Worker }
450*cc4ad7daSAndroid Build Coastguard Worker 
451*cc4ad7daSAndroid Build Coastguard Worker /**
452*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_unref:
453*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
454*cc4ad7daSAndroid Build Coastguard Worker  *
455*cc4ad7daSAndroid Build Coastguard Worker  * Drop a reference of the kmod module. If the refcount reaches zero, its
456*cc4ad7daSAndroid Build Coastguard Worker  * resources are released.
457*cc4ad7daSAndroid Build Coastguard Worker  *
458*cc4ad7daSAndroid Build Coastguard Worker  * Returns: NULL if @mod is NULL or if the module was released. Otherwise it
459*cc4ad7daSAndroid Build Coastguard Worker  * returns the passed @mod with its refcount decremented.
460*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_unref(struct kmod_module * mod)461*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
462*cc4ad7daSAndroid Build Coastguard Worker {
463*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
464*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
465*cc4ad7daSAndroid Build Coastguard Worker 
466*cc4ad7daSAndroid Build Coastguard Worker 	if (--mod->refcount > 0)
467*cc4ad7daSAndroid Build Coastguard Worker 		return mod;
468*cc4ad7daSAndroid Build Coastguard Worker 
469*cc4ad7daSAndroid Build Coastguard Worker 	DBG(mod->ctx, "kmod_module %p released\n", mod);
470*cc4ad7daSAndroid Build Coastguard Worker 
471*cc4ad7daSAndroid Build Coastguard Worker 	kmod_pool_del_module(mod->ctx, mod, mod->hashkey);
472*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(mod->dep);
473*cc4ad7daSAndroid Build Coastguard Worker 
474*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->file)
475*cc4ad7daSAndroid Build Coastguard Worker 		kmod_file_unref(mod->file);
476*cc4ad7daSAndroid Build Coastguard Worker 
477*cc4ad7daSAndroid Build Coastguard Worker 	kmod_unref(mod->ctx);
478*cc4ad7daSAndroid Build Coastguard Worker 	free(mod->options);
479*cc4ad7daSAndroid Build Coastguard Worker 	free(mod->path);
480*cc4ad7daSAndroid Build Coastguard Worker 	free(mod);
481*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
482*cc4ad7daSAndroid Build Coastguard Worker }
483*cc4ad7daSAndroid Build Coastguard Worker 
484*cc4ad7daSAndroid Build Coastguard Worker /**
485*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_ref:
486*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
487*cc4ad7daSAndroid Build Coastguard Worker  *
488*cc4ad7daSAndroid Build Coastguard Worker  * Take a reference of the kmod module, incrementing its refcount.
489*cc4ad7daSAndroid Build Coastguard Worker  *
490*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the passed @module with its refcount incremented.
491*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_ref(struct kmod_module * mod)492*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
493*cc4ad7daSAndroid Build Coastguard Worker {
494*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
495*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
496*cc4ad7daSAndroid Build Coastguard Worker 
497*cc4ad7daSAndroid Build Coastguard Worker 	mod->refcount++;
498*cc4ad7daSAndroid Build Coastguard Worker 
499*cc4ad7daSAndroid Build Coastguard Worker 	return mod;
500*cc4ad7daSAndroid Build Coastguard Worker }
501*cc4ad7daSAndroid Build Coastguard Worker 
502*cc4ad7daSAndroid Build Coastguard Worker typedef int (*lookup_func)(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
503*cc4ad7daSAndroid Build Coastguard Worker 
__kmod_module_new_from_lookup(struct kmod_ctx * ctx,const lookup_func lookup[],size_t lookup_count,const char * s,struct kmod_list ** list)504*cc4ad7daSAndroid Build Coastguard Worker static int __kmod_module_new_from_lookup(struct kmod_ctx *ctx, const lookup_func lookup[],
505*cc4ad7daSAndroid Build Coastguard Worker 					 size_t lookup_count, const char *s,
506*cc4ad7daSAndroid Build Coastguard Worker 					 struct kmod_list **list)
507*cc4ad7daSAndroid Build Coastguard Worker {
508*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int i;
509*cc4ad7daSAndroid Build Coastguard Worker 
510*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < lookup_count; i++) {
511*cc4ad7daSAndroid Build Coastguard Worker 		int err;
512*cc4ad7daSAndroid Build Coastguard Worker 
513*cc4ad7daSAndroid Build Coastguard Worker 		err = lookup[i](ctx, s, list);
514*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0 && err != -ENOSYS)
515*cc4ad7daSAndroid Build Coastguard Worker 			return err;
516*cc4ad7daSAndroid Build Coastguard Worker 		else if (*list != NULL)
517*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
518*cc4ad7daSAndroid Build Coastguard Worker 	}
519*cc4ad7daSAndroid Build Coastguard Worker 
520*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
521*cc4ad7daSAndroid Build Coastguard Worker }
522*cc4ad7daSAndroid Build Coastguard Worker 
523*cc4ad7daSAndroid Build Coastguard Worker /**
524*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_new_from_lookup:
525*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
526*cc4ad7daSAndroid Build Coastguard Worker  * @given_alias: alias to look for
527*cc4ad7daSAndroid Build Coastguard Worker  * @list: an empty list where to save the list of modules matching
528*cc4ad7daSAndroid Build Coastguard Worker  * @given_alias
529*cc4ad7daSAndroid Build Coastguard Worker  *
530*cc4ad7daSAndroid Build Coastguard Worker  * Create a new list of kmod modules using an alias or module name and lookup
531*cc4ad7daSAndroid Build Coastguard Worker  * libkmod's configuration files and indexes in order to find the module.
532*cc4ad7daSAndroid Build Coastguard Worker  * Once it's found in one of the places, it stops searching and create the
533*cc4ad7daSAndroid Build Coastguard Worker  * list of modules that is saved in @list.
534*cc4ad7daSAndroid Build Coastguard Worker  *
535*cc4ad7daSAndroid Build Coastguard Worker  * The search order is: 1. aliases in configuration file; 2. module names in
536*cc4ad7daSAndroid Build Coastguard Worker  * modules.dep index; 3. symbol aliases in modules.symbols index; 4. aliases
537*cc4ad7daSAndroid Build Coastguard Worker  * from install commands; 5. builtin indexes from kernel.
538*cc4ad7daSAndroid Build Coastguard Worker  *
539*cc4ad7daSAndroid Build Coastguard Worker  * The initial refcount is 1, and needs to be decremented to release the
540*cc4ad7daSAndroid Build Coastguard Worker  * resources of the kmod_module. The returned @list must be released by
541*cc4ad7daSAndroid Build Coastguard Worker  * calling kmod_module_unref_list(). Since libkmod keeps track of all
542*cc4ad7daSAndroid Build Coastguard Worker  * kmod_modules created, they are all released upon @ctx destruction too. Do
543*cc4ad7daSAndroid Build Coastguard Worker  * not unref @ctx before all the desired operations with the returned list are
544*cc4ad7daSAndroid Build Coastguard Worker  * completed.
545*cc4ad7daSAndroid Build Coastguard Worker  *
546*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise. It fails if any of the lookup
547*cc4ad7daSAndroid Build Coastguard Worker  * methods failed, which is basically due to memory allocation fail. If module
548*cc4ad7daSAndroid Build Coastguard Worker  * is not found, it still returns 0, but @list is an empty list.
549*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_new_from_lookup(struct kmod_ctx * ctx,const char * given_alias,struct kmod_list ** list)550*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
551*cc4ad7daSAndroid Build Coastguard Worker 						const char *given_alias,
552*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
553*cc4ad7daSAndroid Build Coastguard Worker {
554*cc4ad7daSAndroid Build Coastguard Worker 	static const lookup_func lookup[] = {
555*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_config,
556*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_moddep_file,
557*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_symbols_file,
558*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_commands,
559*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_aliases_file,
560*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_builtin_file,
561*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_kernel_builtin_file,
562*cc4ad7daSAndroid Build Coastguard Worker 	};
563*cc4ad7daSAndroid Build Coastguard Worker 	char alias[PATH_MAX];
564*cc4ad7daSAndroid Build Coastguard Worker 	int err;
565*cc4ad7daSAndroid Build Coastguard Worker 
566*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || given_alias == NULL)
567*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
568*cc4ad7daSAndroid Build Coastguard Worker 
569*cc4ad7daSAndroid Build Coastguard Worker 	if (list == NULL || *list != NULL) {
570*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "An empty list is needed to create lookup\n");
571*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOSYS;
572*cc4ad7daSAndroid Build Coastguard Worker 	}
573*cc4ad7daSAndroid Build Coastguard Worker 
574*cc4ad7daSAndroid Build Coastguard Worker 	if (alias_normalize(given_alias, alias, NULL) < 0) {
575*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "invalid alias: %s\n", given_alias);
576*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
577*cc4ad7daSAndroid Build Coastguard Worker 	}
578*cc4ad7daSAndroid Build Coastguard Worker 
579*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias);
580*cc4ad7daSAndroid Build Coastguard Worker 
581*cc4ad7daSAndroid Build Coastguard Worker 	err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup),
582*cc4ad7daSAndroid Build Coastguard Worker 					    alias, list);
583*cc4ad7daSAndroid Build Coastguard Worker 
584*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "lookup=%s found=%d\n", alias, err >= 0 && *list);
585*cc4ad7daSAndroid Build Coastguard Worker 
586*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
587*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_unref_list(*list);
588*cc4ad7daSAndroid Build Coastguard Worker 		*list = NULL;
589*cc4ad7daSAndroid Build Coastguard Worker 	}
590*cc4ad7daSAndroid Build Coastguard Worker 
591*cc4ad7daSAndroid Build Coastguard Worker 	return err;
592*cc4ad7daSAndroid Build Coastguard Worker }
593*cc4ad7daSAndroid Build Coastguard Worker 
594*cc4ad7daSAndroid Build Coastguard Worker /**
595*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_new_from_name_lookup:
596*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
597*cc4ad7daSAndroid Build Coastguard Worker  * @modname: module name to look for
598*cc4ad7daSAndroid Build Coastguard Worker  * @mod: returned module on success
599*cc4ad7daSAndroid Build Coastguard Worker  *
600*cc4ad7daSAndroid Build Coastguard Worker  * Lookup by module name, without considering possible aliases. This is similar
601*cc4ad7daSAndroid Build Coastguard Worker  * to kmod_module_new_from_lookup(), but don't consider as source indexes and
602*cc4ad7daSAndroid Build Coastguard Worker  * configurations that work with aliases. When succesful, this always resolves
603*cc4ad7daSAndroid Build Coastguard Worker  * to one and only one module.
604*cc4ad7daSAndroid Build Coastguard Worker  *
605*cc4ad7daSAndroid Build Coastguard Worker  * The search order is: 1. module names in modules.dep index;
606*cc4ad7daSAndroid Build Coastguard Worker  * 2. builtin indexes from kernel.
607*cc4ad7daSAndroid Build Coastguard Worker  *
608*cc4ad7daSAndroid Build Coastguard Worker  * The initial refcount is 1, and needs to be decremented to release the
609*cc4ad7daSAndroid Build Coastguard Worker  * resources of the kmod_module. Since libkmod keeps track of all
610*cc4ad7daSAndroid Build Coastguard Worker  * kmod_modules created, they are all released upon @ctx destruction too. Do
611*cc4ad7daSAndroid Build Coastguard Worker  * not unref @ctx before all the desired operations with the returned list are
612*cc4ad7daSAndroid Build Coastguard Worker  * completed.
613*cc4ad7daSAndroid Build Coastguard Worker  *
614*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise. It fails if any of the lookup
615*cc4ad7daSAndroid Build Coastguard Worker  * methods failed, which is basically due to memory allocation failure. If
616*cc4ad7daSAndroid Build Coastguard Worker  * module is not found, it still returns 0, but @mod is left untouched.
617*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_new_from_name_lookup(struct kmod_ctx * ctx,const char * modname,struct kmod_module ** mod)618*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx,
619*cc4ad7daSAndroid Build Coastguard Worker 						 const char *modname,
620*cc4ad7daSAndroid Build Coastguard Worker 						 struct kmod_module **mod)
621*cc4ad7daSAndroid Build Coastguard Worker {
622*cc4ad7daSAndroid Build Coastguard Worker 	static const lookup_func lookup[] = {
623*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_moddep_file,
624*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_builtin_file,
625*cc4ad7daSAndroid Build Coastguard Worker 		kmod_lookup_alias_from_kernel_builtin_file,
626*cc4ad7daSAndroid Build Coastguard Worker 	};
627*cc4ad7daSAndroid Build Coastguard Worker 	char name_norm[PATH_MAX];
628*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list = NULL;
629*cc4ad7daSAndroid Build Coastguard Worker 	int err;
630*cc4ad7daSAndroid Build Coastguard Worker 
631*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || modname == NULL || mod == NULL)
632*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
633*cc4ad7daSAndroid Build Coastguard Worker 
634*cc4ad7daSAndroid Build Coastguard Worker 	modname_normalize(modname, name_norm, NULL);
635*cc4ad7daSAndroid Build Coastguard Worker 
636*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "input modname=%s, normalized=%s\n", modname, name_norm);
637*cc4ad7daSAndroid Build Coastguard Worker 
638*cc4ad7daSAndroid Build Coastguard Worker 	err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup),
639*cc4ad7daSAndroid Build Coastguard Worker 					    name_norm, &list);
640*cc4ad7daSAndroid Build Coastguard Worker 
641*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "lookup=%s found=%d\n", name_norm, err >= 0 && list);
642*cc4ad7daSAndroid Build Coastguard Worker 
643*cc4ad7daSAndroid Build Coastguard Worker 	if (err >= 0 && list != NULL)
644*cc4ad7daSAndroid Build Coastguard Worker 		*mod = kmod_module_get_module(list);
645*cc4ad7daSAndroid Build Coastguard Worker 
646*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(list);
647*cc4ad7daSAndroid Build Coastguard Worker 
648*cc4ad7daSAndroid Build Coastguard Worker 	return err;
649*cc4ad7daSAndroid Build Coastguard Worker }
650*cc4ad7daSAndroid Build Coastguard Worker 
651*cc4ad7daSAndroid Build Coastguard Worker /**
652*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_unref_list:
653*cc4ad7daSAndroid Build Coastguard Worker  * @list: list of kmod modules
654*cc4ad7daSAndroid Build Coastguard Worker  *
655*cc4ad7daSAndroid Build Coastguard Worker  * Drop a reference of each kmod module in @list and releases the resources
656*cc4ad7daSAndroid Build Coastguard Worker  * taken by the list itself.
657*cc4ad7daSAndroid Build Coastguard Worker  *
658*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0
659*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_unref_list(struct kmod_list * list)660*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
661*cc4ad7daSAndroid Build Coastguard Worker {
662*cc4ad7daSAndroid Build Coastguard Worker 	for (; list != NULL; list = kmod_list_remove(list))
663*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_unref(list->data);
664*cc4ad7daSAndroid Build Coastguard Worker 
665*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
666*cc4ad7daSAndroid Build Coastguard Worker }
667*cc4ad7daSAndroid Build Coastguard Worker 
668*cc4ad7daSAndroid Build Coastguard Worker /**
669*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_filtered_blacklist:
670*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
671*cc4ad7daSAndroid Build Coastguard Worker  * @input: list of kmod_module to be filtered with blacklist
672*cc4ad7daSAndroid Build Coastguard Worker  * @output: where to save the new list
673*cc4ad7daSAndroid Build Coastguard Worker  *
674*cc4ad7daSAndroid Build Coastguard Worker  * This function should not be used. Use kmod_module_apply_filter instead.
675*cc4ad7daSAndroid Build Coastguard Worker  *
676*cc4ad7daSAndroid Build Coastguard Worker  * Given a list @input, this function filter it out with config's blacklist
677*cc4ad7daSAndroid Build Coastguard Worker  * and save it in @output.
678*cc4ad7daSAndroid Build Coastguard Worker  *
679*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise. @output is saved with the updated
680*cc4ad7daSAndroid Build Coastguard Worker  * list.
681*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_filtered_blacklist(const struct kmod_ctx * ctx,const struct kmod_list * input,struct kmod_list ** output)682*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_filtered_blacklist(const struct kmod_ctx *ctx,
683*cc4ad7daSAndroid Build Coastguard Worker 						const struct kmod_list *input,
684*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **output)
685*cc4ad7daSAndroid Build Coastguard Worker {
686*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, input, output);
687*cc4ad7daSAndroid Build Coastguard Worker }
688*cc4ad7daSAndroid Build Coastguard Worker 
module_get_dependencies_noref(const struct kmod_module * mod)689*cc4ad7daSAndroid Build Coastguard Worker static const struct kmod_list *module_get_dependencies_noref(const struct kmod_module *mod)
690*cc4ad7daSAndroid Build Coastguard Worker {
691*cc4ad7daSAndroid Build Coastguard Worker 	if (!mod->init.dep) {
692*cc4ad7daSAndroid Build Coastguard Worker 		/* lazy init */
693*cc4ad7daSAndroid Build Coastguard Worker 		char *line = kmod_search_moddep(mod->ctx, mod->name);
694*cc4ad7daSAndroid Build Coastguard Worker 
695*cc4ad7daSAndroid Build Coastguard Worker 		if (line == NULL)
696*cc4ad7daSAndroid Build Coastguard Worker 			return NULL;
697*cc4ad7daSAndroid Build Coastguard Worker 
698*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_parse_depline((struct kmod_module *)mod, line);
699*cc4ad7daSAndroid Build Coastguard Worker 		free(line);
700*cc4ad7daSAndroid Build Coastguard Worker 
701*cc4ad7daSAndroid Build Coastguard Worker 		if (!mod->init.dep)
702*cc4ad7daSAndroid Build Coastguard Worker 			return NULL;
703*cc4ad7daSAndroid Build Coastguard Worker 	}
704*cc4ad7daSAndroid Build Coastguard Worker 
705*cc4ad7daSAndroid Build Coastguard Worker 	return mod->dep;
706*cc4ad7daSAndroid Build Coastguard Worker }
707*cc4ad7daSAndroid Build Coastguard Worker 
708*cc4ad7daSAndroid Build Coastguard Worker /**
709*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_dependencies:
710*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
711*cc4ad7daSAndroid Build Coastguard Worker  *
712*cc4ad7daSAndroid Build Coastguard Worker  * Search the modules.dep index to find the dependencies of the given @mod.
713*cc4ad7daSAndroid Build Coastguard Worker  * The result is cached in @mod, so subsequent calls to this function will
714*cc4ad7daSAndroid Build Coastguard Worker  * return the already searched list of modules.
715*cc4ad7daSAndroid Build Coastguard Worker  *
716*cc4ad7daSAndroid Build Coastguard Worker  * Returns: NULL on failure. Otherwise it returns a list of kmod modules
717*cc4ad7daSAndroid Build Coastguard Worker  * that can be released by calling kmod_module_unref_list().
718*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_dependencies(const struct kmod_module * mod)719*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
720*cc4ad7daSAndroid Build Coastguard Worker {
721*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l, *l_new, *list_new = NULL;
722*cc4ad7daSAndroid Build Coastguard Worker 
723*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
724*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
725*cc4ad7daSAndroid Build Coastguard Worker 
726*cc4ad7daSAndroid Build Coastguard Worker 	module_get_dependencies_noref(mod);
727*cc4ad7daSAndroid Build Coastguard Worker 
728*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, mod->dep) {
729*cc4ad7daSAndroid Build Coastguard Worker 		l_new = kmod_list_append(list_new, kmod_module_ref(l->data));
730*cc4ad7daSAndroid Build Coastguard Worker 		if (l_new == NULL) {
731*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_unref(l->data);
732*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
733*cc4ad7daSAndroid Build Coastguard Worker 		}
734*cc4ad7daSAndroid Build Coastguard Worker 
735*cc4ad7daSAndroid Build Coastguard Worker 		list_new = l_new;
736*cc4ad7daSAndroid Build Coastguard Worker 	}
737*cc4ad7daSAndroid Build Coastguard Worker 
738*cc4ad7daSAndroid Build Coastguard Worker 	return list_new;
739*cc4ad7daSAndroid Build Coastguard Worker 
740*cc4ad7daSAndroid Build Coastguard Worker fail:
741*cc4ad7daSAndroid Build Coastguard Worker 	ERR(mod->ctx, "out of memory\n");
742*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(list_new);
743*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
744*cc4ad7daSAndroid Build Coastguard Worker }
745*cc4ad7daSAndroid Build Coastguard Worker 
746*cc4ad7daSAndroid Build Coastguard Worker /**
747*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_module:
748*cc4ad7daSAndroid Build Coastguard Worker  * @entry: an entry in a list of kmod modules.
749*cc4ad7daSAndroid Build Coastguard Worker  *
750*cc4ad7daSAndroid Build Coastguard Worker  * Get the kmod module of this @entry in the list, increasing its refcount.
751*cc4ad7daSAndroid Build Coastguard Worker  * After it's used, unref it. Since the refcount is incremented upon return,
752*cc4ad7daSAndroid Build Coastguard Worker  * you still have to call kmod_module_unref_list() to release the list of kmod
753*cc4ad7daSAndroid Build Coastguard Worker  * modules.
754*cc4ad7daSAndroid Build Coastguard Worker  *
755*cc4ad7daSAndroid Build Coastguard Worker  * Returns: NULL on failure or the kmod_module contained in this list entry
756*cc4ad7daSAndroid Build Coastguard Worker  * with its refcount incremented.
757*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_module(const struct kmod_list * entry)758*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
759*cc4ad7daSAndroid Build Coastguard Worker {
760*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL)
761*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
762*cc4ad7daSAndroid Build Coastguard Worker 
763*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_module_ref(entry->data);
764*cc4ad7daSAndroid Build Coastguard Worker }
765*cc4ad7daSAndroid Build Coastguard Worker 
766*cc4ad7daSAndroid Build Coastguard Worker /**
767*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_name:
768*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
769*cc4ad7daSAndroid Build Coastguard Worker  *
770*cc4ad7daSAndroid Build Coastguard Worker  * Get the name of this kmod module. Name is always available, independently
771*cc4ad7daSAndroid Build Coastguard Worker  * if it was created by kmod_module_new_from_name() or another function and
772*cc4ad7daSAndroid Build Coastguard Worker  * it's always normalized (dashes are replaced with underscores).
773*cc4ad7daSAndroid Build Coastguard Worker  *
774*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the name of this kmod module.
775*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_name(const struct kmod_module * mod)776*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
777*cc4ad7daSAndroid Build Coastguard Worker {
778*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
779*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
780*cc4ad7daSAndroid Build Coastguard Worker 
781*cc4ad7daSAndroid Build Coastguard Worker 	return mod->name;
782*cc4ad7daSAndroid Build Coastguard Worker }
783*cc4ad7daSAndroid Build Coastguard Worker 
784*cc4ad7daSAndroid Build Coastguard Worker /**
785*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_path:
786*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
787*cc4ad7daSAndroid Build Coastguard Worker  *
788*cc4ad7daSAndroid Build Coastguard Worker  * Get the path of this kmod module. If this kmod module was not created by
789*cc4ad7daSAndroid Build Coastguard Worker  * path, it can search the modules.dep index in order to find out the module
790*cc4ad7daSAndroid Build Coastguard Worker  * under context's dirname.
791*cc4ad7daSAndroid Build Coastguard Worker  *
792*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the path of this kmod module or NULL if such information is not
793*cc4ad7daSAndroid Build Coastguard Worker  * available.
794*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_path(const struct kmod_module * mod)795*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
796*cc4ad7daSAndroid Build Coastguard Worker {
797*cc4ad7daSAndroid Build Coastguard Worker 	char *line;
798*cc4ad7daSAndroid Build Coastguard Worker 
799*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
800*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
801*cc4ad7daSAndroid Build Coastguard Worker 
802*cc4ad7daSAndroid Build Coastguard Worker 	DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
803*cc4ad7daSAndroid Build Coastguard Worker 
804*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->path != NULL)
805*cc4ad7daSAndroid Build Coastguard Worker 		return mod->path;
806*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->init.dep)
807*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
808*cc4ad7daSAndroid Build Coastguard Worker 
809*cc4ad7daSAndroid Build Coastguard Worker 	/* lazy init */
810*cc4ad7daSAndroid Build Coastguard Worker 	line = kmod_search_moddep(mod->ctx, mod->name);
811*cc4ad7daSAndroid Build Coastguard Worker 	if (line == NULL)
812*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
813*cc4ad7daSAndroid Build Coastguard Worker 
814*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_parse_depline((struct kmod_module *) mod, line);
815*cc4ad7daSAndroid Build Coastguard Worker 	free(line);
816*cc4ad7daSAndroid Build Coastguard Worker 
817*cc4ad7daSAndroid Build Coastguard Worker 	return mod->path;
818*cc4ad7daSAndroid Build Coastguard Worker }
819*cc4ad7daSAndroid Build Coastguard Worker 
820*cc4ad7daSAndroid Build Coastguard Worker 
821*cc4ad7daSAndroid Build Coastguard Worker extern long delete_module(const char *name, unsigned int flags);
822*cc4ad7daSAndroid Build Coastguard Worker 
823*cc4ad7daSAndroid Build Coastguard Worker /**
824*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_remove_module:
825*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
826*cc4ad7daSAndroid Build Coastguard Worker  * @flags: flags used when removing the module.
827*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_REMOVE_FORCE: force remove module regardless if it's still in
828*cc4ad7daSAndroid Build Coastguard Worker  * use by a kernel subsystem or other process; passed directly to Linux kernel
829*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_REMOVE_NOWAIT: is always enforced, causing us to pass O_NONBLOCK to
830*cc4ad7daSAndroid Build Coastguard Worker  * delete_module(2).
831*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_REMOVE_NOLOG: when module removal fails, do not log anything as the
832*cc4ad7daSAndroid Build Coastguard Worker  * caller may want to handle retries and log when appropriate.
833*cc4ad7daSAndroid Build Coastguard Worker  *
834*cc4ad7daSAndroid Build Coastguard Worker  * Remove a module from Linux kernel.
835*cc4ad7daSAndroid Build Coastguard Worker  *
836*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 on failure.
837*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_remove_module(struct kmod_module * mod,unsigned int flags)838*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
839*cc4ad7daSAndroid Build Coastguard Worker 							unsigned int flags)
840*cc4ad7daSAndroid Build Coastguard Worker {
841*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int libkmod_flags = flags & 0xff;
842*cc4ad7daSAndroid Build Coastguard Worker 
843*cc4ad7daSAndroid Build Coastguard Worker 	int err;
844*cc4ad7daSAndroid Build Coastguard Worker 
845*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
846*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
847*cc4ad7daSAndroid Build Coastguard Worker 
848*cc4ad7daSAndroid Build Coastguard Worker 	/* Filter out other flags and force ONONBLOCK */
849*cc4ad7daSAndroid Build Coastguard Worker 	flags &= KMOD_REMOVE_FORCE;
850*cc4ad7daSAndroid Build Coastguard Worker 	flags |= KMOD_REMOVE_NOWAIT;
851*cc4ad7daSAndroid Build Coastguard Worker 
852*cc4ad7daSAndroid Build Coastguard Worker 	err = delete_module(mod->name, flags);
853*cc4ad7daSAndroid Build Coastguard Worker 	if (err != 0) {
854*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
855*cc4ad7daSAndroid Build Coastguard Worker 		if (!(libkmod_flags & KMOD_REMOVE_NOLOG))
856*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "could not remove '%s': %m\n", mod->name);
857*cc4ad7daSAndroid Build Coastguard Worker 	}
858*cc4ad7daSAndroid Build Coastguard Worker 
859*cc4ad7daSAndroid Build Coastguard Worker 	return err;
860*cc4ad7daSAndroid Build Coastguard Worker }
861*cc4ad7daSAndroid Build Coastguard Worker 
862*cc4ad7daSAndroid Build Coastguard Worker extern long init_module(const void *mem, unsigned long len, const char *args);
863*cc4ad7daSAndroid Build Coastguard Worker 
do_finit_module(struct kmod_module * mod,unsigned int flags,const char * args)864*cc4ad7daSAndroid Build Coastguard Worker static int do_finit_module(struct kmod_module *mod, unsigned int flags,
865*cc4ad7daSAndroid Build Coastguard Worker 			   const char *args)
866*cc4ad7daSAndroid Build Coastguard Worker {
867*cc4ad7daSAndroid Build Coastguard Worker 	enum kmod_file_compression_type compression, kernel_compression;
868*cc4ad7daSAndroid Build Coastguard Worker 	unsigned int kernel_flags = 0;
869*cc4ad7daSAndroid Build Coastguard Worker 	int err;
870*cc4ad7daSAndroid Build Coastguard Worker 
871*cc4ad7daSAndroid Build Coastguard Worker 	/*
872*cc4ad7daSAndroid Build Coastguard Worker 	 * When module is not compressed or its compression type matches the
873*cc4ad7daSAndroid Build Coastguard Worker 	 * one in use by the kernel, there is no need to read the file
874*cc4ad7daSAndroid Build Coastguard Worker 	 * in userspace. Otherwise, re-use ENOSYS to trigger the same fallback
875*cc4ad7daSAndroid Build Coastguard Worker 	 * as when finit_module() is not supported.
876*cc4ad7daSAndroid Build Coastguard Worker 	 */
877*cc4ad7daSAndroid Build Coastguard Worker 	compression = kmod_file_get_compression(mod->file);
878*cc4ad7daSAndroid Build Coastguard Worker 	kernel_compression = kmod_get_kernel_compression(mod->ctx);
879*cc4ad7daSAndroid Build Coastguard Worker 	if (!(compression == KMOD_FILE_COMPRESSION_NONE ||
880*cc4ad7daSAndroid Build Coastguard Worker 	      compression == kernel_compression))
881*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOSYS;
882*cc4ad7daSAndroid Build Coastguard Worker 
883*cc4ad7daSAndroid Build Coastguard Worker 	if (compression != KMOD_FILE_COMPRESSION_NONE)
884*cc4ad7daSAndroid Build Coastguard Worker 		kernel_flags |= MODULE_INIT_COMPRESSED_FILE;
885*cc4ad7daSAndroid Build Coastguard Worker 
886*cc4ad7daSAndroid Build Coastguard Worker 	if (flags & KMOD_INSERT_FORCE_VERMAGIC)
887*cc4ad7daSAndroid Build Coastguard Worker 		kernel_flags |= MODULE_INIT_IGNORE_VERMAGIC;
888*cc4ad7daSAndroid Build Coastguard Worker 	if (flags & KMOD_INSERT_FORCE_MODVERSION)
889*cc4ad7daSAndroid Build Coastguard Worker 		kernel_flags |= MODULE_INIT_IGNORE_MODVERSIONS;
890*cc4ad7daSAndroid Build Coastguard Worker 
891*cc4ad7daSAndroid Build Coastguard Worker 	err = finit_module(kmod_file_get_fd(mod->file), args, kernel_flags);
892*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
893*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
894*cc4ad7daSAndroid Build Coastguard Worker 
895*cc4ad7daSAndroid Build Coastguard Worker 	return err;
896*cc4ad7daSAndroid Build Coastguard Worker }
897*cc4ad7daSAndroid Build Coastguard Worker 
do_init_module(struct kmod_module * mod,unsigned int flags,const char * args)898*cc4ad7daSAndroid Build Coastguard Worker static int do_init_module(struct kmod_module *mod, unsigned int flags,
899*cc4ad7daSAndroid Build Coastguard Worker 			  const char *args)
900*cc4ad7daSAndroid Build Coastguard Worker {
901*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_elf *elf;
902*cc4ad7daSAndroid Build Coastguard Worker 	const void *mem;
903*cc4ad7daSAndroid Build Coastguard Worker 	off_t size;
904*cc4ad7daSAndroid Build Coastguard Worker 	int err;
905*cc4ad7daSAndroid Build Coastguard Worker 
906*cc4ad7daSAndroid Build Coastguard Worker 	kmod_file_load_contents(mod->file);
907*cc4ad7daSAndroid Build Coastguard Worker 
908*cc4ad7daSAndroid Build Coastguard Worker 	if (flags & (KMOD_INSERT_FORCE_VERMAGIC | KMOD_INSERT_FORCE_MODVERSION)) {
909*cc4ad7daSAndroid Build Coastguard Worker 		elf = kmod_file_get_elf(mod->file);
910*cc4ad7daSAndroid Build Coastguard Worker 		if (elf == NULL) {
911*cc4ad7daSAndroid Build Coastguard Worker 			err = -errno;
912*cc4ad7daSAndroid Build Coastguard Worker 			return err;
913*cc4ad7daSAndroid Build Coastguard Worker 		}
914*cc4ad7daSAndroid Build Coastguard Worker 
915*cc4ad7daSAndroid Build Coastguard Worker 		if (flags & KMOD_INSERT_FORCE_MODVERSION) {
916*cc4ad7daSAndroid Build Coastguard Worker 			err = kmod_elf_strip_section(elf, "__versions");
917*cc4ad7daSAndroid Build Coastguard Worker 			if (err < 0)
918*cc4ad7daSAndroid Build Coastguard Worker 				INFO(mod->ctx, "Failed to strip modversion: %s\n", strerror(-err));
919*cc4ad7daSAndroid Build Coastguard Worker 		}
920*cc4ad7daSAndroid Build Coastguard Worker 
921*cc4ad7daSAndroid Build Coastguard Worker 		if (flags & KMOD_INSERT_FORCE_VERMAGIC) {
922*cc4ad7daSAndroid Build Coastguard Worker 			err = kmod_elf_strip_vermagic(elf);
923*cc4ad7daSAndroid Build Coastguard Worker 			if (err < 0)
924*cc4ad7daSAndroid Build Coastguard Worker 				INFO(mod->ctx, "Failed to strip vermagic: %s\n", strerror(-err));
925*cc4ad7daSAndroid Build Coastguard Worker 		}
926*cc4ad7daSAndroid Build Coastguard Worker 
927*cc4ad7daSAndroid Build Coastguard Worker 		mem = kmod_elf_get_memory(elf);
928*cc4ad7daSAndroid Build Coastguard Worker 	} else {
929*cc4ad7daSAndroid Build Coastguard Worker 		mem = kmod_file_get_contents(mod->file);
930*cc4ad7daSAndroid Build Coastguard Worker 	}
931*cc4ad7daSAndroid Build Coastguard Worker 	size = kmod_file_get_size(mod->file);
932*cc4ad7daSAndroid Build Coastguard Worker 
933*cc4ad7daSAndroid Build Coastguard Worker 	err = init_module(mem, size, args);
934*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
935*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
936*cc4ad7daSAndroid Build Coastguard Worker 
937*cc4ad7daSAndroid Build Coastguard Worker 	return err;
938*cc4ad7daSAndroid Build Coastguard Worker }
939*cc4ad7daSAndroid Build Coastguard Worker 
940*cc4ad7daSAndroid Build Coastguard Worker /**
941*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_insert_module:
942*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
943*cc4ad7daSAndroid Build Coastguard Worker  * @flags: flags are not passed to Linux Kernel, but instead they dictate the
944*cc4ad7daSAndroid Build Coastguard Worker  * behavior of this function, valid flags are
945*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_INSERT_FORCE_VERMAGIC: ignore kernel version magic;
946*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_INSERT_FORCE_MODVERSION: ignore symbol version hashes.
947*cc4ad7daSAndroid Build Coastguard Worker  * @options: module's options to pass to Linux Kernel.
948*cc4ad7daSAndroid Build Coastguard Worker  *
949*cc4ad7daSAndroid Build Coastguard Worker  * Insert a module in Linux kernel. It opens the file pointed by @mod,
950*cc4ad7daSAndroid Build Coastguard Worker  * mmap'ing it and passing to kernel.
951*cc4ad7daSAndroid Build Coastguard Worker  *
952*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 on failure. If module is already loaded it
953*cc4ad7daSAndroid Build Coastguard Worker  * returns -EEXIST.
954*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_insert_module(struct kmod_module * mod,unsigned int flags,const char * options)955*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
956*cc4ad7daSAndroid Build Coastguard Worker 							unsigned int flags,
957*cc4ad7daSAndroid Build Coastguard Worker 							const char *options)
958*cc4ad7daSAndroid Build Coastguard Worker {
959*cc4ad7daSAndroid Build Coastguard Worker 	int err;
960*cc4ad7daSAndroid Build Coastguard Worker 	const char *path;
961*cc4ad7daSAndroid Build Coastguard Worker 	const char *args = options ? options : "";
962*cc4ad7daSAndroid Build Coastguard Worker 
963*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
964*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
965*cc4ad7daSAndroid Build Coastguard Worker 
966*cc4ad7daSAndroid Build Coastguard Worker 	path = kmod_module_get_path(mod);
967*cc4ad7daSAndroid Build Coastguard Worker 	if (path == NULL) {
968*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "could not find module by name='%s'\n", mod->name);
969*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
970*cc4ad7daSAndroid Build Coastguard Worker 	}
971*cc4ad7daSAndroid Build Coastguard Worker 
972*cc4ad7daSAndroid Build Coastguard Worker 	if (!mod->file) {
973*cc4ad7daSAndroid Build Coastguard Worker 		mod->file = kmod_file_open(mod->ctx, path);
974*cc4ad7daSAndroid Build Coastguard Worker 		if (mod->file == NULL) {
975*cc4ad7daSAndroid Build Coastguard Worker 			err = -errno;
976*cc4ad7daSAndroid Build Coastguard Worker 			return err;
977*cc4ad7daSAndroid Build Coastguard Worker 		}
978*cc4ad7daSAndroid Build Coastguard Worker 	}
979*cc4ad7daSAndroid Build Coastguard Worker 
980*cc4ad7daSAndroid Build Coastguard Worker 	err = do_finit_module(mod, flags, args);
981*cc4ad7daSAndroid Build Coastguard Worker 	if (err == -ENOSYS)
982*cc4ad7daSAndroid Build Coastguard Worker 		err = do_init_module(mod, flags, args);
983*cc4ad7daSAndroid Build Coastguard Worker 
984*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
985*cc4ad7daSAndroid Build Coastguard Worker 		INFO(mod->ctx, "Failed to insert module '%s': %s\n",
986*cc4ad7daSAndroid Build Coastguard Worker 		     path, strerror(-err));
987*cc4ad7daSAndroid Build Coastguard Worker 
988*cc4ad7daSAndroid Build Coastguard Worker 	return err;
989*cc4ad7daSAndroid Build Coastguard Worker }
990*cc4ad7daSAndroid Build Coastguard Worker 
module_is_blacklisted(struct kmod_module * mod)991*cc4ad7daSAndroid Build Coastguard Worker static bool module_is_blacklisted(struct kmod_module *mod)
992*cc4ad7daSAndroid Build Coastguard Worker {
993*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_ctx *ctx = mod->ctx;
994*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_config *config = kmod_get_config(ctx);
995*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_list *bl = config->blacklists;
996*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_list *l;
997*cc4ad7daSAndroid Build Coastguard Worker 
998*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, bl) {
999*cc4ad7daSAndroid Build Coastguard Worker 		const char *modname = kmod_blacklist_get_modname(l);
1000*cc4ad7daSAndroid Build Coastguard Worker 
1001*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(modname, mod->name))
1002*cc4ad7daSAndroid Build Coastguard Worker 			return true;
1003*cc4ad7daSAndroid Build Coastguard Worker 	}
1004*cc4ad7daSAndroid Build Coastguard Worker 
1005*cc4ad7daSAndroid Build Coastguard Worker 	return false;
1006*cc4ad7daSAndroid Build Coastguard Worker }
1007*cc4ad7daSAndroid Build Coastguard Worker 
1008*cc4ad7daSAndroid Build Coastguard Worker /**
1009*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_apply_filter
1010*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1011*cc4ad7daSAndroid Build Coastguard Worker  * @filter_type: bitmask to filter modules out, valid types are
1012*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_FILTER_BLACKLIST: filter modules in blacklist out;
1013*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_FILTER_BUILTIN: filter builtin modules out.
1014*cc4ad7daSAndroid Build Coastguard Worker  * @input: list of kmod_module to be filtered
1015*cc4ad7daSAndroid Build Coastguard Worker  * @output: where to save the new list
1016*cc4ad7daSAndroid Build Coastguard Worker  *
1017*cc4ad7daSAndroid Build Coastguard Worker  * Given a list @input, this function filter it out by the filter mask
1018*cc4ad7daSAndroid Build Coastguard Worker  * and save it in @output.
1019*cc4ad7daSAndroid Build Coastguard Worker  *
1020*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise. @output is saved with the updated
1021*cc4ad7daSAndroid Build Coastguard Worker  * list.
1022*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_apply_filter(const struct kmod_ctx * ctx,enum kmod_filter filter_type,const struct kmod_list * input,struct kmod_list ** output)1023*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_apply_filter(const struct kmod_ctx *ctx,
1024*cc4ad7daSAndroid Build Coastguard Worker 						enum kmod_filter filter_type,
1025*cc4ad7daSAndroid Build Coastguard Worker 						const struct kmod_list *input,
1026*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **output)
1027*cc4ad7daSAndroid Build Coastguard Worker {
1028*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_list *li;
1029*cc4ad7daSAndroid Build Coastguard Worker 
1030*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || output == NULL)
1031*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1032*cc4ad7daSAndroid Build Coastguard Worker 
1033*cc4ad7daSAndroid Build Coastguard Worker 	*output = NULL;
1034*cc4ad7daSAndroid Build Coastguard Worker 	if (input == NULL)
1035*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
1036*cc4ad7daSAndroid Build Coastguard Worker 
1037*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(li, input) {
1038*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *mod = li->data;
1039*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *node;
1040*cc4ad7daSAndroid Build Coastguard Worker 
1041*cc4ad7daSAndroid Build Coastguard Worker 		if ((filter_type & KMOD_FILTER_BLACKLIST) &&
1042*cc4ad7daSAndroid Build Coastguard Worker 				module_is_blacklisted(mod))
1043*cc4ad7daSAndroid Build Coastguard Worker 			continue;
1044*cc4ad7daSAndroid Build Coastguard Worker 
1045*cc4ad7daSAndroid Build Coastguard Worker 		if ((filter_type & KMOD_FILTER_BUILTIN)
1046*cc4ad7daSAndroid Build Coastguard Worker 		    && kmod_module_is_builtin(mod))
1047*cc4ad7daSAndroid Build Coastguard Worker 			continue;
1048*cc4ad7daSAndroid Build Coastguard Worker 
1049*cc4ad7daSAndroid Build Coastguard Worker 		node = kmod_list_append(*output, mod);
1050*cc4ad7daSAndroid Build Coastguard Worker 		if (node == NULL)
1051*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
1052*cc4ad7daSAndroid Build Coastguard Worker 
1053*cc4ad7daSAndroid Build Coastguard Worker 		*output = node;
1054*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_ref(mod);
1055*cc4ad7daSAndroid Build Coastguard Worker 	}
1056*cc4ad7daSAndroid Build Coastguard Worker 
1057*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
1058*cc4ad7daSAndroid Build Coastguard Worker 
1059*cc4ad7daSAndroid Build Coastguard Worker fail:
1060*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(*output);
1061*cc4ad7daSAndroid Build Coastguard Worker 	*output = NULL;
1062*cc4ad7daSAndroid Build Coastguard Worker 	return -ENOMEM;
1063*cc4ad7daSAndroid Build Coastguard Worker }
1064*cc4ad7daSAndroid Build Coastguard Worker 
command_do(struct kmod_module * mod,const char * type,const char * cmd)1065*cc4ad7daSAndroid Build Coastguard Worker static int command_do(struct kmod_module *mod, const char *type,
1066*cc4ad7daSAndroid Build Coastguard Worker 							const char *cmd)
1067*cc4ad7daSAndroid Build Coastguard Worker {
1068*cc4ad7daSAndroid Build Coastguard Worker 	const char *modname = kmod_module_get_name(mod);
1069*cc4ad7daSAndroid Build Coastguard Worker 	int err;
1070*cc4ad7daSAndroid Build Coastguard Worker 
1071*cc4ad7daSAndroid Build Coastguard Worker 	DBG(mod->ctx, "%s %s\n", type, cmd);
1072*cc4ad7daSAndroid Build Coastguard Worker 
1073*cc4ad7daSAndroid Build Coastguard Worker 	setenv("MODPROBE_MODULE", modname, 1);
1074*cc4ad7daSAndroid Build Coastguard Worker 	err = system(cmd);
1075*cc4ad7daSAndroid Build Coastguard Worker 	unsetenv("MODPROBE_MODULE");
1076*cc4ad7daSAndroid Build Coastguard Worker 
1077*cc4ad7daSAndroid Build Coastguard Worker 	if (err == -1) {
1078*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "Could not run %s command '%s' for module %s: %m\n",
1079*cc4ad7daSAndroid Build Coastguard Worker 		    type, cmd, modname);
1080*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
1081*cc4ad7daSAndroid Build Coastguard Worker 	}
1082*cc4ad7daSAndroid Build Coastguard Worker 
1083*cc4ad7daSAndroid Build Coastguard Worker 	if (WEXITSTATUS(err)) {
1084*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "Error running %s command '%s' for module %s: retcode %d\n",
1085*cc4ad7daSAndroid Build Coastguard Worker 		    type, cmd, modname, WEXITSTATUS(err));
1086*cc4ad7daSAndroid Build Coastguard Worker 		return -EINVAL;
1087*cc4ad7daSAndroid Build Coastguard Worker 	}
1088*cc4ad7daSAndroid Build Coastguard Worker 
1089*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
1090*cc4ad7daSAndroid Build Coastguard Worker }
1091*cc4ad7daSAndroid Build Coastguard Worker 
1092*cc4ad7daSAndroid Build Coastguard Worker struct probe_insert_cb {
1093*cc4ad7daSAndroid Build Coastguard Worker 	int (*run_install)(struct kmod_module *m, const char *cmd, void *data);
1094*cc4ad7daSAndroid Build Coastguard Worker 	void *data;
1095*cc4ad7daSAndroid Build Coastguard Worker };
1096*cc4ad7daSAndroid Build Coastguard Worker 
module_do_install_commands(struct kmod_module * mod,const char * options,struct probe_insert_cb * cb)1097*cc4ad7daSAndroid Build Coastguard Worker static int module_do_install_commands(struct kmod_module *mod,
1098*cc4ad7daSAndroid Build Coastguard Worker 					const char *options,
1099*cc4ad7daSAndroid Build Coastguard Worker 					struct probe_insert_cb *cb)
1100*cc4ad7daSAndroid Build Coastguard Worker {
1101*cc4ad7daSAndroid Build Coastguard Worker 	const char *command = kmod_module_get_install_commands(mod);
1102*cc4ad7daSAndroid Build Coastguard Worker 	char *p;
1103*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ char *cmd;
1104*cc4ad7daSAndroid Build Coastguard Worker 	int err;
1105*cc4ad7daSAndroid Build Coastguard Worker 	size_t cmdlen, options_len, varlen;
1106*cc4ad7daSAndroid Build Coastguard Worker 
1107*cc4ad7daSAndroid Build Coastguard Worker 	assert(command);
1108*cc4ad7daSAndroid Build Coastguard Worker 
1109*cc4ad7daSAndroid Build Coastguard Worker 	if (options == NULL)
1110*cc4ad7daSAndroid Build Coastguard Worker 		options = "";
1111*cc4ad7daSAndroid Build Coastguard Worker 
1112*cc4ad7daSAndroid Build Coastguard Worker 	options_len = strlen(options);
1113*cc4ad7daSAndroid Build Coastguard Worker 	cmdlen = strlen(command);
1114*cc4ad7daSAndroid Build Coastguard Worker 	varlen = sizeof("$CMDLINE_OPTS") - 1;
1115*cc4ad7daSAndroid Build Coastguard Worker 
1116*cc4ad7daSAndroid Build Coastguard Worker 	cmd = memdup(command, cmdlen + 1);
1117*cc4ad7daSAndroid Build Coastguard Worker 	if (cmd == NULL)
1118*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOMEM;
1119*cc4ad7daSAndroid Build Coastguard Worker 
1120*cc4ad7daSAndroid Build Coastguard Worker 	while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) {
1121*cc4ad7daSAndroid Build Coastguard Worker 		size_t prefixlen = p - cmd;
1122*cc4ad7daSAndroid Build Coastguard Worker 		size_t suffixlen = cmdlen - prefixlen - varlen;
1123*cc4ad7daSAndroid Build Coastguard Worker 		size_t slen = cmdlen - varlen + options_len;
1124*cc4ad7daSAndroid Build Coastguard Worker 		char *suffix = p + varlen;
1125*cc4ad7daSAndroid Build Coastguard Worker 		char *s = malloc(slen + 1);
1126*cc4ad7daSAndroid Build Coastguard Worker 		if (!s)
1127*cc4ad7daSAndroid Build Coastguard Worker 			return -ENOMEM;
1128*cc4ad7daSAndroid Build Coastguard Worker 
1129*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(s, cmd, p - cmd);
1130*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(s + prefixlen, options, options_len);
1131*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(s + prefixlen + options_len, suffix, suffixlen);
1132*cc4ad7daSAndroid Build Coastguard Worker 		s[slen] = '\0';
1133*cc4ad7daSAndroid Build Coastguard Worker 
1134*cc4ad7daSAndroid Build Coastguard Worker 		free(cmd);
1135*cc4ad7daSAndroid Build Coastguard Worker 		cmd = s;
1136*cc4ad7daSAndroid Build Coastguard Worker 		cmdlen = slen;
1137*cc4ad7daSAndroid Build Coastguard Worker 	}
1138*cc4ad7daSAndroid Build Coastguard Worker 
1139*cc4ad7daSAndroid Build Coastguard Worker 	if (cb->run_install != NULL)
1140*cc4ad7daSAndroid Build Coastguard Worker 		err = cb->run_install(mod, cmd, cb->data);
1141*cc4ad7daSAndroid Build Coastguard Worker 	else
1142*cc4ad7daSAndroid Build Coastguard Worker 		err = command_do(mod, "install", cmd);
1143*cc4ad7daSAndroid Build Coastguard Worker 
1144*cc4ad7daSAndroid Build Coastguard Worker 	return err;
1145*cc4ad7daSAndroid Build Coastguard Worker }
1146*cc4ad7daSAndroid Build Coastguard Worker 
module_options_concat(const char * opt,const char * xopt)1147*cc4ad7daSAndroid Build Coastguard Worker static char *module_options_concat(const char *opt, const char *xopt)
1148*cc4ad7daSAndroid Build Coastguard Worker {
1149*cc4ad7daSAndroid Build Coastguard Worker 	// TODO: we might need to check if xopt overrides options on opt
1150*cc4ad7daSAndroid Build Coastguard Worker 	size_t optlen = opt == NULL ? 0 : strlen(opt);
1151*cc4ad7daSAndroid Build Coastguard Worker 	size_t xoptlen = xopt == NULL ? 0 : strlen(xopt);
1152*cc4ad7daSAndroid Build Coastguard Worker 	char *r;
1153*cc4ad7daSAndroid Build Coastguard Worker 
1154*cc4ad7daSAndroid Build Coastguard Worker 	if (optlen == 0 && xoptlen == 0)
1155*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1156*cc4ad7daSAndroid Build Coastguard Worker 
1157*cc4ad7daSAndroid Build Coastguard Worker 	r = malloc(optlen + xoptlen + 2);
1158*cc4ad7daSAndroid Build Coastguard Worker 
1159*cc4ad7daSAndroid Build Coastguard Worker 	if (opt != NULL) {
1160*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(r, opt, optlen);
1161*cc4ad7daSAndroid Build Coastguard Worker 		r[optlen] = ' ';
1162*cc4ad7daSAndroid Build Coastguard Worker 		optlen++;
1163*cc4ad7daSAndroid Build Coastguard Worker 	}
1164*cc4ad7daSAndroid Build Coastguard Worker 
1165*cc4ad7daSAndroid Build Coastguard Worker 	if (xopt != NULL)
1166*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(r + optlen, xopt, xoptlen);
1167*cc4ad7daSAndroid Build Coastguard Worker 
1168*cc4ad7daSAndroid Build Coastguard Worker 	r[optlen + xoptlen] = '\0';
1169*cc4ad7daSAndroid Build Coastguard Worker 
1170*cc4ad7daSAndroid Build Coastguard Worker 	return r;
1171*cc4ad7daSAndroid Build Coastguard Worker }
1172*cc4ad7daSAndroid Build Coastguard Worker 
1173*cc4ad7daSAndroid Build Coastguard Worker static int __kmod_module_get_probe_list(struct kmod_module *mod,
1174*cc4ad7daSAndroid Build Coastguard Worker 						bool required,
1175*cc4ad7daSAndroid Build Coastguard Worker 						bool ignorecmd,
1176*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list);
1177*cc4ad7daSAndroid Build Coastguard Worker 
1178*cc4ad7daSAndroid Build Coastguard Worker /* re-entrant */
__kmod_module_fill_softdep(struct kmod_module * mod,struct kmod_list ** list)1179*cc4ad7daSAndroid Build Coastguard Worker static int __kmod_module_fill_softdep(struct kmod_module *mod,
1180*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
1181*cc4ad7daSAndroid Build Coastguard Worker {
1182*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *pre = NULL, *post = NULL, *l;
1183*cc4ad7daSAndroid Build Coastguard Worker 	int err;
1184*cc4ad7daSAndroid Build Coastguard Worker 
1185*cc4ad7daSAndroid Build Coastguard Worker 	err = kmod_module_get_softdeps(mod, &pre, &post);
1186*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
1187*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "could not get softdep: %s\n",
1188*cc4ad7daSAndroid Build Coastguard Worker 							strerror(-err));
1189*cc4ad7daSAndroid Build Coastguard Worker 		goto fail;
1190*cc4ad7daSAndroid Build Coastguard Worker 	}
1191*cc4ad7daSAndroid Build Coastguard Worker 
1192*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, pre) {
1193*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = l->data;
1194*cc4ad7daSAndroid Build Coastguard Worker 		err = __kmod_module_get_probe_list(m, false, false, list);
1195*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0)
1196*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
1197*cc4ad7daSAndroid Build Coastguard Worker 	}
1198*cc4ad7daSAndroid Build Coastguard Worker 
1199*cc4ad7daSAndroid Build Coastguard Worker 	l = kmod_list_append(*list, kmod_module_ref(mod));
1200*cc4ad7daSAndroid Build Coastguard Worker 	if (l == NULL) {
1201*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_unref(mod);
1202*cc4ad7daSAndroid Build Coastguard Worker 		err = -ENOMEM;
1203*cc4ad7daSAndroid Build Coastguard Worker 		goto fail;
1204*cc4ad7daSAndroid Build Coastguard Worker 	}
1205*cc4ad7daSAndroid Build Coastguard Worker 	*list = l;
1206*cc4ad7daSAndroid Build Coastguard Worker 	mod->ignorecmd = (pre != NULL || post != NULL);
1207*cc4ad7daSAndroid Build Coastguard Worker 
1208*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, post) {
1209*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = l->data;
1210*cc4ad7daSAndroid Build Coastguard Worker 		err = __kmod_module_get_probe_list(m, false, false, list);
1211*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0)
1212*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
1213*cc4ad7daSAndroid Build Coastguard Worker 	}
1214*cc4ad7daSAndroid Build Coastguard Worker 
1215*cc4ad7daSAndroid Build Coastguard Worker fail:
1216*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(pre);
1217*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(post);
1218*cc4ad7daSAndroid Build Coastguard Worker 
1219*cc4ad7daSAndroid Build Coastguard Worker 	return err;
1220*cc4ad7daSAndroid Build Coastguard Worker }
1221*cc4ad7daSAndroid Build Coastguard Worker 
1222*cc4ad7daSAndroid Build Coastguard Worker /* re-entrant */
__kmod_module_get_probe_list(struct kmod_module * mod,bool required,bool ignorecmd,struct kmod_list ** list)1223*cc4ad7daSAndroid Build Coastguard Worker static int __kmod_module_get_probe_list(struct kmod_module *mod,
1224*cc4ad7daSAndroid Build Coastguard Worker 						bool required,
1225*cc4ad7daSAndroid Build Coastguard Worker 						bool ignorecmd,
1226*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
1227*cc4ad7daSAndroid Build Coastguard Worker {
1228*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *dep, *l;
1229*cc4ad7daSAndroid Build Coastguard Worker 	int err = 0;
1230*cc4ad7daSAndroid Build Coastguard Worker 
1231*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->visited) {
1232*cc4ad7daSAndroid Build Coastguard Worker 		DBG(mod->ctx, "Ignore module '%s': already visited\n",
1233*cc4ad7daSAndroid Build Coastguard Worker 								mod->name);
1234*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
1235*cc4ad7daSAndroid Build Coastguard Worker 	}
1236*cc4ad7daSAndroid Build Coastguard Worker 	mod->visited = true;
1237*cc4ad7daSAndroid Build Coastguard Worker 
1238*cc4ad7daSAndroid Build Coastguard Worker 	dep = kmod_module_get_dependencies(mod);
1239*cc4ad7daSAndroid Build Coastguard Worker 	if (required) {
1240*cc4ad7daSAndroid Build Coastguard Worker 		/*
1241*cc4ad7daSAndroid Build Coastguard Worker 		 * Called from kmod_module_probe_insert_module(); set the
1242*cc4ad7daSAndroid Build Coastguard Worker 		 * ->required flag on mod and all its dependencies before
1243*cc4ad7daSAndroid Build Coastguard Worker 		 * they are possibly visited through some softdeps.
1244*cc4ad7daSAndroid Build Coastguard Worker 		 */
1245*cc4ad7daSAndroid Build Coastguard Worker 		mod->required = true;
1246*cc4ad7daSAndroid Build Coastguard Worker 		kmod_list_foreach(l, dep) {
1247*cc4ad7daSAndroid Build Coastguard Worker 			struct kmod_module *m = l->data;
1248*cc4ad7daSAndroid Build Coastguard Worker 			m->required = true;
1249*cc4ad7daSAndroid Build Coastguard Worker 		}
1250*cc4ad7daSAndroid Build Coastguard Worker 	}
1251*cc4ad7daSAndroid Build Coastguard Worker 
1252*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, dep) {
1253*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = l->data;
1254*cc4ad7daSAndroid Build Coastguard Worker 		err = __kmod_module_fill_softdep(m, list);
1255*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0)
1256*cc4ad7daSAndroid Build Coastguard Worker 			goto finish;
1257*cc4ad7daSAndroid Build Coastguard Worker 	}
1258*cc4ad7daSAndroid Build Coastguard Worker 
1259*cc4ad7daSAndroid Build Coastguard Worker 	if (ignorecmd) {
1260*cc4ad7daSAndroid Build Coastguard Worker 		l = kmod_list_append(*list, kmod_module_ref(mod));
1261*cc4ad7daSAndroid Build Coastguard Worker 		if (l == NULL) {
1262*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_unref(mod);
1263*cc4ad7daSAndroid Build Coastguard Worker 			err = -ENOMEM;
1264*cc4ad7daSAndroid Build Coastguard Worker 			goto finish;
1265*cc4ad7daSAndroid Build Coastguard Worker 		}
1266*cc4ad7daSAndroid Build Coastguard Worker 		*list = l;
1267*cc4ad7daSAndroid Build Coastguard Worker 		mod->ignorecmd = true;
1268*cc4ad7daSAndroid Build Coastguard Worker 	} else
1269*cc4ad7daSAndroid Build Coastguard Worker 		err = __kmod_module_fill_softdep(mod, list);
1270*cc4ad7daSAndroid Build Coastguard Worker 
1271*cc4ad7daSAndroid Build Coastguard Worker finish:
1272*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(dep);
1273*cc4ad7daSAndroid Build Coastguard Worker 	return err;
1274*cc4ad7daSAndroid Build Coastguard Worker }
1275*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_get_probe_list(struct kmod_module * mod,bool ignorecmd,struct kmod_list ** list)1276*cc4ad7daSAndroid Build Coastguard Worker static int kmod_module_get_probe_list(struct kmod_module *mod,
1277*cc4ad7daSAndroid Build Coastguard Worker 						bool ignorecmd,
1278*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
1279*cc4ad7daSAndroid Build Coastguard Worker {
1280*cc4ad7daSAndroid Build Coastguard Worker 	int err;
1281*cc4ad7daSAndroid Build Coastguard Worker 
1282*cc4ad7daSAndroid Build Coastguard Worker 	assert(mod != NULL);
1283*cc4ad7daSAndroid Build Coastguard Worker 	assert(list != NULL && *list == NULL);
1284*cc4ad7daSAndroid Build Coastguard Worker 
1285*cc4ad7daSAndroid Build Coastguard Worker 	/*
1286*cc4ad7daSAndroid Build Coastguard Worker 	 * Make sure we don't get screwed by previous calls to this function
1287*cc4ad7daSAndroid Build Coastguard Worker 	 */
1288*cc4ad7daSAndroid Build Coastguard Worker 	kmod_set_modules_visited(mod->ctx, false);
1289*cc4ad7daSAndroid Build Coastguard Worker 	kmod_set_modules_required(mod->ctx, false);
1290*cc4ad7daSAndroid Build Coastguard Worker 
1291*cc4ad7daSAndroid Build Coastguard Worker 	err = __kmod_module_get_probe_list(mod, true, ignorecmd, list);
1292*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
1293*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_unref_list(*list);
1294*cc4ad7daSAndroid Build Coastguard Worker 		*list = NULL;
1295*cc4ad7daSAndroid Build Coastguard Worker 	}
1296*cc4ad7daSAndroid Build Coastguard Worker 
1297*cc4ad7daSAndroid Build Coastguard Worker 	return err;
1298*cc4ad7daSAndroid Build Coastguard Worker }
1299*cc4ad7daSAndroid Build Coastguard Worker 
1300*cc4ad7daSAndroid Build Coastguard Worker /**
1301*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_probe_insert_module:
1302*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1303*cc4ad7daSAndroid Build Coastguard Worker  * @flags: flags are not passed to Linux Kernel, but instead they dictate the
1304*cc4ad7daSAndroid Build Coastguard Worker  * behavior of this function, valid flags are
1305*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_FORCE_VERMAGIC: ignore kernel version magic;
1306*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_FORCE_MODVERSION: ignore symbol version hashes;
1307*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_IGNORE_COMMAND: whether the probe should ignore install
1308*cc4ad7daSAndroid Build Coastguard Worker  * commands and softdeps configured in the system;
1309*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_IGNORE_LOADED: do not check whether the module is already
1310*cc4ad7daSAndroid Build Coastguard Worker  * live in kernel or not;
1311*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_DRY_RUN: dry run, do not insert module, just call the
1312*cc4ad7daSAndroid Build Coastguard Worker  * associated callback function;
1313*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_FAIL_ON_LOADED: if KMOD_PROBE_IGNORE_LOADED is not specified
1314*cc4ad7daSAndroid Build Coastguard Worker  * and the module is already live in kernel, the function will fail if this
1315*cc4ad7daSAndroid Build Coastguard Worker  * flag is specified;
1316*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_APPLY_BLACKLIST_ALL: probe will apply KMOD_FILTER_BLACKLIST
1317*cc4ad7daSAndroid Build Coastguard Worker  * filter to this module and its dependencies. If any of the dependencies (or
1318*cc4ad7daSAndroid Build Coastguard Worker  * the module) is blacklisted, the probe will fail, unless the blacklisted
1319*cc4ad7daSAndroid Build Coastguard Worker  * module is already live in kernel;
1320*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_APPLY_BLACKLIST: probe will fail if the module is blacklisted;
1321*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY: probe will fail if the module is an
1322*cc4ad7daSAndroid Build Coastguard Worker  * alias and is blacklisted.
1323*cc4ad7daSAndroid Build Coastguard Worker  * @extra_options: module's options to pass to Linux Kernel. It applies only
1324*cc4ad7daSAndroid Build Coastguard Worker  * to @mod, not to its dependencies.
1325*cc4ad7daSAndroid Build Coastguard Worker  * @run_install: function to run when @mod is backed by an install command.
1326*cc4ad7daSAndroid Build Coastguard Worker  * @data: data to give back to @run_install callback
1327*cc4ad7daSAndroid Build Coastguard Worker  * @print_action: function to call with the action being taken (install or
1328*cc4ad7daSAndroid Build Coastguard Worker  * insmod). It's useful for tools like modprobe when running with verbose
1329*cc4ad7daSAndroid Build Coastguard Worker  * output or in dry-run mode.
1330*cc4ad7daSAndroid Build Coastguard Worker  *
1331*cc4ad7daSAndroid Build Coastguard Worker  * Insert a module in Linux kernel resolving dependencies, soft dependencies,
1332*cc4ad7daSAndroid Build Coastguard Worker  * install commands and applying blacklist.
1333*cc4ad7daSAndroid Build Coastguard Worker  *
1334*cc4ad7daSAndroid Build Coastguard Worker  * If @run_install is NULL, this function will fork and exec by calling
1335*cc4ad7daSAndroid Build Coastguard Worker  * system(3). Don't pass a NULL argument in @run_install if your binary is
1336*cc4ad7daSAndroid Build Coastguard Worker  * setuid/setgid (see warning in system(3)). If you need control over the
1337*cc4ad7daSAndroid Build Coastguard Worker  * execution of an install command, give a callback function instead.
1338*cc4ad7daSAndroid Build Coastguard Worker  *
1339*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success, > 0 if stopped by a reason given in @flags or < 0 on
1340*cc4ad7daSAndroid Build Coastguard Worker  * failure.
1341*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_probe_insert_module(struct kmod_module * mod,unsigned int flags,const char * extra_options,int (* run_install)(struct kmod_module * m,const char * cmd,void * data),const void * data,void (* print_action)(struct kmod_module * m,bool install,const char * options))1342*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_probe_insert_module(struct kmod_module *mod,
1343*cc4ad7daSAndroid Build Coastguard Worker 			unsigned int flags, const char *extra_options,
1344*cc4ad7daSAndroid Build Coastguard Worker 			int (*run_install)(struct kmod_module *m,
1345*cc4ad7daSAndroid Build Coastguard Worker 						const char *cmd, void *data),
1346*cc4ad7daSAndroid Build Coastguard Worker 			const void *data,
1347*cc4ad7daSAndroid Build Coastguard Worker 			void (*print_action)(struct kmod_module *m,
1348*cc4ad7daSAndroid Build Coastguard Worker 						bool install,
1349*cc4ad7daSAndroid Build Coastguard Worker 						const char *options))
1350*cc4ad7daSAndroid Build Coastguard Worker {
1351*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list = NULL, *l;
1352*cc4ad7daSAndroid Build Coastguard Worker 	struct probe_insert_cb cb;
1353*cc4ad7daSAndroid Build Coastguard Worker 	int err;
1354*cc4ad7daSAndroid Build Coastguard Worker 
1355*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1356*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1357*cc4ad7daSAndroid Build Coastguard Worker 
1358*cc4ad7daSAndroid Build Coastguard Worker 	if (!(flags & KMOD_PROBE_IGNORE_LOADED)
1359*cc4ad7daSAndroid Build Coastguard Worker 					&& module_is_inkernel(mod)) {
1360*cc4ad7daSAndroid Build Coastguard Worker 		if (flags & KMOD_PROBE_FAIL_ON_LOADED)
1361*cc4ad7daSAndroid Build Coastguard Worker 			return -EEXIST;
1362*cc4ad7daSAndroid Build Coastguard Worker 		else
1363*cc4ad7daSAndroid Build Coastguard Worker 			return 0;
1364*cc4ad7daSAndroid Build Coastguard Worker 	}
1365*cc4ad7daSAndroid Build Coastguard Worker 
1366*cc4ad7daSAndroid Build Coastguard Worker 	/*
1367*cc4ad7daSAndroid Build Coastguard Worker 	 * Ugly assignement + check. We need to check if we were told to check
1368*cc4ad7daSAndroid Build Coastguard Worker 	 * blacklist and also return the reason why we failed.
1369*cc4ad7daSAndroid Build Coastguard Worker 	 * KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY will take effect only if the
1370*cc4ad7daSAndroid Build Coastguard Worker 	 * module is an alias, so we also need to check it
1371*cc4ad7daSAndroid Build Coastguard Worker 	 */
1372*cc4ad7daSAndroid Build Coastguard Worker 	if ((mod->alias != NULL && ((err = flags & KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY)))
1373*cc4ad7daSAndroid Build Coastguard Worker 			|| (err = flags & KMOD_PROBE_APPLY_BLACKLIST_ALL)
1374*cc4ad7daSAndroid Build Coastguard Worker 			|| (err = flags & KMOD_PROBE_APPLY_BLACKLIST)) {
1375*cc4ad7daSAndroid Build Coastguard Worker 		if (module_is_blacklisted(mod))
1376*cc4ad7daSAndroid Build Coastguard Worker 			return err;
1377*cc4ad7daSAndroid Build Coastguard Worker 	}
1378*cc4ad7daSAndroid Build Coastguard Worker 
1379*cc4ad7daSAndroid Build Coastguard Worker 	err = kmod_module_get_probe_list(mod,
1380*cc4ad7daSAndroid Build Coastguard Worker 				!!(flags & KMOD_PROBE_IGNORE_COMMAND), &list);
1381*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0)
1382*cc4ad7daSAndroid Build Coastguard Worker 		return err;
1383*cc4ad7daSAndroid Build Coastguard Worker 
1384*cc4ad7daSAndroid Build Coastguard Worker 	if (flags & KMOD_PROBE_APPLY_BLACKLIST_ALL) {
1385*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *filtered = NULL;
1386*cc4ad7daSAndroid Build Coastguard Worker 
1387*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_apply_filter(mod->ctx,
1388*cc4ad7daSAndroid Build Coastguard Worker 				KMOD_FILTER_BLACKLIST, list, &filtered);
1389*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0)
1390*cc4ad7daSAndroid Build Coastguard Worker 			return err;
1391*cc4ad7daSAndroid Build Coastguard Worker 
1392*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_unref_list(list);
1393*cc4ad7daSAndroid Build Coastguard Worker 		if (filtered == NULL)
1394*cc4ad7daSAndroid Build Coastguard Worker 			return KMOD_PROBE_APPLY_BLACKLIST_ALL;
1395*cc4ad7daSAndroid Build Coastguard Worker 
1396*cc4ad7daSAndroid Build Coastguard Worker 		list = filtered;
1397*cc4ad7daSAndroid Build Coastguard Worker 	}
1398*cc4ad7daSAndroid Build Coastguard Worker 
1399*cc4ad7daSAndroid Build Coastguard Worker 	cb.run_install = run_install;
1400*cc4ad7daSAndroid Build Coastguard Worker 	cb.data = (void *) data;
1401*cc4ad7daSAndroid Build Coastguard Worker 
1402*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, list) {
1403*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = l->data;
1404*cc4ad7daSAndroid Build Coastguard Worker 		const char *moptions = kmod_module_get_options(m);
1405*cc4ad7daSAndroid Build Coastguard Worker 		const char *cmd = kmod_module_get_install_commands(m);
1406*cc4ad7daSAndroid Build Coastguard Worker 		char *options;
1407*cc4ad7daSAndroid Build Coastguard Worker 
1408*cc4ad7daSAndroid Build Coastguard Worker 		if (!(flags & KMOD_PROBE_IGNORE_LOADED)
1409*cc4ad7daSAndroid Build Coastguard Worker 						&& module_is_inkernel(m)) {
1410*cc4ad7daSAndroid Build Coastguard Worker 			DBG(mod->ctx, "Ignoring module '%s': already loaded\n",
1411*cc4ad7daSAndroid Build Coastguard Worker 								m->name);
1412*cc4ad7daSAndroid Build Coastguard Worker 			err = -EEXIST;
1413*cc4ad7daSAndroid Build Coastguard Worker 			goto finish_module;
1414*cc4ad7daSAndroid Build Coastguard Worker 		}
1415*cc4ad7daSAndroid Build Coastguard Worker 
1416*cc4ad7daSAndroid Build Coastguard Worker 		options = module_options_concat(moptions,
1417*cc4ad7daSAndroid Build Coastguard Worker 					m == mod ? extra_options : NULL);
1418*cc4ad7daSAndroid Build Coastguard Worker 
1419*cc4ad7daSAndroid Build Coastguard Worker 		if (cmd != NULL && !m->ignorecmd) {
1420*cc4ad7daSAndroid Build Coastguard Worker 			if (print_action != NULL)
1421*cc4ad7daSAndroid Build Coastguard Worker 				print_action(m, true, options ?: "");
1422*cc4ad7daSAndroid Build Coastguard Worker 
1423*cc4ad7daSAndroid Build Coastguard Worker 			if (!(flags & KMOD_PROBE_DRY_RUN))
1424*cc4ad7daSAndroid Build Coastguard Worker 				err = module_do_install_commands(m, options,
1425*cc4ad7daSAndroid Build Coastguard Worker 									&cb);
1426*cc4ad7daSAndroid Build Coastguard Worker 		} else {
1427*cc4ad7daSAndroid Build Coastguard Worker 			if (print_action != NULL)
1428*cc4ad7daSAndroid Build Coastguard Worker 				print_action(m, false, options ?: "");
1429*cc4ad7daSAndroid Build Coastguard Worker 
1430*cc4ad7daSAndroid Build Coastguard Worker 			if (!(flags & KMOD_PROBE_DRY_RUN))
1431*cc4ad7daSAndroid Build Coastguard Worker 				err = kmod_module_insert_module(m, flags,
1432*cc4ad7daSAndroid Build Coastguard Worker 								options);
1433*cc4ad7daSAndroid Build Coastguard Worker 		}
1434*cc4ad7daSAndroid Build Coastguard Worker 
1435*cc4ad7daSAndroid Build Coastguard Worker 		free(options);
1436*cc4ad7daSAndroid Build Coastguard Worker 
1437*cc4ad7daSAndroid Build Coastguard Worker finish_module:
1438*cc4ad7daSAndroid Build Coastguard Worker 		/*
1439*cc4ad7daSAndroid Build Coastguard Worker 		 * Treat "already loaded" error. If we were told to stop on
1440*cc4ad7daSAndroid Build Coastguard Worker 		 * already loaded and the module being loaded is not a softdep
1441*cc4ad7daSAndroid Build Coastguard Worker 		 * or dep, bail out. Otherwise, just ignore and continue.
1442*cc4ad7daSAndroid Build Coastguard Worker 		 *
1443*cc4ad7daSAndroid Build Coastguard Worker 		 * We need to check here because of race conditions. We
1444*cc4ad7daSAndroid Build Coastguard Worker 		 * checked first if module was already loaded but it may have
1445*cc4ad7daSAndroid Build Coastguard Worker 		 * been loaded between the check and the moment we try to
1446*cc4ad7daSAndroid Build Coastguard Worker 		 * insert it.
1447*cc4ad7daSAndroid Build Coastguard Worker 		 */
1448*cc4ad7daSAndroid Build Coastguard Worker 		if (err == -EEXIST && m == mod &&
1449*cc4ad7daSAndroid Build Coastguard Worker 				(flags & KMOD_PROBE_FAIL_ON_LOADED))
1450*cc4ad7daSAndroid Build Coastguard Worker 			break;
1451*cc4ad7daSAndroid Build Coastguard Worker 
1452*cc4ad7daSAndroid Build Coastguard Worker 		/*
1453*cc4ad7daSAndroid Build Coastguard Worker 		 * Ignore errors from softdeps
1454*cc4ad7daSAndroid Build Coastguard Worker 		 */
1455*cc4ad7daSAndroid Build Coastguard Worker 		if (err == -EEXIST || !m->required)
1456*cc4ad7daSAndroid Build Coastguard Worker 			err = 0;
1457*cc4ad7daSAndroid Build Coastguard Worker 
1458*cc4ad7daSAndroid Build Coastguard Worker 		else if (err < 0)
1459*cc4ad7daSAndroid Build Coastguard Worker 			break;
1460*cc4ad7daSAndroid Build Coastguard Worker 	}
1461*cc4ad7daSAndroid Build Coastguard Worker 
1462*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(list);
1463*cc4ad7daSAndroid Build Coastguard Worker 	return err;
1464*cc4ad7daSAndroid Build Coastguard Worker }
1465*cc4ad7daSAndroid Build Coastguard Worker 
1466*cc4ad7daSAndroid Build Coastguard Worker /**
1467*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_options:
1468*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1469*cc4ad7daSAndroid Build Coastguard Worker  *
1470*cc4ad7daSAndroid Build Coastguard Worker  * Get options of this kmod module. Options come from the configuration file
1471*cc4ad7daSAndroid Build Coastguard Worker  * and are cached in @mod. The first call to this function will search for
1472*cc4ad7daSAndroid Build Coastguard Worker  * this module in configuration and subsequent calls return the cached string.
1473*cc4ad7daSAndroid Build Coastguard Worker  *
1474*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a string with all the options separated by spaces. This string is
1475*cc4ad7daSAndroid Build Coastguard Worker  * owned by @mod, do not free it.
1476*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_options(const struct kmod_module * mod)1477*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
1478*cc4ad7daSAndroid Build Coastguard Worker {
1479*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1480*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1481*cc4ad7daSAndroid Build Coastguard Worker 
1482*cc4ad7daSAndroid Build Coastguard Worker 	if (!mod->init.options) {
1483*cc4ad7daSAndroid Build Coastguard Worker 		/* lazy init */
1484*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = (struct kmod_module *)mod;
1485*cc4ad7daSAndroid Build Coastguard Worker 		const struct kmod_list *l;
1486*cc4ad7daSAndroid Build Coastguard Worker 		const struct kmod_config *config;
1487*cc4ad7daSAndroid Build Coastguard Worker 		char *opts = NULL;
1488*cc4ad7daSAndroid Build Coastguard Worker 		size_t optslen = 0;
1489*cc4ad7daSAndroid Build Coastguard Worker 
1490*cc4ad7daSAndroid Build Coastguard Worker 		config = kmod_get_config(mod->ctx);
1491*cc4ad7daSAndroid Build Coastguard Worker 
1492*cc4ad7daSAndroid Build Coastguard Worker 		kmod_list_foreach(l, config->options) {
1493*cc4ad7daSAndroid Build Coastguard Worker 			const char *modname = kmod_option_get_modname(l);
1494*cc4ad7daSAndroid Build Coastguard Worker 			const char *str;
1495*cc4ad7daSAndroid Build Coastguard Worker 			size_t len;
1496*cc4ad7daSAndroid Build Coastguard Worker 			void *tmp;
1497*cc4ad7daSAndroid Build Coastguard Worker 
1498*cc4ad7daSAndroid Build Coastguard Worker 			DBG(mod->ctx, "modname=%s mod->name=%s mod->alias=%s\n", modname, mod->name, mod->alias);
1499*cc4ad7daSAndroid Build Coastguard Worker 			if (!(streq(modname, mod->name) || (mod->alias != NULL &&
1500*cc4ad7daSAndroid Build Coastguard Worker 						streq(modname, mod->alias))))
1501*cc4ad7daSAndroid Build Coastguard Worker 				continue;
1502*cc4ad7daSAndroid Build Coastguard Worker 
1503*cc4ad7daSAndroid Build Coastguard Worker 			DBG(mod->ctx, "passed = modname=%s mod->name=%s mod->alias=%s\n", modname, mod->name, mod->alias);
1504*cc4ad7daSAndroid Build Coastguard Worker 			str = kmod_option_get_options(l);
1505*cc4ad7daSAndroid Build Coastguard Worker 			len = strlen(str);
1506*cc4ad7daSAndroid Build Coastguard Worker 			if (len < 1)
1507*cc4ad7daSAndroid Build Coastguard Worker 				continue;
1508*cc4ad7daSAndroid Build Coastguard Worker 
1509*cc4ad7daSAndroid Build Coastguard Worker 			tmp = realloc(opts, optslen + len + 2);
1510*cc4ad7daSAndroid Build Coastguard Worker 			if (tmp == NULL) {
1511*cc4ad7daSAndroid Build Coastguard Worker 				free(opts);
1512*cc4ad7daSAndroid Build Coastguard Worker 				goto failed;
1513*cc4ad7daSAndroid Build Coastguard Worker 			}
1514*cc4ad7daSAndroid Build Coastguard Worker 
1515*cc4ad7daSAndroid Build Coastguard Worker 			opts = tmp;
1516*cc4ad7daSAndroid Build Coastguard Worker 
1517*cc4ad7daSAndroid Build Coastguard Worker 			if (optslen > 0) {
1518*cc4ad7daSAndroid Build Coastguard Worker 				opts[optslen] = ' ';
1519*cc4ad7daSAndroid Build Coastguard Worker 				optslen++;
1520*cc4ad7daSAndroid Build Coastguard Worker 			}
1521*cc4ad7daSAndroid Build Coastguard Worker 
1522*cc4ad7daSAndroid Build Coastguard Worker 			memcpy(opts + optslen, str, len);
1523*cc4ad7daSAndroid Build Coastguard Worker 			optslen += len;
1524*cc4ad7daSAndroid Build Coastguard Worker 			opts[optslen] = '\0';
1525*cc4ad7daSAndroid Build Coastguard Worker 		}
1526*cc4ad7daSAndroid Build Coastguard Worker 
1527*cc4ad7daSAndroid Build Coastguard Worker 		m->init.options = true;
1528*cc4ad7daSAndroid Build Coastguard Worker 		m->options = opts;
1529*cc4ad7daSAndroid Build Coastguard Worker 	}
1530*cc4ad7daSAndroid Build Coastguard Worker 
1531*cc4ad7daSAndroid Build Coastguard Worker 	return mod->options;
1532*cc4ad7daSAndroid Build Coastguard Worker 
1533*cc4ad7daSAndroid Build Coastguard Worker failed:
1534*cc4ad7daSAndroid Build Coastguard Worker 	ERR(mod->ctx, "out of memory\n");
1535*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
1536*cc4ad7daSAndroid Build Coastguard Worker }
1537*cc4ad7daSAndroid Build Coastguard Worker 
1538*cc4ad7daSAndroid Build Coastguard Worker /**
1539*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_install_commands:
1540*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1541*cc4ad7daSAndroid Build Coastguard Worker  *
1542*cc4ad7daSAndroid Build Coastguard Worker  * Get install commands for this kmod module. Install commands come from the
1543*cc4ad7daSAndroid Build Coastguard Worker  * configuration file and are cached in @mod. The first call to this function
1544*cc4ad7daSAndroid Build Coastguard Worker  * will search for this module in configuration and subsequent calls return
1545*cc4ad7daSAndroid Build Coastguard Worker  * the cached string. The install commands are returned as they were in the
1546*cc4ad7daSAndroid Build Coastguard Worker  * configuration, concatenated by ';'. No other processing is made in this
1547*cc4ad7daSAndroid Build Coastguard Worker  * string.
1548*cc4ad7daSAndroid Build Coastguard Worker  *
1549*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a string with all install commands separated by semicolons. This
1550*cc4ad7daSAndroid Build Coastguard Worker  * string is owned by @mod, do not free it.
1551*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_install_commands(const struct kmod_module * mod)1552*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
1553*cc4ad7daSAndroid Build Coastguard Worker {
1554*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1555*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1556*cc4ad7daSAndroid Build Coastguard Worker 
1557*cc4ad7daSAndroid Build Coastguard Worker 	if (!mod->init.install_commands) {
1558*cc4ad7daSAndroid Build Coastguard Worker 		/* lazy init */
1559*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = (struct kmod_module *)mod;
1560*cc4ad7daSAndroid Build Coastguard Worker 		const struct kmod_list *l;
1561*cc4ad7daSAndroid Build Coastguard Worker 		const struct kmod_config *config;
1562*cc4ad7daSAndroid Build Coastguard Worker 
1563*cc4ad7daSAndroid Build Coastguard Worker 		config = kmod_get_config(mod->ctx);
1564*cc4ad7daSAndroid Build Coastguard Worker 
1565*cc4ad7daSAndroid Build Coastguard Worker 		kmod_list_foreach(l, config->install_commands) {
1566*cc4ad7daSAndroid Build Coastguard Worker 			const char *modname = kmod_command_get_modname(l);
1567*cc4ad7daSAndroid Build Coastguard Worker 
1568*cc4ad7daSAndroid Build Coastguard Worker 			if (fnmatch(modname, mod->name, 0) != 0)
1569*cc4ad7daSAndroid Build Coastguard Worker 				continue;
1570*cc4ad7daSAndroid Build Coastguard Worker 
1571*cc4ad7daSAndroid Build Coastguard Worker 			m->install_commands = kmod_command_get_command(l);
1572*cc4ad7daSAndroid Build Coastguard Worker 
1573*cc4ad7daSAndroid Build Coastguard Worker 			/*
1574*cc4ad7daSAndroid Build Coastguard Worker 			 * find only the first command, as modprobe from
1575*cc4ad7daSAndroid Build Coastguard Worker 			 * module-init-tools does
1576*cc4ad7daSAndroid Build Coastguard Worker 			 */
1577*cc4ad7daSAndroid Build Coastguard Worker 			break;
1578*cc4ad7daSAndroid Build Coastguard Worker 		}
1579*cc4ad7daSAndroid Build Coastguard Worker 
1580*cc4ad7daSAndroid Build Coastguard Worker 		m->init.install_commands = true;
1581*cc4ad7daSAndroid Build Coastguard Worker 	}
1582*cc4ad7daSAndroid Build Coastguard Worker 
1583*cc4ad7daSAndroid Build Coastguard Worker 	return mod->install_commands;
1584*cc4ad7daSAndroid Build Coastguard Worker }
1585*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_set_install_commands(struct kmod_module * mod,const char * cmd)1586*cc4ad7daSAndroid Build Coastguard Worker void kmod_module_set_install_commands(struct kmod_module *mod, const char *cmd)
1587*cc4ad7daSAndroid Build Coastguard Worker {
1588*cc4ad7daSAndroid Build Coastguard Worker 	mod->init.install_commands = true;
1589*cc4ad7daSAndroid Build Coastguard Worker 	mod->install_commands = cmd;
1590*cc4ad7daSAndroid Build Coastguard Worker }
1591*cc4ad7daSAndroid Build Coastguard Worker 
lookup_softdep(struct kmod_ctx * ctx,const char * const * array,unsigned int count)1592*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_list *lookup_softdep(struct kmod_ctx *ctx, const char * const * array, unsigned int count)
1593*cc4ad7daSAndroid Build Coastguard Worker {
1594*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *ret = NULL;
1595*cc4ad7daSAndroid Build Coastguard Worker 	unsigned i;
1596*cc4ad7daSAndroid Build Coastguard Worker 
1597*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
1598*cc4ad7daSAndroid Build Coastguard Worker 		const char *depname = array[i];
1599*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *lst = NULL;
1600*cc4ad7daSAndroid Build Coastguard Worker 		int err;
1601*cc4ad7daSAndroid Build Coastguard Worker 
1602*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new_from_lookup(ctx, depname, &lst);
1603*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
1604*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "failed to lookup soft dependency '%s', continuing anyway.\n", depname);
1605*cc4ad7daSAndroid Build Coastguard Worker 			continue;
1606*cc4ad7daSAndroid Build Coastguard Worker 		} else if (lst != NULL)
1607*cc4ad7daSAndroid Build Coastguard Worker 			ret = kmod_list_append_list(ret, lst);
1608*cc4ad7daSAndroid Build Coastguard Worker 	}
1609*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
1610*cc4ad7daSAndroid Build Coastguard Worker }
1611*cc4ad7daSAndroid Build Coastguard Worker 
1612*cc4ad7daSAndroid Build Coastguard Worker /**
1613*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_softdeps:
1614*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1615*cc4ad7daSAndroid Build Coastguard Worker  * @pre: where to save the list of preceding soft dependencies.
1616*cc4ad7daSAndroid Build Coastguard Worker  * @post: where to save the list of post soft dependencies.
1617*cc4ad7daSAndroid Build Coastguard Worker  *
1618*cc4ad7daSAndroid Build Coastguard Worker  * Get soft dependencies for this kmod module. Soft dependencies come
1619*cc4ad7daSAndroid Build Coastguard Worker  * from configuration file and are not cached in @mod because it may include
1620*cc4ad7daSAndroid Build Coastguard Worker  * dependency cycles that would make we leak kmod_module. Any call
1621*cc4ad7daSAndroid Build Coastguard Worker  * to this function will search for this module in configuration, allocate a
1622*cc4ad7daSAndroid Build Coastguard Worker  * list and return the result.
1623*cc4ad7daSAndroid Build Coastguard Worker  *
1624*cc4ad7daSAndroid Build Coastguard Worker  * Both @pre and @post are newly created list of kmod_module and
1625*cc4ad7daSAndroid Build Coastguard Worker  * should be unreferenced with kmod_module_unref_list().
1626*cc4ad7daSAndroid Build Coastguard Worker  *
1627*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
1628*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_softdeps(const struct kmod_module * mod,struct kmod_list ** pre,struct kmod_list ** post)1629*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod,
1630*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **pre,
1631*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **post)
1632*cc4ad7daSAndroid Build Coastguard Worker {
1633*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_list *l;
1634*cc4ad7daSAndroid Build Coastguard Worker 	const struct kmod_config *config;
1635*cc4ad7daSAndroid Build Coastguard Worker 
1636*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL || pre == NULL || post == NULL)
1637*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1638*cc4ad7daSAndroid Build Coastguard Worker 
1639*cc4ad7daSAndroid Build Coastguard Worker 	assert(*pre == NULL);
1640*cc4ad7daSAndroid Build Coastguard Worker 	assert(*post == NULL);
1641*cc4ad7daSAndroid Build Coastguard Worker 
1642*cc4ad7daSAndroid Build Coastguard Worker 	config = kmod_get_config(mod->ctx);
1643*cc4ad7daSAndroid Build Coastguard Worker 
1644*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, config->softdeps) {
1645*cc4ad7daSAndroid Build Coastguard Worker 		const char *modname = kmod_softdep_get_name(l);
1646*cc4ad7daSAndroid Build Coastguard Worker 		const char * const *array;
1647*cc4ad7daSAndroid Build Coastguard Worker 		unsigned count;
1648*cc4ad7daSAndroid Build Coastguard Worker 
1649*cc4ad7daSAndroid Build Coastguard Worker 		if (fnmatch(modname, mod->name, 0) != 0)
1650*cc4ad7daSAndroid Build Coastguard Worker 			continue;
1651*cc4ad7daSAndroid Build Coastguard Worker 
1652*cc4ad7daSAndroid Build Coastguard Worker 		array = kmod_softdep_get_pre(l, &count);
1653*cc4ad7daSAndroid Build Coastguard Worker 		*pre = lookup_softdep(mod->ctx, array, count);
1654*cc4ad7daSAndroid Build Coastguard Worker 		array = kmod_softdep_get_post(l, &count);
1655*cc4ad7daSAndroid Build Coastguard Worker 		*post = lookup_softdep(mod->ctx, array, count);
1656*cc4ad7daSAndroid Build Coastguard Worker 
1657*cc4ad7daSAndroid Build Coastguard Worker 		/*
1658*cc4ad7daSAndroid Build Coastguard Worker 		 * find only the first command, as modprobe from
1659*cc4ad7daSAndroid Build Coastguard Worker 		 * module-init-tools does
1660*cc4ad7daSAndroid Build Coastguard Worker 		 */
1661*cc4ad7daSAndroid Build Coastguard Worker 		break;
1662*cc4ad7daSAndroid Build Coastguard Worker 	}
1663*cc4ad7daSAndroid Build Coastguard Worker 
1664*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
1665*cc4ad7daSAndroid Build Coastguard Worker }
1666*cc4ad7daSAndroid Build Coastguard Worker 
1667*cc4ad7daSAndroid Build Coastguard Worker /**
1668*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_remove_commands:
1669*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1670*cc4ad7daSAndroid Build Coastguard Worker  *
1671*cc4ad7daSAndroid Build Coastguard Worker  * Get remove commands for this kmod module. Remove commands come from the
1672*cc4ad7daSAndroid Build Coastguard Worker  * configuration file and are cached in @mod. The first call to this function
1673*cc4ad7daSAndroid Build Coastguard Worker  * will search for this module in configuration and subsequent calls return
1674*cc4ad7daSAndroid Build Coastguard Worker  * the cached string. The remove commands are returned as they were in the
1675*cc4ad7daSAndroid Build Coastguard Worker  * configuration, concatenated by ';'. No other processing is made in this
1676*cc4ad7daSAndroid Build Coastguard Worker  * string.
1677*cc4ad7daSAndroid Build Coastguard Worker  *
1678*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a string with all remove commands separated by semicolons. This
1679*cc4ad7daSAndroid Build Coastguard Worker  * string is owned by @mod, do not free it.
1680*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_remove_commands(const struct kmod_module * mod)1681*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
1682*cc4ad7daSAndroid Build Coastguard Worker {
1683*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1684*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1685*cc4ad7daSAndroid Build Coastguard Worker 
1686*cc4ad7daSAndroid Build Coastguard Worker 	if (!mod->init.remove_commands) {
1687*cc4ad7daSAndroid Build Coastguard Worker 		/* lazy init */
1688*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m = (struct kmod_module *)mod;
1689*cc4ad7daSAndroid Build Coastguard Worker 		const struct kmod_list *l;
1690*cc4ad7daSAndroid Build Coastguard Worker 		const struct kmod_config *config;
1691*cc4ad7daSAndroid Build Coastguard Worker 
1692*cc4ad7daSAndroid Build Coastguard Worker 		config = kmod_get_config(mod->ctx);
1693*cc4ad7daSAndroid Build Coastguard Worker 
1694*cc4ad7daSAndroid Build Coastguard Worker 		kmod_list_foreach(l, config->remove_commands) {
1695*cc4ad7daSAndroid Build Coastguard Worker 			const char *modname = kmod_command_get_modname(l);
1696*cc4ad7daSAndroid Build Coastguard Worker 
1697*cc4ad7daSAndroid Build Coastguard Worker 			if (fnmatch(modname, mod->name, 0) != 0)
1698*cc4ad7daSAndroid Build Coastguard Worker 				continue;
1699*cc4ad7daSAndroid Build Coastguard Worker 
1700*cc4ad7daSAndroid Build Coastguard Worker 			m->remove_commands = kmod_command_get_command(l);
1701*cc4ad7daSAndroid Build Coastguard Worker 
1702*cc4ad7daSAndroid Build Coastguard Worker 			/*
1703*cc4ad7daSAndroid Build Coastguard Worker 			 * find only the first command, as modprobe from
1704*cc4ad7daSAndroid Build Coastguard Worker 			 * module-init-tools does
1705*cc4ad7daSAndroid Build Coastguard Worker 			 */
1706*cc4ad7daSAndroid Build Coastguard Worker 			break;
1707*cc4ad7daSAndroid Build Coastguard Worker 		}
1708*cc4ad7daSAndroid Build Coastguard Worker 
1709*cc4ad7daSAndroid Build Coastguard Worker 		m->init.remove_commands = true;
1710*cc4ad7daSAndroid Build Coastguard Worker 	}
1711*cc4ad7daSAndroid Build Coastguard Worker 
1712*cc4ad7daSAndroid Build Coastguard Worker 	return mod->remove_commands;
1713*cc4ad7daSAndroid Build Coastguard Worker }
1714*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_set_remove_commands(struct kmod_module * mod,const char * cmd)1715*cc4ad7daSAndroid Build Coastguard Worker void kmod_module_set_remove_commands(struct kmod_module *mod, const char *cmd)
1716*cc4ad7daSAndroid Build Coastguard Worker {
1717*cc4ad7daSAndroid Build Coastguard Worker 	mod->init.remove_commands = true;
1718*cc4ad7daSAndroid Build Coastguard Worker 	mod->remove_commands = cmd;
1719*cc4ad7daSAndroid Build Coastguard Worker }
1720*cc4ad7daSAndroid Build Coastguard Worker 
1721*cc4ad7daSAndroid Build Coastguard Worker /**
1722*cc4ad7daSAndroid Build Coastguard Worker  * SECTION:libkmod-loaded
1723*cc4ad7daSAndroid Build Coastguard Worker  * @short_description: currently loaded modules
1724*cc4ad7daSAndroid Build Coastguard Worker  *
1725*cc4ad7daSAndroid Build Coastguard Worker  * Information about currently loaded modules, as reported by Linux kernel.
1726*cc4ad7daSAndroid Build Coastguard Worker  * These information are not cached by libkmod and are always read from /sys
1727*cc4ad7daSAndroid Build Coastguard Worker  * and /proc/modules.
1728*cc4ad7daSAndroid Build Coastguard Worker  */
1729*cc4ad7daSAndroid Build Coastguard Worker 
1730*cc4ad7daSAndroid Build Coastguard Worker /**
1731*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_new_from_loaded:
1732*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
1733*cc4ad7daSAndroid Build Coastguard Worker  * @list: where to save the list of loaded modules
1734*cc4ad7daSAndroid Build Coastguard Worker  *
1735*cc4ad7daSAndroid Build Coastguard Worker  * Create a new list of kmod modules with all modules currently loaded in
1736*cc4ad7daSAndroid Build Coastguard Worker  * kernel. It uses /proc/modules to get the names of loaded modules and to
1737*cc4ad7daSAndroid Build Coastguard Worker  * create kmod modules by calling kmod_module_new_from_name() in each of them.
1738*cc4ad7daSAndroid Build Coastguard Worker  * They are put in @list in no particular order.
1739*cc4ad7daSAndroid Build Coastguard Worker  *
1740*cc4ad7daSAndroid Build Coastguard Worker  * The initial refcount is 1, and needs to be decremented to release the
1741*cc4ad7daSAndroid Build Coastguard Worker  * resources of the kmod_module. The returned @list must be released by
1742*cc4ad7daSAndroid Build Coastguard Worker  * calling kmod_module_unref_list(). Since libkmod keeps track of all
1743*cc4ad7daSAndroid Build Coastguard Worker  * kmod_modules created, they are all released upon @ctx destruction too. Do
1744*cc4ad7daSAndroid Build Coastguard Worker  * not unref @ctx before all the desired operations with the returned list are
1745*cc4ad7daSAndroid Build Coastguard Worker  * completed.
1746*cc4ad7daSAndroid Build Coastguard Worker  *
1747*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 on error.
1748*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_new_from_loaded(struct kmod_ctx * ctx,struct kmod_list ** list)1749*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx,
1750*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
1751*cc4ad7daSAndroid Build Coastguard Worker {
1752*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l = NULL;
1753*cc4ad7daSAndroid Build Coastguard Worker 	FILE *fp;
1754*cc4ad7daSAndroid Build Coastguard Worker 	char line[4096];
1755*cc4ad7daSAndroid Build Coastguard Worker 
1756*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || list == NULL)
1757*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1758*cc4ad7daSAndroid Build Coastguard Worker 
1759*cc4ad7daSAndroid Build Coastguard Worker 	fp = fopen("/proc/modules", "re");
1760*cc4ad7daSAndroid Build Coastguard Worker 	if (fp == NULL) {
1761*cc4ad7daSAndroid Build Coastguard Worker 		int err = -errno;
1762*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "could not open /proc/modules: %s\n", strerror(errno));
1763*cc4ad7daSAndroid Build Coastguard Worker 		return err;
1764*cc4ad7daSAndroid Build Coastguard Worker 	}
1765*cc4ad7daSAndroid Build Coastguard Worker 
1766*cc4ad7daSAndroid Build Coastguard Worker 	while (fgets(line, sizeof(line), fp)) {
1767*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *m;
1768*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *node;
1769*cc4ad7daSAndroid Build Coastguard Worker 		int err;
1770*cc4ad7daSAndroid Build Coastguard Worker 		size_t len = strlen(line);
1771*cc4ad7daSAndroid Build Coastguard Worker 		char *saveptr, *name = strtok_r(line, " \t", &saveptr);
1772*cc4ad7daSAndroid Build Coastguard Worker 
1773*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new_from_name(ctx, name, &m);
1774*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
1775*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "could not get module from name '%s': %s\n",
1776*cc4ad7daSAndroid Build Coastguard Worker 				name, strerror(-err));
1777*cc4ad7daSAndroid Build Coastguard Worker 			goto eat_line;
1778*cc4ad7daSAndroid Build Coastguard Worker 		}
1779*cc4ad7daSAndroid Build Coastguard Worker 
1780*cc4ad7daSAndroid Build Coastguard Worker 		node = kmod_list_append(l, m);
1781*cc4ad7daSAndroid Build Coastguard Worker 		if (node)
1782*cc4ad7daSAndroid Build Coastguard Worker 			l = node;
1783*cc4ad7daSAndroid Build Coastguard Worker 		else {
1784*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "out of memory\n");
1785*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_unref(m);
1786*cc4ad7daSAndroid Build Coastguard Worker 		}
1787*cc4ad7daSAndroid Build Coastguard Worker eat_line:
1788*cc4ad7daSAndroid Build Coastguard Worker 		while (line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
1789*cc4ad7daSAndroid Build Coastguard Worker 			len = strlen(line);
1790*cc4ad7daSAndroid Build Coastguard Worker 	}
1791*cc4ad7daSAndroid Build Coastguard Worker 
1792*cc4ad7daSAndroid Build Coastguard Worker 	fclose(fp);
1793*cc4ad7daSAndroid Build Coastguard Worker 	*list = l;
1794*cc4ad7daSAndroid Build Coastguard Worker 
1795*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
1796*cc4ad7daSAndroid Build Coastguard Worker }
1797*cc4ad7daSAndroid Build Coastguard Worker 
1798*cc4ad7daSAndroid Build Coastguard Worker /**
1799*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_initstate_str:
1800*cc4ad7daSAndroid Build Coastguard Worker  * @state: the state as returned by kmod_module_get_initstate()
1801*cc4ad7daSAndroid Build Coastguard Worker  *
1802*cc4ad7daSAndroid Build Coastguard Worker  * Translate a initstate to a string.
1803*cc4ad7daSAndroid Build Coastguard Worker  *
1804*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the string associated to the @state. This string is statically
1805*cc4ad7daSAndroid Build Coastguard Worker  * allocated, do not free it.
1806*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_initstate_str(enum kmod_module_initstate state)1807*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
1808*cc4ad7daSAndroid Build Coastguard Worker {
1809*cc4ad7daSAndroid Build Coastguard Worker 	switch (state) {
1810*cc4ad7daSAndroid Build Coastguard Worker 	case KMOD_MODULE_BUILTIN:
1811*cc4ad7daSAndroid Build Coastguard Worker 		return "builtin";
1812*cc4ad7daSAndroid Build Coastguard Worker 	case KMOD_MODULE_LIVE:
1813*cc4ad7daSAndroid Build Coastguard Worker 		return "live";
1814*cc4ad7daSAndroid Build Coastguard Worker 	case KMOD_MODULE_COMING:
1815*cc4ad7daSAndroid Build Coastguard Worker 		return "coming";
1816*cc4ad7daSAndroid Build Coastguard Worker 	case KMOD_MODULE_GOING:
1817*cc4ad7daSAndroid Build Coastguard Worker 		return "going";
1818*cc4ad7daSAndroid Build Coastguard Worker 	default:
1819*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
1820*cc4ad7daSAndroid Build Coastguard Worker 	}
1821*cc4ad7daSAndroid Build Coastguard Worker }
1822*cc4ad7daSAndroid Build Coastguard Worker 
1823*cc4ad7daSAndroid Build Coastguard Worker /**
1824*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_initstate:
1825*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1826*cc4ad7daSAndroid Build Coastguard Worker  *
1827*cc4ad7daSAndroid Build Coastguard Worker  * Get the initstate of this @mod, as returned by Linux Kernel, by reading
1828*cc4ad7daSAndroid Build Coastguard Worker  * /sys filesystem.
1829*cc4ad7daSAndroid Build Coastguard Worker  *
1830*cc4ad7daSAndroid Build Coastguard Worker  * Returns: < 0 on error or module state if module is found in kernel, valid states are
1831*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_MODULE_BUILTIN: module is builtin;
1832*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_MODULE_LIVE: module is live in kernel;
1833*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_MODULE_COMING: module is being loaded;
1834*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_MODULE_GOING: module is being unloaded.
1835*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_initstate(const struct kmod_module * mod)1836*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
1837*cc4ad7daSAndroid Build Coastguard Worker {
1838*cc4ad7daSAndroid Build Coastguard Worker 	char path[PATH_MAX], buf[32];
1839*cc4ad7daSAndroid Build Coastguard Worker 	int fd, err, pathlen;
1840*cc4ad7daSAndroid Build Coastguard Worker 
1841*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1842*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1843*cc4ad7daSAndroid Build Coastguard Worker 
1844*cc4ad7daSAndroid Build Coastguard Worker 	/* remove const: this can only change internal state */
1845*cc4ad7daSAndroid Build Coastguard Worker 	if (kmod_module_is_builtin((struct kmod_module *)mod))
1846*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_MODULE_BUILTIN;
1847*cc4ad7daSAndroid Build Coastguard Worker 
1848*cc4ad7daSAndroid Build Coastguard Worker 	pathlen = snprintf(path, sizeof(path),
1849*cc4ad7daSAndroid Build Coastguard Worker 				"/sys/module/%s/initstate", mod->name);
1850*cc4ad7daSAndroid Build Coastguard Worker 	if (pathlen >= (int)sizeof(path)) {
1851*cc4ad7daSAndroid Build Coastguard Worker 		/* Too long path was truncated */
1852*cc4ad7daSAndroid Build Coastguard Worker 		return -ENAMETOOLONG;
1853*cc4ad7daSAndroid Build Coastguard Worker 	}
1854*cc4ad7daSAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY|O_CLOEXEC);
1855*cc4ad7daSAndroid Build Coastguard Worker 	if (fd < 0) {
1856*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
1857*cc4ad7daSAndroid Build Coastguard Worker 
1858*cc4ad7daSAndroid Build Coastguard Worker 		DBG(mod->ctx, "could not open '%s': %s\n",
1859*cc4ad7daSAndroid Build Coastguard Worker 			path, strerror(-err));
1860*cc4ad7daSAndroid Build Coastguard Worker 
1861*cc4ad7daSAndroid Build Coastguard Worker 		if (pathlen > (int)sizeof("/initstate") - 1) {
1862*cc4ad7daSAndroid Build Coastguard Worker 			struct stat st;
1863*cc4ad7daSAndroid Build Coastguard Worker 			path[pathlen - (sizeof("/initstate") - 1)] = '\0';
1864*cc4ad7daSAndroid Build Coastguard Worker 			if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
1865*cc4ad7daSAndroid Build Coastguard Worker 				return KMOD_MODULE_COMING;
1866*cc4ad7daSAndroid Build Coastguard Worker 		}
1867*cc4ad7daSAndroid Build Coastguard Worker 
1868*cc4ad7daSAndroid Build Coastguard Worker 		DBG(mod->ctx, "could not open '%s': %s\n",
1869*cc4ad7daSAndroid Build Coastguard Worker 			path, strerror(-err));
1870*cc4ad7daSAndroid Build Coastguard Worker 		return err;
1871*cc4ad7daSAndroid Build Coastguard Worker 	}
1872*cc4ad7daSAndroid Build Coastguard Worker 
1873*cc4ad7daSAndroid Build Coastguard Worker 	err = read_str_safe(fd, buf, sizeof(buf));
1874*cc4ad7daSAndroid Build Coastguard Worker 	close(fd);
1875*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
1876*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "could not read from '%s': %s\n",
1877*cc4ad7daSAndroid Build Coastguard Worker 			path, strerror(-err));
1878*cc4ad7daSAndroid Build Coastguard Worker 		return err;
1879*cc4ad7daSAndroid Build Coastguard Worker 	}
1880*cc4ad7daSAndroid Build Coastguard Worker 
1881*cc4ad7daSAndroid Build Coastguard Worker 	if (streq(buf, "live\n"))
1882*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_MODULE_LIVE;
1883*cc4ad7daSAndroid Build Coastguard Worker 	else if (streq(buf, "coming\n"))
1884*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_MODULE_COMING;
1885*cc4ad7daSAndroid Build Coastguard Worker 	else if (streq(buf, "going\n"))
1886*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_MODULE_GOING;
1887*cc4ad7daSAndroid Build Coastguard Worker 
1888*cc4ad7daSAndroid Build Coastguard Worker 	ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
1889*cc4ad7daSAndroid Build Coastguard Worker 	return -EINVAL;
1890*cc4ad7daSAndroid Build Coastguard Worker }
1891*cc4ad7daSAndroid Build Coastguard Worker 
1892*cc4ad7daSAndroid Build Coastguard Worker /**
1893*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_size:
1894*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1895*cc4ad7daSAndroid Build Coastguard Worker  *
1896*cc4ad7daSAndroid Build Coastguard Worker  * Get the size of this kmod module as returned by Linux kernel. If supported,
1897*cc4ad7daSAndroid Build Coastguard Worker  * the size is read from the coresize attribute in /sys/module. For older
1898*cc4ad7daSAndroid Build Coastguard Worker  * kernels, this falls back on /proc/modules and searches for the specified
1899*cc4ad7daSAndroid Build Coastguard Worker  * module to get its size.
1900*cc4ad7daSAndroid Build Coastguard Worker  *
1901*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the size of this kmod module.
1902*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_size(const struct kmod_module * mod)1903*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
1904*cc4ad7daSAndroid Build Coastguard Worker {
1905*cc4ad7daSAndroid Build Coastguard Worker 	FILE *fp;
1906*cc4ad7daSAndroid Build Coastguard Worker 	char line[4096];
1907*cc4ad7daSAndroid Build Coastguard Worker 	int lineno = 0;
1908*cc4ad7daSAndroid Build Coastguard Worker 	long size = -ENOENT;
1909*cc4ad7daSAndroid Build Coastguard Worker 	int dfd, cfd;
1910*cc4ad7daSAndroid Build Coastguard Worker 
1911*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1912*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1913*cc4ad7daSAndroid Build Coastguard Worker 
1914*cc4ad7daSAndroid Build Coastguard Worker 	/* try to open the module dir in /sys. If this fails, don't
1915*cc4ad7daSAndroid Build Coastguard Worker 	 * bother trying to find the size as we know the module isn't
1916*cc4ad7daSAndroid Build Coastguard Worker 	 * loaded.
1917*cc4ad7daSAndroid Build Coastguard Worker 	 */
1918*cc4ad7daSAndroid Build Coastguard Worker 	snprintf(line, sizeof(line), "/sys/module/%s", mod->name);
1919*cc4ad7daSAndroid Build Coastguard Worker 	dfd = open(line, O_RDONLY|O_CLOEXEC);
1920*cc4ad7daSAndroid Build Coastguard Worker 	if (dfd < 0)
1921*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
1922*cc4ad7daSAndroid Build Coastguard Worker 
1923*cc4ad7daSAndroid Build Coastguard Worker 	/* available as of linux 3.3.x */
1924*cc4ad7daSAndroid Build Coastguard Worker 	cfd = openat(dfd, "coresize", O_RDONLY|O_CLOEXEC);
1925*cc4ad7daSAndroid Build Coastguard Worker 	if (cfd >= 0) {
1926*cc4ad7daSAndroid Build Coastguard Worker 		if (read_str_long(cfd, &size, 10) < 0)
1927*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "failed to read coresize from %s\n", line);
1928*cc4ad7daSAndroid Build Coastguard Worker 		close(cfd);
1929*cc4ad7daSAndroid Build Coastguard Worker 		goto done;
1930*cc4ad7daSAndroid Build Coastguard Worker 	}
1931*cc4ad7daSAndroid Build Coastguard Worker 
1932*cc4ad7daSAndroid Build Coastguard Worker 	/* fall back on parsing /proc/modules */
1933*cc4ad7daSAndroid Build Coastguard Worker 	fp = fopen("/proc/modules", "re");
1934*cc4ad7daSAndroid Build Coastguard Worker 	if (fp == NULL) {
1935*cc4ad7daSAndroid Build Coastguard Worker 		int err = -errno;
1936*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx,
1937*cc4ad7daSAndroid Build Coastguard Worker 		    "could not open /proc/modules: %s\n", strerror(errno));
1938*cc4ad7daSAndroid Build Coastguard Worker 		close(dfd);
1939*cc4ad7daSAndroid Build Coastguard Worker 		return err;
1940*cc4ad7daSAndroid Build Coastguard Worker 	}
1941*cc4ad7daSAndroid Build Coastguard Worker 
1942*cc4ad7daSAndroid Build Coastguard Worker 	while (fgets(line, sizeof(line), fp)) {
1943*cc4ad7daSAndroid Build Coastguard Worker 		size_t len = strlen(line);
1944*cc4ad7daSAndroid Build Coastguard Worker 		char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
1945*cc4ad7daSAndroid Build Coastguard Worker 		long value;
1946*cc4ad7daSAndroid Build Coastguard Worker 
1947*cc4ad7daSAndroid Build Coastguard Worker 		lineno++;
1948*cc4ad7daSAndroid Build Coastguard Worker 		if (tok == NULL || !streq(tok, mod->name))
1949*cc4ad7daSAndroid Build Coastguard Worker 			goto eat_line;
1950*cc4ad7daSAndroid Build Coastguard Worker 
1951*cc4ad7daSAndroid Build Coastguard Worker 		tok = strtok_r(NULL, " \t", &saveptr);
1952*cc4ad7daSAndroid Build Coastguard Worker 		if (tok == NULL) {
1953*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx,
1954*cc4ad7daSAndroid Build Coastguard Worker 			"invalid line format at /proc/modules:%d\n", lineno);
1955*cc4ad7daSAndroid Build Coastguard Worker 			break;
1956*cc4ad7daSAndroid Build Coastguard Worker 		}
1957*cc4ad7daSAndroid Build Coastguard Worker 
1958*cc4ad7daSAndroid Build Coastguard Worker 		value = strtol(tok, &endptr, 10);
1959*cc4ad7daSAndroid Build Coastguard Worker 		if (endptr == tok || *endptr != '\0') {
1960*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx,
1961*cc4ad7daSAndroid Build Coastguard Worker 			"invalid line format at /proc/modules:%d\n", lineno);
1962*cc4ad7daSAndroid Build Coastguard Worker 			break;
1963*cc4ad7daSAndroid Build Coastguard Worker 		}
1964*cc4ad7daSAndroid Build Coastguard Worker 
1965*cc4ad7daSAndroid Build Coastguard Worker 		size = value;
1966*cc4ad7daSAndroid Build Coastguard Worker 		break;
1967*cc4ad7daSAndroid Build Coastguard Worker eat_line:
1968*cc4ad7daSAndroid Build Coastguard Worker 		while (line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
1969*cc4ad7daSAndroid Build Coastguard Worker 			len = strlen(line);
1970*cc4ad7daSAndroid Build Coastguard Worker 	}
1971*cc4ad7daSAndroid Build Coastguard Worker 	fclose(fp);
1972*cc4ad7daSAndroid Build Coastguard Worker 
1973*cc4ad7daSAndroid Build Coastguard Worker done:
1974*cc4ad7daSAndroid Build Coastguard Worker 	close(dfd);
1975*cc4ad7daSAndroid Build Coastguard Worker 	return size;
1976*cc4ad7daSAndroid Build Coastguard Worker }
1977*cc4ad7daSAndroid Build Coastguard Worker 
1978*cc4ad7daSAndroid Build Coastguard Worker /**
1979*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_refcnt:
1980*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
1981*cc4ad7daSAndroid Build Coastguard Worker  *
1982*cc4ad7daSAndroid Build Coastguard Worker  * Get the ref count of this @mod, as returned by Linux Kernel, by reading
1983*cc4ad7daSAndroid Build Coastguard Worker  * /sys filesystem.
1984*cc4ad7daSAndroid Build Coastguard Worker  *
1985*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the reference count on success or < 0 on failure.
1986*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_refcnt(const struct kmod_module * mod)1987*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
1988*cc4ad7daSAndroid Build Coastguard Worker {
1989*cc4ad7daSAndroid Build Coastguard Worker 	char path[PATH_MAX];
1990*cc4ad7daSAndroid Build Coastguard Worker 	long refcnt;
1991*cc4ad7daSAndroid Build Coastguard Worker 	int fd, err;
1992*cc4ad7daSAndroid Build Coastguard Worker 
1993*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
1994*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
1995*cc4ad7daSAndroid Build Coastguard Worker 
1996*cc4ad7daSAndroid Build Coastguard Worker 	snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
1997*cc4ad7daSAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY|O_CLOEXEC);
1998*cc4ad7daSAndroid Build Coastguard Worker 	if (fd < 0) {
1999*cc4ad7daSAndroid Build Coastguard Worker 		err = -errno;
2000*cc4ad7daSAndroid Build Coastguard Worker 		DBG(mod->ctx, "could not open '%s': %s\n",
2001*cc4ad7daSAndroid Build Coastguard Worker 			path, strerror(errno));
2002*cc4ad7daSAndroid Build Coastguard Worker 		return err;
2003*cc4ad7daSAndroid Build Coastguard Worker 	}
2004*cc4ad7daSAndroid Build Coastguard Worker 
2005*cc4ad7daSAndroid Build Coastguard Worker 	err = read_str_long(fd, &refcnt, 10);
2006*cc4ad7daSAndroid Build Coastguard Worker 	close(fd);
2007*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
2008*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "could not read integer from '%s': '%s'\n",
2009*cc4ad7daSAndroid Build Coastguard Worker 			path, strerror(-err));
2010*cc4ad7daSAndroid Build Coastguard Worker 		return err;
2011*cc4ad7daSAndroid Build Coastguard Worker 	}
2012*cc4ad7daSAndroid Build Coastguard Worker 
2013*cc4ad7daSAndroid Build Coastguard Worker 	return (int)refcnt;
2014*cc4ad7daSAndroid Build Coastguard Worker }
2015*cc4ad7daSAndroid Build Coastguard Worker 
2016*cc4ad7daSAndroid Build Coastguard Worker /**
2017*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_holders:
2018*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
2019*cc4ad7daSAndroid Build Coastguard Worker  *
2020*cc4ad7daSAndroid Build Coastguard Worker  * Get a list of kmod modules that are holding this @mod, as returned by Linux
2021*cc4ad7daSAndroid Build Coastguard Worker  * Kernel. After use, free the @list by calling kmod_module_unref_list().
2022*cc4ad7daSAndroid Build Coastguard Worker  *
2023*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new list of kmod modules on success or NULL on failure.
2024*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_holders(const struct kmod_module * mod)2025*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
2026*cc4ad7daSAndroid Build Coastguard Worker {
2027*cc4ad7daSAndroid Build Coastguard Worker 	char dname[PATH_MAX];
2028*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list = NULL;
2029*cc4ad7daSAndroid Build Coastguard Worker 	struct dirent *dent;
2030*cc4ad7daSAndroid Build Coastguard Worker 	DIR *d;
2031*cc4ad7daSAndroid Build Coastguard Worker 
2032*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL || mod->ctx == NULL)
2033*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2034*cc4ad7daSAndroid Build Coastguard Worker 
2035*cc4ad7daSAndroid Build Coastguard Worker 	snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
2036*cc4ad7daSAndroid Build Coastguard Worker 
2037*cc4ad7daSAndroid Build Coastguard Worker 	d = opendir(dname);
2038*cc4ad7daSAndroid Build Coastguard Worker 	if (d == NULL) {
2039*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "could not open '%s': %s\n",
2040*cc4ad7daSAndroid Build Coastguard Worker 						dname, strerror(errno));
2041*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2042*cc4ad7daSAndroid Build Coastguard Worker 	}
2043*cc4ad7daSAndroid Build Coastguard Worker 
2044*cc4ad7daSAndroid Build Coastguard Worker 	for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
2045*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *holder;
2046*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *l;
2047*cc4ad7daSAndroid Build Coastguard Worker 		int err;
2048*cc4ad7daSAndroid Build Coastguard Worker 
2049*cc4ad7daSAndroid Build Coastguard Worker 		if (dent->d_name[0] == '.') {
2050*cc4ad7daSAndroid Build Coastguard Worker 			if (dent->d_name[1] == '\0' ||
2051*cc4ad7daSAndroid Build Coastguard Worker 			    (dent->d_name[1] == '.' && dent->d_name[2] == '\0'))
2052*cc4ad7daSAndroid Build Coastguard Worker 				continue;
2053*cc4ad7daSAndroid Build Coastguard Worker 		}
2054*cc4ad7daSAndroid Build Coastguard Worker 
2055*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new_from_name(mod->ctx, dent->d_name,
2056*cc4ad7daSAndroid Build Coastguard Worker 						&holder);
2057*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
2058*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "could not create module for '%s': %s\n",
2059*cc4ad7daSAndroid Build Coastguard Worker 				dent->d_name, strerror(-err));
2060*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
2061*cc4ad7daSAndroid Build Coastguard Worker 		}
2062*cc4ad7daSAndroid Build Coastguard Worker 
2063*cc4ad7daSAndroid Build Coastguard Worker 		l = kmod_list_append(list, holder);
2064*cc4ad7daSAndroid Build Coastguard Worker 		if (l != NULL) {
2065*cc4ad7daSAndroid Build Coastguard Worker 			list = l;
2066*cc4ad7daSAndroid Build Coastguard Worker 		} else {
2067*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "out of memory\n");
2068*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_unref(holder);
2069*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
2070*cc4ad7daSAndroid Build Coastguard Worker 		}
2071*cc4ad7daSAndroid Build Coastguard Worker 	}
2072*cc4ad7daSAndroid Build Coastguard Worker 
2073*cc4ad7daSAndroid Build Coastguard Worker 	closedir(d);
2074*cc4ad7daSAndroid Build Coastguard Worker 	return list;
2075*cc4ad7daSAndroid Build Coastguard Worker 
2076*cc4ad7daSAndroid Build Coastguard Worker fail:
2077*cc4ad7daSAndroid Build Coastguard Worker 	closedir(d);
2078*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(list);
2079*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
2080*cc4ad7daSAndroid Build Coastguard Worker }
2081*cc4ad7daSAndroid Build Coastguard Worker 
2082*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module_section {
2083*cc4ad7daSAndroid Build Coastguard Worker 	unsigned long address;
2084*cc4ad7daSAndroid Build Coastguard Worker 	char name[];
2085*cc4ad7daSAndroid Build Coastguard Worker };
2086*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_section_free(struct kmod_module_section * section)2087*cc4ad7daSAndroid Build Coastguard Worker static void kmod_module_section_free(struct kmod_module_section *section)
2088*cc4ad7daSAndroid Build Coastguard Worker {
2089*cc4ad7daSAndroid Build Coastguard Worker 	free(section);
2090*cc4ad7daSAndroid Build Coastguard Worker }
2091*cc4ad7daSAndroid Build Coastguard Worker 
2092*cc4ad7daSAndroid Build Coastguard Worker /**
2093*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_sections:
2094*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
2095*cc4ad7daSAndroid Build Coastguard Worker  *
2096*cc4ad7daSAndroid Build Coastguard Worker  * Get a list of kmod sections of this @mod, as returned by Linux Kernel. The
2097*cc4ad7daSAndroid Build Coastguard Worker  * structure contained in this list is internal to libkmod and their fields
2098*cc4ad7daSAndroid Build Coastguard Worker  * can be obtained by calling kmod_module_section_get_name() and
2099*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_section_get_address().
2100*cc4ad7daSAndroid Build Coastguard Worker  *
2101*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling kmod_module_section_free_list().
2102*cc4ad7daSAndroid Build Coastguard Worker  *
2103*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new list of kmod module sections on success or NULL on failure.
2104*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_sections(const struct kmod_module * mod)2105*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
2106*cc4ad7daSAndroid Build Coastguard Worker {
2107*cc4ad7daSAndroid Build Coastguard Worker 	char dname[PATH_MAX];
2108*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *list = NULL;
2109*cc4ad7daSAndroid Build Coastguard Worker 	struct dirent *dent;
2110*cc4ad7daSAndroid Build Coastguard Worker 	DIR *d;
2111*cc4ad7daSAndroid Build Coastguard Worker 	int dfd;
2112*cc4ad7daSAndroid Build Coastguard Worker 
2113*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL)
2114*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2115*cc4ad7daSAndroid Build Coastguard Worker 
2116*cc4ad7daSAndroid Build Coastguard Worker 	snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
2117*cc4ad7daSAndroid Build Coastguard Worker 
2118*cc4ad7daSAndroid Build Coastguard Worker 	d = opendir(dname);
2119*cc4ad7daSAndroid Build Coastguard Worker 	if (d == NULL) {
2120*cc4ad7daSAndroid Build Coastguard Worker 		ERR(mod->ctx, "could not open '%s': %s\n",
2121*cc4ad7daSAndroid Build Coastguard Worker 			dname, strerror(errno));
2122*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2123*cc4ad7daSAndroid Build Coastguard Worker 	}
2124*cc4ad7daSAndroid Build Coastguard Worker 
2125*cc4ad7daSAndroid Build Coastguard Worker 	dfd = dirfd(d);
2126*cc4ad7daSAndroid Build Coastguard Worker 
2127*cc4ad7daSAndroid Build Coastguard Worker 	for (dent = readdir(d); dent; dent = readdir(d)) {
2128*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module_section *section;
2129*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *l;
2130*cc4ad7daSAndroid Build Coastguard Worker 		unsigned long address;
2131*cc4ad7daSAndroid Build Coastguard Worker 		size_t namesz;
2132*cc4ad7daSAndroid Build Coastguard Worker 		int fd, err;
2133*cc4ad7daSAndroid Build Coastguard Worker 
2134*cc4ad7daSAndroid Build Coastguard Worker 		if (dent->d_name[0] == '.') {
2135*cc4ad7daSAndroid Build Coastguard Worker 			if (dent->d_name[1] == '\0' ||
2136*cc4ad7daSAndroid Build Coastguard Worker 			    (dent->d_name[1] == '.' && dent->d_name[2] == '\0'))
2137*cc4ad7daSAndroid Build Coastguard Worker 				continue;
2138*cc4ad7daSAndroid Build Coastguard Worker 		}
2139*cc4ad7daSAndroid Build Coastguard Worker 
2140*cc4ad7daSAndroid Build Coastguard Worker 		fd = openat(dfd, dent->d_name, O_RDONLY|O_CLOEXEC);
2141*cc4ad7daSAndroid Build Coastguard Worker 		if (fd < 0) {
2142*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "could not open '%s/%s': %m\n",
2143*cc4ad7daSAndroid Build Coastguard Worker 							dname, dent->d_name);
2144*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
2145*cc4ad7daSAndroid Build Coastguard Worker 		}
2146*cc4ad7daSAndroid Build Coastguard Worker 
2147*cc4ad7daSAndroid Build Coastguard Worker 		err = read_str_ulong(fd, &address, 16);
2148*cc4ad7daSAndroid Build Coastguard Worker 		close(fd);
2149*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
2150*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "could not read long from '%s/%s': %m\n",
2151*cc4ad7daSAndroid Build Coastguard Worker 							dname, dent->d_name);
2152*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
2153*cc4ad7daSAndroid Build Coastguard Worker 		}
2154*cc4ad7daSAndroid Build Coastguard Worker 
2155*cc4ad7daSAndroid Build Coastguard Worker 		namesz = strlen(dent->d_name) + 1;
2156*cc4ad7daSAndroid Build Coastguard Worker 		section = malloc(sizeof(*section) + namesz);
2157*cc4ad7daSAndroid Build Coastguard Worker 
2158*cc4ad7daSAndroid Build Coastguard Worker 		if (section == NULL) {
2159*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "out of memory\n");
2160*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
2161*cc4ad7daSAndroid Build Coastguard Worker 		}
2162*cc4ad7daSAndroid Build Coastguard Worker 
2163*cc4ad7daSAndroid Build Coastguard Worker 		section->address = address;
2164*cc4ad7daSAndroid Build Coastguard Worker 		memcpy(section->name, dent->d_name, namesz);
2165*cc4ad7daSAndroid Build Coastguard Worker 
2166*cc4ad7daSAndroid Build Coastguard Worker 		l = kmod_list_append(list, section);
2167*cc4ad7daSAndroid Build Coastguard Worker 		if (l != NULL) {
2168*cc4ad7daSAndroid Build Coastguard Worker 			list = l;
2169*cc4ad7daSAndroid Build Coastguard Worker 		} else {
2170*cc4ad7daSAndroid Build Coastguard Worker 			ERR(mod->ctx, "out of memory\n");
2171*cc4ad7daSAndroid Build Coastguard Worker 			free(section);
2172*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
2173*cc4ad7daSAndroid Build Coastguard Worker 		}
2174*cc4ad7daSAndroid Build Coastguard Worker 	}
2175*cc4ad7daSAndroid Build Coastguard Worker 
2176*cc4ad7daSAndroid Build Coastguard Worker 	closedir(d);
2177*cc4ad7daSAndroid Build Coastguard Worker 	return list;
2178*cc4ad7daSAndroid Build Coastguard Worker 
2179*cc4ad7daSAndroid Build Coastguard Worker fail:
2180*cc4ad7daSAndroid Build Coastguard Worker 	closedir(d);
2181*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_unref_list(list);
2182*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
2183*cc4ad7daSAndroid Build Coastguard Worker }
2184*cc4ad7daSAndroid Build Coastguard Worker 
2185*cc4ad7daSAndroid Build Coastguard Worker /**
2186*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_section_get_module_name:
2187*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module section
2188*cc4ad7daSAndroid Build Coastguard Worker  *
2189*cc4ad7daSAndroid Build Coastguard Worker  * Get the name of a kmod module section.
2190*cc4ad7daSAndroid Build Coastguard Worker  *
2191*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling kmod_module_section_free_list().
2192*cc4ad7daSAndroid Build Coastguard Worker  *
2193*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the name of this kmod module section on success or NULL on
2194*cc4ad7daSAndroid Build Coastguard Worker  * failure. The string is owned by the section, do not free it.
2195*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_section_get_name(const struct kmod_list * entry)2196*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
2197*cc4ad7daSAndroid Build Coastguard Worker {
2198*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_section *section;
2199*cc4ad7daSAndroid Build Coastguard Worker 
2200*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL)
2201*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2202*cc4ad7daSAndroid Build Coastguard Worker 
2203*cc4ad7daSAndroid Build Coastguard Worker 	section = entry->data;
2204*cc4ad7daSAndroid Build Coastguard Worker 	return section->name;
2205*cc4ad7daSAndroid Build Coastguard Worker }
2206*cc4ad7daSAndroid Build Coastguard Worker 
2207*cc4ad7daSAndroid Build Coastguard Worker /**
2208*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_section_get_address:
2209*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module section
2210*cc4ad7daSAndroid Build Coastguard Worker  *
2211*cc4ad7daSAndroid Build Coastguard Worker  * Get the address of a kmod module section.
2212*cc4ad7daSAndroid Build Coastguard Worker  *
2213*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling kmod_module_section_free_list().
2214*cc4ad7daSAndroid Build Coastguard Worker  *
2215*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the address of this kmod module section on success or ULONG_MAX
2216*cc4ad7daSAndroid Build Coastguard Worker  * on failure.
2217*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_section_get_address(const struct kmod_list * entry)2218*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
2219*cc4ad7daSAndroid Build Coastguard Worker {
2220*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_section *section;
2221*cc4ad7daSAndroid Build Coastguard Worker 
2222*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL)
2223*cc4ad7daSAndroid Build Coastguard Worker 		return (unsigned long)-1;
2224*cc4ad7daSAndroid Build Coastguard Worker 
2225*cc4ad7daSAndroid Build Coastguard Worker 	section = entry->data;
2226*cc4ad7daSAndroid Build Coastguard Worker 	return section->address;
2227*cc4ad7daSAndroid Build Coastguard Worker }
2228*cc4ad7daSAndroid Build Coastguard Worker 
2229*cc4ad7daSAndroid Build Coastguard Worker /**
2230*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_section_free_list:
2231*cc4ad7daSAndroid Build Coastguard Worker  * @list: kmod module section list
2232*cc4ad7daSAndroid Build Coastguard Worker  *
2233*cc4ad7daSAndroid Build Coastguard Worker  * Release the resources taken by @list
2234*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_section_free_list(struct kmod_list * list)2235*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
2236*cc4ad7daSAndroid Build Coastguard Worker {
2237*cc4ad7daSAndroid Build Coastguard Worker 	while (list) {
2238*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_section_free(list->data);
2239*cc4ad7daSAndroid Build Coastguard Worker 		list = kmod_list_remove(list);
2240*cc4ad7daSAndroid Build Coastguard Worker 	}
2241*cc4ad7daSAndroid Build Coastguard Worker }
2242*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_get_elf(const struct kmod_module * mod)2243*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_elf *kmod_module_get_elf(const struct kmod_module *mod)
2244*cc4ad7daSAndroid Build Coastguard Worker {
2245*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->file == NULL) {
2246*cc4ad7daSAndroid Build Coastguard Worker 		const char *path = kmod_module_get_path(mod);
2247*cc4ad7daSAndroid Build Coastguard Worker 
2248*cc4ad7daSAndroid Build Coastguard Worker 		if (path == NULL) {
2249*cc4ad7daSAndroid Build Coastguard Worker 			errno = ENOENT;
2250*cc4ad7daSAndroid Build Coastguard Worker 			return NULL;
2251*cc4ad7daSAndroid Build Coastguard Worker 		}
2252*cc4ad7daSAndroid Build Coastguard Worker 
2253*cc4ad7daSAndroid Build Coastguard Worker 		((struct kmod_module *)mod)->file = kmod_file_open(mod->ctx,
2254*cc4ad7daSAndroid Build Coastguard Worker 									path);
2255*cc4ad7daSAndroid Build Coastguard Worker 		if (mod->file == NULL)
2256*cc4ad7daSAndroid Build Coastguard Worker 			return NULL;
2257*cc4ad7daSAndroid Build Coastguard Worker 	}
2258*cc4ad7daSAndroid Build Coastguard Worker 
2259*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_file_get_elf(mod->file);
2260*cc4ad7daSAndroid Build Coastguard Worker }
2261*cc4ad7daSAndroid Build Coastguard Worker 
2262*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module_info {
2263*cc4ad7daSAndroid Build Coastguard Worker 	char *key;
2264*cc4ad7daSAndroid Build Coastguard Worker 	char value[];
2265*cc4ad7daSAndroid Build Coastguard Worker };
2266*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_info_new(const char * key,size_t keylen,const char * value,size_t valuelen)2267*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_module_info *kmod_module_info_new(const char *key, size_t keylen, const char *value, size_t valuelen)
2268*cc4ad7daSAndroid Build Coastguard Worker {
2269*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_info *info;
2270*cc4ad7daSAndroid Build Coastguard Worker 
2271*cc4ad7daSAndroid Build Coastguard Worker 	info = malloc(sizeof(struct kmod_module_info) + keylen + valuelen + 2);
2272*cc4ad7daSAndroid Build Coastguard Worker 	if (info == NULL)
2273*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2274*cc4ad7daSAndroid Build Coastguard Worker 
2275*cc4ad7daSAndroid Build Coastguard Worker 	info->key = (char *)info + sizeof(struct kmod_module_info)
2276*cc4ad7daSAndroid Build Coastguard Worker 		    + valuelen + 1;
2277*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(info->key, key, keylen);
2278*cc4ad7daSAndroid Build Coastguard Worker 	info->key[keylen] = '\0';
2279*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(info->value, value, valuelen);
2280*cc4ad7daSAndroid Build Coastguard Worker 	info->value[valuelen] = '\0';
2281*cc4ad7daSAndroid Build Coastguard Worker 	return info;
2282*cc4ad7daSAndroid Build Coastguard Worker }
2283*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_info_free(struct kmod_module_info * info)2284*cc4ad7daSAndroid Build Coastguard Worker static void kmod_module_info_free(struct kmod_module_info *info)
2285*cc4ad7daSAndroid Build Coastguard Worker {
2286*cc4ad7daSAndroid Build Coastguard Worker 	free(info);
2287*cc4ad7daSAndroid Build Coastguard Worker }
2288*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_info_append(struct kmod_list ** list,const char * key,size_t keylen,const char * value,size_t valuelen)2289*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_list *kmod_module_info_append(struct kmod_list **list, const char *key, size_t keylen, const char *value, size_t valuelen)
2290*cc4ad7daSAndroid Build Coastguard Worker {
2291*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_info *info;
2292*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *n;
2293*cc4ad7daSAndroid Build Coastguard Worker 
2294*cc4ad7daSAndroid Build Coastguard Worker 	info = kmod_module_info_new(key, keylen, value, valuelen);
2295*cc4ad7daSAndroid Build Coastguard Worker 	if (info == NULL)
2296*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2297*cc4ad7daSAndroid Build Coastguard Worker 	n = kmod_list_append(*list, info);
2298*cc4ad7daSAndroid Build Coastguard Worker 	if (n != NULL)
2299*cc4ad7daSAndroid Build Coastguard Worker 		*list = n;
2300*cc4ad7daSAndroid Build Coastguard Worker 	else
2301*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_info_free(info);
2302*cc4ad7daSAndroid Build Coastguard Worker 	return n;
2303*cc4ad7daSAndroid Build Coastguard Worker }
2304*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_hex_to_str(const char * hex,size_t len)2305*cc4ad7daSAndroid Build Coastguard Worker static char *kmod_module_hex_to_str(const char *hex, size_t len)
2306*cc4ad7daSAndroid Build Coastguard Worker {
2307*cc4ad7daSAndroid Build Coastguard Worker 	char *str;
2308*cc4ad7daSAndroid Build Coastguard Worker 	int i;
2309*cc4ad7daSAndroid Build Coastguard Worker 	int j;
2310*cc4ad7daSAndroid Build Coastguard Worker 	const size_t line_limit = 20;
2311*cc4ad7daSAndroid Build Coastguard Worker 	size_t str_len;
2312*cc4ad7daSAndroid Build Coastguard Worker 
2313*cc4ad7daSAndroid Build Coastguard Worker 	str_len = len * 3; /* XX: or XX\0 */
2314*cc4ad7daSAndroid Build Coastguard Worker 	str_len += ((str_len + line_limit - 1) / line_limit - 1) * 3; /* \n\t\t */
2315*cc4ad7daSAndroid Build Coastguard Worker 
2316*cc4ad7daSAndroid Build Coastguard Worker 	str = malloc(str_len);
2317*cc4ad7daSAndroid Build Coastguard Worker 	if (str == NULL)
2318*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2319*cc4ad7daSAndroid Build Coastguard Worker 
2320*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0, j = 0; i < (int)len; i++) {
2321*cc4ad7daSAndroid Build Coastguard Worker 		j += sprintf(str + j, "%02X", (unsigned char)hex[i]);
2322*cc4ad7daSAndroid Build Coastguard Worker 		if (i < (int)len - 1) {
2323*cc4ad7daSAndroid Build Coastguard Worker 			str[j++] = ':';
2324*cc4ad7daSAndroid Build Coastguard Worker 
2325*cc4ad7daSAndroid Build Coastguard Worker 			if ((i + 1) % line_limit == 0)
2326*cc4ad7daSAndroid Build Coastguard Worker 				j += sprintf(str + j, "\n\t\t");
2327*cc4ad7daSAndroid Build Coastguard Worker 		}
2328*cc4ad7daSAndroid Build Coastguard Worker 	}
2329*cc4ad7daSAndroid Build Coastguard Worker 	return str;
2330*cc4ad7daSAndroid Build Coastguard Worker }
2331*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_info_append_hex(struct kmod_list ** list,const char * key,size_t keylen,const char * value,size_t valuelen)2332*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_list *kmod_module_info_append_hex(struct kmod_list **list,
2333*cc4ad7daSAndroid Build Coastguard Worker 						     const char *key,
2334*cc4ad7daSAndroid Build Coastguard Worker 						     size_t keylen,
2335*cc4ad7daSAndroid Build Coastguard Worker 						     const char *value,
2336*cc4ad7daSAndroid Build Coastguard Worker 						     size_t valuelen)
2337*cc4ad7daSAndroid Build Coastguard Worker {
2338*cc4ad7daSAndroid Build Coastguard Worker 	char *hex;
2339*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *n;
2340*cc4ad7daSAndroid Build Coastguard Worker 
2341*cc4ad7daSAndroid Build Coastguard Worker 	if (valuelen > 0) {
2342*cc4ad7daSAndroid Build Coastguard Worker 		/* Display as 01:12:DE:AD:BE:EF:... */
2343*cc4ad7daSAndroid Build Coastguard Worker 		hex = kmod_module_hex_to_str(value, valuelen);
2344*cc4ad7daSAndroid Build Coastguard Worker 		if (hex == NULL)
2345*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2346*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append(list, key, keylen, hex, strlen(hex));
2347*cc4ad7daSAndroid Build Coastguard Worker 		free(hex);
2348*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2349*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2350*cc4ad7daSAndroid Build Coastguard Worker 	} else {
2351*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append(list, key, keylen, NULL, 0);
2352*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2353*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2354*cc4ad7daSAndroid Build Coastguard Worker 	}
2355*cc4ad7daSAndroid Build Coastguard Worker 
2356*cc4ad7daSAndroid Build Coastguard Worker 	return n;
2357*cc4ad7daSAndroid Build Coastguard Worker 
2358*cc4ad7daSAndroid Build Coastguard Worker list_error:
2359*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
2360*cc4ad7daSAndroid Build Coastguard Worker }
2361*cc4ad7daSAndroid Build Coastguard Worker 
2362*cc4ad7daSAndroid Build Coastguard Worker /**
2363*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_info:
2364*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
2365*cc4ad7daSAndroid Build Coastguard Worker  * @list: where to return list of module information. Use
2366*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_info_get_key() and
2367*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_info_get_value(). Release this list with
2368*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_info_free_list()
2369*cc4ad7daSAndroid Build Coastguard Worker  *
2370*cc4ad7daSAndroid Build Coastguard Worker  * Get a list of entries in ELF section ".modinfo", these contain
2371*cc4ad7daSAndroid Build Coastguard Worker  * alias, license, depends, vermagic and other keys with respective
2372*cc4ad7daSAndroid Build Coastguard Worker  * values. If the module is signed (CONFIG_MODULE_SIG), information
2373*cc4ad7daSAndroid Build Coastguard Worker  * about the module signature is included as well: signer,
2374*cc4ad7daSAndroid Build Coastguard Worker  * sig_key and sig_hashalgo.
2375*cc4ad7daSAndroid Build Coastguard Worker  *
2376*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling kmod_module_info_free_list().
2377*cc4ad7daSAndroid Build Coastguard Worker  *
2378*cc4ad7daSAndroid Build Coastguard Worker  * Returns: number of entries in @list on success or < 0 otherwise.
2379*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_info(const struct kmod_module * mod,struct kmod_list ** list)2380*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_list **list)
2381*cc4ad7daSAndroid Build Coastguard Worker {
2382*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_elf *elf;
2383*cc4ad7daSAndroid Build Coastguard Worker 	char **strings;
2384*cc4ad7daSAndroid Build Coastguard Worker 	int i, count, ret = -ENOMEM;
2385*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_signature_info sig_info = {};
2386*cc4ad7daSAndroid Build Coastguard Worker 
2387*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL || list == NULL)
2388*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
2389*cc4ad7daSAndroid Build Coastguard Worker 
2390*cc4ad7daSAndroid Build Coastguard Worker 	assert(*list == NULL);
2391*cc4ad7daSAndroid Build Coastguard Worker 
2392*cc4ad7daSAndroid Build Coastguard Worker 	/* remove const: this can only change internal state */
2393*cc4ad7daSAndroid Build Coastguard Worker 	if (kmod_module_is_builtin((struct kmod_module *)mod)) {
2394*cc4ad7daSAndroid Build Coastguard Worker 		count = kmod_builtin_get_modinfo(mod->ctx,
2395*cc4ad7daSAndroid Build Coastguard Worker 						kmod_module_get_name(mod),
2396*cc4ad7daSAndroid Build Coastguard Worker 						&strings);
2397*cc4ad7daSAndroid Build Coastguard Worker 		if (count < 0)
2398*cc4ad7daSAndroid Build Coastguard Worker 			return count;
2399*cc4ad7daSAndroid Build Coastguard Worker 	} else {
2400*cc4ad7daSAndroid Build Coastguard Worker 		elf = kmod_module_get_elf(mod);
2401*cc4ad7daSAndroid Build Coastguard Worker 		if (elf == NULL)
2402*cc4ad7daSAndroid Build Coastguard Worker 			return -errno;
2403*cc4ad7daSAndroid Build Coastguard Worker 
2404*cc4ad7daSAndroid Build Coastguard Worker 		count = kmod_elf_get_strings(elf, ".modinfo", &strings);
2405*cc4ad7daSAndroid Build Coastguard Worker 		if (count < 0)
2406*cc4ad7daSAndroid Build Coastguard Worker 			return count;
2407*cc4ad7daSAndroid Build Coastguard Worker 	}
2408*cc4ad7daSAndroid Build Coastguard Worker 
2409*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
2410*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *n;
2411*cc4ad7daSAndroid Build Coastguard Worker 		const char *key, *value;
2412*cc4ad7daSAndroid Build Coastguard Worker 		size_t keylen, valuelen;
2413*cc4ad7daSAndroid Build Coastguard Worker 
2414*cc4ad7daSAndroid Build Coastguard Worker 		key = strings[i];
2415*cc4ad7daSAndroid Build Coastguard Worker 		value = strchr(key, '=');
2416*cc4ad7daSAndroid Build Coastguard Worker 		if (value == NULL) {
2417*cc4ad7daSAndroid Build Coastguard Worker 			keylen = strlen(key);
2418*cc4ad7daSAndroid Build Coastguard Worker 			valuelen = 0;
2419*cc4ad7daSAndroid Build Coastguard Worker 			value = key;
2420*cc4ad7daSAndroid Build Coastguard Worker 		} else {
2421*cc4ad7daSAndroid Build Coastguard Worker 			keylen = value - key;
2422*cc4ad7daSAndroid Build Coastguard Worker 			value++;
2423*cc4ad7daSAndroid Build Coastguard Worker 			valuelen = strlen(value);
2424*cc4ad7daSAndroid Build Coastguard Worker 		}
2425*cc4ad7daSAndroid Build Coastguard Worker 
2426*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append(list, key, keylen, value, valuelen);
2427*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2428*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2429*cc4ad7daSAndroid Build Coastguard Worker 	}
2430*cc4ad7daSAndroid Build Coastguard Worker 
2431*cc4ad7daSAndroid Build Coastguard Worker 	if (mod->file && kmod_module_signature_info(mod->file, &sig_info)) {
2432*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *n;
2433*cc4ad7daSAndroid Build Coastguard Worker 
2434*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append(list, "sig_id", strlen("sig_id"),
2435*cc4ad7daSAndroid Build Coastguard Worker 				sig_info.id_type, strlen(sig_info.id_type));
2436*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2437*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2438*cc4ad7daSAndroid Build Coastguard Worker 		count++;
2439*cc4ad7daSAndroid Build Coastguard Worker 
2440*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append(list, "signer", strlen("signer"),
2441*cc4ad7daSAndroid Build Coastguard Worker 				sig_info.signer, sig_info.signer_len);
2442*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2443*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2444*cc4ad7daSAndroid Build Coastguard Worker 		count++;
2445*cc4ad7daSAndroid Build Coastguard Worker 
2446*cc4ad7daSAndroid Build Coastguard Worker 
2447*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append_hex(list, "sig_key", strlen("sig_key"),
2448*cc4ad7daSAndroid Build Coastguard Worker 						sig_info.key_id,
2449*cc4ad7daSAndroid Build Coastguard Worker 						sig_info.key_id_len);
2450*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2451*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2452*cc4ad7daSAndroid Build Coastguard Worker 		count++;
2453*cc4ad7daSAndroid Build Coastguard Worker 
2454*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append(list,
2455*cc4ad7daSAndroid Build Coastguard Worker 				"sig_hashalgo", strlen("sig_hashalgo"),
2456*cc4ad7daSAndroid Build Coastguard Worker 				sig_info.hash_algo, strlen(sig_info.hash_algo));
2457*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2458*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2459*cc4ad7daSAndroid Build Coastguard Worker 		count++;
2460*cc4ad7daSAndroid Build Coastguard Worker 
2461*cc4ad7daSAndroid Build Coastguard Worker 		/*
2462*cc4ad7daSAndroid Build Coastguard Worker 		 * Omit sig_info.algo for now, as these
2463*cc4ad7daSAndroid Build Coastguard Worker 		 * are currently constant.
2464*cc4ad7daSAndroid Build Coastguard Worker 		 */
2465*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_info_append_hex(list, "signature",
2466*cc4ad7daSAndroid Build Coastguard Worker 						strlen("signature"),
2467*cc4ad7daSAndroid Build Coastguard Worker 						sig_info.sig,
2468*cc4ad7daSAndroid Build Coastguard Worker 						sig_info.sig_len);
2469*cc4ad7daSAndroid Build Coastguard Worker 
2470*cc4ad7daSAndroid Build Coastguard Worker 		if (n == NULL)
2471*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2472*cc4ad7daSAndroid Build Coastguard Worker 		count++;
2473*cc4ad7daSAndroid Build Coastguard Worker 
2474*cc4ad7daSAndroid Build Coastguard Worker 	}
2475*cc4ad7daSAndroid Build Coastguard Worker 	ret = count;
2476*cc4ad7daSAndroid Build Coastguard Worker 
2477*cc4ad7daSAndroid Build Coastguard Worker list_error:
2478*cc4ad7daSAndroid Build Coastguard Worker 	/* aux structures freed in normal case also */
2479*cc4ad7daSAndroid Build Coastguard Worker 	kmod_module_signature_info_free(&sig_info);
2480*cc4ad7daSAndroid Build Coastguard Worker 
2481*cc4ad7daSAndroid Build Coastguard Worker 	if (ret < 0) {
2482*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_info_free_list(*list);
2483*cc4ad7daSAndroid Build Coastguard Worker 		*list = NULL;
2484*cc4ad7daSAndroid Build Coastguard Worker 	}
2485*cc4ad7daSAndroid Build Coastguard Worker 	free(strings);
2486*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
2487*cc4ad7daSAndroid Build Coastguard Worker }
2488*cc4ad7daSAndroid Build Coastguard Worker 
2489*cc4ad7daSAndroid Build Coastguard Worker /**
2490*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_info_get_key:
2491*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module info
2492*cc4ad7daSAndroid Build Coastguard Worker  *
2493*cc4ad7daSAndroid Build Coastguard Worker  * Get the key of a kmod module info.
2494*cc4ad7daSAndroid Build Coastguard Worker  *
2495*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the key of this kmod module info on success or NULL on
2496*cc4ad7daSAndroid Build Coastguard Worker  * failure. The string is owned by the info, do not free it.
2497*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_info_get_key(const struct kmod_list * entry)2498*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_info_get_key(const struct kmod_list *entry)
2499*cc4ad7daSAndroid Build Coastguard Worker {
2500*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_info *info;
2501*cc4ad7daSAndroid Build Coastguard Worker 
2502*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL)
2503*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2504*cc4ad7daSAndroid Build Coastguard Worker 
2505*cc4ad7daSAndroid Build Coastguard Worker 	info = entry->data;
2506*cc4ad7daSAndroid Build Coastguard Worker 	return info->key;
2507*cc4ad7daSAndroid Build Coastguard Worker }
2508*cc4ad7daSAndroid Build Coastguard Worker 
2509*cc4ad7daSAndroid Build Coastguard Worker /**
2510*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_info_get_value:
2511*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module info
2512*cc4ad7daSAndroid Build Coastguard Worker  *
2513*cc4ad7daSAndroid Build Coastguard Worker  * Get the value of a kmod module info.
2514*cc4ad7daSAndroid Build Coastguard Worker  *
2515*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the value of this kmod module info on success or NULL on
2516*cc4ad7daSAndroid Build Coastguard Worker  * failure. The string is owned by the info, do not free it.
2517*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_info_get_value(const struct kmod_list * entry)2518*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_info_get_value(const struct kmod_list *entry)
2519*cc4ad7daSAndroid Build Coastguard Worker {
2520*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_info *info;
2521*cc4ad7daSAndroid Build Coastguard Worker 
2522*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL)
2523*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2524*cc4ad7daSAndroid Build Coastguard Worker 
2525*cc4ad7daSAndroid Build Coastguard Worker 	info = entry->data;
2526*cc4ad7daSAndroid Build Coastguard Worker 	return info->value;
2527*cc4ad7daSAndroid Build Coastguard Worker }
2528*cc4ad7daSAndroid Build Coastguard Worker 
2529*cc4ad7daSAndroid Build Coastguard Worker /**
2530*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_info_free_list:
2531*cc4ad7daSAndroid Build Coastguard Worker  * @list: kmod module info list
2532*cc4ad7daSAndroid Build Coastguard Worker  *
2533*cc4ad7daSAndroid Build Coastguard Worker  * Release the resources taken by @list
2534*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_info_free_list(struct kmod_list * list)2535*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_module_info_free_list(struct kmod_list *list)
2536*cc4ad7daSAndroid Build Coastguard Worker {
2537*cc4ad7daSAndroid Build Coastguard Worker 	while (list) {
2538*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_info_free(list->data);
2539*cc4ad7daSAndroid Build Coastguard Worker 		list = kmod_list_remove(list);
2540*cc4ad7daSAndroid Build Coastguard Worker 	}
2541*cc4ad7daSAndroid Build Coastguard Worker }
2542*cc4ad7daSAndroid Build Coastguard Worker 
2543*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module_version {
2544*cc4ad7daSAndroid Build Coastguard Worker 	uint64_t crc;
2545*cc4ad7daSAndroid Build Coastguard Worker 	char symbol[];
2546*cc4ad7daSAndroid Build Coastguard Worker };
2547*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_versions_new(uint64_t crc,const char * symbol)2548*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_module_version *kmod_module_versions_new(uint64_t crc, const char *symbol)
2549*cc4ad7daSAndroid Build Coastguard Worker {
2550*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_version *mv;
2551*cc4ad7daSAndroid Build Coastguard Worker 	size_t symbollen = strlen(symbol) + 1;
2552*cc4ad7daSAndroid Build Coastguard Worker 
2553*cc4ad7daSAndroid Build Coastguard Worker 	mv = malloc(sizeof(struct kmod_module_version) + symbollen);
2554*cc4ad7daSAndroid Build Coastguard Worker 	if (mv == NULL)
2555*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2556*cc4ad7daSAndroid Build Coastguard Worker 
2557*cc4ad7daSAndroid Build Coastguard Worker 	mv->crc = crc;
2558*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(mv->symbol, symbol, symbollen);
2559*cc4ad7daSAndroid Build Coastguard Worker 	return mv;
2560*cc4ad7daSAndroid Build Coastguard Worker }
2561*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_version_free(struct kmod_module_version * version)2562*cc4ad7daSAndroid Build Coastguard Worker static void kmod_module_version_free(struct kmod_module_version *version)
2563*cc4ad7daSAndroid Build Coastguard Worker {
2564*cc4ad7daSAndroid Build Coastguard Worker 	free(version);
2565*cc4ad7daSAndroid Build Coastguard Worker }
2566*cc4ad7daSAndroid Build Coastguard Worker 
2567*cc4ad7daSAndroid Build Coastguard Worker /**
2568*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_versions:
2569*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
2570*cc4ad7daSAndroid Build Coastguard Worker  * @list: where to return list of module versions. Use
2571*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_version_get_symbol() and
2572*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_version_get_crc(). Release this list with
2573*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_versions_free_list()
2574*cc4ad7daSAndroid Build Coastguard Worker  *
2575*cc4ad7daSAndroid Build Coastguard Worker  * Get a list of entries in ELF section "__versions".
2576*cc4ad7daSAndroid Build Coastguard Worker  *
2577*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling kmod_module_versions_free_list().
2578*cc4ad7daSAndroid Build Coastguard Worker  *
2579*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
2580*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_versions(const struct kmod_module * mod,struct kmod_list ** list)2581*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod, struct kmod_list **list)
2582*cc4ad7daSAndroid Build Coastguard Worker {
2583*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_elf *elf;
2584*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_modversion *versions;
2585*cc4ad7daSAndroid Build Coastguard Worker 	int i, count, ret = 0;
2586*cc4ad7daSAndroid Build Coastguard Worker 
2587*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL || list == NULL)
2588*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
2589*cc4ad7daSAndroid Build Coastguard Worker 
2590*cc4ad7daSAndroid Build Coastguard Worker 	assert(*list == NULL);
2591*cc4ad7daSAndroid Build Coastguard Worker 
2592*cc4ad7daSAndroid Build Coastguard Worker 	elf = kmod_module_get_elf(mod);
2593*cc4ad7daSAndroid Build Coastguard Worker 	if (elf == NULL)
2594*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
2595*cc4ad7daSAndroid Build Coastguard Worker 
2596*cc4ad7daSAndroid Build Coastguard Worker 	count = kmod_elf_get_modversions(elf, &versions);
2597*cc4ad7daSAndroid Build Coastguard Worker 	if (count < 0)
2598*cc4ad7daSAndroid Build Coastguard Worker 		return count;
2599*cc4ad7daSAndroid Build Coastguard Worker 
2600*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
2601*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module_version *mv;
2602*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *n;
2603*cc4ad7daSAndroid Build Coastguard Worker 
2604*cc4ad7daSAndroid Build Coastguard Worker 		mv = kmod_module_versions_new(versions[i].crc, versions[i].symbol);
2605*cc4ad7daSAndroid Build Coastguard Worker 		if (mv == NULL) {
2606*cc4ad7daSAndroid Build Coastguard Worker 			ret = -errno;
2607*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_versions_free_list(*list);
2608*cc4ad7daSAndroid Build Coastguard Worker 			*list = NULL;
2609*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2610*cc4ad7daSAndroid Build Coastguard Worker 		}
2611*cc4ad7daSAndroid Build Coastguard Worker 
2612*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_list_append(*list, mv);
2613*cc4ad7daSAndroid Build Coastguard Worker 		if (n != NULL)
2614*cc4ad7daSAndroid Build Coastguard Worker 			*list = n;
2615*cc4ad7daSAndroid Build Coastguard Worker 		else {
2616*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_version_free(mv);
2617*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_versions_free_list(*list);
2618*cc4ad7daSAndroid Build Coastguard Worker 			*list = NULL;
2619*cc4ad7daSAndroid Build Coastguard Worker 			ret = -ENOMEM;
2620*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2621*cc4ad7daSAndroid Build Coastguard Worker 		}
2622*cc4ad7daSAndroid Build Coastguard Worker 	}
2623*cc4ad7daSAndroid Build Coastguard Worker 	ret = count;
2624*cc4ad7daSAndroid Build Coastguard Worker 
2625*cc4ad7daSAndroid Build Coastguard Worker list_error:
2626*cc4ad7daSAndroid Build Coastguard Worker 	free(versions);
2627*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
2628*cc4ad7daSAndroid Build Coastguard Worker }
2629*cc4ad7daSAndroid Build Coastguard Worker 
2630*cc4ad7daSAndroid Build Coastguard Worker /**
2631*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_version_get_symbol:
2632*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module versions
2633*cc4ad7daSAndroid Build Coastguard Worker  *
2634*cc4ad7daSAndroid Build Coastguard Worker  * Get the symbol of a kmod module versions.
2635*cc4ad7daSAndroid Build Coastguard Worker  *
2636*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the symbol of this kmod module versions on success or NULL
2637*cc4ad7daSAndroid Build Coastguard Worker  * on failure. The string is owned by the versions, do not free it.
2638*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_version_get_symbol(const struct kmod_list * entry)2639*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_version_get_symbol(const struct kmod_list *entry)
2640*cc4ad7daSAndroid Build Coastguard Worker {
2641*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_version *version;
2642*cc4ad7daSAndroid Build Coastguard Worker 
2643*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2644*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2645*cc4ad7daSAndroid Build Coastguard Worker 
2646*cc4ad7daSAndroid Build Coastguard Worker 	version = entry->data;
2647*cc4ad7daSAndroid Build Coastguard Worker 	return version->symbol;
2648*cc4ad7daSAndroid Build Coastguard Worker }
2649*cc4ad7daSAndroid Build Coastguard Worker 
2650*cc4ad7daSAndroid Build Coastguard Worker /**
2651*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_version_get_crc:
2652*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module version
2653*cc4ad7daSAndroid Build Coastguard Worker  *
2654*cc4ad7daSAndroid Build Coastguard Worker  * Get the crc of a kmod module version.
2655*cc4ad7daSAndroid Build Coastguard Worker  *
2656*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the crc of this kmod module version if available, otherwise default to 0.
2657*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_version_get_crc(const struct kmod_list * entry)2658*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT uint64_t kmod_module_version_get_crc(const struct kmod_list *entry)
2659*cc4ad7daSAndroid Build Coastguard Worker {
2660*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_version *version;
2661*cc4ad7daSAndroid Build Coastguard Worker 
2662*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2663*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
2664*cc4ad7daSAndroid Build Coastguard Worker 
2665*cc4ad7daSAndroid Build Coastguard Worker 	version = entry->data;
2666*cc4ad7daSAndroid Build Coastguard Worker 	return version->crc;
2667*cc4ad7daSAndroid Build Coastguard Worker }
2668*cc4ad7daSAndroid Build Coastguard Worker 
2669*cc4ad7daSAndroid Build Coastguard Worker /**
2670*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_versions_free_list:
2671*cc4ad7daSAndroid Build Coastguard Worker  * @list: kmod module versions list
2672*cc4ad7daSAndroid Build Coastguard Worker  *
2673*cc4ad7daSAndroid Build Coastguard Worker  * Release the resources taken by @list
2674*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_versions_free_list(struct kmod_list * list)2675*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_module_versions_free_list(struct kmod_list *list)
2676*cc4ad7daSAndroid Build Coastguard Worker {
2677*cc4ad7daSAndroid Build Coastguard Worker 	while (list) {
2678*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_version_free(list->data);
2679*cc4ad7daSAndroid Build Coastguard Worker 		list = kmod_list_remove(list);
2680*cc4ad7daSAndroid Build Coastguard Worker 	}
2681*cc4ad7daSAndroid Build Coastguard Worker }
2682*cc4ad7daSAndroid Build Coastguard Worker 
2683*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module_symbol {
2684*cc4ad7daSAndroid Build Coastguard Worker 	uint64_t crc;
2685*cc4ad7daSAndroid Build Coastguard Worker 	char symbol[];
2686*cc4ad7daSAndroid Build Coastguard Worker };
2687*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_symbols_new(uint64_t crc,const char * symbol)2688*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_module_symbol *kmod_module_symbols_new(uint64_t crc, const char *symbol)
2689*cc4ad7daSAndroid Build Coastguard Worker {
2690*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_symbol *mv;
2691*cc4ad7daSAndroid Build Coastguard Worker 	size_t symbollen = strlen(symbol) + 1;
2692*cc4ad7daSAndroid Build Coastguard Worker 
2693*cc4ad7daSAndroid Build Coastguard Worker 	mv = malloc(sizeof(struct kmod_module_symbol) + symbollen);
2694*cc4ad7daSAndroid Build Coastguard Worker 	if (mv == NULL)
2695*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2696*cc4ad7daSAndroid Build Coastguard Worker 
2697*cc4ad7daSAndroid Build Coastguard Worker 	mv->crc = crc;
2698*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(mv->symbol, symbol, symbollen);
2699*cc4ad7daSAndroid Build Coastguard Worker 	return mv;
2700*cc4ad7daSAndroid Build Coastguard Worker }
2701*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_symbol_free(struct kmod_module_symbol * symbol)2702*cc4ad7daSAndroid Build Coastguard Worker static void kmod_module_symbol_free(struct kmod_module_symbol *symbol)
2703*cc4ad7daSAndroid Build Coastguard Worker {
2704*cc4ad7daSAndroid Build Coastguard Worker 	free(symbol);
2705*cc4ad7daSAndroid Build Coastguard Worker }
2706*cc4ad7daSAndroid Build Coastguard Worker 
2707*cc4ad7daSAndroid Build Coastguard Worker /**
2708*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_symbols:
2709*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
2710*cc4ad7daSAndroid Build Coastguard Worker  * @list: where to return list of module symbols. Use
2711*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_symbol_get_symbol() and
2712*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_symbol_get_crc(). Release this list with
2713*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_symbols_free_list()
2714*cc4ad7daSAndroid Build Coastguard Worker  *
2715*cc4ad7daSAndroid Build Coastguard Worker  * Get a list of entries in ELF section ".symtab" or "__ksymtab_strings".
2716*cc4ad7daSAndroid Build Coastguard Worker  *
2717*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling kmod_module_symbols_free_list().
2718*cc4ad7daSAndroid Build Coastguard Worker  *
2719*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
2720*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_symbols(const struct kmod_module * mod,struct kmod_list ** list)2721*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod, struct kmod_list **list)
2722*cc4ad7daSAndroid Build Coastguard Worker {
2723*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_elf *elf;
2724*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_modversion *symbols;
2725*cc4ad7daSAndroid Build Coastguard Worker 	int i, count, ret = 0;
2726*cc4ad7daSAndroid Build Coastguard Worker 
2727*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL || list == NULL)
2728*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
2729*cc4ad7daSAndroid Build Coastguard Worker 
2730*cc4ad7daSAndroid Build Coastguard Worker 	assert(*list == NULL);
2731*cc4ad7daSAndroid Build Coastguard Worker 
2732*cc4ad7daSAndroid Build Coastguard Worker 	elf = kmod_module_get_elf(mod);
2733*cc4ad7daSAndroid Build Coastguard Worker 	if (elf == NULL)
2734*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
2735*cc4ad7daSAndroid Build Coastguard Worker 
2736*cc4ad7daSAndroid Build Coastguard Worker 	count = kmod_elf_get_symbols(elf, &symbols);
2737*cc4ad7daSAndroid Build Coastguard Worker 	if (count < 0)
2738*cc4ad7daSAndroid Build Coastguard Worker 		return count;
2739*cc4ad7daSAndroid Build Coastguard Worker 
2740*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
2741*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module_symbol *mv;
2742*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *n;
2743*cc4ad7daSAndroid Build Coastguard Worker 
2744*cc4ad7daSAndroid Build Coastguard Worker 		mv = kmod_module_symbols_new(symbols[i].crc, symbols[i].symbol);
2745*cc4ad7daSAndroid Build Coastguard Worker 		if (mv == NULL) {
2746*cc4ad7daSAndroid Build Coastguard Worker 			ret = -errno;
2747*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_symbols_free_list(*list);
2748*cc4ad7daSAndroid Build Coastguard Worker 			*list = NULL;
2749*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2750*cc4ad7daSAndroid Build Coastguard Worker 		}
2751*cc4ad7daSAndroid Build Coastguard Worker 
2752*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_list_append(*list, mv);
2753*cc4ad7daSAndroid Build Coastguard Worker 		if (n != NULL)
2754*cc4ad7daSAndroid Build Coastguard Worker 			*list = n;
2755*cc4ad7daSAndroid Build Coastguard Worker 		else {
2756*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_symbol_free(mv);
2757*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_symbols_free_list(*list);
2758*cc4ad7daSAndroid Build Coastguard Worker 			*list = NULL;
2759*cc4ad7daSAndroid Build Coastguard Worker 			ret = -ENOMEM;
2760*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2761*cc4ad7daSAndroid Build Coastguard Worker 		}
2762*cc4ad7daSAndroid Build Coastguard Worker 	}
2763*cc4ad7daSAndroid Build Coastguard Worker 	ret = count;
2764*cc4ad7daSAndroid Build Coastguard Worker 
2765*cc4ad7daSAndroid Build Coastguard Worker list_error:
2766*cc4ad7daSAndroid Build Coastguard Worker 	free(symbols);
2767*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
2768*cc4ad7daSAndroid Build Coastguard Worker }
2769*cc4ad7daSAndroid Build Coastguard Worker 
2770*cc4ad7daSAndroid Build Coastguard Worker /**
2771*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_symbol_get_symbol:
2772*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module symbols
2773*cc4ad7daSAndroid Build Coastguard Worker  *
2774*cc4ad7daSAndroid Build Coastguard Worker  * Get the symbol of a kmod module symbols.
2775*cc4ad7daSAndroid Build Coastguard Worker  *
2776*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the symbol of this kmod module symbols on success or NULL
2777*cc4ad7daSAndroid Build Coastguard Worker  * on failure. The string is owned by the symbols, do not free it.
2778*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_symbol_get_symbol(const struct kmod_list * entry)2779*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_symbol_get_symbol(const struct kmod_list *entry)
2780*cc4ad7daSAndroid Build Coastguard Worker {
2781*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_symbol *symbol;
2782*cc4ad7daSAndroid Build Coastguard Worker 
2783*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2784*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2785*cc4ad7daSAndroid Build Coastguard Worker 
2786*cc4ad7daSAndroid Build Coastguard Worker 	symbol = entry->data;
2787*cc4ad7daSAndroid Build Coastguard Worker 	return symbol->symbol;
2788*cc4ad7daSAndroid Build Coastguard Worker }
2789*cc4ad7daSAndroid Build Coastguard Worker 
2790*cc4ad7daSAndroid Build Coastguard Worker /**
2791*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_symbol_get_crc:
2792*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module symbol
2793*cc4ad7daSAndroid Build Coastguard Worker  *
2794*cc4ad7daSAndroid Build Coastguard Worker  * Get the crc of a kmod module symbol.
2795*cc4ad7daSAndroid Build Coastguard Worker  *
2796*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the crc of this kmod module symbol if available, otherwise default to 0.
2797*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_symbol_get_crc(const struct kmod_list * entry)2798*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT uint64_t kmod_module_symbol_get_crc(const struct kmod_list *entry)
2799*cc4ad7daSAndroid Build Coastguard Worker {
2800*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_symbol *symbol;
2801*cc4ad7daSAndroid Build Coastguard Worker 
2802*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2803*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
2804*cc4ad7daSAndroid Build Coastguard Worker 
2805*cc4ad7daSAndroid Build Coastguard Worker 	symbol = entry->data;
2806*cc4ad7daSAndroid Build Coastguard Worker 	return symbol->crc;
2807*cc4ad7daSAndroid Build Coastguard Worker }
2808*cc4ad7daSAndroid Build Coastguard Worker 
2809*cc4ad7daSAndroid Build Coastguard Worker /**
2810*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_symbols_free_list:
2811*cc4ad7daSAndroid Build Coastguard Worker  * @list: kmod module symbols list
2812*cc4ad7daSAndroid Build Coastguard Worker  *
2813*cc4ad7daSAndroid Build Coastguard Worker  * Release the resources taken by @list
2814*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_symbols_free_list(struct kmod_list * list)2815*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_module_symbols_free_list(struct kmod_list *list)
2816*cc4ad7daSAndroid Build Coastguard Worker {
2817*cc4ad7daSAndroid Build Coastguard Worker 	while (list) {
2818*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_symbol_free(list->data);
2819*cc4ad7daSAndroid Build Coastguard Worker 		list = kmod_list_remove(list);
2820*cc4ad7daSAndroid Build Coastguard Worker 	}
2821*cc4ad7daSAndroid Build Coastguard Worker }
2822*cc4ad7daSAndroid Build Coastguard Worker 
2823*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module_dependency_symbol {
2824*cc4ad7daSAndroid Build Coastguard Worker 	uint64_t crc;
2825*cc4ad7daSAndroid Build Coastguard Worker 	uint8_t bind;
2826*cc4ad7daSAndroid Build Coastguard Worker 	char symbol[];
2827*cc4ad7daSAndroid Build Coastguard Worker };
2828*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_dependency_symbols_new(uint64_t crc,uint8_t bind,const char * symbol)2829*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_module_dependency_symbol *kmod_module_dependency_symbols_new(uint64_t crc, uint8_t bind, const char *symbol)
2830*cc4ad7daSAndroid Build Coastguard Worker {
2831*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_dependency_symbol *mv;
2832*cc4ad7daSAndroid Build Coastguard Worker 	size_t symbollen = strlen(symbol) + 1;
2833*cc4ad7daSAndroid Build Coastguard Worker 
2834*cc4ad7daSAndroid Build Coastguard Worker 	mv = malloc(sizeof(struct kmod_module_dependency_symbol) + symbollen);
2835*cc4ad7daSAndroid Build Coastguard Worker 	if (mv == NULL)
2836*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2837*cc4ad7daSAndroid Build Coastguard Worker 
2838*cc4ad7daSAndroid Build Coastguard Worker 	mv->crc = crc;
2839*cc4ad7daSAndroid Build Coastguard Worker 	mv->bind = bind;
2840*cc4ad7daSAndroid Build Coastguard Worker 	memcpy(mv->symbol, symbol, symbollen);
2841*cc4ad7daSAndroid Build Coastguard Worker 	return mv;
2842*cc4ad7daSAndroid Build Coastguard Worker }
2843*cc4ad7daSAndroid Build Coastguard Worker 
kmod_module_dependency_symbol_free(struct kmod_module_dependency_symbol * dependency_symbol)2844*cc4ad7daSAndroid Build Coastguard Worker static void kmod_module_dependency_symbol_free(struct kmod_module_dependency_symbol *dependency_symbol)
2845*cc4ad7daSAndroid Build Coastguard Worker {
2846*cc4ad7daSAndroid Build Coastguard Worker 	free(dependency_symbol);
2847*cc4ad7daSAndroid Build Coastguard Worker }
2848*cc4ad7daSAndroid Build Coastguard Worker 
2849*cc4ad7daSAndroid Build Coastguard Worker /**
2850*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_get_dependency_symbols:
2851*cc4ad7daSAndroid Build Coastguard Worker  * @mod: kmod module
2852*cc4ad7daSAndroid Build Coastguard Worker  * @list: where to return list of module dependency_symbols. Use
2853*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_dependency_symbol_get_symbol() and
2854*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_dependency_symbol_get_crc(). Release this list with
2855*cc4ad7daSAndroid Build Coastguard Worker  *        kmod_module_dependency_symbols_free_list()
2856*cc4ad7daSAndroid Build Coastguard Worker  *
2857*cc4ad7daSAndroid Build Coastguard Worker  * Get a list of entries in ELF section ".symtab" or "__ksymtab_strings".
2858*cc4ad7daSAndroid Build Coastguard Worker  *
2859*cc4ad7daSAndroid Build Coastguard Worker  * After use, free the @list by calling
2860*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_dependency_symbols_free_list().
2861*cc4ad7daSAndroid Build Coastguard Worker  *
2862*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
2863*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_get_dependency_symbols(const struct kmod_module * mod,struct kmod_list ** list)2864*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod, struct kmod_list **list)
2865*cc4ad7daSAndroid Build Coastguard Worker {
2866*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_elf *elf;
2867*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_modversion *symbols;
2868*cc4ad7daSAndroid Build Coastguard Worker 	int i, count, ret = 0;
2869*cc4ad7daSAndroid Build Coastguard Worker 
2870*cc4ad7daSAndroid Build Coastguard Worker 	if (mod == NULL || list == NULL)
2871*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
2872*cc4ad7daSAndroid Build Coastguard Worker 
2873*cc4ad7daSAndroid Build Coastguard Worker 	assert(*list == NULL);
2874*cc4ad7daSAndroid Build Coastguard Worker 
2875*cc4ad7daSAndroid Build Coastguard Worker 	elf = kmod_module_get_elf(mod);
2876*cc4ad7daSAndroid Build Coastguard Worker 	if (elf == NULL)
2877*cc4ad7daSAndroid Build Coastguard Worker 		return -errno;
2878*cc4ad7daSAndroid Build Coastguard Worker 
2879*cc4ad7daSAndroid Build Coastguard Worker 	count = kmod_elf_get_dependency_symbols(elf, &symbols);
2880*cc4ad7daSAndroid Build Coastguard Worker 	if (count < 0)
2881*cc4ad7daSAndroid Build Coastguard Worker 		return count;
2882*cc4ad7daSAndroid Build Coastguard Worker 
2883*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
2884*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module_dependency_symbol *mv;
2885*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_list *n;
2886*cc4ad7daSAndroid Build Coastguard Worker 
2887*cc4ad7daSAndroid Build Coastguard Worker 		mv = kmod_module_dependency_symbols_new(symbols[i].crc,
2888*cc4ad7daSAndroid Build Coastguard Worker 							symbols[i].bind,
2889*cc4ad7daSAndroid Build Coastguard Worker 							symbols[i].symbol);
2890*cc4ad7daSAndroid Build Coastguard Worker 		if (mv == NULL) {
2891*cc4ad7daSAndroid Build Coastguard Worker 			ret = -errno;
2892*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_dependency_symbols_free_list(*list);
2893*cc4ad7daSAndroid Build Coastguard Worker 			*list = NULL;
2894*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2895*cc4ad7daSAndroid Build Coastguard Worker 		}
2896*cc4ad7daSAndroid Build Coastguard Worker 
2897*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_list_append(*list, mv);
2898*cc4ad7daSAndroid Build Coastguard Worker 		if (n != NULL)
2899*cc4ad7daSAndroid Build Coastguard Worker 			*list = n;
2900*cc4ad7daSAndroid Build Coastguard Worker 		else {
2901*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_dependency_symbol_free(mv);
2902*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_dependency_symbols_free_list(*list);
2903*cc4ad7daSAndroid Build Coastguard Worker 			*list = NULL;
2904*cc4ad7daSAndroid Build Coastguard Worker 			ret = -ENOMEM;
2905*cc4ad7daSAndroid Build Coastguard Worker 			goto list_error;
2906*cc4ad7daSAndroid Build Coastguard Worker 		}
2907*cc4ad7daSAndroid Build Coastguard Worker 	}
2908*cc4ad7daSAndroid Build Coastguard Worker 	ret = count;
2909*cc4ad7daSAndroid Build Coastguard Worker 
2910*cc4ad7daSAndroid Build Coastguard Worker list_error:
2911*cc4ad7daSAndroid Build Coastguard Worker 	free(symbols);
2912*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
2913*cc4ad7daSAndroid Build Coastguard Worker }
2914*cc4ad7daSAndroid Build Coastguard Worker 
2915*cc4ad7daSAndroid Build Coastguard Worker /**
2916*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_dependency_symbol_get_symbol:
2917*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module dependency_symbols
2918*cc4ad7daSAndroid Build Coastguard Worker  *
2919*cc4ad7daSAndroid Build Coastguard Worker  * Get the dependency symbol of a kmod module
2920*cc4ad7daSAndroid Build Coastguard Worker  *
2921*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the symbol of this kmod module dependency_symbols on success or NULL
2922*cc4ad7daSAndroid Build Coastguard Worker  * on failure. The string is owned by the dependency_symbols, do not free it.
2923*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_dependency_symbol_get_symbol(const struct kmod_list * entry)2924*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_module_dependency_symbol_get_symbol(const struct kmod_list *entry)
2925*cc4ad7daSAndroid Build Coastguard Worker {
2926*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_dependency_symbol *dependency_symbol;
2927*cc4ad7daSAndroid Build Coastguard Worker 
2928*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2929*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
2930*cc4ad7daSAndroid Build Coastguard Worker 
2931*cc4ad7daSAndroid Build Coastguard Worker 	dependency_symbol = entry->data;
2932*cc4ad7daSAndroid Build Coastguard Worker 	return dependency_symbol->symbol;
2933*cc4ad7daSAndroid Build Coastguard Worker }
2934*cc4ad7daSAndroid Build Coastguard Worker 
2935*cc4ad7daSAndroid Build Coastguard Worker /**
2936*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_dependency_symbol_get_crc:
2937*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module dependency_symbol
2938*cc4ad7daSAndroid Build Coastguard Worker  *
2939*cc4ad7daSAndroid Build Coastguard Worker  * Get the crc of a kmod module dependency_symbol.
2940*cc4ad7daSAndroid Build Coastguard Worker  *
2941*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the crc of this kmod module dependency_symbol if available, otherwise default to 0.
2942*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_dependency_symbol_get_crc(const struct kmod_list * entry)2943*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT uint64_t kmod_module_dependency_symbol_get_crc(const struct kmod_list *entry)
2944*cc4ad7daSAndroid Build Coastguard Worker {
2945*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_dependency_symbol *dependency_symbol;
2946*cc4ad7daSAndroid Build Coastguard Worker 
2947*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2948*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
2949*cc4ad7daSAndroid Build Coastguard Worker 
2950*cc4ad7daSAndroid Build Coastguard Worker 	dependency_symbol = entry->data;
2951*cc4ad7daSAndroid Build Coastguard Worker 	return dependency_symbol->crc;
2952*cc4ad7daSAndroid Build Coastguard Worker }
2953*cc4ad7daSAndroid Build Coastguard Worker 
2954*cc4ad7daSAndroid Build Coastguard Worker /**
2955*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_dependency_symbol_get_bind:
2956*cc4ad7daSAndroid Build Coastguard Worker  * @entry: a list entry representing a kmod module dependency_symbol
2957*cc4ad7daSAndroid Build Coastguard Worker  *
2958*cc4ad7daSAndroid Build Coastguard Worker  * Get the bind type of a kmod module dependency_symbol.
2959*cc4ad7daSAndroid Build Coastguard Worker  *
2960*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the bind of this kmod module dependency_symbol on success
2961*cc4ad7daSAndroid Build Coastguard Worker  * or < 0 on failure.
2962*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_dependency_symbol_get_bind(const struct kmod_list * entry)2963*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_module_dependency_symbol_get_bind(const struct kmod_list *entry)
2964*cc4ad7daSAndroid Build Coastguard Worker {
2965*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module_dependency_symbol *dependency_symbol;
2966*cc4ad7daSAndroid Build Coastguard Worker 
2967*cc4ad7daSAndroid Build Coastguard Worker 	if (entry == NULL || entry->data == NULL)
2968*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
2969*cc4ad7daSAndroid Build Coastguard Worker 
2970*cc4ad7daSAndroid Build Coastguard Worker 	dependency_symbol = entry->data;
2971*cc4ad7daSAndroid Build Coastguard Worker 	return dependency_symbol->bind;
2972*cc4ad7daSAndroid Build Coastguard Worker }
2973*cc4ad7daSAndroid Build Coastguard Worker 
2974*cc4ad7daSAndroid Build Coastguard Worker /**
2975*cc4ad7daSAndroid Build Coastguard Worker  * kmod_module_dependency_symbols_free_list:
2976*cc4ad7daSAndroid Build Coastguard Worker  * @list: kmod module dependency_symbols list
2977*cc4ad7daSAndroid Build Coastguard Worker  *
2978*cc4ad7daSAndroid Build Coastguard Worker  * Release the resources taken by @list
2979*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_module_dependency_symbols_free_list(struct kmod_list * list)2980*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_module_dependency_symbols_free_list(struct kmod_list *list)
2981*cc4ad7daSAndroid Build Coastguard Worker {
2982*cc4ad7daSAndroid Build Coastguard Worker 	while (list) {
2983*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_dependency_symbol_free(list->data);
2984*cc4ad7daSAndroid Build Coastguard Worker 		list = kmod_list_remove(list);
2985*cc4ad7daSAndroid Build Coastguard Worker 	}
2986*cc4ad7daSAndroid Build Coastguard Worker }
2987