blob: 0e71aea7424de220ef872e813864acfbece13e1e [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;
Lucas De Marchi219f9c32011-12-13 13:07:40 -020048 char *name;
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -020049 char *path;
Lucas De Marchi7636e722011-12-01 17:56:03 -020050 struct kmod_list *dep;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020051 char *options;
52 char *install_commands;
53 char *remove_commands;
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -020054 int n_dep;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020055 int refcount;
Lucas De Marchi7636e722011-12-01 17:56:03 -020056 struct {
57 bool dep : 1;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020058 bool options : 1;
59 bool install_commands : 1;
60 bool remove_commands : 1;
Lucas De Marchi7636e722011-12-01 17:56:03 -020061 } init;
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 Marchi219f9c32011-12-13 13:07:40 -0200217 m->name = (char *)m + sizeof(*m);
Lucas De Marchi4f2bb7c2011-12-06 02:46:22 -0200218 memcpy(m->name, name_norm, namelen + 1);
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200219 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200220
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200221 kmod_pool_add_module(ctx, m);
222
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200223 *mod = m;
224
225 return 0;
226}
227
228KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
229 const char *path,
230 struct kmod_module **mod)
231{
232 struct kmod_module *m;
233 int err;
234 struct stat st;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200235 char name[NAME_MAX];
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200236 char *abspath;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200237 size_t namelen;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200238
239 if (ctx == NULL || path == NULL)
240 return -ENOENT;
241
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200242 abspath = path_make_absolute_cwd(path);
243 if (abspath == NULL)
244 return -ENOMEM;
245
246 err = stat(abspath, &st);
247 if (err < 0) {
248 free(abspath);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200249 return -errno;
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200250 }
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200251
Gustavo Sverzut Barbieri973c80b2011-12-12 18:28:52 -0200252 if (path_to_modname(path, name, &namelen) == NULL) {
253 free(abspath);
254 return -ENOENT;
255 }
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200256
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200257 m = kmod_pool_get_module(ctx, name);
258 if (m != NULL) {
Lucas De Marchi6bd0b8d2011-12-07 14:08:01 -0200259 if (m->path == NULL)
260 m->path = abspath;
261 else if (streq(m->path, abspath))
262 free(abspath);
263 else {
264 ERR(ctx, "kmod_module '%s' already exists with different path\n",
265 name);
266 free(abspath);
267 return -EEXIST;
268 }
269
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200270 *mod = kmod_module_ref(m);
271 return 0;
272 }
273
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200274 m = calloc(1, sizeof(*m) + namelen + 1);
275 if (m == NULL)
276 return -errno;
277
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200278 m->ctx = kmod_ref(ctx);
Lucas De Marchi219f9c32011-12-13 13:07:40 -0200279 m->name = (char *)m + sizeof(*m);
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200280 memcpy(m->name, name, namelen);
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200281 m->path = abspath;
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200282 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200283
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200284 kmod_pool_add_module(ctx, m);
285
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200286 *mod = m;
287
288 return 0;
289}
290
291KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
292{
293 if (mod == NULL)
294 return NULL;
295
296 if (--mod->refcount > 0)
297 return mod;
298
299 DBG(mod->ctx, "kmod_module %p released\n", mod);
300
Lucas De Marchi7636e722011-12-01 17:56:03 -0200301 kmod_module_unref_list(mod->dep);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200302 kmod_unref(mod->ctx);
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -0200303 free(mod->options);
304 free(mod->install_commands);
305 free(mod->remove_commands);
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -0200306 free(mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200307 free(mod);
308 return NULL;
309}
310
311KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
312{
313 if (mod == NULL)
314 return NULL;
315
316 mod->refcount++;
317
318 return mod;
319}
320
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200321#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
322 do { \
323 if ((_err) < 0) \
324 goto _label_err; \
325 if (*(_list) != NULL) \
326 goto finish; \
327 } while (0)
328
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200329KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200330 const char *given_alias,
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200331 struct kmod_list **list)
332{
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200333 int err;
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200334 char alias[NAME_MAX];
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200335
Lucas De Marchi4308b172011-12-13 10:26:04 -0200336 if (ctx == NULL || given_alias == NULL)
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200337 return -ENOENT;
338
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200339 if (list == NULL || *list != NULL) {
340 ERR(ctx, "An empty list is needed to create lookup\n");
341 return -ENOSYS;
342 }
343
Lucas De Marchid470db12011-12-13 10:28:00 -0200344 if (alias_normalize(given_alias, alias, NULL) < 0)
345 return -EINVAL;
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200346
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200347 /* Aliases from config file override all the others */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200348 err = kmod_lookup_alias_from_config(ctx, alias, list);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200349 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200350
Lucas De Marchi64700e42011-12-01 15:57:53 -0200351 err = kmod_lookup_alias_from_moddep_file(ctx, alias, list);
352 CHECK_ERR_AND_FINISH(err, fail, list, finish);
353
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200354 err = kmod_lookup_alias_from_symbols_file(ctx, alias, list);
355 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200356
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200357 err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
358 CHECK_ERR_AND_FINISH(err, fail, list, finish);
359
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200360finish:
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200361
362 return err;
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200363fail:
364 kmod_module_unref_list(*list);
365 *list = NULL;
Lucas De Marchi84f42202011-12-02 10:03:34 -0200366 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200367}
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200368#undef CHECK_ERR_AND_FINISH
369
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200370
371KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
372{
373 for (; list != NULL; list = kmod_list_remove(list))
374 kmod_module_unref(list->data);
375
376 return 0;
377}
378
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200379KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200380{
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200381 struct kmod_list *l, *l_new, *list_new = NULL;
382
383 if (mod == NULL)
384 return NULL;
385
Lucas De Marchi671d4892011-12-05 20:23:05 -0200386 if (!mod->init.dep) {
387 /* lazy init */
388 char *line = kmod_search_moddep(mod->ctx, mod->name);
389
390 if (line == NULL)
391 return NULL;
392
393 kmod_module_parse_depline((struct kmod_module *)mod, line);
394 free(line);
395
396 if (!mod->init.dep)
397 return NULL;
398 }
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200399
400 kmod_list_foreach(l, mod->dep) {
401 l_new = kmod_list_append(list_new, kmod_module_ref(l->data));
402 if (l_new == NULL) {
403 kmod_module_unref(l->data);
404 goto fail;
405 }
406
407 list_new = l_new;
408 }
409
410 return list_new;
411
412fail:
413 ERR(mod->ctx, "out of memory\n");
414 kmod_module_unref_list(list_new);
415 return NULL;
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200416}
417
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200418KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200419{
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200420 if (entry == NULL)
421 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200422
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200423 return kmod_module_ref(entry->data);
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200424}
425
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200426KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
427{
428 // FIXME TODO: this should be available from /sys/module/foo
429 FILE *fp;
430 char line[4096];
431 int lineno = 0;
432 long size = -ENOENT;
433
434 if (mod == NULL)
435 return -ENOENT;
436
437 fp = fopen("/proc/modules", "r");
438 if (fp == NULL) {
439 int err = -errno;
440 ERR(mod->ctx,
441 "could not open /proc/modules: %s\n", strerror(errno));
442 return err;
443 }
444
445 while (fgets(line, sizeof(line), fp)) {
446 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
447 long value;
448
449 lineno++;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200450 if (tok == NULL || !streq(tok, mod->name))
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200451 continue;
452
453 tok = strtok_r(NULL, " \t", &saveptr);
454 if (tok == NULL) {
455 ERR(mod->ctx,
456 "invalid line format at /proc/modules:%d\n", lineno);
457 break;
458 }
459
460 value = strtol(tok, &endptr, 10);
461 if (endptr == tok || *endptr != '\0') {
462 ERR(mod->ctx,
463 "invalid line format at /proc/modules:%d\n", lineno);
464 break;
465 }
466
467 size = value;
468 break;
469 }
470 fclose(fp);
471 return size;
472}
473
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200474KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200475{
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200476 return mod->name;
477}
478
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200479KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200480{
Lucas De Marchie005fac2011-12-08 10:42:34 -0200481 char *line;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200482
Gustavo Sverzut Barbierid01c67e2011-12-11 19:42:02 -0200483 DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200484
Lucas De Marchie005fac2011-12-08 10:42:34 -0200485 if (mod->path != NULL)
486 return mod->path;
487 if (mod->init.dep)
488 return NULL;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200489
Lucas De Marchie005fac2011-12-08 10:42:34 -0200490 /* lazy init */
491 line = kmod_search_moddep(mod->ctx, mod->name);
492 if (line == NULL)
493 return NULL;
494
495 kmod_module_parse_depline((struct kmod_module *) mod, line);
496 free(line);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200497
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200498 return mod->path;
499}
500
501
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200502extern long delete_module(const char *name, unsigned int flags);
503
504KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
505 unsigned int flags)
506{
507 int err;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200508
509 if (mod == NULL)
510 return -ENOENT;
511
512 /* Filter out other flags */
513 flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
514
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200515 err = delete_module(mod->name, flags);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200516 if (err != 0) {
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200517 ERR(mod->ctx, "Removing '%s': %s\n", mod->name,
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200518 strerror(-err));
519 return err;
520 }
521
522 return 0;
523}
524
525extern long init_module(void *mem, unsigned long len, const char *args);
526
527KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200528 unsigned int flags,
529 const char *options)
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200530{
531 int err;
532 void *mmaped_file;
533 struct stat st;
534 int fd;
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200535 const char *args = options ? options : "";
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200536
537 if (mod == NULL)
538 return -ENOENT;
539
540 if (mod->path == NULL) {
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200541 ERR(mod->ctx, "Not supported to load a module by name yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200542 return -ENOSYS;
543 }
544
545 if (flags != 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200546 INFO(mod->ctx, "Flags are not implemented yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200547
548 if ((fd = open(mod->path, O_RDONLY)) < 0) {
549 err = -errno;
550 return err;
551 }
552
Lucas De Marchib418a822011-12-01 23:13:27 -0200553 fstat(fd, &st);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200554
555 if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
556 MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
557 close(fd);
558 return -errno;
559 }
560
561 err = init_module(mmaped_file, st.st_size, args);
562 if (err < 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200563 ERR(mod->ctx, "Failed to insert module '%s'\n", mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200564
565 munmap(mmaped_file, st.st_size);
566 close(fd);
567
568 return err;
569}
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200570
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200571KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
572{
573 if (mod == NULL)
574 return NULL;
575
576 if (!mod->init.options) {
577 /* lazy init */
578 struct kmod_module *m = (struct kmod_module *)mod;
579 const struct kmod_list *l, *ctx_options;
580 char *opts = NULL;
581 size_t optslen = 0;
582
583 ctx_options = kmod_get_options(mod->ctx);
584
585 kmod_list_foreach(l, ctx_options) {
586 const char *modname = kmod_option_get_modname(l);
587 const char *str;
588 size_t len;
589 void *tmp;
590
591 if (strcmp(modname, mod->name) != 0)
592 continue;
593
594 str = kmod_option_get_options(l);
595 len = strlen(str);
596 if (len < 1)
597 continue;
598
599 tmp = realloc(opts, optslen + len + 2);
600 if (tmp == NULL) {
601 free(opts);
602 goto failed;
603 }
604
605 opts = tmp;
606
607 if (optslen > 0) {
608 opts[optslen] = ' ';
609 optslen++;
610 }
611
612 memcpy(opts + optslen, str, len);
613 optslen += len;
614 opts[optslen] = '\0';
615 }
616
617 m->init.options = true;
618 m->options = opts;
619 }
620
621 return mod->options;
622
623failed:
624 ERR(mod->ctx, "out of memory\n");
625 return NULL;
626}
627
628KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
629{
630 if (mod == NULL)
631 return NULL;
632
633 if (!mod->init.install_commands) {
634 /* lazy init */
635 struct kmod_module *m = (struct kmod_module *)mod;
636 const struct kmod_list *l, *ctx_install_commands;
637 char *cmds = NULL;
638 size_t cmdslen = 0;
639
640 ctx_install_commands = kmod_get_install_commands(mod->ctx);
641
642 kmod_list_foreach(l, ctx_install_commands) {
643 const char *modname = kmod_command_get_modname(l);
644 const char *str;
645 size_t len;
646 void *tmp;
647
648 if (strcmp(modname, mod->name) != 0)
649 continue;
650
651 str = kmod_command_get_command(l);
652 len = strlen(str);
653 if (len < 1)
654 continue;
655
656 tmp = realloc(cmds, cmdslen + len + 2);
657 if (tmp == NULL) {
658 free(cmds);
659 goto failed;
660 }
661
662 cmds = tmp;
663
664 if (cmdslen > 0) {
665 cmds[cmdslen] = ';';
666 cmdslen++;
667 }
668
669 memcpy(cmds + cmdslen, str, len);
670 cmdslen += len;
671 cmds[cmdslen] = '\0';
672 }
673
674 m->init.install_commands = true;
675 m->install_commands = cmds;
676 }
677
678 return mod->install_commands;
679
680failed:
681 ERR(mod->ctx, "out of memory\n");
682 return NULL;
683}
684
685KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
686{
687 if (mod == NULL)
688 return NULL;
689
690 if (!mod->init.remove_commands) {
691 /* lazy init */
692 struct kmod_module *m = (struct kmod_module *)mod;
693 const struct kmod_list *l, *ctx_remove_commands;
694 char *cmds = NULL;
695 size_t cmdslen = 0;
696
697 ctx_remove_commands = kmod_get_remove_commands(mod->ctx);
698
699 kmod_list_foreach(l, ctx_remove_commands) {
700 const char *modname = kmod_command_get_modname(l);
701 const char *str;
702 size_t len;
703 void *tmp;
704
705 if (strcmp(modname, mod->name) != 0)
706 continue;
707
708 str = kmod_command_get_command(l);
709 len = strlen(str);
710 if (len < 1)
711 continue;
712
713 tmp = realloc(cmds, cmdslen + len + 2);
714 if (tmp == NULL) {
715 free(cmds);
716 goto failed;
717 }
718
719 cmds = tmp;
720
721 if (cmdslen > 0) {
722 cmds[cmdslen] = ';';
723 cmdslen++;
724 }
725
726 memcpy(cmds + cmdslen, str, len);
727 cmdslen += len;
728 cmds[cmdslen] = '\0';
729 }
730
731 m->init.remove_commands = true;
732 m->remove_commands = cmds;
733 }
734
735 return mod->remove_commands;
736
737failed:
738 ERR(mod->ctx, "out of memory\n");
739 return NULL;
740}
741
742/**
743 * SECTION:libkmod-loaded
744 * @short_description: currently loaded modules
745 *
746 * Information about currently loaded modules, as reported by Linux kernel.
747 * These information are not cached by libkmod and are always read from /sys
748 * and /proc/modules.
749 */
750
751/**
752 * kmod_module_new_from_loaded:
753 * @ctx: kmod library context
754 * @list: where to save the list of loaded modules
755 *
756 * Get a list of all modules currently loaded in kernel. It uses /proc/modules
757 * to get the names of loaded modules and to create kmod_module objects by
758 * calling kmod_module_new_from_name() in each of them. They are put are put
759 * in @list in no particular order.
760 *
761 * All the returned modules get their refcount incremented (or are created if
762 * they do not exist yet). After using the list, release the resources by
763 * calling kmod_module_unref_list().
764 *
765 * Returns: 0 on success or < 0 on error.
766 */
767KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx,
768 struct kmod_list **list)
769{
770 struct kmod_list *l = NULL;
771 FILE *fp;
772 char line[4096];
773
774 if (ctx == NULL || list == NULL)
775 return -ENOENT;
776
777 fp = fopen("/proc/modules", "r");
778 if (fp == NULL) {
779 int err = -errno;
780 ERR(ctx, "could not open /proc/modules: %s\n", strerror(errno));
781 return err;
782 }
783
784 while (fgets(line, sizeof(line), fp)) {
785 struct kmod_module *m;
786 struct kmod_list *node;
787 int err;
788 char *saveptr, *name = strtok_r(line, " \t", &saveptr);
789
790 err = kmod_module_new_from_name(ctx, name, &m);
791 if (err < 0) {
792 ERR(ctx, "could not get module from name '%s': %s\n",
793 name, strerror(-err));
794 continue;
795 }
796
797 node = kmod_list_append(l, m);
798 if (node)
799 l = node;
800 else {
801 ERR(ctx, "out of memory\n");
802 kmod_module_unref(m);
803 }
804 }
805
806 fclose(fp);
807 *list = l;
808
809 return 0;
810}
811
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200812KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
813{
814 switch (state) {
815 case KMOD_MODULE_BUILTIN:
816 return "builtin";
817 case KMOD_MODULE_LIVE:
818 return "live";
819 case KMOD_MODULE_COMING:
820 return "coming";
821 case KMOD_MODULE_GOING:
822 return "going";
823 default:
824 return NULL;
825 }
826}
827
828KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
829{
830 char path[PATH_MAX], buf[32];
831 int fd, err, pathlen;
832
833 pathlen = snprintf(path, sizeof(path),
834 "/sys/module/%s/initstate", mod->name);
835 fd = open(path, O_RDONLY);
836 if (fd < 0) {
837 err = -errno;
838
839 if (pathlen > (int)sizeof("/initstate") - 1) {
840 struct stat st;
841 path[pathlen - (sizeof("/initstate") - 1)] = '\0';
842 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
843 return KMOD_MODULE_BUILTIN;
844 }
845
Gustavo Sverzut Barbieri926f67a2011-12-11 19:33:03 -0200846 DBG(mod->ctx, "could not open '%s': %s\n",
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200847 path, strerror(-err));
848 return err;
849 }
850
851 err = read_str_safe(fd, buf, sizeof(buf));
852 close(fd);
853 if (err < 0) {
854 ERR(mod->ctx, "could not read from '%s': %s\n",
855 path, strerror(-err));
856 return err;
857 }
858
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200859 if (streq(buf, "live\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200860 return KMOD_MODULE_LIVE;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200861 else if (streq(buf, "coming\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200862 return KMOD_MODULE_COMING;
Lucas De Marchi877e80c2011-12-07 02:26:31 -0200863 else if (streq(buf, "going\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200864 return KMOD_MODULE_GOING;
865
866 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
867 return -EINVAL;
868}
869
870KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
871{
872 char path[PATH_MAX];
873 long refcnt;
874 int fd, err;
875
876 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
877 fd = open(path, O_RDONLY);
878 if (fd < 0) {
879 err = -errno;
880 ERR(mod->ctx, "could not open '%s': %s\n",
881 path, strerror(errno));
882 return err;
883 }
884
885 err = read_str_long(fd, &refcnt, 10);
886 close(fd);
887 if (err < 0) {
888 ERR(mod->ctx, "could not read integer from '%s': '%s'\n",
889 path, strerror(-err));
890 return err;
891 }
892
893 return (int)refcnt;
894}
895
896KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
897{
898 char dname[PATH_MAX];
899 struct kmod_list *list = NULL;
900 DIR *d;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200901
902 if (mod == NULL)
903 return NULL;
904 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
905
906 d = opendir(dname);
907 if (d == NULL) {
908 ERR(mod->ctx, "could not open '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200909 dname, strerror(errno));
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200910 return NULL;
911 }
912
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200913 for (;;) {
914 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200915 struct kmod_module *holder;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200916 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200917 int err;
918
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200919 err = readdir_r(d, &de, &entp);
920 if (err != 0) {
921 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
922 mod->name, strerror(-err));
923 goto fail;
924 }
925
926 if (entp == NULL)
927 break;
928
929 if (de.d_name[0] == '.') {
930 if (de.d_name[1] == '\0' ||
931 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200932 continue;
933 }
934
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200935 err = kmod_module_new_from_name(mod->ctx, de.d_name, &holder);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200936 if (err < 0) {
937 ERR(mod->ctx, "could not create module for '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200938 de.d_name, strerror(-err));
939 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200940 }
941
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200942 l = kmod_list_append(list, holder);
943 if (l != NULL) {
944 list = l;
945 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200946 ERR(mod->ctx, "out of memory\n");
947 kmod_module_unref(holder);
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200948 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200949 }
950 }
951
952 closedir(d);
953 return list;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200954
955fail:
956 closedir(d);
957 kmod_module_unref_list(list);
958 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200959}
960
961struct kmod_module_section {
962 unsigned long address;
963 char name[];
964};
965
966static void kmod_module_section_free(struct kmod_module_section *section)
967{
968 free(section);
969}
970
971KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
972{
973 char dname[PATH_MAX];
974 struct kmod_list *list = NULL;
975 DIR *d;
976 int dfd;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200977
978 if (mod == NULL)
979 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200980
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200981 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
982
983 d = opendir(dname);
984 if (d == NULL) {
985 ERR(mod->ctx, "could not open '%s': %s\n",
986 dname, strerror(errno));
987 return NULL;
988 }
989
990 dfd = dirfd(d);
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200991
992 for (;;) {
993 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200994 struct kmod_module_section *section;
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200995 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200996 unsigned long address;
997 size_t namesz;
998 int fd, err;
999
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001000 err = readdir_r(d, &de, &entp);
1001 if (err != 0) {
1002 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
1003 mod->name, strerror(-err));
1004 goto fail;
1005 }
1006
1007 if (de.d_name[0] == '.') {
1008 if (de.d_name[1] == '\0' ||
1009 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001010 continue;
1011 }
1012
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001013 fd = openat(dfd, de.d_name, O_RDONLY);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001014 if (fd < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001015 ERR(mod->ctx, "could not open '%s/%s': %m\n",
1016 dname, de.d_name);
1017 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001018 }
1019
1020 err = read_str_ulong(fd, &address, 16);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001021 close(fd);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001022 if (err < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001023 ERR(mod->ctx, "could not read long from '%s/%s': %m\n",
1024 dname, de.d_name);
1025 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001026 }
1027
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001028 namesz = strlen(de.d_name) + 1;
1029 section = malloc(sizeof(*section) + namesz);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001030
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001031 if (section == NULL) {
1032 ERR(mod->ctx, "out of memory\n");
1033 goto fail;
1034 }
1035
1036 section->address = address;
1037 memcpy(section->name, de.d_name, namesz);
1038
1039 l = kmod_list_append(list, section);
1040 if (l != NULL) {
1041 list = l;
1042 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001043 ERR(mod->ctx, "out of memory\n");
1044 free(section);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001045 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001046 }
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001047 }
1048
1049 closedir(d);
1050 return list;
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001051
1052fail:
1053 closedir(d);
1054 kmod_module_unref_list(list);
1055 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001056}
1057
1058KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
1059{
1060 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001061
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001062 if (entry == NULL)
1063 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001064
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001065 section = entry->data;
1066 return section->name;
1067}
1068
1069KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
1070{
1071 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001072
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001073 if (entry == NULL)
1074 return (unsigned long)-1;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001075
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001076 section = entry->data;
1077 return section->address;
1078}
1079
1080KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
1081{
1082 while (list) {
1083 kmod_module_section_free(list->data);
1084 list = kmod_list_remove(list);
1085 }
1086}