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