xref: /aosp_15_r20/external/kmod/libkmod/libkmod.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 <errno.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <fnmatch.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <limits.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stdarg.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <stddef.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
28*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
29*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
30*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
31*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
32*cc4ad7daSAndroid Build Coastguard Worker #include <sys/utsname.h>
33*cc4ad7daSAndroid Build Coastguard Worker 
34*cc4ad7daSAndroid Build Coastguard Worker #include <shared/hash.h>
35*cc4ad7daSAndroid Build Coastguard Worker #include <shared/util.h>
36*cc4ad7daSAndroid Build Coastguard Worker 
37*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod.h"
38*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod-internal.h"
39*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod-index.h"
40*cc4ad7daSAndroid Build Coastguard Worker 
41*cc4ad7daSAndroid Build Coastguard Worker #define KMOD_HASH_SIZE (256)
42*cc4ad7daSAndroid Build Coastguard Worker #define KMOD_LRU_MAX (128)
43*cc4ad7daSAndroid Build Coastguard Worker #define _KMOD_INDEX_MODULES_SIZE KMOD_INDEX_MODULES_BUILTIN + 1
44*cc4ad7daSAndroid Build Coastguard Worker 
45*cc4ad7daSAndroid Build Coastguard Worker /**
46*cc4ad7daSAndroid Build Coastguard Worker  * SECTION:libkmod
47*cc4ad7daSAndroid Build Coastguard Worker  * @short_description: libkmod context
48*cc4ad7daSAndroid Build Coastguard Worker  *
49*cc4ad7daSAndroid Build Coastguard Worker  * The context contains the default values for the library user,
50*cc4ad7daSAndroid Build Coastguard Worker  * and is passed to all library operations.
51*cc4ad7daSAndroid Build Coastguard Worker  */
52*cc4ad7daSAndroid Build Coastguard Worker 
53*cc4ad7daSAndroid Build Coastguard Worker static const struct {
54*cc4ad7daSAndroid Build Coastguard Worker 	const char *fn;
55*cc4ad7daSAndroid Build Coastguard Worker 	const char *prefix;
56*cc4ad7daSAndroid Build Coastguard Worker } index_files[] = {
57*cc4ad7daSAndroid Build Coastguard Worker 	[KMOD_INDEX_MODULES_DEP] = { .fn = "modules.dep", .prefix = "" },
58*cc4ad7daSAndroid Build Coastguard Worker 	[KMOD_INDEX_MODULES_ALIAS] = { .fn = "modules.alias", .prefix = "alias " },
59*cc4ad7daSAndroid Build Coastguard Worker 	[KMOD_INDEX_MODULES_SYMBOL] = { .fn = "modules.symbols", .prefix = "alias "},
60*cc4ad7daSAndroid Build Coastguard Worker 	[KMOD_INDEX_MODULES_BUILTIN_ALIAS] = { .fn = "modules.builtin.alias", .prefix = "" },
61*cc4ad7daSAndroid Build Coastguard Worker 	[KMOD_INDEX_MODULES_BUILTIN] = { .fn = "modules.builtin", .prefix = ""},
62*cc4ad7daSAndroid Build Coastguard Worker };
63*cc4ad7daSAndroid Build Coastguard Worker 
64*cc4ad7daSAndroid Build Coastguard Worker static const char *const default_config_paths[] = {
65*cc4ad7daSAndroid Build Coastguard Worker 	SYSCONFDIR "/modprobe.d",
66*cc4ad7daSAndroid Build Coastguard Worker 	"/run/modprobe.d",
67*cc4ad7daSAndroid Build Coastguard Worker 	"/usr/local/lib/modprobe.d",
68*cc4ad7daSAndroid Build Coastguard Worker 	DISTCONFDIR "/modprobe.d",
69*cc4ad7daSAndroid Build Coastguard Worker 	"/lib/modprobe.d",
70*cc4ad7daSAndroid Build Coastguard Worker 	NULL
71*cc4ad7daSAndroid Build Coastguard Worker };
72*cc4ad7daSAndroid Build Coastguard Worker 
73*cc4ad7daSAndroid Build Coastguard Worker /**
74*cc4ad7daSAndroid Build Coastguard Worker  * kmod_ctx:
75*cc4ad7daSAndroid Build Coastguard Worker  *
76*cc4ad7daSAndroid Build Coastguard Worker  * Opaque object representing the library context.
77*cc4ad7daSAndroid Build Coastguard Worker  */
78*cc4ad7daSAndroid Build Coastguard Worker struct kmod_ctx {
79*cc4ad7daSAndroid Build Coastguard Worker 	int refcount;
80*cc4ad7daSAndroid Build Coastguard Worker 	int log_priority;
81*cc4ad7daSAndroid Build Coastguard Worker 	void (*log_fn)(void *data,
82*cc4ad7daSAndroid Build Coastguard Worker 			int priority, const char *file, int line,
83*cc4ad7daSAndroid Build Coastguard Worker 			const char *fn, const char *format, va_list args);
84*cc4ad7daSAndroid Build Coastguard Worker 	void *log_data;
85*cc4ad7daSAndroid Build Coastguard Worker 	const void *userdata;
86*cc4ad7daSAndroid Build Coastguard Worker 	char *dirname;
87*cc4ad7daSAndroid Build Coastguard Worker 	enum kmod_file_compression_type kernel_compression;
88*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_config *config;
89*cc4ad7daSAndroid Build Coastguard Worker 	struct hash *modules_by_name;
90*cc4ad7daSAndroid Build Coastguard Worker 	struct index_mm *indexes[_KMOD_INDEX_MODULES_SIZE];
91*cc4ad7daSAndroid Build Coastguard Worker 	unsigned long long indexes_stamp[_KMOD_INDEX_MODULES_SIZE];
92*cc4ad7daSAndroid Build Coastguard Worker };
93*cc4ad7daSAndroid Build Coastguard Worker 
kmod_log(const struct kmod_ctx * ctx,int priority,const char * file,int line,const char * fn,const char * format,...)94*cc4ad7daSAndroid Build Coastguard Worker void kmod_log(const struct kmod_ctx *ctx,
95*cc4ad7daSAndroid Build Coastguard Worker 		int priority, const char *file, int line, const char *fn,
96*cc4ad7daSAndroid Build Coastguard Worker 		const char *format, ...)
97*cc4ad7daSAndroid Build Coastguard Worker {
98*cc4ad7daSAndroid Build Coastguard Worker 	va_list args;
99*cc4ad7daSAndroid Build Coastguard Worker 
100*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->log_fn == NULL)
101*cc4ad7daSAndroid Build Coastguard Worker 		return;
102*cc4ad7daSAndroid Build Coastguard Worker 
103*cc4ad7daSAndroid Build Coastguard Worker 	va_start(args, format);
104*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_fn(ctx->log_data, priority, file, line, fn, format, args);
105*cc4ad7daSAndroid Build Coastguard Worker 	va_end(args);
106*cc4ad7daSAndroid Build Coastguard Worker }
107*cc4ad7daSAndroid Build Coastguard Worker 
108*cc4ad7daSAndroid Build Coastguard Worker _printf_format_(6, 0)
log_filep(void * data,int priority,const char * file,int line,const char * fn,const char * format,va_list args)109*cc4ad7daSAndroid Build Coastguard Worker static void log_filep(void *data,
110*cc4ad7daSAndroid Build Coastguard Worker 			int priority, const char *file, int line,
111*cc4ad7daSAndroid Build Coastguard Worker 			const char *fn, const char *format, va_list args)
112*cc4ad7daSAndroid Build Coastguard Worker {
113*cc4ad7daSAndroid Build Coastguard Worker 	FILE *fp = data;
114*cc4ad7daSAndroid Build Coastguard Worker #ifdef ENABLE_DEBUG
115*cc4ad7daSAndroid Build Coastguard Worker 	char buf[16];
116*cc4ad7daSAndroid Build Coastguard Worker 	const char *priname;
117*cc4ad7daSAndroid Build Coastguard Worker 	switch (priority) {
118*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_EMERG:
119*cc4ad7daSAndroid Build Coastguard Worker 		priname = "EMERGENCY";
120*cc4ad7daSAndroid Build Coastguard Worker 		break;
121*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_ALERT:
122*cc4ad7daSAndroid Build Coastguard Worker 		priname = "ALERT";
123*cc4ad7daSAndroid Build Coastguard Worker 		break;
124*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_CRIT:
125*cc4ad7daSAndroid Build Coastguard Worker 		priname = "CRITICAL";
126*cc4ad7daSAndroid Build Coastguard Worker 		break;
127*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_ERR:
128*cc4ad7daSAndroid Build Coastguard Worker 		priname = "ERROR";
129*cc4ad7daSAndroid Build Coastguard Worker 		break;
130*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_WARNING:
131*cc4ad7daSAndroid Build Coastguard Worker 		priname = "WARNING";
132*cc4ad7daSAndroid Build Coastguard Worker 		break;
133*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_NOTICE:
134*cc4ad7daSAndroid Build Coastguard Worker 		priname = "NOTICE";
135*cc4ad7daSAndroid Build Coastguard Worker 		break;
136*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_INFO:
137*cc4ad7daSAndroid Build Coastguard Worker 		priname = "INFO";
138*cc4ad7daSAndroid Build Coastguard Worker 		break;
139*cc4ad7daSAndroid Build Coastguard Worker 	case LOG_DEBUG:
140*cc4ad7daSAndroid Build Coastguard Worker 		priname = "DEBUG";
141*cc4ad7daSAndroid Build Coastguard Worker 		break;
142*cc4ad7daSAndroid Build Coastguard Worker 	default:
143*cc4ad7daSAndroid Build Coastguard Worker 		snprintf(buf, sizeof(buf), "L:%d", priority);
144*cc4ad7daSAndroid Build Coastguard Worker 		priname = buf;
145*cc4ad7daSAndroid Build Coastguard Worker 	}
146*cc4ad7daSAndroid Build Coastguard Worker 	fprintf(fp, "libkmod: %s %s:%d %s: ", priname, file, line, fn);
147*cc4ad7daSAndroid Build Coastguard Worker #else
148*cc4ad7daSAndroid Build Coastguard Worker 	fprintf(fp, "libkmod: %s: ", fn);
149*cc4ad7daSAndroid Build Coastguard Worker #endif
150*cc4ad7daSAndroid Build Coastguard Worker 	vfprintf(fp, format, args);
151*cc4ad7daSAndroid Build Coastguard Worker }
152*cc4ad7daSAndroid Build Coastguard Worker 
153*cc4ad7daSAndroid Build Coastguard Worker 
154*cc4ad7daSAndroid Build Coastguard Worker /**
155*cc4ad7daSAndroid Build Coastguard Worker  * kmod_get_dirname:
156*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
157*cc4ad7daSAndroid Build Coastguard Worker  *
158*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve the absolute path used for linux modules in this context. The path
159*cc4ad7daSAndroid Build Coastguard Worker  * is computed from the arguments to kmod_new().
160*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_get_dirname(const struct kmod_ctx * ctx)161*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT const char *kmod_get_dirname(const struct kmod_ctx *ctx)
162*cc4ad7daSAndroid Build Coastguard Worker {
163*cc4ad7daSAndroid Build Coastguard Worker 	return ctx->dirname;
164*cc4ad7daSAndroid Build Coastguard Worker }
165*cc4ad7daSAndroid Build Coastguard Worker 
166*cc4ad7daSAndroid Build Coastguard Worker /**
167*cc4ad7daSAndroid Build Coastguard Worker  * kmod_get_userdata:
168*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
169*cc4ad7daSAndroid Build Coastguard Worker  *
170*cc4ad7daSAndroid Build Coastguard Worker  * Retrieve stored data pointer from library context. This might be useful
171*cc4ad7daSAndroid Build Coastguard Worker  * to access from callbacks.
172*cc4ad7daSAndroid Build Coastguard Worker  *
173*cc4ad7daSAndroid Build Coastguard Worker  * Returns: stored userdata
174*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_get_userdata(const struct kmod_ctx * ctx)175*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void *kmod_get_userdata(const struct kmod_ctx *ctx)
176*cc4ad7daSAndroid Build Coastguard Worker {
177*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
178*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
179*cc4ad7daSAndroid Build Coastguard Worker 	return (void *)ctx->userdata;
180*cc4ad7daSAndroid Build Coastguard Worker }
181*cc4ad7daSAndroid Build Coastguard Worker 
182*cc4ad7daSAndroid Build Coastguard Worker /**
183*cc4ad7daSAndroid Build Coastguard Worker  * kmod_set_userdata:
184*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
185*cc4ad7daSAndroid Build Coastguard Worker  * @userdata: data pointer
186*cc4ad7daSAndroid Build Coastguard Worker  *
187*cc4ad7daSAndroid Build Coastguard Worker  * Store custom @userdata in the library context.
188*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_set_userdata(struct kmod_ctx * ctx,const void * userdata)189*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_set_userdata(struct kmod_ctx *ctx, const void *userdata)
190*cc4ad7daSAndroid Build Coastguard Worker {
191*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
192*cc4ad7daSAndroid Build Coastguard Worker 		return;
193*cc4ad7daSAndroid Build Coastguard Worker 	ctx->userdata = userdata;
194*cc4ad7daSAndroid Build Coastguard Worker }
195*cc4ad7daSAndroid Build Coastguard Worker 
log_priority(const char * priority)196*cc4ad7daSAndroid Build Coastguard Worker static int log_priority(const char *priority)
197*cc4ad7daSAndroid Build Coastguard Worker {
198*cc4ad7daSAndroid Build Coastguard Worker 	char *endptr;
199*cc4ad7daSAndroid Build Coastguard Worker 	int prio;
200*cc4ad7daSAndroid Build Coastguard Worker 
201*cc4ad7daSAndroid Build Coastguard Worker 	prio = strtol(priority, &endptr, 10);
202*cc4ad7daSAndroid Build Coastguard Worker 	if (endptr[0] == '\0' || isspace(endptr[0]))
203*cc4ad7daSAndroid Build Coastguard Worker 		return prio;
204*cc4ad7daSAndroid Build Coastguard Worker 	if (strncmp(priority, "err", 3) == 0)
205*cc4ad7daSAndroid Build Coastguard Worker 		return LOG_ERR;
206*cc4ad7daSAndroid Build Coastguard Worker 	if (strncmp(priority, "info", 4) == 0)
207*cc4ad7daSAndroid Build Coastguard Worker 		return LOG_INFO;
208*cc4ad7daSAndroid Build Coastguard Worker 	if (strncmp(priority, "debug", 5) == 0)
209*cc4ad7daSAndroid Build Coastguard Worker 		return LOG_DEBUG;
210*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
211*cc4ad7daSAndroid Build Coastguard Worker }
212*cc4ad7daSAndroid Build Coastguard Worker 
213*cc4ad7daSAndroid Build Coastguard Worker static const char *dirname_default_prefix = MODULE_DIRECTORY;
214*cc4ad7daSAndroid Build Coastguard Worker 
get_kernel_release(const char * dirname)215*cc4ad7daSAndroid Build Coastguard Worker static char *get_kernel_release(const char *dirname)
216*cc4ad7daSAndroid Build Coastguard Worker {
217*cc4ad7daSAndroid Build Coastguard Worker 	struct utsname u;
218*cc4ad7daSAndroid Build Coastguard Worker 	char *p;
219*cc4ad7daSAndroid Build Coastguard Worker 
220*cc4ad7daSAndroid Build Coastguard Worker 	if (dirname != NULL)
221*cc4ad7daSAndroid Build Coastguard Worker 		return path_make_absolute_cwd(dirname);
222*cc4ad7daSAndroid Build Coastguard Worker 
223*cc4ad7daSAndroid Build Coastguard Worker 	if (uname(&u) < 0)
224*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
225*cc4ad7daSAndroid Build Coastguard Worker 
226*cc4ad7daSAndroid Build Coastguard Worker 	if (asprintf(&p, "%s/%s", dirname_default_prefix, u.release) < 0)
227*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
228*cc4ad7daSAndroid Build Coastguard Worker 
229*cc4ad7daSAndroid Build Coastguard Worker 	return p;
230*cc4ad7daSAndroid Build Coastguard Worker }
231*cc4ad7daSAndroid Build Coastguard Worker 
get_kernel_compression(struct kmod_ctx * ctx)232*cc4ad7daSAndroid Build Coastguard Worker static enum kmod_file_compression_type get_kernel_compression(struct kmod_ctx *ctx)
233*cc4ad7daSAndroid Build Coastguard Worker {
234*cc4ad7daSAndroid Build Coastguard Worker 	const char *path = "/sys/module/compression";
235*cc4ad7daSAndroid Build Coastguard Worker 	char buf[16];
236*cc4ad7daSAndroid Build Coastguard Worker 	int fd;
237*cc4ad7daSAndroid Build Coastguard Worker 	int err;
238*cc4ad7daSAndroid Build Coastguard Worker 
239*cc4ad7daSAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY|O_CLOEXEC);
240*cc4ad7daSAndroid Build Coastguard Worker 	if (fd < 0) {
241*cc4ad7daSAndroid Build Coastguard Worker 		/* Not having the file is not an error: kernel may be too old */
242*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "could not open '%s' for reading: %m\n", path);
243*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_FILE_COMPRESSION_NONE;
244*cc4ad7daSAndroid Build Coastguard Worker 	}
245*cc4ad7daSAndroid Build Coastguard Worker 
246*cc4ad7daSAndroid Build Coastguard Worker 	err = read_str_safe(fd, buf, sizeof(buf));
247*cc4ad7daSAndroid Build Coastguard Worker 	close(fd);
248*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
249*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "could not read from '%s': %s\n",
250*cc4ad7daSAndroid Build Coastguard Worker 		    path, strerror(-err));
251*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_FILE_COMPRESSION_NONE;
252*cc4ad7daSAndroid Build Coastguard Worker 	}
253*cc4ad7daSAndroid Build Coastguard Worker 
254*cc4ad7daSAndroid Build Coastguard Worker 	if (streq(buf, "zstd\n"))
255*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_FILE_COMPRESSION_ZSTD;
256*cc4ad7daSAndroid Build Coastguard Worker 	else if (streq(buf, "xz\n"))
257*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_FILE_COMPRESSION_XZ;
258*cc4ad7daSAndroid Build Coastguard Worker 	else if (streq(buf, "gzip\n"))
259*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_FILE_COMPRESSION_ZLIB;
260*cc4ad7daSAndroid Build Coastguard Worker 
261*cc4ad7daSAndroid Build Coastguard Worker 	ERR(ctx, "unknown kernel compression %s", buf);
262*cc4ad7daSAndroid Build Coastguard Worker 
263*cc4ad7daSAndroid Build Coastguard Worker 	return KMOD_FILE_COMPRESSION_NONE;
264*cc4ad7daSAndroid Build Coastguard Worker }
265*cc4ad7daSAndroid Build Coastguard Worker 
266*cc4ad7daSAndroid Build Coastguard Worker /**
267*cc4ad7daSAndroid Build Coastguard Worker  * kmod_new:
268*cc4ad7daSAndroid Build Coastguard Worker  * @dirname: what to consider as linux module's directory, if NULL
269*cc4ad7daSAndroid Build Coastguard Worker  *           defaults to $MODULE_DIRECTORY/`uname -r`. If it's relative,
270*cc4ad7daSAndroid Build Coastguard Worker  *           it's treated as relative to the current working directory.
271*cc4ad7daSAndroid Build Coastguard Worker  *           Otherwise, give an absolute dirname.
272*cc4ad7daSAndroid Build Coastguard Worker  * @config_paths: ordered array of paths (directories or files) where
273*cc4ad7daSAndroid Build Coastguard Worker  *                to load from user-defined configuration parameters such as
274*cc4ad7daSAndroid Build Coastguard Worker  *                alias, blacklists, commands (install, remove). If NULL
275*cc4ad7daSAndroid Build Coastguard Worker  *                defaults to /etc/modprobe.d, /run/modprobe.d,
276*cc4ad7daSAndroid Build Coastguard Worker  *                /usr/local/lib/modprobe.d, DISTCONFDIR/modprobe.d, and
277*cc4ad7daSAndroid Build Coastguard Worker  *                /lib/modprobe.d. Give an empty vector if configuration should
278*cc4ad7daSAndroid Build Coastguard Worker  *                not be read. This array must be null terminated.
279*cc4ad7daSAndroid Build Coastguard Worker  *
280*cc4ad7daSAndroid Build Coastguard Worker  * Create kmod library context. This reads the kmod configuration
281*cc4ad7daSAndroid Build Coastguard Worker  * and fills in the default values.
282*cc4ad7daSAndroid Build Coastguard Worker  *
283*cc4ad7daSAndroid Build Coastguard Worker  * The initial refcount is 1, and needs to be decremented to
284*cc4ad7daSAndroid Build Coastguard Worker  * release the resources of the kmod library context.
285*cc4ad7daSAndroid Build Coastguard Worker  *
286*cc4ad7daSAndroid Build Coastguard Worker  * Returns: a new kmod library context
287*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_new(const char * dirname,const char * const * config_paths)288*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname,
289*cc4ad7daSAndroid Build Coastguard Worker 					const char * const *config_paths)
290*cc4ad7daSAndroid Build Coastguard Worker {
291*cc4ad7daSAndroid Build Coastguard Worker 	const char *env;
292*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_ctx *ctx;
293*cc4ad7daSAndroid Build Coastguard Worker 	int err;
294*cc4ad7daSAndroid Build Coastguard Worker 
295*cc4ad7daSAndroid Build Coastguard Worker 	ctx = calloc(1, sizeof(struct kmod_ctx));
296*cc4ad7daSAndroid Build Coastguard Worker 	if (!ctx)
297*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
298*cc4ad7daSAndroid Build Coastguard Worker 
299*cc4ad7daSAndroid Build Coastguard Worker 	ctx->refcount = 1;
300*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_fn = log_filep;
301*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_data = stderr;
302*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_priority = LOG_ERR;
303*cc4ad7daSAndroid Build Coastguard Worker 
304*cc4ad7daSAndroid Build Coastguard Worker 	ctx->dirname = get_kernel_release(dirname);
305*cc4ad7daSAndroid Build Coastguard Worker 
306*cc4ad7daSAndroid Build Coastguard Worker 	/* environment overwrites config */
307*cc4ad7daSAndroid Build Coastguard Worker 	env = secure_getenv("KMOD_LOG");
308*cc4ad7daSAndroid Build Coastguard Worker 	if (env != NULL)
309*cc4ad7daSAndroid Build Coastguard Worker 		kmod_set_log_priority(ctx, log_priority(env));
310*cc4ad7daSAndroid Build Coastguard Worker 
311*cc4ad7daSAndroid Build Coastguard Worker 	ctx->kernel_compression = get_kernel_compression(ctx);
312*cc4ad7daSAndroid Build Coastguard Worker 
313*cc4ad7daSAndroid Build Coastguard Worker 	if (config_paths == NULL)
314*cc4ad7daSAndroid Build Coastguard Worker 		config_paths = default_config_paths;
315*cc4ad7daSAndroid Build Coastguard Worker 	err = kmod_config_new(ctx, &ctx->config, config_paths);
316*cc4ad7daSAndroid Build Coastguard Worker 	if (err < 0) {
317*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "could not create config\n");
318*cc4ad7daSAndroid Build Coastguard Worker 		goto fail;
319*cc4ad7daSAndroid Build Coastguard Worker 	}
320*cc4ad7daSAndroid Build Coastguard Worker 
321*cc4ad7daSAndroid Build Coastguard Worker 	ctx->modules_by_name = hash_new(KMOD_HASH_SIZE, NULL);
322*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->modules_by_name == NULL) {
323*cc4ad7daSAndroid Build Coastguard Worker 		ERR(ctx, "could not create by-name hash\n");
324*cc4ad7daSAndroid Build Coastguard Worker 		goto fail;
325*cc4ad7daSAndroid Build Coastguard Worker 	}
326*cc4ad7daSAndroid Build Coastguard Worker 
327*cc4ad7daSAndroid Build Coastguard Worker 	INFO(ctx, "ctx %p created\n", ctx);
328*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "log_priority=%d\n", ctx->log_priority);
329*cc4ad7daSAndroid Build Coastguard Worker 
330*cc4ad7daSAndroid Build Coastguard Worker 	return ctx;
331*cc4ad7daSAndroid Build Coastguard Worker 
332*cc4ad7daSAndroid Build Coastguard Worker fail:
333*cc4ad7daSAndroid Build Coastguard Worker 	free(ctx->modules_by_name);
334*cc4ad7daSAndroid Build Coastguard Worker 	free(ctx->dirname);
335*cc4ad7daSAndroid Build Coastguard Worker 	free(ctx);
336*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
337*cc4ad7daSAndroid Build Coastguard Worker }
338*cc4ad7daSAndroid Build Coastguard Worker 
339*cc4ad7daSAndroid Build Coastguard Worker /**
340*cc4ad7daSAndroid Build Coastguard Worker  * kmod_ref:
341*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
342*cc4ad7daSAndroid Build Coastguard Worker  *
343*cc4ad7daSAndroid Build Coastguard Worker  * Take a reference of the kmod library context.
344*cc4ad7daSAndroid Build Coastguard Worker  *
345*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the passed kmod library context
346*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_ref(struct kmod_ctx * ctx)347*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx)
348*cc4ad7daSAndroid Build Coastguard Worker {
349*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
350*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
351*cc4ad7daSAndroid Build Coastguard Worker 	ctx->refcount++;
352*cc4ad7daSAndroid Build Coastguard Worker 	return ctx;
353*cc4ad7daSAndroid Build Coastguard Worker }
354*cc4ad7daSAndroid Build Coastguard Worker 
355*cc4ad7daSAndroid Build Coastguard Worker /**
356*cc4ad7daSAndroid Build Coastguard Worker  * kmod_unref:
357*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
358*cc4ad7daSAndroid Build Coastguard Worker  *
359*cc4ad7daSAndroid Build Coastguard Worker  * Drop a reference of the kmod library context. If the refcount
360*cc4ad7daSAndroid Build Coastguard Worker  * reaches zero, the resources of the context will be released.
361*cc4ad7daSAndroid Build Coastguard Worker  *
362*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the passed kmod library context or NULL if it's freed
363*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_unref(struct kmod_ctx * ctx)364*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx)
365*cc4ad7daSAndroid Build Coastguard Worker {
366*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
367*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
368*cc4ad7daSAndroid Build Coastguard Worker 
369*cc4ad7daSAndroid Build Coastguard Worker 	if (--ctx->refcount > 0)
370*cc4ad7daSAndroid Build Coastguard Worker 		return ctx;
371*cc4ad7daSAndroid Build Coastguard Worker 
372*cc4ad7daSAndroid Build Coastguard Worker 	INFO(ctx, "context %p released\n", ctx);
373*cc4ad7daSAndroid Build Coastguard Worker 
374*cc4ad7daSAndroid Build Coastguard Worker 	kmod_unload_resources(ctx);
375*cc4ad7daSAndroid Build Coastguard Worker 	hash_free(ctx->modules_by_name);
376*cc4ad7daSAndroid Build Coastguard Worker 	free(ctx->dirname);
377*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->config)
378*cc4ad7daSAndroid Build Coastguard Worker 		kmod_config_free(ctx->config);
379*cc4ad7daSAndroid Build Coastguard Worker 
380*cc4ad7daSAndroid Build Coastguard Worker 	free(ctx);
381*cc4ad7daSAndroid Build Coastguard Worker 	return NULL;
382*cc4ad7daSAndroid Build Coastguard Worker }
383*cc4ad7daSAndroid Build Coastguard Worker 
384*cc4ad7daSAndroid Build Coastguard Worker /**
385*cc4ad7daSAndroid Build Coastguard Worker  * kmod_set_log_fn:
386*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
387*cc4ad7daSAndroid Build Coastguard Worker  * @log_fn: function to be called for logging messages
388*cc4ad7daSAndroid Build Coastguard Worker  * @data: data to pass to log function
389*cc4ad7daSAndroid Build Coastguard Worker  *
390*cc4ad7daSAndroid Build Coastguard Worker  * The built-in logging writes to stderr. It can be
391*cc4ad7daSAndroid Build Coastguard Worker  * overridden by a custom function, to plug log messages
392*cc4ad7daSAndroid Build Coastguard Worker  * into the user's logging functionality.
393*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_set_log_fn(struct kmod_ctx * ctx,void (* log_fn)(void * data,int priority,const char * file,int line,const char * fn,const char * format,va_list args),const void * data)394*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_set_log_fn(struct kmod_ctx *ctx,
395*cc4ad7daSAndroid Build Coastguard Worker 					void (*log_fn)(void *data,
396*cc4ad7daSAndroid Build Coastguard Worker 						int priority, const char *file,
397*cc4ad7daSAndroid Build Coastguard Worker 						int line, const char *fn,
398*cc4ad7daSAndroid Build Coastguard Worker 						const char *format, va_list args),
399*cc4ad7daSAndroid Build Coastguard Worker 					const void *data)
400*cc4ad7daSAndroid Build Coastguard Worker {
401*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
402*cc4ad7daSAndroid Build Coastguard Worker 		return;
403*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_fn = log_fn;
404*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_data = (void *)data;
405*cc4ad7daSAndroid Build Coastguard Worker 	INFO(ctx, "custom logging function %p registered\n", log_fn);
406*cc4ad7daSAndroid Build Coastguard Worker }
407*cc4ad7daSAndroid Build Coastguard Worker 
408*cc4ad7daSAndroid Build Coastguard Worker /**
409*cc4ad7daSAndroid Build Coastguard Worker  * kmod_get_log_priority:
410*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
411*cc4ad7daSAndroid Build Coastguard Worker  *
412*cc4ad7daSAndroid Build Coastguard Worker  * Returns: the current logging priority
413*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_get_log_priority(const struct kmod_ctx * ctx)414*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_get_log_priority(const struct kmod_ctx *ctx)
415*cc4ad7daSAndroid Build Coastguard Worker {
416*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
417*cc4ad7daSAndroid Build Coastguard Worker 		return -1;
418*cc4ad7daSAndroid Build Coastguard Worker 	return ctx->log_priority;
419*cc4ad7daSAndroid Build Coastguard Worker }
420*cc4ad7daSAndroid Build Coastguard Worker 
421*cc4ad7daSAndroid Build Coastguard Worker /**
422*cc4ad7daSAndroid Build Coastguard Worker  * kmod_set_log_priority:
423*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
424*cc4ad7daSAndroid Build Coastguard Worker  * @priority: the new logging priority
425*cc4ad7daSAndroid Build Coastguard Worker  *
426*cc4ad7daSAndroid Build Coastguard Worker  * Set the current logging priority. The value controls which messages
427*cc4ad7daSAndroid Build Coastguard Worker  * are logged.
428*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_set_log_priority(struct kmod_ctx * ctx,int priority)429*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority)
430*cc4ad7daSAndroid Build Coastguard Worker {
431*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
432*cc4ad7daSAndroid Build Coastguard Worker 		return;
433*cc4ad7daSAndroid Build Coastguard Worker 	ctx->log_priority = priority;
434*cc4ad7daSAndroid Build Coastguard Worker }
435*cc4ad7daSAndroid Build Coastguard Worker 
kmod_pool_get_module(struct kmod_ctx * ctx,const char * key)436*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *kmod_pool_get_module(struct kmod_ctx *ctx,
437*cc4ad7daSAndroid Build Coastguard Worker 							const char *key)
438*cc4ad7daSAndroid Build Coastguard Worker {
439*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_module *mod;
440*cc4ad7daSAndroid Build Coastguard Worker 
441*cc4ad7daSAndroid Build Coastguard Worker 	mod = hash_find(ctx->modules_by_name, key);
442*cc4ad7daSAndroid Build Coastguard Worker 
443*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "get module name='%s' found=%p\n", key, mod);
444*cc4ad7daSAndroid Build Coastguard Worker 
445*cc4ad7daSAndroid Build Coastguard Worker 	return mod;
446*cc4ad7daSAndroid Build Coastguard Worker }
447*cc4ad7daSAndroid Build Coastguard Worker 
kmod_pool_add_module(struct kmod_ctx * ctx,struct kmod_module * mod,const char * key)448*cc4ad7daSAndroid Build Coastguard Worker void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod,
449*cc4ad7daSAndroid Build Coastguard Worker 							const char *key)
450*cc4ad7daSAndroid Build Coastguard Worker {
451*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "add %p key='%s'\n", mod, key);
452*cc4ad7daSAndroid Build Coastguard Worker 
453*cc4ad7daSAndroid Build Coastguard Worker 	hash_add(ctx->modules_by_name, key, mod);
454*cc4ad7daSAndroid Build Coastguard Worker }
455*cc4ad7daSAndroid Build Coastguard Worker 
kmod_pool_del_module(struct kmod_ctx * ctx,struct kmod_module * mod,const char * key)456*cc4ad7daSAndroid Build Coastguard Worker void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod,
457*cc4ad7daSAndroid Build Coastguard Worker 							const char *key)
458*cc4ad7daSAndroid Build Coastguard Worker {
459*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "del %p key='%s'\n", mod, key);
460*cc4ad7daSAndroid Build Coastguard Worker 
461*cc4ad7daSAndroid Build Coastguard Worker 	hash_del(ctx->modules_by_name, key);
462*cc4ad7daSAndroid Build Coastguard Worker }
463*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_alias_bin(struct kmod_ctx * ctx,enum kmod_index index_number,const char * name,struct kmod_list ** list)464*cc4ad7daSAndroid Build Coastguard Worker static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx,
465*cc4ad7daSAndroid Build Coastguard Worker 						enum kmod_index index_number,
466*cc4ad7daSAndroid Build Coastguard Worker 						const char *name,
467*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
468*cc4ad7daSAndroid Build Coastguard Worker {
469*cc4ad7daSAndroid Build Coastguard Worker 	int err, nmatch = 0;
470*cc4ad7daSAndroid Build Coastguard Worker 	struct index_file *idx;
471*cc4ad7daSAndroid Build Coastguard Worker 	struct index_value *realnames, *realname;
472*cc4ad7daSAndroid Build Coastguard Worker 
473*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->indexes[index_number] != NULL) {
474*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "use mmaped index '%s' for name=%s\n",
475*cc4ad7daSAndroid Build Coastguard Worker 			index_files[index_number].fn, name);
476*cc4ad7daSAndroid Build Coastguard Worker 		realnames = index_mm_searchwild(ctx->indexes[index_number],
477*cc4ad7daSAndroid Build Coastguard Worker 									name);
478*cc4ad7daSAndroid Build Coastguard Worker 	} else {
479*cc4ad7daSAndroid Build Coastguard Worker 		char fn[PATH_MAX];
480*cc4ad7daSAndroid Build Coastguard Worker 
481*cc4ad7daSAndroid Build Coastguard Worker 		snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname,
482*cc4ad7daSAndroid Build Coastguard Worker 					index_files[index_number].fn);
483*cc4ad7daSAndroid Build Coastguard Worker 
484*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "file=%s name=%s\n", fn, name);
485*cc4ad7daSAndroid Build Coastguard Worker 
486*cc4ad7daSAndroid Build Coastguard Worker 		idx = index_file_open(fn);
487*cc4ad7daSAndroid Build Coastguard Worker 		if (idx == NULL)
488*cc4ad7daSAndroid Build Coastguard Worker 			return -ENOSYS;
489*cc4ad7daSAndroid Build Coastguard Worker 
490*cc4ad7daSAndroid Build Coastguard Worker 		realnames = index_searchwild(idx, name);
491*cc4ad7daSAndroid Build Coastguard Worker 		index_file_close(idx);
492*cc4ad7daSAndroid Build Coastguard Worker 	}
493*cc4ad7daSAndroid Build Coastguard Worker 
494*cc4ad7daSAndroid Build Coastguard Worker 	for (realname = realnames; realname; realname = realname->next) {
495*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *mod;
496*cc4ad7daSAndroid Build Coastguard Worker 
497*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new_from_alias(ctx, name, realname->value, &mod);
498*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
499*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "Could not create module for alias=%s realname=%s: %s\n",
500*cc4ad7daSAndroid Build Coastguard Worker 			    name, realname->value, strerror(-err));
501*cc4ad7daSAndroid Build Coastguard Worker 			goto fail;
502*cc4ad7daSAndroid Build Coastguard Worker 		}
503*cc4ad7daSAndroid Build Coastguard Worker 
504*cc4ad7daSAndroid Build Coastguard Worker 		*list = kmod_list_append(*list, mod);
505*cc4ad7daSAndroid Build Coastguard Worker 		nmatch++;
506*cc4ad7daSAndroid Build Coastguard Worker 	}
507*cc4ad7daSAndroid Build Coastguard Worker 
508*cc4ad7daSAndroid Build Coastguard Worker 	index_values_free(realnames);
509*cc4ad7daSAndroid Build Coastguard Worker 	return nmatch;
510*cc4ad7daSAndroid Build Coastguard Worker 
511*cc4ad7daSAndroid Build Coastguard Worker fail:
512*cc4ad7daSAndroid Build Coastguard Worker 	*list = kmod_list_remove_n_latest(*list, nmatch);
513*cc4ad7daSAndroid Build Coastguard Worker 	index_values_free(realnames);
514*cc4ad7daSAndroid Build Coastguard Worker 	return err;
515*cc4ad7daSAndroid Build Coastguard Worker 
516*cc4ad7daSAndroid Build Coastguard Worker }
517*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_symbols_file(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)518*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name,
519*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
520*cc4ad7daSAndroid Build Coastguard Worker {
521*cc4ad7daSAndroid Build Coastguard Worker 	if (!strstartswith(name, "symbol:"))
522*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
523*cc4ad7daSAndroid Build Coastguard Worker 
524*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_lookup_alias_from_alias_bin(ctx, KMOD_INDEX_MODULES_SYMBOL,
525*cc4ad7daSAndroid Build Coastguard Worker 								name, list);
526*cc4ad7daSAndroid Build Coastguard Worker }
527*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_aliases_file(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)528*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name,
529*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
530*cc4ad7daSAndroid Build Coastguard Worker {
531*cc4ad7daSAndroid Build Coastguard Worker 	return kmod_lookup_alias_from_alias_bin(ctx, KMOD_INDEX_MODULES_ALIAS,
532*cc4ad7daSAndroid Build Coastguard Worker 								name, list);
533*cc4ad7daSAndroid Build Coastguard Worker }
534*cc4ad7daSAndroid Build Coastguard Worker 
lookup_builtin_file(struct kmod_ctx * ctx,const char * name)535*cc4ad7daSAndroid Build Coastguard Worker static char *lookup_builtin_file(struct kmod_ctx *ctx, const char *name)
536*cc4ad7daSAndroid Build Coastguard Worker {
537*cc4ad7daSAndroid Build Coastguard Worker 	char *line;
538*cc4ad7daSAndroid Build Coastguard Worker 
539*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->indexes[KMOD_INDEX_MODULES_BUILTIN]) {
540*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "use mmaped index '%s' modname=%s\n",
541*cc4ad7daSAndroid Build Coastguard Worker 				index_files[KMOD_INDEX_MODULES_BUILTIN].fn,
542*cc4ad7daSAndroid Build Coastguard Worker 				name);
543*cc4ad7daSAndroid Build Coastguard Worker 		line = index_mm_search(ctx->indexes[KMOD_INDEX_MODULES_BUILTIN],
544*cc4ad7daSAndroid Build Coastguard Worker 									name);
545*cc4ad7daSAndroid Build Coastguard Worker 	} else {
546*cc4ad7daSAndroid Build Coastguard Worker 		struct index_file *idx;
547*cc4ad7daSAndroid Build Coastguard Worker 		char fn[PATH_MAX];
548*cc4ad7daSAndroid Build Coastguard Worker 
549*cc4ad7daSAndroid Build Coastguard Worker 		snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname,
550*cc4ad7daSAndroid Build Coastguard Worker 				index_files[KMOD_INDEX_MODULES_BUILTIN].fn);
551*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "file=%s modname=%s\n", fn, name);
552*cc4ad7daSAndroid Build Coastguard Worker 
553*cc4ad7daSAndroid Build Coastguard Worker 		idx = index_file_open(fn);
554*cc4ad7daSAndroid Build Coastguard Worker 		if (idx == NULL) {
555*cc4ad7daSAndroid Build Coastguard Worker 			DBG(ctx, "could not open builtin file '%s'\n", fn);
556*cc4ad7daSAndroid Build Coastguard Worker 			return NULL;
557*cc4ad7daSAndroid Build Coastguard Worker 		}
558*cc4ad7daSAndroid Build Coastguard Worker 
559*cc4ad7daSAndroid Build Coastguard Worker 		line = index_search(idx, name);
560*cc4ad7daSAndroid Build Coastguard Worker 		index_file_close(idx);
561*cc4ad7daSAndroid Build Coastguard Worker 	}
562*cc4ad7daSAndroid Build Coastguard Worker 
563*cc4ad7daSAndroid Build Coastguard Worker 	return line;
564*cc4ad7daSAndroid Build Coastguard Worker }
565*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_kernel_builtin_file(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)566*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_kernel_builtin_file(struct kmod_ctx *ctx,
567*cc4ad7daSAndroid Build Coastguard Worker 						const char *name,
568*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
569*cc4ad7daSAndroid Build Coastguard Worker {
570*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l;
571*cc4ad7daSAndroid Build Coastguard Worker 	int ret;
572*cc4ad7daSAndroid Build Coastguard Worker 
573*cc4ad7daSAndroid Build Coastguard Worker 	assert(*list == NULL);
574*cc4ad7daSAndroid Build Coastguard Worker 
575*cc4ad7daSAndroid Build Coastguard Worker 	ret = kmod_lookup_alias_from_alias_bin(ctx,
576*cc4ad7daSAndroid Build Coastguard Worker 					       KMOD_INDEX_MODULES_BUILTIN_ALIAS,
577*cc4ad7daSAndroid Build Coastguard Worker 					       name, list);
578*cc4ad7daSAndroid Build Coastguard Worker 
579*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, *list) {
580*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *mod = l->data;
581*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_set_builtin(mod, true);
582*cc4ad7daSAndroid Build Coastguard Worker 	}
583*cc4ad7daSAndroid Build Coastguard Worker 
584*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
585*cc4ad7daSAndroid Build Coastguard Worker }
586*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_builtin_file(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)587*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_builtin_file(struct kmod_ctx *ctx, const char *name,
588*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
589*cc4ad7daSAndroid Build Coastguard Worker {
590*cc4ad7daSAndroid Build Coastguard Worker 	char *line;
591*cc4ad7daSAndroid Build Coastguard Worker 	int err = 0;
592*cc4ad7daSAndroid Build Coastguard Worker 
593*cc4ad7daSAndroid Build Coastguard Worker 	assert(*list == NULL);
594*cc4ad7daSAndroid Build Coastguard Worker 
595*cc4ad7daSAndroid Build Coastguard Worker 	line = lookup_builtin_file(ctx, name);
596*cc4ad7daSAndroid Build Coastguard Worker 	if (line != NULL) {
597*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *mod;
598*cc4ad7daSAndroid Build Coastguard Worker 
599*cc4ad7daSAndroid Build Coastguard Worker 		err = kmod_module_new_from_name(ctx, name, &mod);
600*cc4ad7daSAndroid Build Coastguard Worker 		if (err < 0) {
601*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "Could not create module from name %s: %s\n",
602*cc4ad7daSAndroid Build Coastguard Worker 							name, strerror(-err));
603*cc4ad7daSAndroid Build Coastguard Worker 			goto finish;
604*cc4ad7daSAndroid Build Coastguard Worker 		}
605*cc4ad7daSAndroid Build Coastguard Worker 
606*cc4ad7daSAndroid Build Coastguard Worker 		/* already mark it as builtin since it's being created from
607*cc4ad7daSAndroid Build Coastguard Worker 		 * this index */
608*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_set_builtin(mod, true);
609*cc4ad7daSAndroid Build Coastguard Worker 		*list = kmod_list_append(*list, mod);
610*cc4ad7daSAndroid Build Coastguard Worker 		if (*list == NULL)
611*cc4ad7daSAndroid Build Coastguard Worker 			err = -ENOMEM;
612*cc4ad7daSAndroid Build Coastguard Worker 	}
613*cc4ad7daSAndroid Build Coastguard Worker 
614*cc4ad7daSAndroid Build Coastguard Worker finish:
615*cc4ad7daSAndroid Build Coastguard Worker 	free(line);
616*cc4ad7daSAndroid Build Coastguard Worker 	return err;
617*cc4ad7daSAndroid Build Coastguard Worker }
618*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_is_builtin(struct kmod_ctx * ctx,const char * name)619*cc4ad7daSAndroid Build Coastguard Worker bool kmod_lookup_alias_is_builtin(struct kmod_ctx *ctx, const char *name)
620*cc4ad7daSAndroid Build Coastguard Worker {
621*cc4ad7daSAndroid Build Coastguard Worker 	_cleanup_free_ char *line;
622*cc4ad7daSAndroid Build Coastguard Worker 
623*cc4ad7daSAndroid Build Coastguard Worker 	line = lookup_builtin_file(ctx, name);
624*cc4ad7daSAndroid Build Coastguard Worker 
625*cc4ad7daSAndroid Build Coastguard Worker 	return line != NULL;
626*cc4ad7daSAndroid Build Coastguard Worker }
627*cc4ad7daSAndroid Build Coastguard Worker 
kmod_search_moddep(struct kmod_ctx * ctx,const char * name)628*cc4ad7daSAndroid Build Coastguard Worker char *kmod_search_moddep(struct kmod_ctx *ctx, const char *name)
629*cc4ad7daSAndroid Build Coastguard Worker {
630*cc4ad7daSAndroid Build Coastguard Worker 	struct index_file *idx;
631*cc4ad7daSAndroid Build Coastguard Worker 	char fn[PATH_MAX];
632*cc4ad7daSAndroid Build Coastguard Worker 	char *line;
633*cc4ad7daSAndroid Build Coastguard Worker 
634*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->indexes[KMOD_INDEX_MODULES_DEP]) {
635*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "use mmaped index '%s' modname=%s\n",
636*cc4ad7daSAndroid Build Coastguard Worker 				index_files[KMOD_INDEX_MODULES_DEP].fn, name);
637*cc4ad7daSAndroid Build Coastguard Worker 		return index_mm_search(ctx->indexes[KMOD_INDEX_MODULES_DEP],
638*cc4ad7daSAndroid Build Coastguard Worker 									name);
639*cc4ad7daSAndroid Build Coastguard Worker 	}
640*cc4ad7daSAndroid Build Coastguard Worker 
641*cc4ad7daSAndroid Build Coastguard Worker 	snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname,
642*cc4ad7daSAndroid Build Coastguard Worker 					index_files[KMOD_INDEX_MODULES_DEP].fn);
643*cc4ad7daSAndroid Build Coastguard Worker 
644*cc4ad7daSAndroid Build Coastguard Worker 	DBG(ctx, "file=%s modname=%s\n", fn, name);
645*cc4ad7daSAndroid Build Coastguard Worker 
646*cc4ad7daSAndroid Build Coastguard Worker 	idx = index_file_open(fn);
647*cc4ad7daSAndroid Build Coastguard Worker 	if (idx == NULL) {
648*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "could not open moddep file '%s'\n", fn);
649*cc4ad7daSAndroid Build Coastguard Worker 		return NULL;
650*cc4ad7daSAndroid Build Coastguard Worker 	}
651*cc4ad7daSAndroid Build Coastguard Worker 
652*cc4ad7daSAndroid Build Coastguard Worker 	line = index_search(idx, name);
653*cc4ad7daSAndroid Build Coastguard Worker 	index_file_close(idx);
654*cc4ad7daSAndroid Build Coastguard Worker 
655*cc4ad7daSAndroid Build Coastguard Worker 	return line;
656*cc4ad7daSAndroid Build Coastguard Worker }
657*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_moddep_file(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)658*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name,
659*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
660*cc4ad7daSAndroid Build Coastguard Worker {
661*cc4ad7daSAndroid Build Coastguard Worker 	char *line;
662*cc4ad7daSAndroid Build Coastguard Worker 	int n = 0;
663*cc4ad7daSAndroid Build Coastguard Worker 
664*cc4ad7daSAndroid Build Coastguard Worker 	/*
665*cc4ad7daSAndroid Build Coastguard Worker 	 * Module names do not contain ':'. Return early if we know it will
666*cc4ad7daSAndroid Build Coastguard Worker 	 * not be found.
667*cc4ad7daSAndroid Build Coastguard Worker 	 */
668*cc4ad7daSAndroid Build Coastguard Worker 	if (strchr(name, ':'))
669*cc4ad7daSAndroid Build Coastguard Worker 		return 0;
670*cc4ad7daSAndroid Build Coastguard Worker 
671*cc4ad7daSAndroid Build Coastguard Worker 	line = kmod_search_moddep(ctx, name);
672*cc4ad7daSAndroid Build Coastguard Worker 	if (line != NULL) {
673*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_module *mod;
674*cc4ad7daSAndroid Build Coastguard Worker 
675*cc4ad7daSAndroid Build Coastguard Worker 		n = kmod_module_new_from_name(ctx, name, &mod);
676*cc4ad7daSAndroid Build Coastguard Worker 		if (n < 0) {
677*cc4ad7daSAndroid Build Coastguard Worker 			ERR(ctx, "Could not create module from name %s: %s\n",
678*cc4ad7daSAndroid Build Coastguard Worker 			    name, strerror(-n));
679*cc4ad7daSAndroid Build Coastguard Worker 			goto finish;
680*cc4ad7daSAndroid Build Coastguard Worker 		}
681*cc4ad7daSAndroid Build Coastguard Worker 
682*cc4ad7daSAndroid Build Coastguard Worker 		*list = kmod_list_append(*list, mod);
683*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_parse_depline(mod, line);
684*cc4ad7daSAndroid Build Coastguard Worker 	}
685*cc4ad7daSAndroid Build Coastguard Worker 
686*cc4ad7daSAndroid Build Coastguard Worker finish:
687*cc4ad7daSAndroid Build Coastguard Worker 	free(line);
688*cc4ad7daSAndroid Build Coastguard Worker 
689*cc4ad7daSAndroid Build Coastguard Worker 	return n;
690*cc4ad7daSAndroid Build Coastguard Worker }
691*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_config(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)692*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name,
693*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
694*cc4ad7daSAndroid Build Coastguard Worker {
695*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_config *config = ctx->config;
696*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l;
697*cc4ad7daSAndroid Build Coastguard Worker 	int err, nmatch = 0;
698*cc4ad7daSAndroid Build Coastguard Worker 
699*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, config->aliases) {
700*cc4ad7daSAndroid Build Coastguard Worker 		const char *aliasname = kmod_alias_get_name(l);
701*cc4ad7daSAndroid Build Coastguard Worker 		const char *modname = kmod_alias_get_modname(l);
702*cc4ad7daSAndroid Build Coastguard Worker 
703*cc4ad7daSAndroid Build Coastguard Worker 		if (fnmatch(aliasname, name, 0) == 0) {
704*cc4ad7daSAndroid Build Coastguard Worker 			struct kmod_module *mod;
705*cc4ad7daSAndroid Build Coastguard Worker 
706*cc4ad7daSAndroid Build Coastguard Worker 			err = kmod_module_new_from_alias(ctx, aliasname,
707*cc4ad7daSAndroid Build Coastguard Worker 								modname, &mod);
708*cc4ad7daSAndroid Build Coastguard Worker 			if (err < 0) {
709*cc4ad7daSAndroid Build Coastguard Worker 				ERR(ctx, "Could not create module for alias=%s modname=%s: %s\n",
710*cc4ad7daSAndroid Build Coastguard Worker 				    name, modname, strerror(-err));
711*cc4ad7daSAndroid Build Coastguard Worker 				goto fail;
712*cc4ad7daSAndroid Build Coastguard Worker 			}
713*cc4ad7daSAndroid Build Coastguard Worker 
714*cc4ad7daSAndroid Build Coastguard Worker 			*list = kmod_list_append(*list, mod);
715*cc4ad7daSAndroid Build Coastguard Worker 			nmatch++;
716*cc4ad7daSAndroid Build Coastguard Worker 		}
717*cc4ad7daSAndroid Build Coastguard Worker 	}
718*cc4ad7daSAndroid Build Coastguard Worker 
719*cc4ad7daSAndroid Build Coastguard Worker 	return nmatch;
720*cc4ad7daSAndroid Build Coastguard Worker 
721*cc4ad7daSAndroid Build Coastguard Worker fail:
722*cc4ad7daSAndroid Build Coastguard Worker 	*list = kmod_list_remove_n_latest(*list, nmatch);
723*cc4ad7daSAndroid Build Coastguard Worker 	return err;
724*cc4ad7daSAndroid Build Coastguard Worker }
725*cc4ad7daSAndroid Build Coastguard Worker 
kmod_lookup_alias_from_commands(struct kmod_ctx * ctx,const char * name,struct kmod_list ** list)726*cc4ad7daSAndroid Build Coastguard Worker int kmod_lookup_alias_from_commands(struct kmod_ctx *ctx, const char *name,
727*cc4ad7daSAndroid Build Coastguard Worker 						struct kmod_list **list)
728*cc4ad7daSAndroid Build Coastguard Worker {
729*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_config *config = ctx->config;
730*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l, *node;
731*cc4ad7daSAndroid Build Coastguard Worker 	int err, nmatch = 0;
732*cc4ad7daSAndroid Build Coastguard Worker 
733*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, config->install_commands) {
734*cc4ad7daSAndroid Build Coastguard Worker 		const char *modname = kmod_command_get_modname(l);
735*cc4ad7daSAndroid Build Coastguard Worker 
736*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(modname, name)) {
737*cc4ad7daSAndroid Build Coastguard Worker 			const char *cmd = kmod_command_get_command(l);
738*cc4ad7daSAndroid Build Coastguard Worker 			struct kmod_module *mod;
739*cc4ad7daSAndroid Build Coastguard Worker 
740*cc4ad7daSAndroid Build Coastguard Worker 			err = kmod_module_new_from_name(ctx, modname, &mod);
741*cc4ad7daSAndroid Build Coastguard Worker 			if (err < 0) {
742*cc4ad7daSAndroid Build Coastguard Worker 				ERR(ctx, "Could not create module from name %s: %s\n",
743*cc4ad7daSAndroid Build Coastguard Worker 				    modname, strerror(-err));
744*cc4ad7daSAndroid Build Coastguard Worker 				return err;
745*cc4ad7daSAndroid Build Coastguard Worker 			}
746*cc4ad7daSAndroid Build Coastguard Worker 
747*cc4ad7daSAndroid Build Coastguard Worker 			node = kmod_list_append(*list, mod);
748*cc4ad7daSAndroid Build Coastguard Worker 			if (node == NULL) {
749*cc4ad7daSAndroid Build Coastguard Worker 				ERR(ctx, "out of memory\n");
750*cc4ad7daSAndroid Build Coastguard Worker 				return -ENOMEM;
751*cc4ad7daSAndroid Build Coastguard Worker 			}
752*cc4ad7daSAndroid Build Coastguard Worker 
753*cc4ad7daSAndroid Build Coastguard Worker 			*list = node;
754*cc4ad7daSAndroid Build Coastguard Worker 			nmatch = 1;
755*cc4ad7daSAndroid Build Coastguard Worker 
756*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_set_install_commands(mod, cmd);
757*cc4ad7daSAndroid Build Coastguard Worker 
758*cc4ad7daSAndroid Build Coastguard Worker 			/*
759*cc4ad7daSAndroid Build Coastguard Worker 			 * match only the first one, like modprobe from
760*cc4ad7daSAndroid Build Coastguard Worker 			 * module-init-tools does
761*cc4ad7daSAndroid Build Coastguard Worker 			 */
762*cc4ad7daSAndroid Build Coastguard Worker 			break;
763*cc4ad7daSAndroid Build Coastguard Worker 		}
764*cc4ad7daSAndroid Build Coastguard Worker 	}
765*cc4ad7daSAndroid Build Coastguard Worker 
766*cc4ad7daSAndroid Build Coastguard Worker 	if (nmatch)
767*cc4ad7daSAndroid Build Coastguard Worker 		return nmatch;
768*cc4ad7daSAndroid Build Coastguard Worker 
769*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, config->remove_commands) {
770*cc4ad7daSAndroid Build Coastguard Worker 		const char *modname = kmod_command_get_modname(l);
771*cc4ad7daSAndroid Build Coastguard Worker 
772*cc4ad7daSAndroid Build Coastguard Worker 		if (streq(modname, name)) {
773*cc4ad7daSAndroid Build Coastguard Worker 			const char *cmd = kmod_command_get_command(l);
774*cc4ad7daSAndroid Build Coastguard Worker 			struct kmod_module *mod;
775*cc4ad7daSAndroid Build Coastguard Worker 
776*cc4ad7daSAndroid Build Coastguard Worker 			err = kmod_module_new_from_name(ctx, modname, &mod);
777*cc4ad7daSAndroid Build Coastguard Worker 			if (err < 0) {
778*cc4ad7daSAndroid Build Coastguard Worker 				ERR(ctx, "Could not create module from name %s: %s\n",
779*cc4ad7daSAndroid Build Coastguard Worker 				    modname, strerror(-err));
780*cc4ad7daSAndroid Build Coastguard Worker 				return err;
781*cc4ad7daSAndroid Build Coastguard Worker 			}
782*cc4ad7daSAndroid Build Coastguard Worker 
783*cc4ad7daSAndroid Build Coastguard Worker 			node = kmod_list_append(*list, mod);
784*cc4ad7daSAndroid Build Coastguard Worker 			if (node == NULL) {
785*cc4ad7daSAndroid Build Coastguard Worker 				ERR(ctx, "out of memory\n");
786*cc4ad7daSAndroid Build Coastguard Worker 				return -ENOMEM;
787*cc4ad7daSAndroid Build Coastguard Worker 			}
788*cc4ad7daSAndroid Build Coastguard Worker 
789*cc4ad7daSAndroid Build Coastguard Worker 			*list = node;
790*cc4ad7daSAndroid Build Coastguard Worker 			nmatch = 1;
791*cc4ad7daSAndroid Build Coastguard Worker 
792*cc4ad7daSAndroid Build Coastguard Worker 			kmod_module_set_remove_commands(mod, cmd);
793*cc4ad7daSAndroid Build Coastguard Worker 
794*cc4ad7daSAndroid Build Coastguard Worker 			/*
795*cc4ad7daSAndroid Build Coastguard Worker 			 * match only the first one, like modprobe from
796*cc4ad7daSAndroid Build Coastguard Worker 			 * module-init-tools does
797*cc4ad7daSAndroid Build Coastguard Worker 			 */
798*cc4ad7daSAndroid Build Coastguard Worker 			break;
799*cc4ad7daSAndroid Build Coastguard Worker 		}
800*cc4ad7daSAndroid Build Coastguard Worker 	}
801*cc4ad7daSAndroid Build Coastguard Worker 
802*cc4ad7daSAndroid Build Coastguard Worker 	return nmatch;
803*cc4ad7daSAndroid Build Coastguard Worker }
804*cc4ad7daSAndroid Build Coastguard Worker 
kmod_set_modules_visited(struct kmod_ctx * ctx,bool visited)805*cc4ad7daSAndroid Build Coastguard Worker void kmod_set_modules_visited(struct kmod_ctx *ctx, bool visited)
806*cc4ad7daSAndroid Build Coastguard Worker {
807*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_iter iter;
808*cc4ad7daSAndroid Build Coastguard Worker 	const void *v;
809*cc4ad7daSAndroid Build Coastguard Worker 
810*cc4ad7daSAndroid Build Coastguard Worker 	hash_iter_init(ctx->modules_by_name, &iter);
811*cc4ad7daSAndroid Build Coastguard Worker 	while (hash_iter_next(&iter, NULL, &v))
812*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_set_visited((struct kmod_module *)v, visited);
813*cc4ad7daSAndroid Build Coastguard Worker }
814*cc4ad7daSAndroid Build Coastguard Worker 
kmod_set_modules_required(struct kmod_ctx * ctx,bool required)815*cc4ad7daSAndroid Build Coastguard Worker void kmod_set_modules_required(struct kmod_ctx *ctx, bool required)
816*cc4ad7daSAndroid Build Coastguard Worker {
817*cc4ad7daSAndroid Build Coastguard Worker 	struct hash_iter iter;
818*cc4ad7daSAndroid Build Coastguard Worker 	const void *v;
819*cc4ad7daSAndroid Build Coastguard Worker 
820*cc4ad7daSAndroid Build Coastguard Worker 	hash_iter_init(ctx->modules_by_name, &iter);
821*cc4ad7daSAndroid Build Coastguard Worker 	while (hash_iter_next(&iter, NULL, &v))
822*cc4ad7daSAndroid Build Coastguard Worker 		kmod_module_set_required((struct kmod_module *)v, required);
823*cc4ad7daSAndroid Build Coastguard Worker }
824*cc4ad7daSAndroid Build Coastguard Worker 
is_cache_invalid(const char * path,unsigned long long stamp)825*cc4ad7daSAndroid Build Coastguard Worker static bool is_cache_invalid(const char *path, unsigned long long stamp)
826*cc4ad7daSAndroid Build Coastguard Worker {
827*cc4ad7daSAndroid Build Coastguard Worker 	struct stat st;
828*cc4ad7daSAndroid Build Coastguard Worker 
829*cc4ad7daSAndroid Build Coastguard Worker 	if (stat(path, &st) < 0)
830*cc4ad7daSAndroid Build Coastguard Worker 		return true;
831*cc4ad7daSAndroid Build Coastguard Worker 
832*cc4ad7daSAndroid Build Coastguard Worker 	if (stamp != stat_mstamp(&st))
833*cc4ad7daSAndroid Build Coastguard Worker 		return true;
834*cc4ad7daSAndroid Build Coastguard Worker 
835*cc4ad7daSAndroid Build Coastguard Worker 	return false;
836*cc4ad7daSAndroid Build Coastguard Worker }
837*cc4ad7daSAndroid Build Coastguard Worker 
838*cc4ad7daSAndroid Build Coastguard Worker /**
839*cc4ad7daSAndroid Build Coastguard Worker  * kmod_validate_resources:
840*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
841*cc4ad7daSAndroid Build Coastguard Worker  *
842*cc4ad7daSAndroid Build Coastguard Worker  * Check if indexes and configuration files changed on disk and the current
843*cc4ad7daSAndroid Build Coastguard Worker  * context is not valid anymore.
844*cc4ad7daSAndroid Build Coastguard Worker  *
845*cc4ad7daSAndroid Build Coastguard Worker  * Returns: KMOD_RESOURCES_OK if resources are still valid,
846*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_RESOURCES_MUST_RELOAD if it's sufficient to call
847*cc4ad7daSAndroid Build Coastguard Worker  * kmod_unload_resources() and kmod_load_resources() or
848*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_RESOURCES_MUST_RECREATE if @ctx must be re-created.
849*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_validate_resources(struct kmod_ctx * ctx)850*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_validate_resources(struct kmod_ctx *ctx)
851*cc4ad7daSAndroid Build Coastguard Worker {
852*cc4ad7daSAndroid Build Coastguard Worker 	struct kmod_list *l;
853*cc4ad7daSAndroid Build Coastguard Worker 	size_t i;
854*cc4ad7daSAndroid Build Coastguard Worker 
855*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL || ctx->config == NULL)
856*cc4ad7daSAndroid Build Coastguard Worker 		return KMOD_RESOURCES_MUST_RECREATE;
857*cc4ad7daSAndroid Build Coastguard Worker 
858*cc4ad7daSAndroid Build Coastguard Worker 	kmod_list_foreach(l, ctx->config->paths) {
859*cc4ad7daSAndroid Build Coastguard Worker 		struct kmod_config_path *cf = l->data;
860*cc4ad7daSAndroid Build Coastguard Worker 
861*cc4ad7daSAndroid Build Coastguard Worker 		if (is_cache_invalid(cf->path, cf->stamp))
862*cc4ad7daSAndroid Build Coastguard Worker 			return KMOD_RESOURCES_MUST_RECREATE;
863*cc4ad7daSAndroid Build Coastguard Worker 	}
864*cc4ad7daSAndroid Build Coastguard Worker 
865*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) {
866*cc4ad7daSAndroid Build Coastguard Worker 		char path[PATH_MAX];
867*cc4ad7daSAndroid Build Coastguard Worker 
868*cc4ad7daSAndroid Build Coastguard Worker 		if (ctx->indexes[i] == NULL)
869*cc4ad7daSAndroid Build Coastguard Worker 			continue;
870*cc4ad7daSAndroid Build Coastguard Worker 
871*cc4ad7daSAndroid Build Coastguard Worker 		snprintf(path, sizeof(path), "%s/%s.bin", ctx->dirname,
872*cc4ad7daSAndroid Build Coastguard Worker 						index_files[i].fn);
873*cc4ad7daSAndroid Build Coastguard Worker 
874*cc4ad7daSAndroid Build Coastguard Worker 		if (is_cache_invalid(path, ctx->indexes_stamp[i]))
875*cc4ad7daSAndroid Build Coastguard Worker 			return KMOD_RESOURCES_MUST_RELOAD;
876*cc4ad7daSAndroid Build Coastguard Worker 	}
877*cc4ad7daSAndroid Build Coastguard Worker 
878*cc4ad7daSAndroid Build Coastguard Worker 	return KMOD_RESOURCES_OK;
879*cc4ad7daSAndroid Build Coastguard Worker }
880*cc4ad7daSAndroid Build Coastguard Worker 
881*cc4ad7daSAndroid Build Coastguard Worker /**
882*cc4ad7daSAndroid Build Coastguard Worker  * kmod_load_resources:
883*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
884*cc4ad7daSAndroid Build Coastguard Worker  *
885*cc4ad7daSAndroid Build Coastguard Worker  * Load indexes and keep them open in @ctx. This way it's faster to lookup
886*cc4ad7daSAndroid Build Coastguard Worker  * information within the indexes. If this function is not called before a
887*cc4ad7daSAndroid Build Coastguard Worker  * search, the necessary index is always opened and closed.
888*cc4ad7daSAndroid Build Coastguard Worker  *
889*cc4ad7daSAndroid Build Coastguard Worker  * If user will do more than one or two lookups, insertions, deletions, most
890*cc4ad7daSAndroid Build Coastguard Worker  * likely it's good to call this function first. Particularly in a daemon like
891*cc4ad7daSAndroid Build Coastguard Worker  * udev that on bootup issues hundreds of calls to lookup the index, calling
892*cc4ad7daSAndroid Build Coastguard Worker  * this function will speedup the searches.
893*cc4ad7daSAndroid Build Coastguard Worker  *
894*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
895*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_load_resources(struct kmod_ctx * ctx)896*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_load_resources(struct kmod_ctx *ctx)
897*cc4ad7daSAndroid Build Coastguard Worker {
898*cc4ad7daSAndroid Build Coastguard Worker 	int ret = 0;
899*cc4ad7daSAndroid Build Coastguard Worker 	size_t i;
900*cc4ad7daSAndroid Build Coastguard Worker 
901*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
902*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
903*cc4ad7daSAndroid Build Coastguard Worker 
904*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) {
905*cc4ad7daSAndroid Build Coastguard Worker 		char path[PATH_MAX];
906*cc4ad7daSAndroid Build Coastguard Worker 
907*cc4ad7daSAndroid Build Coastguard Worker 		if (ctx->indexes[i] != NULL) {
908*cc4ad7daSAndroid Build Coastguard Worker 			INFO(ctx, "Index %s already loaded\n",
909*cc4ad7daSAndroid Build Coastguard Worker 							index_files[i].fn);
910*cc4ad7daSAndroid Build Coastguard Worker 			continue;
911*cc4ad7daSAndroid Build Coastguard Worker 		}
912*cc4ad7daSAndroid Build Coastguard Worker 
913*cc4ad7daSAndroid Build Coastguard Worker 		snprintf(path, sizeof(path), "%s/%s.bin", ctx->dirname,
914*cc4ad7daSAndroid Build Coastguard Worker 							index_files[i].fn);
915*cc4ad7daSAndroid Build Coastguard Worker 		ret = index_mm_open(ctx, path, &ctx->indexes_stamp[i],
916*cc4ad7daSAndroid Build Coastguard Worker 				    &ctx->indexes[i]);
917*cc4ad7daSAndroid Build Coastguard Worker 
918*cc4ad7daSAndroid Build Coastguard Worker 		/*
919*cc4ad7daSAndroid Build Coastguard Worker 		 * modules.builtin.alias are considered optional since it's
920*cc4ad7daSAndroid Build Coastguard Worker 		 * recently added and older installations may not have it;
921*cc4ad7daSAndroid Build Coastguard Worker 		 * we allow failing for any reason
922*cc4ad7daSAndroid Build Coastguard Worker 		 */
923*cc4ad7daSAndroid Build Coastguard Worker 		if (ret) {
924*cc4ad7daSAndroid Build Coastguard Worker 			if (i != KMOD_INDEX_MODULES_BUILTIN_ALIAS)
925*cc4ad7daSAndroid Build Coastguard Worker 				break;
926*cc4ad7daSAndroid Build Coastguard Worker 			ret = 0;
927*cc4ad7daSAndroid Build Coastguard Worker 		}
928*cc4ad7daSAndroid Build Coastguard Worker 	}
929*cc4ad7daSAndroid Build Coastguard Worker 
930*cc4ad7daSAndroid Build Coastguard Worker 	if (ret)
931*cc4ad7daSAndroid Build Coastguard Worker 		kmod_unload_resources(ctx);
932*cc4ad7daSAndroid Build Coastguard Worker 
933*cc4ad7daSAndroid Build Coastguard Worker 	return ret;
934*cc4ad7daSAndroid Build Coastguard Worker }
935*cc4ad7daSAndroid Build Coastguard Worker 
936*cc4ad7daSAndroid Build Coastguard Worker /**
937*cc4ad7daSAndroid Build Coastguard Worker  * kmod_unload_resources:
938*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
939*cc4ad7daSAndroid Build Coastguard Worker  *
940*cc4ad7daSAndroid Build Coastguard Worker  * Unload all the indexes. This will free the resources to maintain the index
941*cc4ad7daSAndroid Build Coastguard Worker  * open and all subsequent searches will need to open and close the index.
942*cc4ad7daSAndroid Build Coastguard Worker  *
943*cc4ad7daSAndroid Build Coastguard Worker  * User is free to call kmod_load_resources() and kmod_unload_resources() as
944*cc4ad7daSAndroid Build Coastguard Worker  * many times as wanted during the lifecycle of @ctx. For example, if a daemon
945*cc4ad7daSAndroid Build Coastguard Worker  * knows that when starting up it will lookup a lot of modules, it could call
946*cc4ad7daSAndroid Build Coastguard Worker  * kmod_load_resources() and after the first burst of searches is gone, it
947*cc4ad7daSAndroid Build Coastguard Worker  * could free the resources by calling kmod_unload_resources().
948*cc4ad7daSAndroid Build Coastguard Worker  *
949*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
950*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_unload_resources(struct kmod_ctx * ctx)951*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT void kmod_unload_resources(struct kmod_ctx *ctx)
952*cc4ad7daSAndroid Build Coastguard Worker {
953*cc4ad7daSAndroid Build Coastguard Worker 	size_t i;
954*cc4ad7daSAndroid Build Coastguard Worker 
955*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
956*cc4ad7daSAndroid Build Coastguard Worker 		return;
957*cc4ad7daSAndroid Build Coastguard Worker 
958*cc4ad7daSAndroid Build Coastguard Worker 	for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) {
959*cc4ad7daSAndroid Build Coastguard Worker 		if (ctx->indexes[i] != NULL) {
960*cc4ad7daSAndroid Build Coastguard Worker 			index_mm_close(ctx->indexes[i]);
961*cc4ad7daSAndroid Build Coastguard Worker 			ctx->indexes[i] = NULL;
962*cc4ad7daSAndroid Build Coastguard Worker 			ctx->indexes_stamp[i] = 0;
963*cc4ad7daSAndroid Build Coastguard Worker 		}
964*cc4ad7daSAndroid Build Coastguard Worker 	}
965*cc4ad7daSAndroid Build Coastguard Worker }
966*cc4ad7daSAndroid Build Coastguard Worker 
967*cc4ad7daSAndroid Build Coastguard Worker /**
968*cc4ad7daSAndroid Build Coastguard Worker  * kmod_dump_index:
969*cc4ad7daSAndroid Build Coastguard Worker  * @ctx: kmod library context
970*cc4ad7daSAndroid Build Coastguard Worker  * @type: index to dump, valid indexes are
971*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_INDEX_MODULES_DEP: index of module dependencies;
972*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_INDEX_MODULES_ALIAS: index of module aliases;
973*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_INDEX_MODULES_SYMBOL: index of symbol aliases;
974*cc4ad7daSAndroid Build Coastguard Worker  * KMOD_INDEX_MODULES_BUILTIN: index of builtin module.
975*cc4ad7daSAndroid Build Coastguard Worker  * @fd: file descriptor to dump index to
976*cc4ad7daSAndroid Build Coastguard Worker  *
977*cc4ad7daSAndroid Build Coastguard Worker  * Dump index to file descriptor. Note that this function doesn't use stdio.h
978*cc4ad7daSAndroid Build Coastguard Worker  * so call fflush() before calling this function to be sure data is written in
979*cc4ad7daSAndroid Build Coastguard Worker  * order.
980*cc4ad7daSAndroid Build Coastguard Worker  *
981*cc4ad7daSAndroid Build Coastguard Worker  * Returns: 0 on success or < 0 otherwise.
982*cc4ad7daSAndroid Build Coastguard Worker  */
kmod_dump_index(struct kmod_ctx * ctx,enum kmod_index type,int fd)983*cc4ad7daSAndroid Build Coastguard Worker KMOD_EXPORT int kmod_dump_index(struct kmod_ctx *ctx, enum kmod_index type,
984*cc4ad7daSAndroid Build Coastguard Worker 									int fd)
985*cc4ad7daSAndroid Build Coastguard Worker {
986*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx == NULL)
987*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOSYS;
988*cc4ad7daSAndroid Build Coastguard Worker 
989*cc4ad7daSAndroid Build Coastguard Worker 	if (type < 0 || type >= _KMOD_INDEX_MODULES_SIZE)
990*cc4ad7daSAndroid Build Coastguard Worker 		return -ENOENT;
991*cc4ad7daSAndroid Build Coastguard Worker 
992*cc4ad7daSAndroid Build Coastguard Worker 	if (ctx->indexes[type] != NULL) {
993*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "use mmaped index '%s'\n", index_files[type].fn);
994*cc4ad7daSAndroid Build Coastguard Worker 		index_mm_dump(ctx->indexes[type], fd,
995*cc4ad7daSAndroid Build Coastguard Worker 						index_files[type].prefix);
996*cc4ad7daSAndroid Build Coastguard Worker 	} else {
997*cc4ad7daSAndroid Build Coastguard Worker 		char fn[PATH_MAX];
998*cc4ad7daSAndroid Build Coastguard Worker 		struct index_file *idx;
999*cc4ad7daSAndroid Build Coastguard Worker 
1000*cc4ad7daSAndroid Build Coastguard Worker 		snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname,
1001*cc4ad7daSAndroid Build Coastguard Worker 						index_files[type].fn);
1002*cc4ad7daSAndroid Build Coastguard Worker 
1003*cc4ad7daSAndroid Build Coastguard Worker 		DBG(ctx, "file=%s\n", fn);
1004*cc4ad7daSAndroid Build Coastguard Worker 
1005*cc4ad7daSAndroid Build Coastguard Worker 		idx = index_file_open(fn);
1006*cc4ad7daSAndroid Build Coastguard Worker 		if (idx == NULL)
1007*cc4ad7daSAndroid Build Coastguard Worker 			return -ENOSYS;
1008*cc4ad7daSAndroid Build Coastguard Worker 
1009*cc4ad7daSAndroid Build Coastguard Worker 		index_dump(idx, fd, index_files[type].prefix);
1010*cc4ad7daSAndroid Build Coastguard Worker 		index_file_close(idx);
1011*cc4ad7daSAndroid Build Coastguard Worker 	}
1012*cc4ad7daSAndroid Build Coastguard Worker 
1013*cc4ad7daSAndroid Build Coastguard Worker 	return 0;
1014*cc4ad7daSAndroid Build Coastguard Worker }
1015*cc4ad7daSAndroid Build Coastguard Worker 
kmod_get_config(const struct kmod_ctx * ctx)1016*cc4ad7daSAndroid Build Coastguard Worker const struct kmod_config *kmod_get_config(const struct kmod_ctx *ctx)
1017*cc4ad7daSAndroid Build Coastguard Worker {
1018*cc4ad7daSAndroid Build Coastguard Worker 	return ctx->config;
1019*cc4ad7daSAndroid Build Coastguard Worker }
1020*cc4ad7daSAndroid Build Coastguard Worker 
kmod_get_kernel_compression(const struct kmod_ctx * ctx)1021*cc4ad7daSAndroid Build Coastguard Worker enum kmod_file_compression_type kmod_get_kernel_compression(const struct kmod_ctx *ctx)
1022*cc4ad7daSAndroid Build Coastguard Worker {
1023*cc4ad7daSAndroid Build Coastguard Worker 	return ctx->kernel_compression;
1024*cc4ad7daSAndroid Build Coastguard Worker }
1025