blob: 1ad4e2742ccb18eeedbb44b951cb57901d44b665 [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>
24#include <unistd.h>
25#include <errno.h>
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -020026#include <fnmatch.h>
Lucas De Marchi586fc302011-11-21 14:35:35 -020027#include <string.h>
28#include <ctype.h>
Lucas De Marchi221631d2011-11-24 16:41:01 -020029#include <sys/utsname.h>
Lucas De Marchi586fc302011-11-21 14:35:35 -020030
31#include "libkmod.h"
32#include "libkmod-private.h"
Lucas De Marchi9ba6f572011-11-30 20:31:45 -020033#include "libkmod-index.h"
Lucas De Marchi586fc302011-11-21 14:35:35 -020034
35/**
36 * SECTION:libkmod
37 * @short_description: libkmod context
38 *
39 * The context contains the default values for the library user,
40 * and is passed to all library operations.
41 */
42
43/**
44 * kmod_ctx:
45 *
46 * Opaque object representing the library context.
47 */
48struct kmod_ctx {
49 int refcount;
Gustavo Sverzut Barbieri8d3f3ef2011-12-02 21:10:24 -020050 int log_priority;
Lucas De Marchi586fc302011-11-21 14:35:35 -020051 void (*log_fn)(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -020052 int priority, const char *file, int line,
53 const char *fn, const char *format, va_list args);
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020054 const void *userdata;
55 char *dirname;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -020056 struct kmod_config *config;
Lucas De Marchi586fc302011-11-21 14:35:35 -020057};
58
59void kmod_log(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -020060 int priority, const char *file, int line, const char *fn,
61 const char *format, ...)
Lucas De Marchi586fc302011-11-21 14:35:35 -020062{
63 va_list args;
64
65 va_start(args, format);
66 ctx->log_fn(ctx, priority, file, line, fn, format, args);
67 va_end(args);
68}
69
70static void log_stderr(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -020071 int priority, const char *file, int line,
72 const char *fn, const char *format, va_list args)
Lucas De Marchi586fc302011-11-21 14:35:35 -020073{
74 fprintf(stderr, "libkmod: %s: ", fn);
75 vfprintf(stderr, format, args);
76}
77
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020078const char *kmod_get_dirname(const struct kmod_ctx *ctx)
Lucas De Marchi221631d2011-11-24 16:41:01 -020079{
80 return ctx->dirname;
81}
82
Lucas De Marchi586fc302011-11-21 14:35:35 -020083/**
84 * kmod_get_userdata:
85 * @ctx: kmod library context
86 *
87 * Retrieve stored data pointer from library context. This might be useful
88 * to access from callbacks like a custom logging function.
89 *
90 * Returns: stored userdata
91 **/
Lucas De Marchi6d177552011-11-23 11:52:30 -020092KMOD_EXPORT void *kmod_get_userdata(const struct kmod_ctx *ctx)
Lucas De Marchi586fc302011-11-21 14:35:35 -020093{
94 if (ctx == NULL)
95 return NULL;
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -020096 return (void *)ctx->userdata;
Lucas De Marchi586fc302011-11-21 14:35:35 -020097}
98
99/**
100 * kmod_set_userdata:
101 * @ctx: kmod library context
102 * @userdata: data pointer
103 *
104 * Store custom @userdata in the library context.
105 **/
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200106KMOD_EXPORT void kmod_set_userdata(struct kmod_ctx *ctx, const void *userdata)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200107{
108 if (ctx == NULL)
109 return;
110 ctx->userdata = userdata;
111}
112
113static int log_priority(const char *priority)
114{
115 char *endptr;
116 int prio;
117
118 prio = strtol(priority, &endptr, 10);
119 if (endptr[0] == '\0' || isspace(endptr[0]))
120 return prio;
121 if (strncmp(priority, "err", 3) == 0)
122 return LOG_ERR;
123 if (strncmp(priority, "info", 4) == 0)
124 return LOG_INFO;
125 if (strncmp(priority, "debug", 5) == 0)
126 return LOG_DEBUG;
127 return 0;
128}
129
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200130static const char *dirname_default_prefix = "/lib/modules";
131
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200132static char *get_kernel_release(const char *dirname)
Lucas De Marchi221631d2011-11-24 16:41:01 -0200133{
134 struct utsname u;
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200135 char *p;
136
137 if (dirname != NULL)
138 return strdup(dirname);
Lucas De Marchi221631d2011-11-24 16:41:01 -0200139
140 if (uname(&u) < 0)
141 return NULL;
142
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200143 if (asprintf(&p, "%s/%s", dirname_default_prefix, u.release) < 0)
144 return NULL;
145
146 return p;
Lucas De Marchi221631d2011-11-24 16:41:01 -0200147}
148
Lucas De Marchi586fc302011-11-21 14:35:35 -0200149/**
150 * kmod_new:
151 *
152 * Create kmod library context. This reads the kmod configuration
153 * and fills in the default values.
154 *
155 * The initial refcount is 1, and needs to be decremented to
156 * release the resources of the kmod library context.
157 *
158 * Returns: a new kmod library context
159 **/
Lucas De Marchi221631d2011-11-24 16:41:01 -0200160KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200161{
162 const char *env;
Lucas De Marchi52a77042011-11-21 15:07:27 -0200163 struct kmod_ctx *ctx;
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200164 int err;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200165
Lucas De Marchi52a77042011-11-21 15:07:27 -0200166 ctx = calloc(1, sizeof(struct kmod_ctx));
167 if (!ctx)
168 return NULL;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200169
Lucas De Marchi52a77042011-11-21 15:07:27 -0200170 ctx->refcount = 1;
171 ctx->log_fn = log_stderr;
172 ctx->log_priority = LOG_ERR;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200173
Lucas De Marchi904c63a2011-11-30 20:27:50 -0200174 ctx->dirname = get_kernel_release(dirname);
Lucas De Marchi221631d2011-11-24 16:41:01 -0200175
Lucas De Marchi586fc302011-11-21 14:35:35 -0200176 /* environment overwrites config */
177 env = getenv("KMOD_LOG");
178 if (env != NULL)
Lucas De Marchi52a77042011-11-21 15:07:27 -0200179 kmod_set_log_priority(ctx, log_priority(env));
Lucas De Marchi586fc302011-11-21 14:35:35 -0200180
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200181 err = kmod_config_new(ctx, &ctx->config);
182 if (err < 0) {
183 ERR(ctx, "could not create config");
184 free(ctx->dirname);
185 free(ctx);
186 return NULL;
187 }
Lucas De Marchi7c2ab352011-11-29 18:07:43 -0200188
Lucas De Marchiae6df842011-11-25 01:05:30 -0200189 INFO(ctx, "ctx %p created\n", ctx);
190 DBG(ctx, "log_priority=%d\n", ctx->log_priority);
Lucas De Marchi52a77042011-11-21 15:07:27 -0200191
192 return ctx;
Lucas De Marchi586fc302011-11-21 14:35:35 -0200193}
194
195/**
196 * kmod_ref:
197 * @ctx: kmod library context
198 *
199 * Take a reference of the kmod library context.
200 *
201 * Returns: the passed kmod library context
202 **/
203KMOD_EXPORT struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx)
204{
205 if (ctx == NULL)
206 return NULL;
207 ctx->refcount++;
208 return ctx;
209}
210
211/**
212 * kmod_unref:
213 * @ctx: kmod library context
214 *
215 * Drop a reference of the kmod library context. If the refcount
216 * reaches zero, the resources of the context will be released.
217 *
218 **/
219KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx)
220{
221 if (ctx == NULL)
222 return NULL;
Lucas De Marchi4d1e6892011-11-24 15:41:48 -0200223
224 if (--ctx->refcount > 0)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200225 return ctx;
Lucas De Marchiae6df842011-11-25 01:05:30 -0200226 INFO(ctx, "context %p released\n", ctx);
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200227 free(ctx->dirname);
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200228 if (ctx->config)
229 kmod_config_free(ctx->config);
Lucas De Marchi586fc302011-11-21 14:35:35 -0200230 free(ctx);
231 return NULL;
232}
233
234/**
235 * kmod_set_log_fn:
236 * @ctx: kmod library context
237 * @log_fn: function to be called for logging messages
238 *
239 * The built-in logging writes to stderr. It can be
240 * overridden by a custom function, to plug log messages
241 * into the user's logging functionality.
242 *
243 **/
244KMOD_EXPORT void kmod_set_log_fn(struct kmod_ctx *ctx,
Lucas De Marchie4351b02011-11-21 14:59:23 -0200245 void (*log_fn)(struct kmod_ctx *ctx,
246 int priority, const char *file,
247 int line, const char *fn,
248 const char *format, va_list args))
Lucas De Marchi586fc302011-11-21 14:35:35 -0200249{
250 ctx->log_fn = log_fn;
Lucas De Marchiae6df842011-11-25 01:05:30 -0200251 INFO(ctx, "custom logging function %p registered\n", log_fn);
Lucas De Marchi586fc302011-11-21 14:35:35 -0200252}
253
254/**
255 * kmod_get_log_priority:
256 * @ctx: kmod library context
257 *
258 * Returns: the current logging priority
259 **/
Lucas De Marchi6d177552011-11-23 11:52:30 -0200260KMOD_EXPORT int kmod_get_log_priority(const struct kmod_ctx *ctx)
Lucas De Marchi586fc302011-11-21 14:35:35 -0200261{
262 return ctx->log_priority;
263}
264
265/**
266 * kmod_set_log_priority:
267 * @ctx: kmod library context
268 * @priority: the new logging priority
269 *
270 * Set the current logging priority. The value controls which messages
271 * are logged.
272 **/
273KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority)
274{
275 ctx->log_priority = priority;
276}
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200277
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200278
Lucas De Marchia0094822011-12-02 09:53:31 -0200279static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx,
280 const char *file,
Lucas De Marchi7b30f4f2011-12-01 16:25:37 -0200281 const char *name,
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200282 struct kmod_list **list)
283{
284 char *fn;
Lucas De Marchi6f1bc6e2011-12-02 10:02:05 -0200285 int err, nmatch = 0;
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200286 struct index_file *idx;
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200287 struct index_value *realnames, *realname;
288
Lucas De Marchi7b30f4f2011-12-01 16:25:37 -0200289 if (asprintf(&fn, "%s/%s.bin", ctx->dirname, file) < 0)
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200290 return -ENOMEM;
291
Lucas De Marchie915f922011-12-01 17:47:49 -0200292 DBG(ctx, "file=%s name=%s\n", fn, name);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200293
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200294 idx = index_file_open(fn);
295 if (idx == NULL) {
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200296 free(fn);
297 return -ENOSYS;
298 }
299
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200300 realnames = index_searchwild(idx, name);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200301 for (realname = realnames; realname; realname = realnames->next) {
302 struct kmod_module *mod;
303
304 err = kmod_module_new_from_name(ctx, realname->value, &mod);
305 if (err < 0) {
306 ERR(ctx, "%s\n", strerror(-err));
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200307 goto fail;
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200308 }
309
310 *list = kmod_list_append(*list, mod);
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200311 nmatch++;
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200312 }
313
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200314 index_values_free(realnames);
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200315 index_file_close(idx);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200316 free(fn);
317
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200318 return nmatch;
319
320fail:
321 *list = kmod_list_remove_n_latest(*list, nmatch);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200322 return err;
Lucas De Marchi7b30f4f2011-12-01 16:25:37 -0200323
324}
325
326static const char *symbols_file = "modules.symbols";
327
328int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name,
329 struct kmod_list **list)
330{
331 if (!startswith(name, "symbol:"))
332 return 0;
333
334 return kmod_lookup_alias_from_alias_bin(ctx, symbols_file, name, list);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200335}
336
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200337
338static const char *aliases_file = "modules.alias";
339
340int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name,
341 struct kmod_list **list)
342{
343 return kmod_lookup_alias_from_alias_bin(ctx, aliases_file, name, list);
344}
345
Lucas De Marchi64700e42011-12-01 15:57:53 -0200346static const char *moddep_file = "modules.dep";
347
348int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name,
349 struct kmod_list **list)
350{
Lucas De Marchi6f1bc6e2011-12-02 10:02:05 -0200351 char *fn, *line;
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200352 struct index_file *idx;
Lucas De Marchi64700e42011-12-01 15:57:53 -0200353 int n = 0;
354
355 /*
356 * Module names do not contain ':'. Return early if we know it will
357 * not be found.
358 */
359 if (strchr(name, ':'))
360 return 0;
361
362 if (asprintf(&fn, "%s/%s.bin", ctx->dirname, moddep_file) < 0)
363 return -ENOMEM;
364
Lucas De Marchie915f922011-12-01 17:47:49 -0200365 DBG(ctx, "file=%s modname=%s\n", fn, name);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200366
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200367 idx = index_file_open(fn);
368 if (idx == NULL) {
Lucas De Marchi64700e42011-12-01 15:57:53 -0200369 free(fn);
370 return -ENOSYS;
371 }
372
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200373 line = index_search(idx, name);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200374 if (line != NULL) {
375 struct kmod_module *mod;
376
377 n = kmod_module_new_from_name(ctx, name, &mod);
378 if (n < 0) {
379 ERR(ctx, "%s\n", strerror(-n));
380 goto finish;
381 }
382
383 *list = kmod_list_append(*list, mod);
Lucas De Marchi4a3eb3a2011-12-01 17:57:07 -0200384 kmod_module_parse_dep(mod, line);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200385 }
386
387finish:
388 free(line);
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200389 index_file_close(idx);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200390 free(fn);
391
392 return n;
393}
394
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200395int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name,
396 struct kmod_list **list)
397{
Gustavo Sverzut Barbierid13e6062011-12-02 21:40:22 -0200398 struct kmod_config *config = ctx->config;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200399 struct kmod_list *l;
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200400 int err, nmatch = 0;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200401
402 kmod_list_foreach(l, config->aliases) {
403 const char *aliasname = kmod_alias_get_name(l);
404 const char *modname = kmod_alias_get_modname(l);
405
406 if (fnmatch(aliasname, name, 0) == 0) {
407 struct kmod_module *mod;
408
409 err = kmod_module_new_from_name(ctx, modname, &mod);
410 if (err < 0) {
411 ERR(ctx, "%s", strerror(-err));
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200412 goto fail;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200413 }
414
415 *list = kmod_list_append(*list, mod);
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200416 nmatch++;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200417 }
418 }
419
Lucas De Marchi23fc91c2011-12-01 15:35:31 -0200420 return nmatch;
421
422fail:
423 *list = kmod_list_remove_n_latest(*list, nmatch);
424 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200425}