blob: 9ad3f827297888d201cc9c247c79985ccf02220b [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>
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -020037#include <fnmatch.h>
Lucas De Marchi8f788d52011-11-25 01:22:56 -020038
39#include "libkmod.h"
40#include "libkmod-private.h"
41
42/**
43 * kmod_module:
44 *
45 * Opaque object representing a module.
46 */
47struct kmod_module {
48 struct kmod_ctx *ctx;
Lucas De Marchi8bdeca12011-12-15 13:11:51 -020049 char *hashkey;
Lucas De Marchi219f9c32011-12-13 13:07:40 -020050 char *name;
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -020051 char *path;
Lucas De Marchi7636e722011-12-01 17:56:03 -020052 struct kmod_list *dep;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020053 char *options;
Lucas De Marchi60f67602011-12-16 03:33:26 -020054 const char *install_commands; /* owned by kmod_config */
55 const char *remove_commands; /* owned by kmod_config */
Lucas De Marchi6ad5f262011-12-13 14:12:50 -020056 char *alias; /* only set if this module was created from an alias */
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -020057 int n_dep;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020058 int refcount;
Lucas De Marchi7636e722011-12-01 17:56:03 -020059 struct {
60 bool dep : 1;
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -020061 bool options : 1;
62 bool install_commands : 1;
63 bool remove_commands : 1;
Lucas De Marchi7636e722011-12-01 17:56:03 -020064 } init;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020065};
66
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -020067inline char *modname_normalize(const char *modname, char buf[NAME_MAX],
Lucas De Marchi6c343b12011-12-06 09:01:01 -020068 size_t *len)
Lucas De Marchi8f788d52011-11-25 01:22:56 -020069{
Lucas De Marchid753b8c2011-12-05 18:14:51 -020070 size_t s;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020071
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -020072 for (s = 0; s < NAME_MAX - 1; s++) {
73 const char c = modname[s];
74 if (c == '-')
75 buf[s] = '_';
76 else if (c == '\0' || c == '.')
77 break;
78 else
79 buf[s] = c;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020080 }
Lucas De Marchi28c175e2011-12-12 11:52:59 -020081
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -020082 buf[s] = '\0';
Lucas De Marchid753b8c2011-12-05 18:14:51 -020083
84 if (len)
85 *len = s;
86
Gustavo Sverzut Barbierie1a6b302011-12-08 04:10:49 -020087 return buf;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020088}
89
Lucas De Marchi6c343b12011-12-06 09:01:01 -020090static char *path_to_modname(const char *path, char buf[NAME_MAX], size_t *len)
91{
92 char *modname;
93
94 modname = basename(path);
95 if (modname == NULL || modname[0] == '\0')
96 return NULL;
97
98 return modname_normalize(modname, buf, len);
99}
100
Lucas De Marchic35347f2011-12-12 10:48:02 -0200101static inline const char *path_join(const char *path, size_t prefixlen,
102 char buf[PATH_MAX])
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200103{
104 size_t pathlen;
105
106 if (path[0] == '/')
107 return path;
108
109 pathlen = strlen(path);
110 if (prefixlen + pathlen + 1 >= PATH_MAX)
111 return NULL;
112
113 memcpy(buf + prefixlen, path, pathlen + 1);
114 return buf;
115}
116
Lucas De Marchi671d4892011-12-05 20:23:05 -0200117int kmod_module_parse_depline(struct kmod_module *mod, char *line)
Lucas De Marchi7636e722011-12-01 17:56:03 -0200118{
119 struct kmod_ctx *ctx = mod->ctx;
120 struct kmod_list *list = NULL;
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200121 const char *dirname;
122 char buf[PATH_MAX];
Lucas De Marchi7636e722011-12-01 17:56:03 -0200123 char *p, *saveptr;
Lucas De Marchi45f27782011-12-12 17:23:04 -0200124 int err = 0, n = 0;
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200125 size_t dirnamelen;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200126
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -0200127 if (mod->init.dep)
128 return mod->n_dep;
129 assert(mod->dep == NULL);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200130 mod->init.dep = true;
131
132 p = strchr(line, ':');
133 if (p == NULL)
134 return 0;
135
Lucas De Marchi671d4892011-12-05 20:23:05 -0200136 *p = '\0';
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200137 dirname = kmod_get_dirname(mod->ctx);
138 dirnamelen = strlen(dirname);
139 if (dirnamelen + 2 >= PATH_MAX)
140 return 0;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200141
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200142 memcpy(buf, dirname, dirnamelen);
143 buf[dirnamelen] = '/';
144 dirnamelen++;
145 buf[dirnamelen] = '\0';
146
147 if (mod->path == NULL) {
148 const char *str = path_join(line, dirnamelen, buf);
149 if (str == NULL)
150 return 0;
151 mod->path = strdup(str);
152 if (mod->path == NULL)
153 return 0;
154 }
Lucas De Marchi671d4892011-12-05 20:23:05 -0200155
Lucas De Marchi7636e722011-12-01 17:56:03 -0200156 p++;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200157 for (p = strtok_r(p, " \t", &saveptr); p != NULL;
158 p = strtok_r(NULL, " \t", &saveptr)) {
Lucas De Marchi1fc1c9a2011-12-02 10:00:03 -0200159 struct kmod_module *depmod;
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200160 const char *path;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200161
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200162 path = path_join(p, dirnamelen, buf);
163 if (path == NULL) {
164 ERR(ctx, "could not join path '%s' and '%s'.\n",
165 dirname, p);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200166 goto fail;
167 }
168
Gustavo Sverzut Barbierie18ad352011-12-08 04:44:03 -0200169 err = kmod_module_new_from_path(ctx, path, &depmod);
170 if (err < 0) {
171 ERR(ctx, "ctx=%p path=%s error=%s\n",
172 ctx, path, strerror(-err));
173 goto fail;
174 }
175
176 DBG(ctx, "add dep: %s\n", path);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200177
Lucas De Marchib94a7372011-12-26 20:10:49 -0200178 list = kmod_list_prepend(list, depmod);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200179 n++;
180 }
181
182 DBG(ctx, "%d dependencies for %s\n", n, mod->name);
183
184 mod->dep = list;
Gustavo Sverzut Barbierib6a534f2011-12-10 20:36:22 -0200185 mod->n_dep = n;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200186 return n;
187
188fail:
189 kmod_module_unref_list(list);
190 mod->init.dep = false;
191 return err;
192}
193
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200194/**
195 * kmod_module_new_from_name:
196 * @ctx: kmod library context
197 * @name: name of the module
198 * @mod: where to save the created struct kmod_module
199 *
200 * Create a new struct kmod_module using the module name. @name can not be an
201 * alias, file name or anything else; it must be a module name. There's no
202 * check if the module does exists in the system.
203 *
204 * This function is also used internally by many others that return a new
205 * struct kmod_module or a new list of modules.
206 *
207 * The initial refcount is 1, and needs to be decremented to release the
208 * resources of the kmod_module. Since libkmod keeps track of all
209 * kmod_modules created, they are all released upon @ctx destruction too. Do
210 * not unref @ctx before all the desired operations with the returned
211 * kmod_module are done.
212 *
213 * Returns: 0 on success or < 0 otherwise. It fails if name is not a valid
214 * module name or if memory allocation failed.
215 */
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200216KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
217 const char *name,
218 struct kmod_module **mod)
219{
220 struct kmod_module *m;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200221 size_t namelen;
Lucas De Marchi4f2bb7c2011-12-06 02:46:22 -0200222 char name_norm[NAME_MAX];
Lucas De Marchi113c66a2011-12-14 15:21:10 -0200223 char *namesep;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200224
Lucas De Marchi818f8e82011-12-15 13:35:40 -0200225 if (ctx == NULL || name == NULL || mod == NULL)
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200226 return -ENOENT;
227
Luis Felipe Strano Moraes9efaf2f2011-12-20 08:13:56 -0800228 if (alias_normalize(name, name_norm, &namelen) < 0) {
229 DBG(ctx, "invalid alias: %s\n", name);
230 return -EINVAL;
231 }
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200232
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200233 m = kmod_pool_get_module(ctx, name_norm);
234 if (m != NULL) {
235 *mod = kmod_module_ref(m);
236 return 0;
237 }
238
Lucas De Marchi8bdeca12011-12-15 13:11:51 -0200239 namesep = strchr(name_norm, '/');
240 m = malloc(sizeof(*m) + (namesep == NULL ? 1 : 2) * namelen + 2);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200241 if (m == NULL) {
242 free(m);
243 return -ENOMEM;
244 }
245
Lucas De Marchi788ef0f2011-12-14 15:05:03 -0200246 memset(m, 0, sizeof(*m));
247
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200248 m->ctx = kmod_ref(ctx);
Lucas De Marchi219f9c32011-12-13 13:07:40 -0200249 m->name = (char *)m + sizeof(*m);
Lucas De Marchi4f2bb7c2011-12-06 02:46:22 -0200250 memcpy(m->name, name_norm, namelen + 1);
Lucas De Marchi113c66a2011-12-14 15:21:10 -0200251
Lucas De Marchi8bdeca12011-12-15 13:11:51 -0200252 if (namesep) {
253 size_t len = namesep - name_norm;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200254
Lucas De Marchi8bdeca12011-12-15 13:11:51 -0200255 m->name[len] = '\0';
256 m->alias = m->name + len + 1;
257 m->hashkey = m->name + namelen + 1;
258 memcpy(m->hashkey, name_norm, namelen + 1);
259 } else {
260 m->hashkey = m->name;
Lucas De Marchi113c66a2011-12-14 15:21:10 -0200261 }
262
Lucas De Marchi8bdeca12011-12-15 13:11:51 -0200263 m->refcount = 1;
264 kmod_pool_add_module(ctx, m, m->hashkey);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200265 *mod = m;
266
267 return 0;
268}
269
Lucas De Marchi6ad5f262011-12-13 14:12:50 -0200270int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias,
271 const char *name, struct kmod_module **mod)
272{
273 int err;
Lucas De Marchi113c66a2011-12-14 15:21:10 -0200274 char key[NAME_MAX];
275 size_t namelen = strlen(name);
276 size_t aliaslen = strlen(alias);
Lucas De Marchi6ad5f262011-12-13 14:12:50 -0200277
Lucas De Marchi113c66a2011-12-14 15:21:10 -0200278 if (namelen + aliaslen + 2 > NAME_MAX)
279 return -ENAMETOOLONG;
280
281 memcpy(key, name, namelen);
282 memcpy(key + namelen + 1, alias, aliaslen + 1);
283 key[namelen] = '/';
284
285 err = kmod_module_new_from_name(ctx, key, mod);
Lucas De Marchi6ad5f262011-12-13 14:12:50 -0200286 if (err < 0)
287 return err;
288
Lucas De Marchi6ad5f262011-12-13 14:12:50 -0200289 return 0;
Lucas De Marchi6ad5f262011-12-13 14:12:50 -0200290}
291
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200292/**
293 * kmod_module_new_from_path:
294 * @ctx: kmod library context
295 * @path: path where to find the given module
296 * @mod: where to save the created struct kmod_module
297 *
298 * Create a new struct kmod_module using the module path. @path must be an
299 * existent file with in the filesystem and must be accessible to libkmod.
300 *
301 * The initial refcount is 1, and needs to be decremented to release the
302 * resources of the kmod_module. Since libkmod keeps track of all
303 * kmod_modules created, they are all released upon @ctx destruction too. Do
304 * not unref @ctx before all the desired operations with the returned
305 * kmod_module are done.
306 *
307 * If @path is relative, it's treated as relative to the current working
308 * directory. Otherwise, give an absolute path.
309 *
310 * Returns: 0 on success or < 0 otherwise. It fails if file does not exist, if
311 * it's not a valid file for a kmod_module or if memory allocation failed.
312 */
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200313KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
314 const char *path,
315 struct kmod_module **mod)
316{
317 struct kmod_module *m;
318 int err;
319 struct stat st;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200320 char name[NAME_MAX];
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200321 char *abspath;
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200322 size_t namelen;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200323
Lucas De Marchi818f8e82011-12-15 13:35:40 -0200324 if (ctx == NULL || path == NULL || mod == NULL)
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200325 return -ENOENT;
326
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200327 abspath = path_make_absolute_cwd(path);
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200328 if (abspath == NULL) {
329 DBG(ctx, "no absolute path for %s\n", path);
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200330 return -ENOMEM;
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200331 }
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200332
333 err = stat(abspath, &st);
334 if (err < 0) {
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200335 err = -errno;
336 DBG(ctx, "stat %s: %s\n", path, strerror(errno));
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200337 free(abspath);
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200338 return err;
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200339 }
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200340
Gustavo Sverzut Barbieri973c80b2011-12-12 18:28:52 -0200341 if (path_to_modname(path, name, &namelen) == NULL) {
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200342 DBG(ctx, "could not get modname from path %s\n", path);
Gustavo Sverzut Barbieri973c80b2011-12-12 18:28:52 -0200343 free(abspath);
344 return -ENOENT;
345 }
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200346
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200347 m = kmod_pool_get_module(ctx, name);
348 if (m != NULL) {
Lucas De Marchi6bd0b8d2011-12-07 14:08:01 -0200349 if (m->path == NULL)
350 m->path = abspath;
351 else if (streq(m->path, abspath))
352 free(abspath);
353 else {
354 ERR(ctx, "kmod_module '%s' already exists with different path\n",
355 name);
356 free(abspath);
357 return -EEXIST;
358 }
359
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200360 *mod = kmod_module_ref(m);
361 return 0;
362 }
363
Lucas De Marchi788ef0f2011-12-14 15:05:03 -0200364 m = malloc(sizeof(*m) + namelen + 1);
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200365 if (m == NULL)
366 return -errno;
367
Lucas De Marchi788ef0f2011-12-14 15:05:03 -0200368 memset(m, 0, sizeof(*m));
369
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200370 m->ctx = kmod_ref(ctx);
Lucas De Marchi219f9c32011-12-13 13:07:40 -0200371 m->name = (char *)m + sizeof(*m);
Lucas De Marchi9dec2442011-12-18 15:12:19 -0200372 memcpy(m->name, name, namelen + 1);
Lucas De Marchi71e975c2011-12-07 13:53:53 -0200373 m->path = abspath;
Lucas De Marchi8bdeca12011-12-15 13:11:51 -0200374 m->hashkey = m->name;
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200375 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200376
Lucas De Marchi8bdeca12011-12-15 13:11:51 -0200377 kmod_pool_add_module(ctx, m, m->hashkey);
Lucas De Marchifd186ae2011-12-06 03:38:37 -0200378
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200379 *mod = m;
380
381 return 0;
382}
383
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200384/**
385 * kmod_module_unref:
386 * @mod: kmod module
387 *
388 * Drop a reference of the kmod module. If the refcount reaches zero, its
389 * resources are released.
390 *
391 * Returns: NULL if @mod is NULL or if the module was released. Otherwise it
392 * returns the passed @mod with its refcount decremented.
393 */
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200394KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
395{
396 if (mod == NULL)
397 return NULL;
398
399 if (--mod->refcount > 0)
400 return mod;
401
402 DBG(mod->ctx, "kmod_module %p released\n", mod);
403
Lucas De Marchi4084c172011-12-15 13:43:22 -0200404 kmod_pool_del_module(mod->ctx, mod, mod->hashkey);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200405 kmod_module_unref_list(mod->dep);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200406 kmod_unref(mod->ctx);
Gustavo Sverzut Barbieribd3f5532011-12-10 20:47:01 -0200407 free(mod->options);
Gustavo Sverzut Barbierif1fb6f82011-12-08 04:44:03 -0200408 free(mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200409 free(mod);
410 return NULL;
411}
412
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200413/**
414 * kmod_module_ref:
415 * @mod: kmod module
416 *
417 * Take a reference of the kmod module, incrementing its refcount.
418 *
419 * Returns: the passed @module with its refcount incremented.
420 */
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200421KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
422{
423 if (mod == NULL)
424 return NULL;
425
426 mod->refcount++;
427
428 return mod;
429}
430
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200431#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
432 do { \
433 if ((_err) < 0) \
434 goto _label_err; \
435 if (*(_list) != NULL) \
436 goto finish; \
437 } while (0)
438
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200439/**
440 * kmod_module_new_from_lookup:
441 * @ctx: kmod library context
442 * @given_alias: alias to look for
443 * @list: an empty list where to save the list of modules matching
444 * @given_alias
445 *
446 * Create a new list of kmod modules using an alias or module name and lookup
447 * libkmod's configuration files and indexes in order to find the module.
448 * Once it's found in one of the places, it stops searching and create the
449 * list of modules that is saved in @list.
450 *
451 * The search order is: 1. aliases in configuration file; 2. module names in
452 * modules.dep index; 3. symbol aliases in modules.symbols index; 4. aliases
453 * in modules.alias index.
454 *
455 * The initial refcount is 1, and needs to be decremented to release the
456 * resources of the kmod_module. The returned @list must be released by
457 * calling kmod_module_unref_list(). Since libkmod keeps track of all
458 * kmod_modules created, they are all released upon @ctx destruction too. Do
459 * not unref @ctx before all the desired operations with the returned list are
460 * completed.
461 *
462 * Returns: 0 on success or < 0 otherwise. It fails if any of the lookup
463 * methods failed, which is basically due to memory allocation fail. If module
464 * is not found, it still returns 0, but @list is an empty list.
465 */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200466KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200467 const char *given_alias,
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200468 struct kmod_list **list)
469{
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200470 int err;
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200471 char alias[NAME_MAX];
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200472
Lucas De Marchi4308b172011-12-13 10:26:04 -0200473 if (ctx == NULL || given_alias == NULL)
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200474 return -ENOENT;
475
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200476 if (list == NULL || *list != NULL) {
477 ERR(ctx, "An empty list is needed to create lookup\n");
478 return -ENOSYS;
479 }
480
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200481 if (alias_normalize(given_alias, alias, NULL) < 0) {
482 DBG(ctx, "invalid alias: %s\n", given_alias);
Lucas De Marchid470db12011-12-13 10:28:00 -0200483 return -EINVAL;
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200484 }
485
486 DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias);
Gustavo Sverzut Barbierid917f272011-12-10 21:00:19 -0200487
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200488 /* Aliases from config file override all the others */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200489 err = kmod_lookup_alias_from_config(ctx, alias, list);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200490 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200491
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200492 DBG(ctx, "lookup modules.dep %s\n", alias);
Lucas De Marchi64700e42011-12-01 15:57:53 -0200493 err = kmod_lookup_alias_from_moddep_file(ctx, alias, list);
494 CHECK_ERR_AND_FINISH(err, fail, list, finish);
495
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200496 DBG(ctx, "lookup modules.symbols %s\n", alias);
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200497 err = kmod_lookup_alias_from_symbols_file(ctx, alias, list);
498 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200499
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200500 DBG(ctx, "lookup install and remove commands %s\n", alias);
Lucas De Marchif4fc5522011-12-16 03:57:12 -0200501 err = kmod_lookup_alias_from_commands(ctx, alias, list);
502 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200503
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200504 DBG(ctx, "lookup modules.aliases %s\n", alias);
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200505 err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
506 CHECK_ERR_AND_FINISH(err, fail, list, finish);
507
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200508finish:
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200509 DBG(ctx, "lookup %s=%d, list=%p\n", alias, err, *list);
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200510 return err;
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200511fail:
Gustavo Sverzut Barbierib55df2e2011-12-20 13:04:10 -0200512 DBG(ctx, "Failed to lookup %s\n", alias);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200513 kmod_module_unref_list(*list);
514 *list = NULL;
Lucas De Marchi84f42202011-12-02 10:03:34 -0200515 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200516}
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200517#undef CHECK_ERR_AND_FINISH
518
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200519/**
Lucas De Marchi91428ae2011-12-15 13:09:46 -0200520 * kmod_module_unref_list:
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200521 * @list: list of kmod modules
522 *
523 * Drop a reference of each kmod module in @list and releases the resources
524 * taken by the list itself.
525 *
526 * Returns: NULL if @mod is NULL or if the module was released. Otherwise it
527 * returns the passed @mod with its refcount decremented.
528 */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200529KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
530{
531 for (; list != NULL; list = kmod_list_remove(list))
532 kmod_module_unref(list->data);
533
534 return 0;
535}
536
Lucas De Marchib72f74b2011-12-27 04:51:05 -0200537static const struct kmod_list *module_get_dependencies_noref(const struct kmod_module *mod)
538{
539 if (!mod->init.dep) {
540 /* lazy init */
541 char *line = kmod_search_moddep(mod->ctx, mod->name);
542
543 if (line == NULL)
544 return NULL;
545
546 kmod_module_parse_depline((struct kmod_module *)mod, line);
547 free(line);
548
549 if (!mod->init.dep)
550 return NULL;
551 }
552
553 return mod->dep;
554}
555
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200556/**
Lucas De Marchi91428ae2011-12-15 13:09:46 -0200557 * kmod_module_get_dependencies:
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200558 * @mod: kmod module
559 *
560 * Search the modules.dep index to find the dependencies of the given @mod.
561 * The result is cached in @mod, so subsequent calls to this function will
562 * return the already searched list of modules.
563 *
564 * Returns: NULL on failure or if there are any dependencies. Otherwise it
565 * returns a list of kmod modules that can be released by calling
566 * kmod_module_unref_list().
567 */
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200568KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod)
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200569{
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200570 struct kmod_list *l, *l_new, *list_new = NULL;
571
572 if (mod == NULL)
573 return NULL;
574
Lucas De Marchib72f74b2011-12-27 04:51:05 -0200575 module_get_dependencies_noref(mod);
Lucas De Marchif1cd7992011-12-05 19:40:45 -0200576
577 kmod_list_foreach(l, mod->dep) {
578 l_new = kmod_list_append(list_new, kmod_module_ref(l->data));
579 if (l_new == NULL) {
580 kmod_module_unref(l->data);
581 goto fail;
582 }
583
584 list_new = l_new;
585 }
586
587 return list_new;
588
589fail:
590 ERR(mod->ctx, "out of memory\n");
591 kmod_module_unref_list(list_new);
592 return NULL;
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200593}
594
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200595/**
596 * kmod_module_get_module:
597 * @entry: an entry in a list of kmod modules.
598 *
599 * Get the kmod module of this @entry in the list, increasing its refcount.
600 * After it's used, unref it. Since the refcount is incremented upon return,
601 * you still have to call kmod_module_unref_list() to release the list of kmod
602 * modules.
603 *
604 * Returns: NULL on failure or the kmod_module contained in this list entry
605 * with its refcount incremented.
606 */
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200607KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200608{
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200609 if (entry == NULL)
610 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -0200611
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200612 return kmod_module_ref(entry->data);
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200613}
614
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200615/**
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200616 * kmod_module_get_name:
617 * @mod: kmod module
618 *
619 * Get the name of this kmod module. Name is always available, independently
620 * if it was created by kmod_module_new_from_name() or another function and
621 * it's always normalized (dashes are replaced with underscores).
622 *
623 * Returns: the name of this kmod module.
624 */
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200625KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200626{
Lucas De Marchi818f8e82011-12-15 13:35:40 -0200627 if (mod == NULL)
628 return NULL;
629
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200630 return mod->name;
631}
632
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200633/**
634 * kmod_module_get_path:
635 * @mod: kmod module
636 *
637 * Get the path of this kmod module. If this kmod module was not created by
638 * path, it can search the modules.dep index in order to find out the module
639 * under context's dirname (see kmod_get_dirname()).
640 *
641 * Returns: the path of this kmod module or NULL if such information is not
642 * available.
643 */
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200644KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200645{
Lucas De Marchie005fac2011-12-08 10:42:34 -0200646 char *line;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200647
Lucas De Marchi818f8e82011-12-15 13:35:40 -0200648 if (mod == NULL)
649 return NULL;
650
Gustavo Sverzut Barbierid01c67e2011-12-11 19:42:02 -0200651 DBG(mod->ctx, "name='%s' path='%s'\n", mod->name, mod->path);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200652
Lucas De Marchie005fac2011-12-08 10:42:34 -0200653 if (mod->path != NULL)
654 return mod->path;
655 if (mod->init.dep)
656 return NULL;
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200657
Lucas De Marchie005fac2011-12-08 10:42:34 -0200658 /* lazy init */
659 line = kmod_search_moddep(mod->ctx, mod->name);
660 if (line == NULL)
661 return NULL;
662
663 kmod_module_parse_depline((struct kmod_module *) mod, line);
664 free(line);
Lucas De Marchic5e7b1f2011-12-05 20:28:13 -0200665
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200666 return mod->path;
667}
668
669
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200670extern long delete_module(const char *name, unsigned int flags);
671
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200672/**
673 * kmod_module_remove_module:
674 * @mod: kmod module
675 * @flags: flags to pass to Linux kernel when removing the module
676 *
677 * Remove a module from Linux kernel.
678 *
679 * Returns: 0 on success or < 0 on failure.
680 */
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200681KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
682 unsigned int flags)
683{
684 int err;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200685
686 if (mod == NULL)
687 return -ENOENT;
688
689 /* Filter out other flags */
690 flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
691
Lucas De Marchid753b8c2011-12-05 18:14:51 -0200692 err = delete_module(mod->name, flags);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200693 if (err != 0) {
Lucas De Marchi63af0612011-12-14 12:07:37 -0200694 ERR(mod->ctx, "Could not remove '%s': %s\n", mod->name,
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200695 strerror(-err));
696 return err;
697 }
698
699 return 0;
700}
701
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200702extern long init_module(const void *mem, unsigned long len, const char *args);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200703
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200704/**
705 * kmod_module_insert_module:
706 * @mod: kmod module
Lucas De Marchi142db572011-12-20 23:39:30 -0200707 * @flags: flags are not passed to Linux Kernel, but instead they dictate the
708 * behavior of this function.
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200709 * @options: module's options to pass to Linux Kernel.
710 *
711 * Insert a module in Linux kernel. It opens the file pointed by @mod,
712 * mmap'ing it and passing to kernel.
713 *
714 * Returns: 0 on success or < 0 on failure.
715 */
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200716KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200717 unsigned int flags,
718 const char *options)
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200719{
720 int err;
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200721 const void *mem;
Gustavo Sverzut Barbieri3d8226e2011-12-16 16:08:53 -0200722 off_t size;
723 struct kmod_file *file;
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200724 struct kmod_elf *elf = NULL;
725 const char *path;
Gustavo Sverzut Barbieri3a721bb2011-12-10 21:02:39 -0200726 const char *args = options ? options : "";
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200727
728 if (mod == NULL)
729 return -ENOENT;
730
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200731 path = kmod_module_get_path(mod);
732 if (path == NULL) {
Lucas De Marchif304afe2011-12-20 23:39:56 -0200733 ERR(mod->ctx, "Could not find module by name='%s'\n", mod->name);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200734 return -ENOSYS;
735 }
736
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200737 file = kmod_file_open(path);
Gustavo Sverzut Barbieri3d8226e2011-12-16 16:08:53 -0200738 if (file == NULL) {
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200739 err = -errno;
740 return err;
741 }
742
Gustavo Sverzut Barbieri3d8226e2011-12-16 16:08:53 -0200743 size = kmod_file_get_size(file);
744 mem = kmod_file_get_contents(file);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200745
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200746 if (flags & (KMOD_INSERT_FORCE_VERMAGIC | KMOD_INSERT_FORCE_MODVERSION)) {
747 elf = kmod_elf_new(mem, size);
748 if (elf == NULL) {
749 err = -errno;
750 goto elf_failed;
751 }
752
753 if (flags & KMOD_INSERT_FORCE_MODVERSION) {
754 err = kmod_elf_strip_section(elf, "__versions");
755 if (err < 0)
756 INFO(mod->ctx, "Failed to strip modversion: %s\n", strerror(-err));
757 }
758
759 if (flags & KMOD_INSERT_FORCE_VERMAGIC) {
760 err = kmod_elf_strip_vermagic(elf);
761 if (err < 0)
762 INFO(mod->ctx, "Failed to strip vermagic: %s\n", strerror(-err));
763 }
764
765 mem = kmod_elf_get_memory(elf);
766 }
767
Gustavo Sverzut Barbieri3d8226e2011-12-16 16:08:53 -0200768 err = init_module(mem, size, args);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200769 if (err < 0)
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200770 ERR(mod->ctx, "Failed to insert module '%s'\n", path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200771
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -0200772 if (elf != NULL)
773 kmod_elf_unref(elf);
774elf_failed:
Gustavo Sverzut Barbieri3d8226e2011-12-16 16:08:53 -0200775 kmod_file_unref(file);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200776
777 return err;
778}
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200779
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200780/**
781 * kmod_module_get_options:
782 * @mod: kmod module
783 *
784 * Get options of this kmod module. Options come from the configuration file
785 * and are cached in @mod. The first call to this function will search for
786 * this module in configuration and subsequent calls return the cached string.
787 *
788 * Returns: a string with all the options separated by spaces. This string is
789 * owned by @mod, do not free it.
790 */
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200791KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod)
792{
793 if (mod == NULL)
794 return NULL;
795
796 if (!mod->init.options) {
797 /* lazy init */
798 struct kmod_module *m = (struct kmod_module *)mod;
799 const struct kmod_list *l, *ctx_options;
800 char *opts = NULL;
801 size_t optslen = 0;
802
803 ctx_options = kmod_get_options(mod->ctx);
804
805 kmod_list_foreach(l, ctx_options) {
806 const char *modname = kmod_option_get_modname(l);
807 const char *str;
808 size_t len;
809 void *tmp;
810
Lucas De Marchi07b8c822011-12-13 14:21:24 -0200811 DBG(mod->ctx, "modname=%s mod->name=%s mod->alias=%s\n", modname, mod->name, mod->alias);
812 if (!(streq(modname, mod->name) || (mod->alias != NULL &&
813 streq(modname, mod->alias))))
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200814 continue;
815
Lucas De Marchi07b8c822011-12-13 14:21:24 -0200816 DBG(mod->ctx, "passed = modname=%s mod->name=%s mod->alias=%s\n", modname, mod->name, mod->alias);
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200817 str = kmod_option_get_options(l);
818 len = strlen(str);
819 if (len < 1)
820 continue;
821
822 tmp = realloc(opts, optslen + len + 2);
823 if (tmp == NULL) {
824 free(opts);
825 goto failed;
826 }
827
828 opts = tmp;
829
830 if (optslen > 0) {
831 opts[optslen] = ' ';
832 optslen++;
833 }
834
835 memcpy(opts + optslen, str, len);
836 optslen += len;
837 opts[optslen] = '\0';
838 }
839
840 m->init.options = true;
841 m->options = opts;
842 }
843
844 return mod->options;
845
846failed:
847 ERR(mod->ctx, "out of memory\n");
848 return NULL;
849}
850
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200851/**
852 * kmod_module_get_install_commands:
853 * @mod: kmod module
854 *
855 * Get install commands for this kmod module. Install commands come from the
856 * configuration file and are cached in @mod. The first call to this function
857 * will search for this module in configuration and subsequent calls return
858 * the cached string. The install commands are returned as they were in the
859 * configuration, concatenated by ';'. No other processing is made in this
860 * string.
861 *
862 * Returns: a string with all install commands separated by semicolons. This
863 * string is owned by @mod, do not free it.
864 */
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200865KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_module *mod)
866{
867 if (mod == NULL)
868 return NULL;
869
870 if (!mod->init.install_commands) {
871 /* lazy init */
872 struct kmod_module *m = (struct kmod_module *)mod;
873 const struct kmod_list *l, *ctx_install_commands;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200874
875 ctx_install_commands = kmod_get_install_commands(mod->ctx);
876
877 kmod_list_foreach(l, ctx_install_commands) {
878 const char *modname = kmod_command_get_modname(l);
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200879
Gustavo Sverzut Barbieria6bf2492011-12-16 22:43:04 -0200880 if (fnmatch(modname, mod->name, 0) != 0)
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200881 continue;
882
Lucas De Marchi60f67602011-12-16 03:33:26 -0200883 m->install_commands = kmod_command_get_command(l);
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200884
Lucas De Marchi60f67602011-12-16 03:33:26 -0200885 /*
886 * find only the first command, as modprobe from
887 * module-init-tools does
888 */
889 break;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200890 }
891
892 m->init.install_commands = true;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200893 }
894
895 return mod->install_commands;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200896}
897
Lucas De Marchif4fc5522011-12-16 03:57:12 -0200898void kmod_module_set_install_commands(struct kmod_module *mod, const char *cmd)
899{
900 mod->init.install_commands = true;
901 mod->install_commands = cmd;
902}
903
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200904static struct kmod_list *lookup_softdep(struct kmod_ctx *ctx, const char * const * array, unsigned int count)
905{
906 struct kmod_list *ret = NULL;
907 unsigned i;
908
909 for (i = 0; i < count; i++) {
910 const char *depname = array[i];
911 struct kmod_list *lst = NULL;
912 int err;
913
914 err = kmod_module_new_from_lookup(ctx, depname, &lst);
915 if (err < 0) {
916 ERR(ctx, "failed to lookup soft dependency '%s', continuing anyway.\n", depname);
917 continue;
918 } else if (lst != NULL)
919 ret = kmod_list_append_list(ret, lst);
920 }
921 return ret;
922}
923
924/**
925 * kmod_module_get_softdeps:
926 * @mod: kmod module
927 * @pre: where to save the list of preceding soft dependencies.
928 * @post: where to save the list of post soft dependencies.
929 *
930 * Get soft dependencies for this kmod module. Soft dependencies come
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200931 * from configuration file and are not cached in @mod because it may include
932 * dependency cycles that would make we leak kmod_module. Any call
933 * to this function will search for this module in configuration, allocate a
934 * list and return the result.
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200935 *
936 * Both @pre and @post are newly created list of kmod_module and
937 * should be unreferenced with kmod_module_unref_list().
938 *
939 * Returns: 0 on success or < 0 otherwise.
940 */
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200941KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod,
942 struct kmod_list **pre,
943 struct kmod_list **post)
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200944{
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200945 const struct kmod_list *l, *ctx_softdeps;
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200946
947 if (mod == NULL || pre == NULL || post == NULL)
948 return -ENOENT;
949
950 assert(*pre == NULL);
951 assert(*post == NULL);
952
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200953 ctx_softdeps = kmod_get_softdeps(mod->ctx);
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200954
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200955 kmod_list_foreach(l, ctx_softdeps) {
956 const char *modname = kmod_softdep_get_name(l);
957 const char * const *array;
958 unsigned count;
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200959
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200960 if (fnmatch(modname, mod->name, 0) != 0)
961 continue;
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200962
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200963 array = kmod_softdep_get_pre(l, &count);
964 *pre = lookup_softdep(mod->ctx, array, count);
965 array = kmod_softdep_get_post(l, &count);
966 *post = lookup_softdep(mod->ctx, array, count);
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200967
Lucas De Marchi2bd7cbf2011-12-27 10:15:40 -0200968 /*
969 * find only the first command, as modprobe from
970 * module-init-tools does
971 */
972 break;
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200973 }
974
975 return 0;
Gustavo Sverzut Barbieri1c522602011-12-16 21:18:10 -0200976}
977
Lucas De Marchi7afc98a2011-12-14 12:06:18 -0200978/**
979 * kmod_module_get_remove_commands:
980 * @mod: kmod module
981 *
982 * Get remove commands for this kmod module. Remove commands come from the
983 * configuration file and are cached in @mod. The first call to this function
984 * will search for this module in configuration and subsequent calls return
985 * the cached string. The remove commands are returned as they were in the
986 * configuration, concatenated by ';'. No other processing is made in this
987 * string.
988 *
989 * Returns: a string with all remove commands separated by semicolons. This
990 * string is owned by @mod, do not free it.
991 */
Lucas De Marchi49ce6d02011-12-12 13:56:47 -0200992KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module *mod)
993{
994 if (mod == NULL)
995 return NULL;
996
997 if (!mod->init.remove_commands) {
998 /* lazy init */
999 struct kmod_module *m = (struct kmod_module *)mod;
1000 const struct kmod_list *l, *ctx_remove_commands;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001001
1002 ctx_remove_commands = kmod_get_remove_commands(mod->ctx);
1003
1004 kmod_list_foreach(l, ctx_remove_commands) {
1005 const char *modname = kmod_command_get_modname(l);
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001006
Gustavo Sverzut Barbieria6bf2492011-12-16 22:43:04 -02001007 if (fnmatch(modname, mod->name, 0) != 0)
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001008 continue;
1009
Lucas De Marchi60f67602011-12-16 03:33:26 -02001010 m->remove_commands = kmod_command_get_command(l);
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001011
Lucas De Marchi60f67602011-12-16 03:33:26 -02001012 /*
1013 * find only the first command, as modprobe from
1014 * module-init-tools does
1015 */
1016 break;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001017 }
1018
1019 m->init.remove_commands = true;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001020 }
1021
1022 return mod->remove_commands;
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001023}
1024
Lucas De Marchif4fc5522011-12-16 03:57:12 -02001025void kmod_module_set_remove_commands(struct kmod_module *mod, const char *cmd)
1026{
1027 mod->init.remove_commands = true;
1028 mod->remove_commands = cmd;
1029}
1030
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001031/**
1032 * SECTION:libkmod-loaded
1033 * @short_description: currently loaded modules
1034 *
1035 * Information about currently loaded modules, as reported by Linux kernel.
1036 * These information are not cached by libkmod and are always read from /sys
1037 * and /proc/modules.
1038 */
1039
1040/**
1041 * kmod_module_new_from_loaded:
1042 * @ctx: kmod library context
1043 * @list: where to save the list of loaded modules
1044 *
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001045 * Create a new list of kmod modules with all modules currently loaded in
1046 * kernel. It uses /proc/modules to get the names of loaded modules and to
1047 * create kmod modules by calling kmod_module_new_from_name() in each of them.
1048 * They are put are put in @list in no particular order.
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001049 *
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001050 * The initial refcount is 1, and needs to be decremented to release the
1051 * resources of the kmod_module. The returned @list must be released by
1052 * calling kmod_module_unref_list(). Since libkmod keeps track of all
1053 * kmod_modules created, they are all released upon @ctx destruction too. Do
1054 * not unref @ctx before all the desired operations with the returned list are
1055 * completed.
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001056 *
1057 * Returns: 0 on success or < 0 on error.
1058 */
1059KMOD_EXPORT int kmod_module_new_from_loaded(struct kmod_ctx *ctx,
1060 struct kmod_list **list)
1061{
1062 struct kmod_list *l = NULL;
1063 FILE *fp;
1064 char line[4096];
1065
1066 if (ctx == NULL || list == NULL)
1067 return -ENOENT;
1068
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -03001069 fp = fopen("/proc/modules", "re");
Lucas De Marchi49ce6d02011-12-12 13:56:47 -02001070 if (fp == NULL) {
1071 int err = -errno;
1072 ERR(ctx, "could not open /proc/modules: %s\n", strerror(errno));
1073 return err;
1074 }
1075
1076 while (fgets(line, sizeof(line), fp)) {
1077 struct kmod_module *m;
1078 struct kmod_list *node;
1079 int err;
1080 char *saveptr, *name = strtok_r(line, " \t", &saveptr);
1081
1082 err = kmod_module_new_from_name(ctx, name, &m);
1083 if (err < 0) {
1084 ERR(ctx, "could not get module from name '%s': %s\n",
1085 name, strerror(-err));
1086 continue;
1087 }
1088
1089 node = kmod_list_append(l, m);
1090 if (node)
1091 l = node;
1092 else {
1093 ERR(ctx, "out of memory\n");
1094 kmod_module_unref(m);
1095 }
1096 }
1097
1098 fclose(fp);
1099 *list = l;
1100
1101 return 0;
1102}
1103
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001104/**
1105 * kmod_module_initstate_str:
1106 * @state: the state as returned by kmod_module_get_initstate()
1107 *
1108 * Translate a initstate to a string.
1109 *
1110 * Returns: the string associated to the @state. This string is statically
1111 * allocated, do not free it.
1112 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001113KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
1114{
1115 switch (state) {
1116 case KMOD_MODULE_BUILTIN:
1117 return "builtin";
1118 case KMOD_MODULE_LIVE:
1119 return "live";
1120 case KMOD_MODULE_COMING:
1121 return "coming";
1122 case KMOD_MODULE_GOING:
1123 return "going";
1124 default:
1125 return NULL;
1126 }
1127}
1128
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001129/**
1130 * kmod_module_get_initstate:
1131 * @mod: kmod module
1132 *
1133 * Get the initstate of this @mod, as returned by Linux Kernel, by reading
1134 * /sys filesystem.
1135 *
1136 * Returns: < 0 on error or enum kmod_initstate if module is found in kernel.
1137 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001138KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
1139{
1140 char path[PATH_MAX], buf[32];
1141 int fd, err, pathlen;
1142
Lucas De Marchi818f8e82011-12-15 13:35:40 -02001143 if (mod == NULL)
1144 return -ENOENT;
1145
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001146 pathlen = snprintf(path, sizeof(path),
1147 "/sys/module/%s/initstate", mod->name);
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -03001148 fd = open(path, O_RDONLY|O_CLOEXEC);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001149 if (fd < 0) {
1150 err = -errno;
1151
1152 if (pathlen > (int)sizeof("/initstate") - 1) {
1153 struct stat st;
1154 path[pathlen - (sizeof("/initstate") - 1)] = '\0';
1155 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
1156 return KMOD_MODULE_BUILTIN;
1157 }
1158
Gustavo Sverzut Barbieri926f67a2011-12-11 19:33:03 -02001159 DBG(mod->ctx, "could not open '%s': %s\n",
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001160 path, strerror(-err));
1161 return err;
1162 }
1163
1164 err = read_str_safe(fd, buf, sizeof(buf));
1165 close(fd);
1166 if (err < 0) {
1167 ERR(mod->ctx, "could not read from '%s': %s\n",
1168 path, strerror(-err));
1169 return err;
1170 }
1171
Lucas De Marchi877e80c2011-12-07 02:26:31 -02001172 if (streq(buf, "live\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001173 return KMOD_MODULE_LIVE;
Lucas De Marchi877e80c2011-12-07 02:26:31 -02001174 else if (streq(buf, "coming\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001175 return KMOD_MODULE_COMING;
Lucas De Marchi877e80c2011-12-07 02:26:31 -02001176 else if (streq(buf, "going\n"))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001177 return KMOD_MODULE_GOING;
1178
1179 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
1180 return -EINVAL;
1181}
1182
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001183/**
Lucas De Marchi2d7bab52011-12-14 12:10:02 -02001184 * kmod_module_get_size:
1185 * @mod: kmod module
1186 *
1187 * Get the size of this kmod module as returned by Linux kernel. It reads the
1188 * file /proc/modules to search for this module and get its size.
1189 *
1190 * Returns: the size of this kmod module.
1191 */
1192KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
1193{
1194 // FIXME TODO: this should be available from /sys/module/foo
1195 FILE *fp;
1196 char line[4096];
1197 int lineno = 0;
1198 long size = -ENOENT;
1199
1200 if (mod == NULL)
1201 return -ENOENT;
1202
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -03001203 fp = fopen("/proc/modules", "re");
Lucas De Marchi2d7bab52011-12-14 12:10:02 -02001204 if (fp == NULL) {
1205 int err = -errno;
1206 ERR(mod->ctx,
1207 "could not open /proc/modules: %s\n", strerror(errno));
1208 return err;
1209 }
1210
1211 while (fgets(line, sizeof(line), fp)) {
1212 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
1213 long value;
1214
1215 lineno++;
1216 if (tok == NULL || !streq(tok, mod->name))
1217 continue;
1218
1219 tok = strtok_r(NULL, " \t", &saveptr);
1220 if (tok == NULL) {
1221 ERR(mod->ctx,
1222 "invalid line format at /proc/modules:%d\n", lineno);
1223 break;
1224 }
1225
1226 value = strtol(tok, &endptr, 10);
1227 if (endptr == tok || *endptr != '\0') {
1228 ERR(mod->ctx,
1229 "invalid line format at /proc/modules:%d\n", lineno);
1230 break;
1231 }
1232
1233 size = value;
1234 break;
1235 }
1236 fclose(fp);
1237 return size;
1238}
1239
1240/**
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001241 * kmod_module_get_refcnt:
1242 * @mod: kmod module
1243 *
1244 * Get the ref count of this @mod, as returned by Linux Kernel, by reading
1245 * /sys filesystem.
1246 *
1247 * Returns: 0 on success or < 0 on failure.
1248 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001249KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
1250{
1251 char path[PATH_MAX];
1252 long refcnt;
1253 int fd, err;
1254
Lucas De Marchi818f8e82011-12-15 13:35:40 -02001255 if (mod == NULL)
1256 return -ENOENT;
1257
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001258 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -03001259 fd = open(path, O_RDONLY|O_CLOEXEC);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001260 if (fd < 0) {
1261 err = -errno;
1262 ERR(mod->ctx, "could not open '%s': %s\n",
1263 path, strerror(errno));
1264 return err;
1265 }
1266
1267 err = read_str_long(fd, &refcnt, 10);
1268 close(fd);
1269 if (err < 0) {
1270 ERR(mod->ctx, "could not read integer from '%s': '%s'\n",
1271 path, strerror(-err));
1272 return err;
1273 }
1274
1275 return (int)refcnt;
1276}
1277
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001278/**
1279 * kmod_module_get_holders:
1280 * @mod: kmod module
1281 *
1282 * Get a list of kmod modules that are holding this @mod, as returned by Linux
1283 * Kernel. After use, free the @list by calling kmod_module_unref_list().
1284 *
1285 * Returns: a new list of kmod modules on success or NULL on failure.
1286 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001287KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
1288{
1289 char dname[PATH_MAX];
1290 struct kmod_list *list = NULL;
1291 DIR *d;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001292
1293 if (mod == NULL)
1294 return NULL;
Lucas De Marchi818f8e82011-12-15 13:35:40 -02001295
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001296 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
1297
1298 d = opendir(dname);
1299 if (d == NULL) {
1300 ERR(mod->ctx, "could not open '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001301 dname, strerror(errno));
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001302 return NULL;
1303 }
1304
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001305 for (;;) {
1306 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001307 struct kmod_module *holder;
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001308 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001309 int err;
1310
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001311 err = readdir_r(d, &de, &entp);
1312 if (err != 0) {
1313 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
1314 mod->name, strerror(-err));
1315 goto fail;
1316 }
1317
1318 if (entp == NULL)
1319 break;
1320
1321 if (de.d_name[0] == '.') {
1322 if (de.d_name[1] == '\0' ||
1323 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001324 continue;
1325 }
1326
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001327 err = kmod_module_new_from_name(mod->ctx, de.d_name, &holder);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001328 if (err < 0) {
1329 ERR(mod->ctx, "could not create module for '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001330 de.d_name, strerror(-err));
1331 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001332 }
1333
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001334 l = kmod_list_append(list, holder);
1335 if (l != NULL) {
1336 list = l;
1337 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001338 ERR(mod->ctx, "out of memory\n");
1339 kmod_module_unref(holder);
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001340 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001341 }
1342 }
1343
1344 closedir(d);
1345 return list;
Lucas De Marchi53886dd2011-12-05 13:24:23 -02001346
1347fail:
1348 closedir(d);
1349 kmod_module_unref_list(list);
1350 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001351}
1352
1353struct kmod_module_section {
1354 unsigned long address;
1355 char name[];
1356};
1357
1358static void kmod_module_section_free(struct kmod_module_section *section)
1359{
1360 free(section);
1361}
1362
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001363/**
1364 * kmod_module_get_sections:
1365 * @mod: kmod module
1366 *
1367 * Get a list of kmod sections of this @mod, as returned by Linux Kernel. The
1368 * structure contained in this list is internal to libkmod and their fields
1369 * can be obtained by calling kmod_module_section_get_name() and
1370 * kmod_module_section_get_address().
1371 *
1372 * After use, free the @list by calling kmod_module_section_free_list().
1373 *
1374 * Returns: a new list of kmod module sections on success or NULL on failure.
1375 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001376KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
1377{
1378 char dname[PATH_MAX];
1379 struct kmod_list *list = NULL;
1380 DIR *d;
1381 int dfd;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001382
1383 if (mod == NULL)
1384 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001385
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001386 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
1387
1388 d = opendir(dname);
1389 if (d == NULL) {
1390 ERR(mod->ctx, "could not open '%s': %s\n",
1391 dname, strerror(errno));
1392 return NULL;
1393 }
1394
1395 dfd = dirfd(d);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001396
1397 for (;;) {
1398 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001399 struct kmod_module_section *section;
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001400 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001401 unsigned long address;
1402 size_t namesz;
1403 int fd, err;
1404
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001405 err = readdir_r(d, &de, &entp);
1406 if (err != 0) {
1407 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
1408 mod->name, strerror(-err));
1409 goto fail;
1410 }
1411
1412 if (de.d_name[0] == '.') {
1413 if (de.d_name[1] == '\0' ||
1414 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001415 continue;
1416 }
1417
Cristian Rodríguez8e3e5832011-12-16 14:46:52 -03001418 fd = openat(dfd, de.d_name, O_RDONLY|O_CLOEXEC);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001419 if (fd < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001420 ERR(mod->ctx, "could not open '%s/%s': %m\n",
1421 dname, de.d_name);
1422 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001423 }
1424
1425 err = read_str_ulong(fd, &address, 16);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001426 close(fd);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001427 if (err < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001428 ERR(mod->ctx, "could not read long from '%s/%s': %m\n",
1429 dname, de.d_name);
1430 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001431 }
1432
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001433 namesz = strlen(de.d_name) + 1;
1434 section = malloc(sizeof(*section) + namesz);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001435
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001436 if (section == NULL) {
1437 ERR(mod->ctx, "out of memory\n");
1438 goto fail;
1439 }
1440
1441 section->address = address;
1442 memcpy(section->name, de.d_name, namesz);
1443
1444 l = kmod_list_append(list, section);
1445 if (l != NULL) {
1446 list = l;
1447 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001448 ERR(mod->ctx, "out of memory\n");
1449 free(section);
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001450 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001451 }
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001452 }
1453
1454 closedir(d);
1455 return list;
Lucas De Marchi40923bd2011-12-05 13:40:16 -02001456
1457fail:
1458 closedir(d);
1459 kmod_module_unref_list(list);
1460 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001461}
1462
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001463/**
1464 * kmod_module_section_get_module_name:
1465 * @entry: a list entry representing a kmod module section
1466 *
1467 * Get the name of a kmod module section.
1468 *
1469 * After use, free the @list by calling kmod_module_section_free_list().
1470 *
1471 * Returns: the name of this kmod module section on success or NULL on
1472 * failure. The string is owned by the section, do not free it.
1473 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001474KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
1475{
1476 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001477
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001478 if (entry == NULL)
1479 return NULL;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001480
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001481 section = entry->data;
1482 return section->name;
1483}
1484
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001485/**
1486 * kmod_module_section_get_address:
1487 * @entry: a list entry representing a kmod module section
1488 *
1489 * Get the address of a kmod module section.
1490 *
1491 * After use, free the @list by calling kmod_module_section_free_list().
1492 *
1493 * Returns: the address of this kmod module section on success or ULONG_MAX
1494 * on failure.
1495 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001496KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
1497{
1498 struct kmod_module_section *section;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001499
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001500 if (entry == NULL)
1501 return (unsigned long)-1;
Lucas De Marchi28c175e2011-12-12 11:52:59 -02001502
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001503 section = entry->data;
1504 return section->address;
1505}
1506
Lucas De Marchi7afc98a2011-12-14 12:06:18 -02001507/**
1508 * kmod_module_section_free_list:
1509 * @list: kmod module section list
1510 *
1511 * Release the resources taken by @list
1512 */
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -02001513KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
1514{
1515 while (list) {
1516 kmod_module_section_free(list->data);
1517 list = kmod_list_remove(list);
1518 }
1519}
Gustavo Sverzut Barbieri708624a2011-12-18 01:25:06 -02001520
1521struct kmod_module_info {
1522 char *key;
1523 char value[];
1524};
1525
1526static struct kmod_module_info *kmod_module_info_new(const char *key, size_t keylen, const char *value, size_t valuelen)
1527{
1528 struct kmod_module_info *info;
1529
1530 info = malloc(sizeof(struct kmod_module_info) + keylen + valuelen + 2);
1531 if (info == NULL)
1532 return NULL;
1533
1534 info->key = (char *)info + sizeof(struct kmod_module_info)
1535 + valuelen + 1;
1536 memcpy(info->key, key, keylen);
1537 info->key[keylen] = '\0';
1538 memcpy(info->value, value, valuelen);
1539 info->value[valuelen] = '\0';
1540 return info;
1541}
1542
1543static void kmod_module_info_free(struct kmod_module_info *info)
1544{
1545 free(info);
1546}
1547
1548/**
1549 * kmod_module_get_info:
1550 * @mod: kmod module
1551 * @list: where to return list of module information. Use
1552 * kmod_module_info_get_key() and
1553 * kmod_module_info_get_value(). Release this list with
1554 * kmod_module_info_unref_list()
1555 *
1556 * Get a list of entries in ELF section ".modinfo", these contain
1557 * alias, license, depends, vermagic and other keys with respective
1558 * values.
1559 *
1560 * After use, free the @list by calling kmod_module_info_free_list().
1561 *
1562 * Returns: 0 on success or < 0 otherwise.
1563 */
1564KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_list **list)
1565{
1566 struct kmod_file *file;
1567 struct kmod_elf *elf;
1568 const char *path;
1569 const void *mem;
1570 char **strings;
1571 size_t size;
1572 int i, count, ret = 0;
1573
1574 if (mod == NULL || list == NULL)
1575 return -ENOENT;
1576
1577 assert(*list == NULL);
1578
1579 path = kmod_module_get_path(mod);
1580 if (path == NULL)
1581 return -ENOENT;
1582
1583 file = kmod_file_open(path);
1584 if (file == NULL)
1585 return -errno;
1586
1587 size = kmod_file_get_size(file);
1588 mem = kmod_file_get_contents(file);
1589
1590 elf = kmod_elf_new(mem, size);
1591 if (elf == NULL) {
1592 ret = -errno;
1593 goto elf_open_error;
1594 }
1595
1596 count = kmod_elf_get_strings(elf, ".modinfo", &strings);
1597 if (count < 0) {
1598 ret = count;
1599 goto get_strings_error;
1600 }
1601
1602 for (i = 0; i < count; i++) {
1603 struct kmod_module_info *info;
1604 struct kmod_list *n;
1605 const char *key, *value;
1606 size_t keylen, valuelen;
1607
1608 key = strings[i];
1609 value = strchr(key, '=');
1610 if (value == NULL) {
1611 keylen = strlen(key);
1612 valuelen = 0;
1613 } else {
1614 keylen = value - key;
1615 value++;
1616 valuelen = strlen(value);
1617 }
1618
1619 info = kmod_module_info_new(key, keylen, value, valuelen);
1620 if (info == NULL) {
1621 ret = -errno;
1622 kmod_module_info_free_list(*list);
1623 *list = NULL;
1624 goto list_error;
1625 }
1626
1627 n = kmod_list_append(*list, info);
1628 if (n != NULL)
1629 *list = n;
1630 else {
1631 kmod_module_info_free(info);
1632 kmod_module_info_free_list(*list);
1633 *list = NULL;
1634 ret = -ENOMEM;
1635 goto list_error;
1636 }
1637 }
1638 ret = count;
1639
1640list_error:
1641 free(strings);
1642get_strings_error:
1643 kmod_elf_unref(elf);
1644elf_open_error:
1645 kmod_file_unref(file);
1646
1647 return ret;
1648}
1649
1650/**
1651 * kmod_module_info_get_key:
1652 * @entry: a list entry representing a kmod module info
1653 *
1654 * Get the key of a kmod module info.
1655 *
1656 * Returns: the key of this kmod module info on success or NULL on
1657 * failure. The string is owned by the info, do not free it.
1658 */
1659KMOD_EXPORT const char *kmod_module_info_get_key(const struct kmod_list *entry)
1660{
1661 struct kmod_module_info *info;
1662
1663 if (entry == NULL)
1664 return NULL;
1665
1666 info = entry->data;
1667 return info->key;
1668}
1669
1670/**
1671 * kmod_module_info_get_value:
1672 * @entry: a list entry representing a kmod module info
1673 *
1674 * Get the value of a kmod module info.
1675 *
1676 * Returns: the value of this kmod module info on success or NULL on
1677 * failure. The string is owned by the info, do not free it.
1678 */
1679KMOD_EXPORT const char *kmod_module_info_get_value(const struct kmod_list *entry)
1680{
1681 struct kmod_module_info *info;
1682
1683 if (entry == NULL)
1684 return NULL;
1685
1686 info = entry->data;
1687 return info->value;
1688}
1689
1690/**
1691 * kmod_module_info_free_list:
1692 * @list: kmod module info list
1693 *
1694 * Release the resources taken by @list
1695 */
1696KMOD_EXPORT void kmod_module_info_free_list(struct kmod_list *list)
1697{
1698 while (list) {
1699 kmod_module_info_free(list->data);
1700 list = kmod_list_remove(list);
1701 }
1702}
1703
1704struct kmod_module_version {
1705 uint64_t crc;
1706 char symbol[];
1707};
1708
1709static struct kmod_module_version *kmod_module_versions_new(uint64_t crc, const char *symbol)
1710{
1711 struct kmod_module_version *mv;
1712 size_t symbollen = strlen(symbol) + 1;
1713
1714 mv = malloc(sizeof(struct kmod_module_version) + symbollen);
1715 if (mv == NULL)
1716 return NULL;
1717
1718 mv->crc = crc;
1719 memcpy(mv->symbol, symbol, symbollen);
1720 return mv;
1721}
1722
1723static void kmod_module_version_free(struct kmod_module_version *version)
1724{
1725 free(version);
1726}
1727
1728/**
1729 * kmod_module_get_versions:
1730 * @mod: kmod module
1731 * @list: where to return list of module versions. Use
1732 * kmod_module_versions_get_symbol() and
1733 * kmod_module_versions_get_crc(). Release this list with
1734 * kmod_module_versions_unref_list()
1735 *
1736 * Get a list of entries in ELF section "__versions".
1737 *
1738 * After use, free the @list by calling kmod_module_versions_free_list().
1739 *
1740 * Returns: 0 on success or < 0 otherwise.
1741 */
1742KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod, struct kmod_list **list)
1743{
1744 struct kmod_file *file;
1745 struct kmod_elf *elf;
1746 const char *path;
1747 const void *mem;
1748 struct kmod_modversion *versions;
1749 size_t size;
1750 int i, count, ret = 0;
1751
1752 if (mod == NULL || list == NULL)
1753 return -ENOENT;
1754
1755 assert(*list == NULL);
1756
1757 path = kmod_module_get_path(mod);
1758 if (path == NULL)
1759 return -ENOENT;
1760
1761 file = kmod_file_open(path);
1762 if (file == NULL)
1763 return -errno;
1764
1765 size = kmod_file_get_size(file);
1766 mem = kmod_file_get_contents(file);
1767
1768 elf = kmod_elf_new(mem, size);
1769 if (elf == NULL) {
1770 ret = -errno;
1771 goto elf_open_error;
1772 }
1773
1774 count = kmod_elf_get_modversions(elf, &versions);
1775 if (count < 0) {
1776 ret = count;
1777 goto get_strings_error;
1778 }
1779
1780 for (i = 0; i < count; i++) {
1781 struct kmod_module_version *mv;
1782 struct kmod_list *n;
1783
1784 mv = kmod_module_versions_new(versions[i].crc, versions[i].symbol);
1785 if (mv == NULL) {
1786 ret = -errno;
1787 kmod_module_versions_free_list(*list);
1788 *list = NULL;
1789 goto list_error;
1790 }
1791
1792 n = kmod_list_append(*list, mv);
1793 if (n != NULL)
1794 *list = n;
1795 else {
1796 kmod_module_version_free(mv);
1797 kmod_module_versions_free_list(*list);
1798 *list = NULL;
1799 ret = -ENOMEM;
1800 goto list_error;
1801 }
1802 }
1803 ret = count;
1804
1805list_error:
1806 free(versions);
1807get_strings_error:
1808 kmod_elf_unref(elf);
1809elf_open_error:
1810 kmod_file_unref(file);
1811
1812 return ret;
1813}
1814
1815/**
1816 * kmod_module_versions_get_symbol:
1817 * @entry: a list entry representing a kmod module versions
1818 *
1819 * Get the symbol of a kmod module versions.
1820 *
1821 * Returns: the symbol of this kmod module versions on success or NULL
1822 * on failure. The string is owned by the versions, do not free it.
1823 */
1824KMOD_EXPORT const char *kmod_module_version_get_symbol(const struct kmod_list *entry)
1825{
1826 struct kmod_module_version *version;
1827
1828 if (entry == NULL)
1829 return NULL;
1830
1831 version = entry->data;
1832 return version->symbol;
1833}
1834
1835/**
1836 * kmod_module_version_get_crc:
1837 * @entry: a list entry representing a kmod module version
1838 *
1839 * Get the crc of a kmod module version.
1840 *
1841 * Returns: the crc of this kmod module version on success or NULL on
1842 * failure. The string is owned by the version, do not free it.
1843 */
1844KMOD_EXPORT uint64_t kmod_module_version_get_crc(const struct kmod_list *entry)
1845{
1846 struct kmod_module_version *version;
1847
1848 if (entry == NULL)
1849 return 0;
1850
1851 version = entry->data;
1852 return version->crc;
1853}
1854
1855/**
1856 * kmod_module_versions_free_list:
1857 * @list: kmod module versions list
1858 *
1859 * Release the resources taken by @list
1860 */
1861KMOD_EXPORT void kmod_module_versions_free_list(struct kmod_list *list)
1862{
1863 while (list) {
1864 kmod_module_version_free(list->data);
1865 list = kmod_list_remove(list);
1866 }
1867}
Gustavo Sverzut Barbieri45e6db92011-12-19 21:23:13 -02001868
1869struct kmod_module_symbol {
1870 uint64_t crc;
1871 char symbol[];
1872};
1873
1874static struct kmod_module_symbol *kmod_module_symbols_new(uint64_t crc, const char *symbol)
1875{
1876 struct kmod_module_symbol *mv;
1877 size_t symbollen = strlen(symbol) + 1;
1878
1879 mv = malloc(sizeof(struct kmod_module_symbol) + symbollen);
1880 if (mv == NULL)
1881 return NULL;
1882
1883 mv->crc = crc;
1884 memcpy(mv->symbol, symbol, symbollen);
1885 return mv;
1886}
1887
1888static void kmod_module_symbol_free(struct kmod_module_symbol *symbol)
1889{
1890 free(symbol);
1891}
1892
1893/**
1894 * kmod_module_get_symbols:
1895 * @mod: kmod module
1896 * @list: where to return list of module symbols. Use
1897 * kmod_module_symbols_get_symbol() and
1898 * kmod_module_symbols_get_crc(). Release this list with
1899 * kmod_module_symbols_unref_list()
1900 *
1901 * Get a list of entries in ELF section ".symtab" or "__ksymtab_strings".
1902 *
1903 * After use, free the @list by calling kmod_module_symbols_free_list().
1904 *
1905 * Returns: 0 on success or < 0 otherwise.
1906 */
1907KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod, struct kmod_list **list)
1908{
1909 struct kmod_file *file;
1910 struct kmod_elf *elf;
1911 const char *path;
1912 const void *mem;
1913 struct kmod_modversion *symbols;
1914 size_t size;
1915 int i, count, ret = 0;
1916
1917 if (mod == NULL || list == NULL)
1918 return -ENOENT;
1919
1920 assert(*list == NULL);
1921
1922 path = kmod_module_get_path(mod);
1923 if (path == NULL)
1924 return -ENOENT;
1925
1926 file = kmod_file_open(path);
1927 if (file == NULL)
1928 return -errno;
1929
1930 size = kmod_file_get_size(file);
1931 mem = kmod_file_get_contents(file);
1932
1933 elf = kmod_elf_new(mem, size);
1934 if (elf == NULL) {
1935 ret = -errno;
1936 goto elf_open_error;
1937 }
1938
1939 count = kmod_elf_get_symbols(elf, &symbols);
1940 if (count < 0) {
1941 ret = count;
1942 goto get_strings_error;
1943 }
1944
1945 for (i = 0; i < count; i++) {
1946 struct kmod_module_symbol *mv;
1947 struct kmod_list *n;
1948
1949 mv = kmod_module_symbols_new(symbols[i].crc, symbols[i].symbol);
1950 if (mv == NULL) {
1951 ret = -errno;
1952 kmod_module_symbols_free_list(*list);
1953 *list = NULL;
1954 goto list_error;
1955 }
1956
1957 n = kmod_list_append(*list, mv);
1958 if (n != NULL)
1959 *list = n;
1960 else {
1961 kmod_module_symbol_free(mv);
1962 kmod_module_symbols_free_list(*list);
1963 *list = NULL;
1964 ret = -ENOMEM;
1965 goto list_error;
1966 }
1967 }
1968 ret = count;
1969
1970list_error:
1971 free(symbols);
1972get_strings_error:
1973 kmod_elf_unref(elf);
1974elf_open_error:
1975 kmod_file_unref(file);
1976
1977 return ret;
1978}
1979
1980/**
1981 * kmod_module_symbols_get_symbol:
1982 * @entry: a list entry representing a kmod module symbols
1983 *
1984 * Get the symbol of a kmod module symbols.
1985 *
1986 * Returns: the symbol of this kmod module symbols on success or NULL
1987 * on failure. The string is owned by the symbols, do not free it.
1988 */
1989KMOD_EXPORT const char *kmod_module_symbol_get_symbol(const struct kmod_list *entry)
1990{
1991 struct kmod_module_symbol *symbol;
1992
1993 if (entry == NULL)
1994 return NULL;
1995
1996 symbol = entry->data;
1997 return symbol->symbol;
1998}
1999
2000/**
2001 * kmod_module_symbol_get_crc:
2002 * @entry: a list entry representing a kmod module symbol
2003 *
2004 * Get the crc of a kmod module symbol.
2005 *
2006 * Returns: the crc of this kmod module symbol on success or NULL on
2007 * failure. The string is owned by the symbol, do not free it.
2008 */
2009KMOD_EXPORT uint64_t kmod_module_symbol_get_crc(const struct kmod_list *entry)
2010{
2011 struct kmod_module_symbol *symbol;
2012
2013 if (entry == NULL)
2014 return 0;
2015
2016 symbol = entry->data;
2017 return symbol->crc;
2018}
2019
2020/**
2021 * kmod_module_symbols_free_list:
2022 * @list: kmod module symbols list
2023 *
2024 * Release the resources taken by @list
2025 */
2026KMOD_EXPORT void kmod_module_symbols_free_list(struct kmod_list *list)
2027{
2028 while (list) {
2029 kmod_module_symbol_free(list->data);
2030 list = kmod_list_remove(list);
2031 }
2032}
Gustavo Sverzut Barbieri674f8592011-12-20 11:54:53 -02002033
2034struct kmod_module_dependency_symbol {
2035 uint64_t crc;
2036 uint8_t bind;
2037 char symbol[];
2038};
2039
2040static struct kmod_module_dependency_symbol *kmod_module_dependency_symbols_new(uint64_t crc, uint8_t bind, const char *symbol)
2041{
2042 struct kmod_module_dependency_symbol *mv;
2043 size_t symbollen = strlen(symbol) + 1;
2044
2045 mv = malloc(sizeof(struct kmod_module_dependency_symbol) + symbollen);
2046 if (mv == NULL)
2047 return NULL;
2048
2049 mv->crc = crc;
2050 mv->bind = bind;
2051 memcpy(mv->symbol, symbol, symbollen);
2052 return mv;
2053}
2054
2055static void kmod_module_dependency_symbol_free(struct kmod_module_dependency_symbol *dependency_symbol)
2056{
2057 free(dependency_symbol);
2058}
2059
2060/**
2061 * kmod_module_get_dependency_symbols:
2062 * @mod: kmod module
2063 * @list: where to return list of module dependency_symbols. Use
2064 * kmod_module_dependency_symbol_get_symbol() and
2065 * kmod_module_dependency_symbol_get_crc(). Release this list with
2066 * kmod_module_dependency_symbols_free_list()
2067 *
2068 * Get a list of entries in ELF section ".symtab" or "__ksymtab_strings".
2069 *
2070 * After use, free the @list by calling
2071 * kmod_module_dependency_symbols_free_list().
2072 *
2073 * Returns: 0 on success or < 0 otherwise.
2074 */
2075KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod, struct kmod_list **list)
2076{
2077 struct kmod_file *file;
2078 struct kmod_elf *elf;
2079 const char *path;
2080 const void *mem;
2081 struct kmod_modversion *symbols;
2082 size_t size;
2083 int i, count, ret = 0;
2084
2085 if (mod == NULL || list == NULL)
2086 return -ENOENT;
2087
2088 assert(*list == NULL);
2089
2090 path = kmod_module_get_path(mod);
2091 if (path == NULL)
2092 return -ENOENT;
2093
2094 file = kmod_file_open(path);
2095 if (file == NULL)
2096 return -errno;
2097
2098 size = kmod_file_get_size(file);
2099 mem = kmod_file_get_contents(file);
2100
2101 elf = kmod_elf_new(mem, size);
2102 if (elf == NULL) {
2103 ret = -errno;
2104 goto elf_open_error;
2105 }
2106
2107 count = kmod_elf_get_dependency_symbols(elf, &symbols);
2108 if (count < 0) {
2109 ret = count;
2110 goto get_strings_error;
2111 }
2112
2113 for (i = 0; i < count; i++) {
2114 struct kmod_module_dependency_symbol *mv;
2115 struct kmod_list *n;
2116
2117 mv = kmod_module_dependency_symbols_new(symbols[i].crc,
2118 symbols[i].bind,
2119 symbols[i].symbol);
2120 if (mv == NULL) {
2121 ret = -errno;
2122 kmod_module_dependency_symbols_free_list(*list);
2123 *list = NULL;
2124 goto list_error;
2125 }
2126
2127 n = kmod_list_append(*list, mv);
2128 if (n != NULL)
2129 *list = n;
2130 else {
2131 kmod_module_dependency_symbol_free(mv);
2132 kmod_module_dependency_symbols_free_list(*list);
2133 *list = NULL;
2134 ret = -ENOMEM;
2135 goto list_error;
2136 }
2137 }
2138 ret = count;
2139
2140list_error:
2141 free(symbols);
2142get_strings_error:
2143 kmod_elf_unref(elf);
2144elf_open_error:
2145 kmod_file_unref(file);
2146
2147 return ret;
2148}
2149
2150/**
2151 * kmod_module_dependency_symbol_get_symbol:
2152 * @entry: a list entry representing a kmod module dependency_symbols
2153 *
2154 * Get the dependency symbol of a kmod module
2155 *
2156 * Returns: the symbol of this kmod module dependency_symbols on success or NULL
2157 * on failure. The string is owned by the dependency_symbols, do not free it.
2158 */
2159KMOD_EXPORT const char *kmod_module_dependency_symbol_get_symbol(const struct kmod_list *entry)
2160{
2161 struct kmod_module_dependency_symbol *dependency_symbol;
2162
2163 if (entry == NULL)
2164 return NULL;
2165
2166 dependency_symbol = entry->data;
2167 return dependency_symbol->symbol;
2168}
2169
2170/**
2171 * kmod_module_dependency_symbol_get_crc:
2172 * @entry: a list entry representing a kmod module dependency_symbol
2173 *
2174 * Get the crc of a kmod module dependency_symbol.
2175 *
2176 * Returns: the crc of this kmod module dependency_symbol on success or NULL on
2177 * failure. The string is owned by the dependency_symbol, do not free it.
2178 */
2179KMOD_EXPORT uint64_t kmod_module_dependency_symbol_get_crc(const struct kmod_list *entry)
2180{
2181 struct kmod_module_dependency_symbol *dependency_symbol;
2182
2183 if (entry == NULL)
2184 return 0;
2185
2186 dependency_symbol = entry->data;
2187 return dependency_symbol->crc;
2188}
2189
2190/**
2191 * kmod_module_dependency_symbol_get_bind:
2192 * @entry: a list entry representing a kmod module dependency_symbol
2193 *
2194 * Get the bind type of a kmod module dependency_symbol.
2195 *
2196 * Returns: the bind of this kmod module dependency_symbol on success
2197 * or < 0 on failure.
2198 */
2199KMOD_EXPORT int kmod_module_dependency_symbol_get_bind(const struct kmod_list *entry)
2200{
2201 struct kmod_module_dependency_symbol *dependency_symbol;
2202
2203 if (entry == NULL)
2204 return 0;
2205
2206 dependency_symbol = entry->data;
2207 return dependency_symbol->bind;
2208}
2209
2210/**
2211 * kmod_module_dependency_symbols_free_list:
2212 * @list: kmod module dependency_symbols list
2213 *
2214 * Release the resources taken by @list
2215 */
2216KMOD_EXPORT void kmod_module_dependency_symbols_free_list(struct kmod_list *list)
2217{
2218 while (list) {
2219 kmod_module_dependency_symbol_free(list->data);
2220 list = kmod_list_remove(list);
2221 }
2222}