blob: 9429f1d79afa9dbaf26fbfc4fc4427d3cda99431 [file] [log] [blame]
Lucas De Marchi8f788d52011-11-25 01:22:56 -02001/*
2 * libkmod - interface to kernel module operations
3 *
4 * Copyright (C) 2011 ProFUSION embedded systems
Lucas De Marchi8f788d52011-11-25 01:22:56 -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
Lucas De Marchicb451f32011-12-12 18:24:35 -02008 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
Lucas De Marchi8f788d52011-11-25 01:22:56 -020010 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
Lucas De Marchi7636e722011-12-01 17:56:03 -020021#include <assert.h>
Lucas De Marchi8f788d52011-11-25 01:22:56 -020022#include <stdio.h>
23#include <stdlib.h>
24#include <stddef.h>
25#include <stdarg.h>
26#include <unistd.h>
27#include <errno.h>
28#include <string.h>
29#include <ctype.h>
30#include <inttypes.h>
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -020031#include <limits.h>
32#include <dirent.h>
Lucas De Marchi8f788d52011-11-25 01:22:56 -020033#include <sys/stat.h>
34#include <sys/types.h>
35#include <sys/mman.h>
36#include <string.h>
37
38#include "libkmod.h"
39#include "libkmod-private.h"
40
41/**
42 * kmod_module:
43 *
44 * Opaque object representing a module.
45 */
46struct kmod_module {
47 struct kmod_ctx *ctx;
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -020048 char *path;
Lucas De Marchi7636e722011-12-01 17:56:03 -020049 struct kmod_list *dep;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020050 char *options;
51 char *install_commands;
52 char *remove_commands;
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -020053 int n_dep;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020054 int refcount;
Lucas De Marchi7636e722011-12-01 17:56:03 -020055 struct {
56 bool dep : 1;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020057 bool options : 1;
58 bool install_commands : 1;
59 bool remove_commands : 1;
Lucas De Marchi7636e722011-12-01 17:56:03 -020060 } init;
Lucas De Marchid753b8c2011-12-05 18:14:51 -020061 char name[];
Lucas De Marchi8f788d52011-11-25 01:22:56 -020062};
63
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -020064inline char *modname_normalize(const char *modname, char buf[NAME_MAX],
Lucas De Marchi6c343b12011-12-06 09:01:01 -020065 size_t *len)
Lucas De Marchi8f788d52011-11-25 01:22:56 -020066{
Lucas De Marchid753b8c2011-12-05 18:14:51 -020067 size_t s;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020068
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -020069 for (s = 0; s < NAME_MAX - 1; s++) {
70 const char c = modname[s];
71 if (c == '-')
72 buf[s] = '_';
73 else if (c == '\0' || c == '.')
74 break;
75 else
76 buf[s] = c;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020077 }
Lucas De Marchi28c175e2011-12-12 11:52:59 -020078
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -020079 buf[s] = '\0';
Lucas De Marchid753b8c2011-12-05 18:14:51 -020080
81 if (len)
82 *len = s;
83
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -020084 return buf;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020085}
86
Lucas De Marchi6c343b12011-12-06 09:01:01 -020087static char *path_to_modname(const char *path, char buf[NAME_MAX], size_t *len)
88{
89 char *modname;
90
91 modname = basename(path);
92 if (modname == NULL || modname[0] == '\0')
93 return NULL;
94
95 return modname_normalize(modname, buf, len);
96}
97
Lucas De Marchic35347f2011-12-12 10:48:02 -020098static inline const char *path_join(const char *path, size_t prefixlen,
99 char buf[PATH_MAX])
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200100{
101 size_t pathlen;
102
103 if (path[0] == '/')
104 return path;
105
106 pathlen = strlen(path);
107 if (prefixlen + pathlen + 1 >= PATH_MAX)
108 return NULL;
109
110 memcpy(buf + prefixlen, path, pathlen + 1);
111 return buf;
112}
113
Lucas De Marchi671d4892011-12-05 20:23:05 -0200114int kmod_module_parse_depline(struct kmod_module *mod, char *line)
Lucas De Marchi7636e722011-12-01 17:56:03 -0200115{
116 struct kmod_ctx *ctx = mod->ctx;
117 struct kmod_list *list = NULL;
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200118 const char *dirname;
119 char buf[PATH_MAX];
Lucas De Marchi7636e722011-12-01 17:56:03 -0200120 char *p, *saveptr;
Lucas De Marchi45f27782011-12-12 17:23:04 -0200121 int err = 0, n = 0;
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200122 size_t dirnamelen;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200123
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -0200124 if (mod->init.dep)
125 return mod->n_dep;
126 assert(mod->dep == NULL);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200127 mod->init.dep = true;
128
129 p = strchr(line, ':');
130 if (p == NULL)
131 return 0;
132
Lucas De Marchi671d4892011-12-05 20:23:05 -0200133 *p = '\0';
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200134 dirname = kmod_get_dirname(mod->ctx);
135 dirnamelen = strlen(dirname);
136 if (dirnamelen + 2 >= PATH_MAX)
137 return 0;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200138
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200139 memcpy(buf, dirname, dirnamelen);
140 buf[dirnamelen] = '/';
141 dirnamelen++;
142 buf[dirnamelen] = '\0';
143
144 if (mod->path == NULL) {
145 const char *str = path_join(line, dirnamelen, buf);
146 if (str == NULL)
147 return 0;
148 mod->path = strdup(str);
149 if (mod->path == NULL)
150 return 0;
151 }
Lucas De Marchi671d4892011-12-05 20:23:05 -0200152
Lucas De Marchi7636e722011-12-01 17:56:03 -0200153 p++;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200154 for (p = strtok_r(p, " \t", &saveptr); p != NULL;
155 p = strtok_r(NULL, " \t", &saveptr)) {
Lucas De Marchi1fc1c9a2011-12-02 10:00:03 -0200156 struct kmod_module *depmod;
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200157 const char *path;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200158
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200159 path = path_join(p, dirnamelen, buf);
160 if (path == NULL) {
161 ERR(ctx, "could not join path '%s' and '%s'.\n",
162 dirname, p);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200163 goto fail;
164 }
165
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200166 err = kmod_module_new_from_path(ctx, path, &depmod);
167 if (err < 0) {
168 ERR(ctx, "ctx=%p path=%s error=%s\n",
169 ctx, path, strerror(-err));
170 goto fail;
171 }
172
173 DBG(ctx, "add dep: %s\n", path);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200174
Lucas De Marchi1fc1c9a2011-12-02 10:00:03 -0200175 list = kmod_list_append(list, depmod);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200176 n++;
177 }
178
179 DBG(ctx, "%d dependencies for %s\n", n, mod->name);
180
181 mod->dep = list;
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -0200182 mod->n_dep = n;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200183 return n;
184
185fail:
186 kmod_module_unref_list(list);
187 mod->init.dep = false;
188 return err;
189}
190
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200191KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
192 const char *name,
193 struct kmod_module **mod)
194{
195 struct kmod_module *m;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200196 size_t namelen;
Lucas De Marchi4f2bb7c2011-12-06 02:46:22 -0200197 char name_norm[NAME_MAX];
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200198
199 if (ctx == NULL || name == NULL)
200 return -ENOENT;
201
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -0200202 modname_normalize(name, name_norm, &namelen);
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200203
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200204 m = kmod_pool_get_module(ctx, name_norm);
205 if (m != NULL) {
206 *mod = kmod_module_ref(m);
207 return 0;
208 }
209
Lucas De Marchi4f2bb7c2011-12-06 02:46:22 -0200210 m = calloc(1, sizeof(*m) + namelen + 1);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200211 if (m == NULL) {
212 free(m);
213 return -ENOMEM;
214 }
215
216 m->ctx = kmod_ref(ctx);
Lucas De Marchi4f2bb7c2011-12-06 02:46:22 -0200217 memcpy(m->name, name_norm, namelen + 1);
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200218 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200219
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200220 kmod_pool_add_module(ctx, m);
221
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200222 *mod = m;
223
224 return 0;
225}
226
227KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
228 const char *path,
229 struct kmod_module **mod)
230{
231 struct kmod_module *m;
232 int err;
233 struct stat st;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200234 char name[NAME_MAX];
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200235 char *abspath;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200236 size_t namelen;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200237
238 if (ctx == NULL || path == NULL)
239 return -ENOENT;
240
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200241 abspath = path_make_absolute_cwd(path);
242 if (abspath == NULL)
243 return -ENOMEM;
244
245 err = stat(abspath, &st);
246 if (err < 0) {
247 free(abspath);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200248 return -errno;
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200249 }
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200250
Gustavo Sverzut Barbieri973c80b2011-12-12 18:28:52 -0200251 if (path_to_modname(path, name, &namelen) == NULL) {
252 free(abspath);
253 return -ENOENT;
254 }
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200255
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200256 m = kmod_pool_get_module(ctx, name);
257 if (m != NULL) {
Lucas De Marchi6bd0b8d2011-12-07 14:08:01 -0200258 if (m->path == NULL)
259 m->path = abspath;
260 else if (streq(m->path, abspath))
261 free(abspath);
262 else {
263 ERR(ctx, "kmod_module '%s' already exists with different path\n",
264 name);
265 free(abspath);
266 return -EEXIST;
267 }
268
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200269 *mod = kmod_module_ref(m);
270 return 0;
271 }
272
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200273 m = calloc(1, sizeof(*m) + namelen + 1);
274 if (m == NULL)
275 return -errno;
276
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200277 m->ctx = kmod_ref(ctx);
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200278 memcpy(m->name, name, namelen);
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200279 m->path = abspath;
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200280 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200281
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200282 kmod_pool_add_module(ctx, m);
283
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200284 *mod = m;
285
286 return 0;
287}
288
289KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
290{
291 if (mod == NULL)
292 return NULL;
293
294 if (--mod->refcount > 0)
295 return mod;
296
297 DBG(mod->ctx, "kmod_module %p released\n", mod);
298
Lucas De Marchi7636e722011-12-01 17:56:03 -0200299 kmod_module_unref_list(mod->dep);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200300 kmod_unref(mod->ctx);
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -0200301 free(mod->options);
302 free(mod->install_commands);
303 free(mod->remove_commands);
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -0200304 free(mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200305 free(mod);
306 return NULL;
307}
308
309KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
310{
311 if (mod == NULL)
312 return NULL;
313
314 mod->refcount++;
315
316 return mod;
317}
318
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200319#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
320 do { \
321 if ((_err) < 0) \
322 goto _label_err; \
323 if (*(_list) != NULL) \
324 goto finish; \
325 } while (0)
326
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200327KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200328 const char *given_alias,
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200329 struct kmod_list **list)
330{
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200331 int err;
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200332 char alias[NAME_MAX];
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200333
Lucas De Marchi4308b172011-12-13 10:26:04 -0200334 if (ctx == NULL || given_alias == NULL)
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200335 return -ENOENT;
336
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200337 if (list == NULL || *list != NULL) {
338 ERR(ctx, "An empty list is needed to create lookup\n");
339 return -ENOSYS;
340 }
341
Lucas De Marchid470db12011-12-13 10:28:00 -0200342 if (alias_normalize(given_alias, alias, NULL) < 0)
343 return -EINVAL;
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200344
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200345 /* Aliases from config file override all the others */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200346 err = kmod_lookup_alias_from_config(ctx, alias, list);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200347 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200348
Lucas De Marchi64700e42011-12-01 15:57:53 -0200349 err = kmod_lookup_alias_from_moddep_file(ctx, alias, list);
350 CHECK_ERR_AND_FINISH(err, fail, list, finish);
351
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200352 err = kmod_lookup_alias_from_symbols_file(ctx, alias, list);
353 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200354
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200355 err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
356 CHECK_ERR_AND_FINISH(err, fail, list, finish);
357
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200358finish:
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200359
360 return err;
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200361fail:
362 kmod_module_unref_list(*list);
363 *list = NULL;
Lucas De Marchi84f42202011-12-02 10:03:34 -0200364 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200365}
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200366#undef CHECK_ERR_AND_FINISH
367
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200368
369KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
370{
371 for (; list != NULL; list = kmod_list_remove(list))
372 kmod_module_unref(list->data);
373
374 return 0;
375}
376
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200377KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200378{
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200379 struct kmod_list *l, *l_new, *list_new = NULL;
380
381 if (mod == NULL)
382 return NULL;
383
Lucas De Marchi671d4892011-12-05 20:23:05 -0200384 if (!mod->init.dep) {
385 /* lazy init */
386 char *line = kmod_search_moddep(mod->ctx, mod->name);
387
388 if (line == NULL)
389 return NULL;
390
391 kmod_module_parse_depline((struct kmod_module *)mod, line);
392 free(line);
393
394 if (!mod->init.dep)
395 return NULL;
396 }
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200397
398 kmod_list_foreach(l, mod->dep) {
399 l_new = kmod_list_append(list_new, kmod_module_ref(l->data));
400 if (l_new == NULL) {
401 kmod_module_unref(l->data);
402 goto fail;
403 }
404
405 list_new = l_new;
406 }
407
408 return list_new;
409
410fail:
411 ERR(mod->ctx, "out of memory\n");
412 kmod_module_unref_list(list_new);
413 return NULL;
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200414}
415
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200416KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200417{
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200418 if (entry == NULL)
419 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200420
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200421 return kmod_module_ref(entry->data);
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200422}
423
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200424KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
425{
426 // FIXME TODO: this should be available from /sys/module/foo
427 FILE *fp;
428 char line[4096];
429 int lineno = 0;
430 long size = -ENOENT;
431
432 if (mod == NULL)
433 return -ENOENT;
434
435 fp = fopen("/proc/modules", "r");
436 if (fp == NULL) {
437 int err = -errno;
438 ERR(mod->ctx,
439 "could not open /proc/modules: %s\n", strerror(errno));
440 return err;
441 }
442
443 while (fgets(line, sizeof(line), fp)) {
444 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
445 long value;
446
447 lineno++;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200448 if (tok == NULL || !streq(tok, mod->name))
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200449 continue;
450
451 tok = strtok_r(NULL, " \t", &saveptr);
452 if (tok == NULL) {
453 ERR(mod->ctx,
454 "invalid line format at /proc/modules:%d\n", lineno);
455 break;
456 }
457
458 value = strtol(tok, &endptr, 10);
459 if (endptr == tok || *endptr != '\0') {
460 ERR(mod->ctx,
461 "invalid line format at /proc/modules:%d\n", lineno);
462 break;
463 }
464
465 size = value;
466 break;
467 }
468 fclose(fp);
469 return size;
470}
471
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200472KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200473{
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200474 return mod->name;
475}
476
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200477KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200478{
Lucas De Marchie005fac2011-12-08 10:42:34 -0200479 char *line;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200480
Gustavo Sverzut Barbierid01c67e2011-12-11 19:42:02 -0200481 DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200482
Lucas De Marchie005fac2011-12-08 10:42:34 -0200483 if (mod->path != NULL)
484 return mod->path;
485 if (mod->init.dep)
486 return NULL;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200487
Lucas De Marchie005fac2011-12-08 10:42:34 -0200488 /* lazy init */
489 line = kmod_search_moddep(mod->ctx, mod->name);
490 if (line == NULL)
491 return NULL;
492
493 kmod_module_parse_depline((struct kmod_module *) mod, line);
494 free(line);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200495
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200496 return mod->path;
497}
498
499
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200500extern long delete_module(const char *name, unsigned int flags);
501
502KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
503 unsigned int flags)
504{
505 int err;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200506
507 if (mod == NULL)
508 return -ENOENT;
509
510 /* Filter out other flags */
511 flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
512
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200513 err = delete_module(mod->name, flags);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200514 if (err != 0) {
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200515 ERR(mod->ctx, "Removing '%s': %s\n", mod->name,
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200516 strerror(-err));
517 return err;
518 }
519
520 return 0;
521}
522
523extern long init_module(void *mem, unsigned long len, const char *args);
524
525KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200526 unsigned int flags,
527 const char *options)
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200528{
529 int err;
530 void *mmaped_file;
531 struct stat st;
532 int fd;
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200533 const char *args = options ? options : "";
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200534
535 if (mod == NULL)
536 return -ENOENT;
537
538 if (mod->path == NULL) {
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200539 ERR(mod->ctx, "Not supported to load a module by name yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200540 return -ENOSYS;
541 }
542
543 if (flags != 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200544 INFO(mod->ctx, "Flags are not implemented yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200545
546 if ((fd = open(mod->path, O_RDONLY)) < 0) {
547 err = -errno;
548 return err;
549 }
550
Lucas De Marchib418a822011-12-01 23:13:27 -0200551 fstat(fd, &st);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200552
553 if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
554 MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
555 close(fd);
556 return -errno;
557 }
558
559 err = init_module(mmaped_file, st.st_size, args);
560 if (err < 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200561 ERR(mod->ctx, "Failed to insert module '%s'\n", mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200562
563 munmap(mmaped_file, st.st_size);
564 close(fd);
565
566 return err;
567}
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200568
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200569KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
570{
571 if (mod == NULL)
572 return NULL;
573
574 if (!mod->init.options) {
575 /* lazy init */
576 struct kmod_module *m = (struct kmod_module *)mod;
577 const struct kmod_list *l, *ctx_options;
578 char *opts = NULL;
579 size_t optslen = 0;
580
581 ctx_options = kmod_get_options(mod->ctx);
582
583 kmod_list_foreach(l, ctx_options) {
584 const char *modname = kmod_option_get_modname(l);
585 const char *str;
586 size_t len;
587 void *tmp;
588
589 if (strcmp(modname, mod->name) != 0)
590 continue;
591
592 str = kmod_option_get_options(l);
593 len = strlen(str);
594 if (len < 1)
595 continue;
596
597 tmp = realloc(opts, optslen + len + 2);
598 if (tmp == NULL) {
599 free(opts);
600 goto failed;
601 }
602
603 opts = tmp;
604
605 if (optslen > 0) {
606 opts[optslen] = ' ';
607 optslen++;
608 }
609
610 memcpy(opts + optslen, str, len);
611 optslen += len;
612 opts[optslen] = '\0';
613 }
614
615 m->init.options = true;
616 m->options = opts;
617 }
618
619 return mod->options;
620
621failed:
622 ERR(mod->ctx, "out of memory\n");
623 return NULL;
624}
625
626KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
627{
628 if (mod == NULL)
629 return NULL;
630
631 if (!mod->init.install_commands) {
632 /* lazy init */
633 struct kmod_module *m = (struct kmod_module *)mod;
634 const struct kmod_list *l, *ctx_install_commands;
635 char *cmds = NULL;
636 size_t cmdslen = 0;
637
638 ctx_install_commands = kmod_get_install_commands(mod->ctx);
639
640 kmod_list_foreach(l, ctx_install_commands) {
641 const char *modname = kmod_command_get_modname(l);
642 const char *str;
643 size_t len;
644 void *tmp;
645
646 if (strcmp(modname, mod->name) != 0)
647 continue;
648
649 str = kmod_command_get_command(l);
650 len = strlen(str);
651 if (len < 1)
652 continue;
653
654 tmp = realloc(cmds, cmdslen + len + 2);
655 if (tmp == NULL) {
656 free(cmds);
657 goto failed;
658 }
659
660 cmds = tmp;
661
662 if (cmdslen > 0) {
663 cmds[cmdslen] = ';';
664 cmdslen++;
665 }
666
667 memcpy(cmds + cmdslen, str, len);
668 cmdslen += len;
669 cmds[cmdslen] = '\0';
670 }
671
672 m->init.install_commands = true;
673 m->install_commands = cmds;
674 }
675
676 return mod->install_commands;
677
678failed:
679 ERR(mod->ctx, "out of memory\n");
680 return NULL;
681}
682
683KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
684{
685 if (mod == NULL)
686 return NULL;
687
688 if (!mod->init.remove_commands) {
689 /* lazy init */
690 struct kmod_module *m = (struct kmod_module *)mod;
691 const struct kmod_list *l, *ctx_remove_commands;
692 char *cmds = NULL;
693 size_t cmdslen = 0;
694
695 ctx_remove_commands = kmod_get_remove_commands(mod->ctx);
696
697 kmod_list_foreach(l, ctx_remove_commands) {
698 const char *modname = kmod_command_get_modname(l);
699 const char *str;
700 size_t len;
701 void *tmp;
702
703 if (strcmp(modname, mod->name) != 0)
704 continue;
705
706 str = kmod_command_get_command(l);
707 len = strlen(str);
708 if (len < 1)
709 continue;
710
711 tmp = realloc(cmds, cmdslen + len + 2);
712 if (tmp == NULL) {
713 free(cmds);
714 goto failed;
715 }
716
717 cmds = tmp;
718
719 if (cmdslen > 0) {
720 cmds[cmdslen] = ';';
721 cmdslen++;
722 }
723
724 memcpy(cmds + cmdslen, str, len);
725 cmdslen += len;
726 cmds[cmdslen] = '\0';
727 }
728
729 m->init.remove_commands = true;
730 m->remove_commands = cmds;
731 }
732
733 return mod->remove_commands;
734
735failed:
736 ERR(mod->ctx, "out of memory\n");
737 return NULL;
738}
739
740/**
741 * SECTION:libkmod-loaded
742 * @short_description: currently loaded modules
743 *
744 * Information about currently loaded modules, as reported by Linux kernel.
745 * These information are not cached by libkmod and are always read from /sys
746 * and /proc/modules.
747 */
748
749/**
750 * kmod_module_new_from_loaded:
751 * @ctx: kmod library context
752 * @list: where to save the list of loaded modules
753 *
754 * Get a list of all modules currently loaded in kernel. It uses /proc/modules
755 * to get the names of loaded modules and to create kmod_module objects by
756 * calling kmod_module_new_from_name() in each of them. They are put are put
757 * in @list in no particular order.
758 *
759 * All the returned modules get their refcount incremented (or are created if
760 * they do not exist yet). After using the list, release the resources by
761 * calling kmod_module_unref_list().
762 *
763 * Returns: 0 on success or < 0 on error.
764 */
765KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx,
766 struct kmod_list **list)
767{
768 struct kmod_list *l = NULL;
769 FILE *fp;
770 char line[4096];
771
772 if (ctx == NULL || list == NULL)
773 return -ENOENT;
774
775 fp = fopen("/proc/modules", "r");
776 if (fp == NULL) {
777 int err = -errno;
778 ERR(ctx, "could not open /proc/modules: %s\n", strerror(errno));
779 return err;
780 }
781
782 while (fgets(line, sizeof(line), fp)) {
783 struct kmod_module *m;
784 struct kmod_list *node;
785 int err;
786 char *saveptr, *name = strtok_r(line, " \t", &saveptr);
787
788 err = kmod_module_new_from_name(ctx, name, &m);
789 if (err < 0) {
790 ERR(ctx, "could not get module from name '%s': %s\n",
791 name, strerror(-err));
792 continue;
793 }
794
795 node = kmod_list_append(l, m);
796 if (node)
797 l = node;
798 else {
799 ERR(ctx, "out of memory\n");
800 kmod_module_unref(m);
801 }
802 }
803
804 fclose(fp);
805 *list = l;
806
807 return 0;
808}
809
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200810KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
811{
812 switch (state) {
813 case KMOD_MODULE_BUILTIN:
814 return "builtin";
815 case KMOD_MODULE_LIVE:
816 return "live";
817 case KMOD_MODULE_COMING:
818 return "coming";
819 case KMOD_MODULE_GOING:
820 return "going";
821 default:
822 return NULL;
823 }
824}
825
826KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
827{
828 char path[PATH_MAX], buf[32];
829 int fd, err, pathlen;
830
831 pathlen = snprintf(path, sizeof(path),
832 "/sys/module/%s/initstate", mod->name);
833 fd = open(path, O_RDONLY);
834 if (fd < 0) {
835 err = -errno;
836
837 if (pathlen > (int)sizeof("/initstate") - 1) {
838 struct stat st;
839 path[pathlen - (sizeof("/initstate") - 1)] = '\0';
840 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
841 return KMOD_MODULE_BUILTIN;
842 }
843
Gustavo Sverzut Barbieri926f67a2011-12-11 19:33:03 -0200844 DBG(mod->ctx, "could not open '%s': %s\n",
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200845 path, strerror(-err));
846 return err;
847 }
848
849 err = read_str_safe(fd, buf, sizeof(buf));
850 close(fd);
851 if (err < 0) {
852 ERR(mod->ctx, "could not read from '%s': %s\n",
853 path, strerror(-err));
854 return err;
855 }
856
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200857 if (streq(buf, "live\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200858 return KMOD_MODULE_LIVE;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200859 else if (streq(buf, "coming\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200860 return KMOD_MODULE_COMING;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200861 else if (streq(buf, "going\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200862 return KMOD_MODULE_GOING;
863
864 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
865 return -EINVAL;
866}
867
868KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
869{
870 char path[PATH_MAX];
871 long refcnt;
872 int fd, err;
873
874 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
875 fd = open(path, O_RDONLY);
876 if (fd < 0) {
877 err = -errno;
878 ERR(mod->ctx, "could not open '%s': %s\n",
879 path, strerror(errno));
880 return err;
881 }
882
883 err = read_str_long(fd, &refcnt, 10);
884 close(fd);
885 if (err < 0) {
886 ERR(mod->ctx, "could not read integer from '%s': '%s'\n",
887 path, strerror(-err));
888 return err;
889 }
890
891 return (int)refcnt;
892}
893
894KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
895{
896 char dname[PATH_MAX];
897 struct kmod_list *list = NULL;
898 DIR *d;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200899
900 if (mod == NULL)
901 return NULL;
902 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
903
904 d = opendir(dname);
905 if (d == NULL) {
906 ERR(mod->ctx, "could not open '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200907 dname, strerror(errno));
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200908 return NULL;
909 }
910
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200911 for (;;) {
912 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200913 struct kmod_module *holder;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200914 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200915 int err;
916
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200917 err = readdir_r(d, &de, &entp);
918 if (err != 0) {
919 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
920 mod->name, strerror(-err));
921 goto fail;
922 }
923
924 if (entp == NULL)
925 break;
926
927 if (de.d_name[0] == '.') {
928 if (de.d_name[1] == '\0' ||
929 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200930 continue;
931 }
932
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200933 err = kmod_module_new_from_name(mod->ctx, de.d_name, &holder);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200934 if (err < 0) {
935 ERR(mod->ctx, "could not create module for '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200936 de.d_name, strerror(-err));
937 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200938 }
939
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200940 l = kmod_list_append(list, holder);
941 if (l != NULL) {
942 list = l;
943 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200944 ERR(mod->ctx, "out of memory\n");
945 kmod_module_unref(holder);
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200946 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200947 }
948 }
949
950 closedir(d);
951 return list;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200952
953fail:
954 closedir(d);
955 kmod_module_unref_list(list);
956 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200957}
958
959struct kmod_module_section {
960 unsigned long address;
961 char name[];
962};
963
964static void kmod_module_section_free(struct kmod_module_section *section)
965{
966 free(section);
967}
968
969KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
970{
971 char dname[PATH_MAX];
972 struct kmod_list *list = NULL;
973 DIR *d;
974 int dfd;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200975
976 if (mod == NULL)
977 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200978
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200979 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
980
981 d = opendir(dname);
982 if (d == NULL) {
983 ERR(mod->ctx, "could not open '%s': %s\n",
984 dname, strerror(errno));
985 return NULL;
986 }
987
988 dfd = dirfd(d);
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200989
990 for (;;) {
991 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200992 struct kmod_module_section *section;
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200993 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200994 unsigned long address;
995 size_t namesz;
996 int fd, err;
997
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200998 err = readdir_r(d, &de, &entp);
999 if (err != 0) {
1000 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
1001 mod->name, strerror(-err));
1002 goto fail;
1003 }
1004
1005 if (de.d_name[0] == '.') {
1006 if (de.d_name[1] == '\0' ||
1007 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001008 continue;
1009 }
1010
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001011 fd = openat(dfd, de.d_name, O_RDONLY);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001012 if (fd < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001013 ERR(mod->ctx, "could not open '%s/%s': %m\n",
1014 dname, de.d_name);
1015 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001016 }
1017
1018 err = read_str_ulong(fd, &address, 16);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001019 close(fd);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001020 if (err < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001021 ERR(mod->ctx, "could not read long from '%s/%s': %m\n",
1022 dname, de.d_name);
1023 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001024 }
1025
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001026 namesz = strlen(de.d_name) + 1;
1027 section = malloc(sizeof(*section) + namesz);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001028
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001029 if (section == NULL) {
1030 ERR(mod->ctx, "out of memory\n");
1031 goto fail;
1032 }
1033
1034 section->address = address;
1035 memcpy(section->name, de.d_name, namesz);
1036
1037 l = kmod_list_append(list, section);
1038 if (l != NULL) {
1039 list = l;
1040 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001041 ERR(mod->ctx, "out of memory\n");
1042 free(section);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001043 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001044 }
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001045 }
1046
1047 closedir(d);
1048 return list;
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001049
1050fail:
1051 closedir(d);
1052 kmod_module_unref_list(list);
1053 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001054}
1055
1056KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
1057{
1058 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001059
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001060 if (entry == NULL)
1061 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001062
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001063 section = entry->data;
1064 return section->name;
1065}
1066
1067KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
1068{
1069 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001070
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001071 if (entry == NULL)
1072 return (unsigned long)-1;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001073
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001074 section = entry->data;
1075 return section->address;
1076}
1077
1078KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
1079{
1080 while (list) {
1081 kmod_module_section_free(list->data);
1082 list = kmod_list_remove(list);
1083 }
1084}