blob: fa1fdbbbc35e097f9b28b41096b2158296512ea4 [file] [log] [blame]
Lucas De Marchi586fc302011-11-21 14:35:35 -02001/*
2 * libkmod - interface to kernel module operations
3 *
4 * Copyright (C) 2011 ProFUSION embedded systems
Lucas De Marchi586fc302011-11-21 14:35:35 -02005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation version 2.1.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <stddef.h>
23#include <stdarg.h>
Lucas De Marchi1eb2ef62011-12-05 19:58:39 -020024#include <limits.h>
Lucas De Marchi586fc302011-11-21 14:35:35 -020025#include <unistd.h>
26#include <errno.h>
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -020027#include <fnmatch.h>
Lucas De Marchi586fc302011-11-21 14:35:35 -020028#include <string.h>
29#include <ctype.h>
Lucas De Marchi221631d2011-11-24 16:41:01 -020030#include <sys/utsname.h>
Lucas De Marchi586fc302011-11-21 14:35:35 -020031
32#include "libkmod.h"
33#include "libkmod-private.h"
Lucas De Marchi9ba6f572011-11-30 20:31:45 -020034#include "libkmod-index.h"
Lucas De Marchi586fc302011-11-21 14:35:35 -020035
Lucas De Marchifd186ae2011-12-06 03:38:37 -020036#define KMOD_HASH_SIZE (256)
37#define KMOD_LRU_MAX (128)
38
Lucas De Marchi586fc302011-11-21 14:35:35 -020039/**
40 * SECTION:libkmod
41 * @short_description: libkmod context
42 *
43 * The context contains the default values for the library user,
44 * and is passed to all library operations.
45 */
46
47/**
48 * kmod_ctx:
49 *
50 * Opaque object representing the library context.
51 */
52struct kmod_ctx {
53 int refcount;
Gustavo Sverzut Barbieri8d3f3ef2011-12-02 21:10:24 -020054 int log_priority;
Lucas De Marchi586fc302011-11-21 14:35:35 -020055 void (*log_fn)(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -020056 int priority, const char *file, int line,
57 const char *fn, const char *format, va_list args);
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020058 const void *userdata;
59 char *dirname;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -020060 struct kmod_config *config;
Lucas De Marchifd186ae2011-12-06 03:38:37 -020061 struct kmod_hash *modules_by_name;
Lucas De Marchi586fc302011-11-21 14:35:35 -020062};
63
64void kmod_log(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -020065 int priority, const char *file, int line, const char *fn,
66 const char *format, ...)
Lucas De Marchi586fc302011-11-21 14:35:35 -020067{
68 va_list args;
69
70 va_start(args, format);
71 ctx->log_fn(ctx, priority, file, line, fn, format, args);
72 va_end(args);
73}
74
75static void log_stderr(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -020076 int priority, const char *file, int line,
77 const char *fn, const char *format, va_list args)
Lucas De Marchi586fc302011-11-21 14:35:35 -020078{
79 fprintf(stderr, "libkmod: %s: ", fn);
80 vfprintf(stderr, format, args);
81}
82
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020083const char *kmod_get_dirname(const struct kmod_ctx *ctx)
Lucas De Marchi221631d2011-11-24 16:41:01 -020084{
85 return ctx->dirname;
86}
87
Lucas De Marchi586fc302011-11-21 14:35:35 -020088/**
89 * kmod_get_userdata:
90 * @ctx: kmod library context
91 *
92 * Retrieve stored data pointer from library context. This might be useful
93 * to access from callbacks like a custom logging function.
94 *
95 * Returns: stored userdata
96 **/
Lucas De Marchi6d177552011-11-23 11:52:30 -020097KMOD_EXPORT void *kmod_get_userdata(const struct kmod_ctx *ctx)
Lucas De Marchi586fc302011-11-21 14:35:35 -020098{
99 if (ctx == NULL)
100 return NULL;
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200101 return (void *)ctx->userdata;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200102}
103
104/**
105 * kmod_set_userdata:
106 * @ctx: kmod library context
107 * @userdata: data pointer
108 *
109 * Store custom @userdata in the library context.
110 **/
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200111KMOD_EXPORT void kmod_set_userdata(struct kmod_ctx *ctx, const void *userdata)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200112{
113 if (ctx == NULL)
114 return;
115 ctx->userdata = userdata;
116}
117
118static int log_priority(const char *priority)
119{
120 char *endptr;
121 int prio;
122
123 prio = strtol(priority, &endptr, 10);
124 if (endptr[0] == '\0' || isspace(endptr[0]))
125 return prio;
126 if (strncmp(priority, "err", 3) == 0)
127 return LOG_ERR;
128 if (strncmp(priority, "info", 4) == 0)
129 return LOG_INFO;
130 if (strncmp(priority, "debug", 5) == 0)
131 return LOG_DEBUG;
132 return 0;
133}
134
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200135static const char *dirname_default_prefix = "/lib/modules";
136
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200137static char *get_kernel_release(const char *dirname)
Lucas De Marchi221631d2011-11-24 16:41:01 -0200138{
139 struct utsname u;
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200140 char *p;
141
142 if (dirname != NULL)
143 return strdup(dirname);
Lucas De Marchi221631d2011-11-24 16:41:01 -0200144
145 if (uname(&u) < 0)
146 return NULL;
147
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200148 if (asprintf(&p, "%s/%s", dirname_default_prefix, u.release) < 0)
149 return NULL;
150
151 return p;
Lucas De Marchi221631d2011-11-24 16:41:01 -0200152}
153
Lucas De Marchi586fc302011-11-21 14:35:35 -0200154/**
155 * kmod_new:
156 *
157 * Create kmod library context. This reads the kmod configuration
158 * and fills in the default values.
159 *
160 * The initial refcount is 1, and needs to be decremented to
161 * release the resources of the kmod library context.
162 *
163 * Returns: a new kmod library context
164 **/
Lucas De Marchi221631d2011-11-24 16:41:01 -0200165KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200166{
167 const char *env;
Lucas De Marchi52a77042011-11-21 15:07:27 -0200168 struct kmod_ctx *ctx;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200169 int err;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200170
Lucas De Marchi52a77042011-11-21 15:07:27 -0200171 ctx = calloc(1, sizeof(struct kmod_ctx));
172 if (!ctx)
173 return NULL;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200174
Lucas De Marchi52a77042011-11-21 15:07:27 -0200175 ctx->refcount = 1;
176 ctx->log_fn = log_stderr;
177 ctx->log_priority = LOG_ERR;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200178
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200179 ctx->dirname = get_kernel_release(dirname);
Lucas De Marchi221631d2011-11-24 16:41:01 -0200180
Lucas De Marchi586fc302011-11-21 14:35:35 -0200181 /* environment overwrites config */
182 env = getenv("KMOD_LOG");
183 if (env != NULL)
Lucas De Marchi52a77042011-11-21 15:07:27 -0200184 kmod_set_log_priority(ctx, log_priority(env));
Lucas De Marchi586fc302011-11-21 14:35:35 -0200185
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200186 err = kmod_config_new(ctx, &ctx->config);
187 if (err < 0) {
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200188 ERR(ctx, "could not create config\n");
189 goto fail;
190 }
191
192 ctx->modules_by_name = kmod_hash_new(KMOD_HASH_SIZE, NULL);
193 if (ctx->modules_by_name == NULL) {
194 ERR(ctx, "could not create by-name hash\n");
195 goto fail;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200196 }
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200197
Lucas De Marchiae6df842011-11-25 01:05:30 -0200198 INFO(ctx, "ctx %p created\n", ctx);
199 DBG(ctx, "log_priority=%d\n", ctx->log_priority);
Lucas De Marchi52a77042011-11-21 15:07:27 -0200200
201 return ctx;
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200202
203fail:
204 free(ctx->modules_by_name);
205 free(ctx->dirname);
206 free(ctx);
207 return NULL;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200208}
209
210/**
211 * kmod_ref:
212 * @ctx: kmod library context
213 *
214 * Take a reference of the kmod library context.
215 *
216 * Returns: the passed kmod library context
217 **/
218KMOD_EXPORT struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx)
219{
220 if (ctx == NULL)
221 return NULL;
222 ctx->refcount++;
223 return ctx;
224}
225
226/**
227 * kmod_unref:
228 * @ctx: kmod library context
229 *
230 * Drop a reference of the kmod library context. If the refcount
231 * reaches zero, the resources of the context will be released.
232 *
233 **/
234KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx)
235{
236 if (ctx == NULL)
237 return NULL;
Lucas De Marchi4d1e6892011-11-24 15:41:48 -0200238
239 if (--ctx->refcount > 0)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200240 return ctx;
Lucas De Marchiae6df842011-11-25 01:05:30 -0200241 INFO(ctx, "context %p released\n", ctx);
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200242 kmod_hash_free(ctx->modules_by_name);
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200243 free(ctx->dirname);
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200244 if (ctx->config)
245 kmod_config_free(ctx->config);
Lucas De Marchi586fc302011-11-21 14:35:35 -0200246 free(ctx);
247 return NULL;
248}
249
250/**
251 * kmod_set_log_fn:
252 * @ctx: kmod library context
253 * @log_fn: function to be called for logging messages
254 *
255 * The built-in logging writes to stderr. It can be
256 * overridden by a custom function, to plug log messages
257 * into the user's logging functionality.
258 *
259 **/
260KMOD_EXPORT void kmod_set_log_fn(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -0200261 void (*log_fn)(struct kmod_ctx *ctx,
262 int priority, const char *file,
263 int line, const char *fn,
264 const char *format, va_list args))
Lucas De Marchi586fc302011-11-21 14:35:35 -0200265{
266 ctx->log_fn = log_fn;
Lucas De Marchiae6df842011-11-25 01:05:30 -0200267 INFO(ctx, "custom logging function %p registered\n", log_fn);
Lucas De Marchi586fc302011-11-21 14:35:35 -0200268}
269
270/**
271 * kmod_get_log_priority:
272 * @ctx: kmod library context
273 *
274 * Returns: the current logging priority
275 **/
Lucas De Marchi6d177552011-11-23 11:52:30 -0200276KMOD_EXPORT int kmod_get_log_priority(const struct kmod_ctx *ctx)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200277{
278 return ctx->log_priority;
279}
280
281/**
282 * kmod_set_log_priority:
283 * @ctx: kmod library context
284 * @priority: the new logging priority
285 *
286 * Set the current logging priority. The value controls which messages
287 * are logged.
288 **/
289KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority)
290{
291 ctx->log_priority = priority;
292}
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200293
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200294struct kmod_module *kmod_pool_get_module(struct kmod_ctx *ctx,
295 const char *name)
296{
297 struct kmod_module *mod;
298
299 mod = kmod_hash_find(ctx->modules_by_name, name);
300
301 DBG(ctx, "get module name='%s' found=%p\n", name, mod);
302
303 return mod;
304}
305
306void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod)
307{
308 const char *name = kmod_module_get_name(mod);
309
310 DBG(ctx, "add %p name='%s'\n", mod, name);
311
312 kmod_hash_add(ctx->modules_by_name, name, mod);
313}
314
315void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod)
316{
317 const char *name = kmod_module_get_name(mod);
318
319 DBG(ctx, "del %p name='%s'\n", mod, name);
320
321 kmod_hash_del(ctx->modules_by_name, name);
322}
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200323
Lucas De Marchia0094822011-12-02 09:53:31 -0200324static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx,
325 const char *file,
Lucas De Marchi7b30f4f2011-12-01 16:25:37 -0200326 const char *name,
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200327 struct kmod_list **list)
328{
329 char *fn;
Lucas De Marchi6f1bc6e2011-12-02 10:02:05 -0200330 int err, nmatch = 0;
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200331 struct index_file *idx;
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200332 struct index_value *realnames, *realname;
333
Lucas De Marchi7b30f4f2011-12-01 16:25:37 -0200334 if (asprintf(&fn, "%s/%s.bin", ctx->dirname, file) < 0)
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200335 return -ENOMEM;
336
Lucas De Marchie915f922011-12-01 17:47:49 -0200337 DBG(ctx, "file=%s name=%s\n", fn, name);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200338
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200339 idx = index_file_open(fn);
340 if (idx == NULL) {
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200341 free(fn);
342 return -ENOSYS;
343 }
344
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200345 realnames = index_searchwild(idx, name);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200346 for (realname = realnames; realname; realname = realnames->next) {
347 struct kmod_module *mod;
348
349 err = kmod_module_new_from_name(ctx, realname->value, &mod);
350 if (err < 0) {
351 ERR(ctx, "%s\n", strerror(-err));
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200352 goto fail;
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200353 }
354
355 *list = kmod_list_append(*list, mod);
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200356 nmatch++;
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200357 }
358
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200359 index_values_free(realnames);
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200360 index_file_close(idx);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200361 free(fn);
362
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200363 return nmatch;
364
365fail:
366 *list = kmod_list_remove_n_latest(*list, nmatch);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200367 return err;
Lucas De Marchi7b30f4f2011-12-01 16:25:37 -0200368
369}
370
371static const char *symbols_file = "modules.symbols";
372
373int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name,
374 struct kmod_list **list)
375{
376 if (!startswith(name, "symbol:"))
377 return 0;
378
379 return kmod_lookup_alias_from_alias_bin(ctx, symbols_file, name, list);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200380}
381
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200382
383static const char *aliases_file = "modules.alias";
384
385int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name,
386 struct kmod_list **list)
387{
388 return kmod_lookup_alias_from_alias_bin(ctx, aliases_file, name, list);
389}
390
Lucas De Marchi64700e42011-12-01 15:57:53 -0200391static const char *moddep_file = "modules.dep";
392
Lucas De Marchi671d4892011-12-05 20:23:05 -0200393char *kmod_search_moddep(struct kmod_ctx *ctx, const char *name)
Lucas De Marchi1eb2ef62011-12-05 19:58:39 -0200394{
395 struct index_file *idx;
396 char fn[PATH_MAX];
397 char *line;
398
399 snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname, moddep_file);
400
401 DBG(ctx, "file=%s modname=%s\n", fn, name);
402
403 idx = index_file_open(fn);
404 if (idx == NULL) {
405 ERR(ctx, "Could not open moddep file '%s'", fn);
406 return NULL;
407 }
408
409 line = index_search(idx, name);
410 index_file_close(idx);
411
412 return line;
413}
414
Lucas De Marchi64700e42011-12-01 15:57:53 -0200415int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name,
416 struct kmod_list **list)
417{
Lucas De Marchi1eb2ef62011-12-05 19:58:39 -0200418 char *line;
Lucas De Marchi64700e42011-12-01 15:57:53 -0200419 int n = 0;
420
421 /*
422 * Module names do not contain ':'. Return early if we know it will
423 * not be found.
424 */
425 if (strchr(name, ':'))
426 return 0;
427
Lucas De Marchi671d4892011-12-05 20:23:05 -0200428 line = kmod_search_moddep(ctx, name);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200429 if (line != NULL) {
430 struct kmod_module *mod;
431
432 n = kmod_module_new_from_name(ctx, name, &mod);
433 if (n < 0) {
434 ERR(ctx, "%s\n", strerror(-n));
435 goto finish;
436 }
437
438 *list = kmod_list_append(*list, mod);
Lucas De Marchi671d4892011-12-05 20:23:05 -0200439 kmod_module_parse_depline(mod, line);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200440 }
441
442finish:
443 free(line);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200444
445 return n;
446}
447
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200448int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name,
449 struct kmod_list **list)
450{
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200451 struct kmod_config *config = ctx->config;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200452 struct kmod_list *l;
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200453 int err, nmatch = 0;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200454
455 kmod_list_foreach(l, config->aliases) {
456 const char *aliasname = kmod_alias_get_name(l);
457 const char *modname = kmod_alias_get_modname(l);
458
459 if (fnmatch(aliasname, name, 0) == 0) {
460 struct kmod_module *mod;
461
462 err = kmod_module_new_from_name(ctx, modname, &mod);
463 if (err < 0) {
464 ERR(ctx, "%s", strerror(-err));
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200465 goto fail;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200466 }
467
468 *list = kmod_list_append(*list, mod);
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200469 nmatch++;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200470 }
471 }
472
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200473 return nmatch;
474
475fail:
476 *list = kmod_list_remove_n_latest(*list, nmatch);
477 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200478}