blob: ee1be6dea1be7d7328b9ed79738500af83be13d7 [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
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200251 path_to_modname(path, name, &namelen);
252
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200253 m = kmod_pool_get_module(ctx, name);
254 if (m != NULL) {
Lucas De Marchi6bd0b8d2011-12-07 14:08:01 -0200255 if (m->path == NULL)
256 m->path = abspath;
257 else if (streq(m->path, abspath))
258 free(abspath);
259 else {
260 ERR(ctx, "kmod_module '%s' already exists with different path\n",
261 name);
262 free(abspath);
263 return -EEXIST;
264 }
265
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200266 *mod = kmod_module_ref(m);
267 return 0;
268 }
269
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200270 m = calloc(1, sizeof(*m) + namelen + 1);
271 if (m == NULL)
272 return -errno;
273
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200274 m->ctx = kmod_ref(ctx);
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200275 memcpy(m->name, name, namelen);
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200276 m->path = abspath;
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200277 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200278
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200279 kmod_pool_add_module(ctx, m);
280
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200281 *mod = m;
282
283 return 0;
284}
285
286KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
287{
288 if (mod == NULL)
289 return NULL;
290
291 if (--mod->refcount > 0)
292 return mod;
293
294 DBG(mod->ctx, "kmod_module %p released\n", mod);
295
Lucas De Marchi7636e722011-12-01 17:56:03 -0200296 kmod_module_unref_list(mod->dep);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200297 kmod_unref(mod->ctx);
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -0200298 free(mod->options);
299 free(mod->install_commands);
300 free(mod->remove_commands);
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -0200301 free(mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200302 free(mod);
303 return NULL;
304}
305
306KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
307{
308 if (mod == NULL)
309 return NULL;
310
311 mod->refcount++;
312
313 return mod;
314}
315
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200316#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
317 do { \
318 if ((_err) < 0) \
319 goto _label_err; \
320 if (*(_list) != NULL) \
321 goto finish; \
322 } while (0)
323
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200324KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200325 const char *given_alias,
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200326 struct kmod_list **list)
327{
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200328 int err;
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200329 char alias[NAME_MAX];
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200330
331 if (ctx == NULL || alias == NULL)
332 return -ENOENT;
333
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200334 if (list == NULL || *list != NULL) {
335 ERR(ctx, "An empty list is needed to create lookup\n");
336 return -ENOSYS;
337 }
338
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200339 modname_normalize(given_alias, alias, NULL);
340
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200341 /* Aliases from config file override all the others */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200342 err = kmod_lookup_alias_from_config(ctx, alias, list);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200343 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200344
Lucas De Marchi64700e42011-12-01 15:57:53 -0200345 err = kmod_lookup_alias_from_moddep_file(ctx, alias, list);
346 CHECK_ERR_AND_FINISH(err, fail, list, finish);
347
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200348 err = kmod_lookup_alias_from_symbols_file(ctx, alias, list);
349 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200350
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200351 err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
352 CHECK_ERR_AND_FINISH(err, fail, list, finish);
353
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200354finish:
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200355
356 return err;
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200357fail:
358 kmod_module_unref_list(*list);
359 *list = NULL;
Lucas De Marchi84f42202011-12-02 10:03:34 -0200360 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200361}
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200362#undef CHECK_ERR_AND_FINISH
363
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200364
365KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
366{
367 for (; list != NULL; list = kmod_list_remove(list))
368 kmod_module_unref(list->data);
369
370 return 0;
371}
372
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200373KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200374{
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200375 struct kmod_list *l, *l_new, *list_new = NULL;
376
377 if (mod == NULL)
378 return NULL;
379
Lucas De Marchi671d4892011-12-05 20:23:05 -0200380 if (!mod->init.dep) {
381 /* lazy init */
382 char *line = kmod_search_moddep(mod->ctx, mod->name);
383
384 if (line == NULL)
385 return NULL;
386
387 kmod_module_parse_depline((struct kmod_module *)mod, line);
388 free(line);
389
390 if (!mod->init.dep)
391 return NULL;
392 }
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200393
394 kmod_list_foreach(l, mod->dep) {
395 l_new = kmod_list_append(list_new, kmod_module_ref(l->data));
396 if (l_new == NULL) {
397 kmod_module_unref(l->data);
398 goto fail;
399 }
400
401 list_new = l_new;
402 }
403
404 return list_new;
405
406fail:
407 ERR(mod->ctx, "out of memory\n");
408 kmod_module_unref_list(list_new);
409 return NULL;
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200410}
411
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200412KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200413{
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200414 if (entry == NULL)
415 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200416
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200417 return kmod_module_ref(entry->data);
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200418}
419
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200420KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
421{
422 // FIXME TODO: this should be available from /sys/module/foo
423 FILE *fp;
424 char line[4096];
425 int lineno = 0;
426 long size = -ENOENT;
427
428 if (mod == NULL)
429 return -ENOENT;
430
431 fp = fopen("/proc/modules", "r");
432 if (fp == NULL) {
433 int err = -errno;
434 ERR(mod->ctx,
435 "could not open /proc/modules: %s\n", strerror(errno));
436 return err;
437 }
438
439 while (fgets(line, sizeof(line), fp)) {
440 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
441 long value;
442
443 lineno++;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200444 if (tok == NULL || !streq(tok, mod->name))
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200445 continue;
446
447 tok = strtok_r(NULL, " \t", &saveptr);
448 if (tok == NULL) {
449 ERR(mod->ctx,
450 "invalid line format at /proc/modules:%d\n", lineno);
451 break;
452 }
453
454 value = strtol(tok, &endptr, 10);
455 if (endptr == tok || *endptr != '\0') {
456 ERR(mod->ctx,
457 "invalid line format at /proc/modules:%d\n", lineno);
458 break;
459 }
460
461 size = value;
462 break;
463 }
464 fclose(fp);
465 return size;
466}
467
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200468KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200469{
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200470 return mod->name;
471}
472
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200473KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200474{
Lucas De Marchie005fac2011-12-08 10:42:34 -0200475 char *line;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200476
Gustavo Sverzut Barbierid01c67e2011-12-11 19:42:02 -0200477 DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200478
Lucas De Marchie005fac2011-12-08 10:42:34 -0200479 if (mod->path != NULL)
480 return mod->path;
481 if (mod->init.dep)
482 return NULL;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200483
Lucas De Marchie005fac2011-12-08 10:42:34 -0200484 /* lazy init */
485 line = kmod_search_moddep(mod->ctx, mod->name);
486 if (line == NULL)
487 return NULL;
488
489 kmod_module_parse_depline((struct kmod_module *) mod, line);
490 free(line);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200491
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200492 return mod->path;
493}
494
495
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200496extern long delete_module(const char *name, unsigned int flags);
497
498KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
499 unsigned int flags)
500{
501 int err;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200502
503 if (mod == NULL)
504 return -ENOENT;
505
506 /* Filter out other flags */
507 flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
508
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200509 err = delete_module(mod->name, flags);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200510 if (err != 0) {
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200511 ERR(mod->ctx, "Removing '%s': %s\n", mod->name,
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200512 strerror(-err));
513 return err;
514 }
515
516 return 0;
517}
518
519extern long init_module(void *mem, unsigned long len, const char *args);
520
521KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200522 unsigned int flags,
523 const char *options)
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200524{
525 int err;
526 void *mmaped_file;
527 struct stat st;
528 int fd;
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200529 const char *args = options ? options : "";
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200530
531 if (mod == NULL)
532 return -ENOENT;
533
534 if (mod->path == NULL) {
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200535 ERR(mod->ctx, "Not supported to load a module by name yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200536 return -ENOSYS;
537 }
538
539 if (flags != 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200540 INFO(mod->ctx, "Flags are not implemented yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200541
542 if ((fd = open(mod->path, O_RDONLY)) < 0) {
543 err = -errno;
544 return err;
545 }
546
Lucas De Marchib418a822011-12-01 23:13:27 -0200547 fstat(fd, &st);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200548
549 if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
550 MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
551 close(fd);
552 return -errno;
553 }
554
555 err = init_module(mmaped_file, st.st_size, args);
556 if (err < 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200557 ERR(mod->ctx, "Failed to insert module '%s'\n", mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200558
559 munmap(mmaped_file, st.st_size);
560 close(fd);
561
562 return err;
563}
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200564
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200565KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
566{
567 if (mod == NULL)
568 return NULL;
569
570 if (!mod->init.options) {
571 /* lazy init */
572 struct kmod_module *m = (struct kmod_module *)mod;
573 const struct kmod_list *l, *ctx_options;
574 char *opts = NULL;
575 size_t optslen = 0;
576
577 ctx_options = kmod_get_options(mod->ctx);
578
579 kmod_list_foreach(l, ctx_options) {
580 const char *modname = kmod_option_get_modname(l);
581 const char *str;
582 size_t len;
583 void *tmp;
584
585 if (strcmp(modname, mod->name) != 0)
586 continue;
587
588 str = kmod_option_get_options(l);
589 len = strlen(str);
590 if (len < 1)
591 continue;
592
593 tmp = realloc(opts, optslen + len + 2);
594 if (tmp == NULL) {
595 free(opts);
596 goto failed;
597 }
598
599 opts = tmp;
600
601 if (optslen > 0) {
602 opts[optslen] = ' ';
603 optslen++;
604 }
605
606 memcpy(opts + optslen, str, len);
607 optslen += len;
608 opts[optslen] = '\0';
609 }
610
611 m->init.options = true;
612 m->options = opts;
613 }
614
615 return mod->options;
616
617failed:
618 ERR(mod->ctx, "out of memory\n");
619 return NULL;
620}
621
622KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
623{
624 if (mod == NULL)
625 return NULL;
626
627 if (!mod->init.install_commands) {
628 /* lazy init */
629 struct kmod_module *m = (struct kmod_module *)mod;
630 const struct kmod_list *l, *ctx_install_commands;
631 char *cmds = NULL;
632 size_t cmdslen = 0;
633
634 ctx_install_commands = kmod_get_install_commands(mod->ctx);
635
636 kmod_list_foreach(l, ctx_install_commands) {
637 const char *modname = kmod_command_get_modname(l);
638 const char *str;
639 size_t len;
640 void *tmp;
641
642 if (strcmp(modname, mod->name) != 0)
643 continue;
644
645 str = kmod_command_get_command(l);
646 len = strlen(str);
647 if (len < 1)
648 continue;
649
650 tmp = realloc(cmds, cmdslen + len + 2);
651 if (tmp == NULL) {
652 free(cmds);
653 goto failed;
654 }
655
656 cmds = tmp;
657
658 if (cmdslen > 0) {
659 cmds[cmdslen] = ';';
660 cmdslen++;
661 }
662
663 memcpy(cmds + cmdslen, str, len);
664 cmdslen += len;
665 cmds[cmdslen] = '\0';
666 }
667
668 m->init.install_commands = true;
669 m->install_commands = cmds;
670 }
671
672 return mod->install_commands;
673
674failed:
675 ERR(mod->ctx, "out of memory\n");
676 return NULL;
677}
678
679KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
680{
681 if (mod == NULL)
682 return NULL;
683
684 if (!mod->init.remove_commands) {
685 /* lazy init */
686 struct kmod_module *m = (struct kmod_module *)mod;
687 const struct kmod_list *l, *ctx_remove_commands;
688 char *cmds = NULL;
689 size_t cmdslen = 0;
690
691 ctx_remove_commands = kmod_get_remove_commands(mod->ctx);
692
693 kmod_list_foreach(l, ctx_remove_commands) {
694 const char *modname = kmod_command_get_modname(l);
695 const char *str;
696 size_t len;
697 void *tmp;
698
699 if (strcmp(modname, mod->name) != 0)
700 continue;
701
702 str = kmod_command_get_command(l);
703 len = strlen(str);
704 if (len < 1)
705 continue;
706
707 tmp = realloc(cmds, cmdslen + len + 2);
708 if (tmp == NULL) {
709 free(cmds);
710 goto failed;
711 }
712
713 cmds = tmp;
714
715 if (cmdslen > 0) {
716 cmds[cmdslen] = ';';
717 cmdslen++;
718 }
719
720 memcpy(cmds + cmdslen, str, len);
721 cmdslen += len;
722 cmds[cmdslen] = '\0';
723 }
724
725 m->init.remove_commands = true;
726 m->remove_commands = cmds;
727 }
728
729 return mod->remove_commands;
730
731failed:
732 ERR(mod->ctx, "out of memory\n");
733 return NULL;
734}
735
736/**
737 * SECTION:libkmod-loaded
738 * @short_description: currently loaded modules
739 *
740 * Information about currently loaded modules, as reported by Linux kernel.
741 * These information are not cached by libkmod and are always read from /sys
742 * and /proc/modules.
743 */
744
745/**
746 * kmod_module_new_from_loaded:
747 * @ctx: kmod library context
748 * @list: where to save the list of loaded modules
749 *
750 * Get a list of all modules currently loaded in kernel. It uses /proc/modules
751 * to get the names of loaded modules and to create kmod_module objects by
752 * calling kmod_module_new_from_name() in each of them. They are put are put
753 * in @list in no particular order.
754 *
755 * All the returned modules get their refcount incremented (or are created if
756 * they do not exist yet). After using the list, release the resources by
757 * calling kmod_module_unref_list().
758 *
759 * Returns: 0 on success or < 0 on error.
760 */
761KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx,
762 struct kmod_list **list)
763{
764 struct kmod_list *l = NULL;
765 FILE *fp;
766 char line[4096];
767
768 if (ctx == NULL || list == NULL)
769 return -ENOENT;
770
771 fp = fopen("/proc/modules", "r");
772 if (fp == NULL) {
773 int err = -errno;
774 ERR(ctx, "could not open /proc/modules: %s\n", strerror(errno));
775 return err;
776 }
777
778 while (fgets(line, sizeof(line), fp)) {
779 struct kmod_module *m;
780 struct kmod_list *node;
781 int err;
782 char *saveptr, *name = strtok_r(line, " \t", &saveptr);
783
784 err = kmod_module_new_from_name(ctx, name, &m);
785 if (err < 0) {
786 ERR(ctx, "could not get module from name '%s': %s\n",
787 name, strerror(-err));
788 continue;
789 }
790
791 node = kmod_list_append(l, m);
792 if (node)
793 l = node;
794 else {
795 ERR(ctx, "out of memory\n");
796 kmod_module_unref(m);
797 }
798 }
799
800 fclose(fp);
801 *list = l;
802
803 return 0;
804}
805
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200806KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
807{
808 switch (state) {
809 case KMOD_MODULE_BUILTIN:
810 return "builtin";
811 case KMOD_MODULE_LIVE:
812 return "live";
813 case KMOD_MODULE_COMING:
814 return "coming";
815 case KMOD_MODULE_GOING:
816 return "going";
817 default:
818 return NULL;
819 }
820}
821
822KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
823{
824 char path[PATH_MAX], buf[32];
825 int fd, err, pathlen;
826
827 pathlen = snprintf(path, sizeof(path),
828 "/sys/module/%s/initstate", mod->name);
829 fd = open(path, O_RDONLY);
830 if (fd < 0) {
831 err = -errno;
832
833 if (pathlen > (int)sizeof("/initstate") - 1) {
834 struct stat st;
835 path[pathlen - (sizeof("/initstate") - 1)] = '\0';
836 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
837 return KMOD_MODULE_BUILTIN;
838 }
839
Gustavo Sverzut Barbieri926f67a2011-12-11 19:33:03 -0200840 DBG(mod->ctx, "could not open '%s': %s\n",
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200841 path, strerror(-err));
842 return err;
843 }
844
845 err = read_str_safe(fd, buf, sizeof(buf));
846 close(fd);
847 if (err < 0) {
848 ERR(mod->ctx, "could not read from '%s': %s\n",
849 path, strerror(-err));
850 return err;
851 }
852
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200853 if (streq(buf, "live\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200854 return KMOD_MODULE_LIVE;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200855 else if (streq(buf, "coming\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200856 return KMOD_MODULE_COMING;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200857 else if (streq(buf, "going\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200858 return KMOD_MODULE_GOING;
859
860 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
861 return -EINVAL;
862}
863
864KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
865{
866 char path[PATH_MAX];
867 long refcnt;
868 int fd, err;
869
870 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
871 fd = open(path, O_RDONLY);
872 if (fd < 0) {
873 err = -errno;
874 ERR(mod->ctx, "could not open '%s': %s\n",
875 path, strerror(errno));
876 return err;
877 }
878
879 err = read_str_long(fd, &refcnt, 10);
880 close(fd);
881 if (err < 0) {
882 ERR(mod->ctx, "could not read integer from '%s': '%s'\n",
883 path, strerror(-err));
884 return err;
885 }
886
887 return (int)refcnt;
888}
889
890KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
891{
892 char dname[PATH_MAX];
893 struct kmod_list *list = NULL;
894 DIR *d;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200895
896 if (mod == NULL)
897 return NULL;
898 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
899
900 d = opendir(dname);
901 if (d == NULL) {
902 ERR(mod->ctx, "could not open '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200903 dname, strerror(errno));
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200904 return NULL;
905 }
906
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200907 for (;;) {
908 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200909 struct kmod_module *holder;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200910 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200911 int err;
912
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200913 err = readdir_r(d, &de, &entp);
914 if (err != 0) {
915 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
916 mod->name, strerror(-err));
917 goto fail;
918 }
919
920 if (entp == NULL)
921 break;
922
923 if (de.d_name[0] == '.') {
924 if (de.d_name[1] == '\0' ||
925 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200926 continue;
927 }
928
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200929 err = kmod_module_new_from_name(mod->ctx, de.d_name, &holder);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200930 if (err < 0) {
931 ERR(mod->ctx, "could not create module for '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200932 de.d_name, strerror(-err));
933 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200934 }
935
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200936 l = kmod_list_append(list, holder);
937 if (l != NULL) {
938 list = l;
939 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200940 ERR(mod->ctx, "out of memory\n");
941 kmod_module_unref(holder);
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200942 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200943 }
944 }
945
946 closedir(d);
947 return list;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200948
949fail:
950 closedir(d);
951 kmod_module_unref_list(list);
952 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200953}
954
955struct kmod_module_section {
956 unsigned long address;
957 char name[];
958};
959
960static void kmod_module_section_free(struct kmod_module_section *section)
961{
962 free(section);
963}
964
965KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
966{
967 char dname[PATH_MAX];
968 struct kmod_list *list = NULL;
969 DIR *d;
970 int dfd;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200971
972 if (mod == NULL)
973 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200974
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200975 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
976
977 d = opendir(dname);
978 if (d == NULL) {
979 ERR(mod->ctx, "could not open '%s': %s\n",
980 dname, strerror(errno));
981 return NULL;
982 }
983
984 dfd = dirfd(d);
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200985
986 for (;;) {
987 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200988 struct kmod_module_section *section;
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200989 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200990 unsigned long address;
991 size_t namesz;
992 int fd, err;
993
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200994 err = readdir_r(d, &de, &entp);
995 if (err != 0) {
996 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
997 mod->name, strerror(-err));
998 goto fail;
999 }
1000
1001 if (de.d_name[0] == '.') {
1002 if (de.d_name[1] == '\0' ||
1003 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001004 continue;
1005 }
1006
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001007 fd = openat(dfd, de.d_name, O_RDONLY);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001008 if (fd < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001009 ERR(mod->ctx, "could not open '%s/%s': %m\n",
1010 dname, de.d_name);
1011 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001012 }
1013
1014 err = read_str_ulong(fd, &address, 16);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001015 close(fd);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001016 if (err < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001017 ERR(mod->ctx, "could not read long from '%s/%s': %m\n",
1018 dname, de.d_name);
1019 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001020 }
1021
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001022 namesz = strlen(de.d_name) + 1;
1023 section = malloc(sizeof(*section) + namesz);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001024
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001025 if (section == NULL) {
1026 ERR(mod->ctx, "out of memory\n");
1027 goto fail;
1028 }
1029
1030 section->address = address;
1031 memcpy(section->name, de.d_name, namesz);
1032
1033 l = kmod_list_append(list, section);
1034 if (l != NULL) {
1035 list = l;
1036 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001037 ERR(mod->ctx, "out of memory\n");
1038 free(section);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001039 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001040 }
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001041 }
1042
1043 closedir(d);
1044 return list;
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001045
1046fail:
1047 closedir(d);
1048 kmod_module_unref_list(list);
1049 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001050}
1051
1052KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
1053{
1054 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001055
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001056 if (entry == NULL)
1057 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001058
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001059 section = entry->data;
1060 return section->name;
1061}
1062
1063KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
1064{
1065 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001066
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001067 if (entry == NULL)
1068 return (unsigned long)-1;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001069
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001070 section = entry->data;
1071 return section->address;
1072}
1073
1074KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
1075{
1076 while (list) {
1077 kmod_module_section_free(list->data);
1078 list = kmod_list_remove(list);
1079 }
1080}