blob: b9e76651686e6df95788a9a90fe5bfda57e2e3ed [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
8 * License as published by the Free Software Foundation version 2.1.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
Lucas De Marchi7636e722011-12-01 17:56:03 -020020#include <assert.h>
Lucas De Marchi8f788d52011-11-25 01:22:56 -020021#include <stdio.h>
22#include <stdlib.h>
23#include <stddef.h>
24#include <stdarg.h>
25#include <unistd.h>
26#include <errno.h>
27#include <string.h>
28#include <ctype.h>
29#include <inttypes.h>
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -020030#include <limits.h>
31#include <dirent.h>
Lucas De Marchi8f788d52011-11-25 01:22:56 -020032#include <sys/stat.h>
33#include <sys/types.h>
34#include <sys/mman.h>
35#include <string.h>
36
37#include "libkmod.h"
38#include "libkmod-private.h"
39
40/**
41 * kmod_module:
42 *
43 * Opaque object representing a module.
44 */
45struct kmod_module {
46 struct kmod_ctx *ctx;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020047 const char *path;
48 const char *name;
Lucas De Marchi7636e722011-12-01 17:56:03 -020049 struct kmod_list *dep;
Gustavo Sverzut Barbieri8d3f3ef2011-12-02 21:10:24 -020050 int refcount;
Lucas De Marchi7636e722011-12-01 17:56:03 -020051 struct {
52 bool dep : 1;
53 } init;
Lucas De Marchi8f788d52011-11-25 01:22:56 -020054};
55
Lucas De Marchi9eaad1f2011-12-01 17:18:24 -020056static char *path_to_modname(const char *path, bool alloc)
Lucas De Marchi8f788d52011-11-25 01:22:56 -020057{
58 char *modname;
59 char *c;
60
61 modname = basename(path);
62 if (modname == NULL || modname[0] == '\0')
63 return NULL;
64
Lucas De Marchi9eaad1f2011-12-01 17:18:24 -020065 if (alloc)
66 modname = strdup(modname);
67
Lucas De Marchi8f788d52011-11-25 01:22:56 -020068 for (c = modname; *c != '\0' && *c != '.'; c++) {
69 if (*c == '-')
70 *c = '_';
71 }
72
73 *c = '\0';
74 return modname;
75}
76
77static const char *get_modname(struct kmod_module *mod)
78{
79 if (mod->name == NULL)
Lucas De Marchi9eaad1f2011-12-01 17:18:24 -020080 mod->name = path_to_modname(mod->path, true);
Lucas De Marchi8f788d52011-11-25 01:22:56 -020081
82 return mod->name;
83}
84
Lucas De Marchi7636e722011-12-01 17:56:03 -020085int kmod_module_parse_dep(struct kmod_module *mod, char *line)
86{
87 struct kmod_ctx *ctx = mod->ctx;
88 struct kmod_list *list = NULL;
89 char *p, *saveptr;
90 int err, n = 0;
91
92 assert(!mod->init.dep && mod->dep == NULL);
93 mod->init.dep = true;
94
95 p = strchr(line, ':');
96 if (p == NULL)
97 return 0;
98
99 p++;
100
101 for (p = strtok_r(p, " \t", &saveptr); p != NULL;
102 p = strtok_r(NULL, " \t", &saveptr)) {
103 const char *modname = path_to_modname(p, false);
Lucas De Marchi1fc1c9a2011-12-02 10:00:03 -0200104 struct kmod_module *depmod;
Lucas De Marchi7636e722011-12-01 17:56:03 -0200105
Lucas De Marchi1fc1c9a2011-12-02 10:00:03 -0200106 err = kmod_module_new_from_name(ctx, modname, &depmod);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200107 if (err < 0) {
108 ERR(ctx, "ctx=%p modname=%s error=%s\n",
109 ctx, modname, strerror(-err));
110 goto fail;
111 }
112
113 DBG(ctx, "add dep: %s\n", modname);
114
Lucas De Marchi1fc1c9a2011-12-02 10:00:03 -0200115 list = kmod_list_append(list, depmod);
Lucas De Marchi7636e722011-12-01 17:56:03 -0200116 n++;
117 }
118
119 DBG(ctx, "%d dependencies for %s\n", n, mod->name);
120
121 mod->dep = list;
122 return n;
123
124fail:
125 kmod_module_unref_list(list);
126 mod->init.dep = false;
127 return err;
128}
129
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200130KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
131 const char *name,
132 struct kmod_module **mod)
133{
134 struct kmod_module *m;
135
136 if (ctx == NULL || name == NULL)
137 return -ENOENT;
138
139 m = calloc(1, sizeof(*m));
140 if (m == NULL) {
141 free(m);
142 return -ENOMEM;
143 }
144
145 m->ctx = kmod_ref(ctx);
146 m->name = strdup(name);
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200147 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200148
149 *mod = m;
150
151 return 0;
152}
153
154KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
155 const char *path,
156 struct kmod_module **mod)
157{
158 struct kmod_module *m;
159 int err;
160 struct stat st;
161
162 if (ctx == NULL || path == NULL)
163 return -ENOENT;
164
165 err = stat(path, &st);
166 if (err < 0)
167 return -errno;
168
169 m = calloc(1, sizeof(*m));
170 if (m == NULL) {
171 free(m);
172 return -ENOMEM;
173 }
174
175 m->ctx = kmod_ref(ctx);
176 m->path = strdup(path);
Gustavo Sverzut Barbieri87ca03b2011-12-04 12:34:02 -0200177 m->refcount = 1;
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200178
179 *mod = m;
180
181 return 0;
182}
183
184KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
185{
186 if (mod == NULL)
187 return NULL;
188
189 if (--mod->refcount > 0)
190 return mod;
191
192 DBG(mod->ctx, "kmod_module %p released\n", mod);
193
Lucas De Marchi7636e722011-12-01 17:56:03 -0200194 kmod_module_unref_list(mod->dep);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200195 kmod_unref(mod->ctx);
196 free((char *) mod->path);
197 free((char *) mod->name);
198 free(mod);
199 return NULL;
200}
201
202KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
203{
204 if (mod == NULL)
205 return NULL;
206
207 mod->refcount++;
208
209 return mod;
210}
211
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200212#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
213 do { \
214 if ((_err) < 0) \
215 goto _label_err; \
216 if (*(_list) != NULL) \
217 goto finish; \
218 } while (0)
219
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200220KMOD_EXPORT int kmod_module_new_from_lookup(struct kmod_ctx *ctx,
221 const char *alias,
222 struct kmod_list **list)
223{
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200224 int err;
225
226 if (ctx == NULL || alias == NULL)
227 return -ENOENT;
228
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200229 if (list == NULL || *list != NULL) {
230 ERR(ctx, "An empty list is needed to create lookup\n");
231 return -ENOSYS;
232 }
233
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200234 /* Aliases from config file override all the others */
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200235 err = kmod_lookup_alias_from_config(ctx, alias, list);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200236 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200237
Lucas De Marchi64700e42011-12-01 15:57:53 -0200238 err = kmod_lookup_alias_from_moddep_file(ctx, alias, list);
239 CHECK_ERR_AND_FINISH(err, fail, list, finish);
240
Lucas De Marchi9ba6f572011-11-30 20:31:45 -0200241 err = kmod_lookup_alias_from_symbols_file(ctx, alias, list);
242 CHECK_ERR_AND_FINISH(err, fail, list, finish);
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200243
Lucas De Marchi49e61ca2011-12-01 16:27:04 -0200244 err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
245 CHECK_ERR_AND_FINISH(err, fail, list, finish);
246
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200247finish:
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200248
249 return err;
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200250fail:
251 kmod_module_unref_list(*list);
252 *list = NULL;
Lucas De Marchi84f42202011-12-02 10:03:34 -0200253 return err;
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200254}
Lucas De Marchib14dcfd2011-11-30 20:29:51 -0200255#undef CHECK_ERR_AND_FINISH
256
Lucas De Marchi7f3eb0c2011-11-30 19:03:41 -0200257
258KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list)
259{
260 for (; list != NULL; list = kmod_list_remove(list))
261 kmod_module_unref(list->data);
262
263 return 0;
264}
265
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200266/*
267 * We don't increase the refcount. Maybe we should.
268 */
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200269KMOD_EXPORT struct kmod_list *kmod_module_get_dependency(const struct kmod_module *mod)
Lucas De Marchi0835fc32011-12-01 20:06:08 -0200270{
271 // FIXME calculate dependency if it's not initialized
272 return mod->dep;
273}
274
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200275KMOD_EXPORT struct kmod_module *kmod_module_get_module(const struct kmod_list *entry)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200276{
Gustavo Sverzut Barbieriad4d1ae2011-12-04 13:14:11 -0200277 if (entry == NULL)
278 return NULL;
279 return kmod_module_ref(entry->data);
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200280}
281
Gustavo Sverzut Barbieri69f9dd42011-12-04 14:02:30 -0200282KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
283{
284 // FIXME TODO: this should be available from /sys/module/foo
285 FILE *fp;
286 char line[4096];
287 int lineno = 0;
288 long size = -ENOENT;
289
290 if (mod == NULL)
291 return -ENOENT;
292
293 fp = fopen("/proc/modules", "r");
294 if (fp == NULL) {
295 int err = -errno;
296 ERR(mod->ctx,
297 "could not open /proc/modules: %s\n", strerror(errno));
298 return err;
299 }
300
301 while (fgets(line, sizeof(line), fp)) {
302 char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
303 long value;
304
305 lineno++;
306 if (tok == NULL || strcmp(tok, mod->name) != 0)
307 continue;
308
309 tok = strtok_r(NULL, " \t", &saveptr);
310 if (tok == NULL) {
311 ERR(mod->ctx,
312 "invalid line format at /proc/modules:%d\n", lineno);
313 break;
314 }
315
316 value = strtol(tok, &endptr, 10);
317 if (endptr == tok || *endptr != '\0') {
318 ERR(mod->ctx,
319 "invalid line format at /proc/modules:%d\n", lineno);
320 break;
321 }
322
323 size = value;
324 break;
325 }
326 fclose(fp);
327 return size;
328}
329
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200330KMOD_EXPORT const char *kmod_module_get_name(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200331{
332 // FIXME calculate name if name == NULL
333 return mod->name;
334}
335
Gustavo Sverzut Barbieri1ce08a52011-12-02 20:24:07 -0200336KMOD_EXPORT const char *kmod_module_get_path(const struct kmod_module *mod)
Lucas De Marchi6e869df2011-11-30 19:01:01 -0200337{
338 // FIXME calculate path if path == NULL
339 return mod->path;
340}
341
342
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200343extern long delete_module(const char *name, unsigned int flags);
344
345KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
346 unsigned int flags)
347{
348 int err;
349 const char *modname;
350
351 if (mod == NULL)
352 return -ENOENT;
353
354 /* Filter out other flags */
355 flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
356
357 modname = get_modname(mod);
358 err = delete_module(modname, flags);
359 if (err != 0) {
360 ERR(mod->ctx, "Removing '%s': %s\n", modname,
361 strerror(-err));
362 return err;
363 }
364
365 return 0;
366}
367
368extern long init_module(void *mem, unsigned long len, const char *args);
369
370KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
371 unsigned int flags)
372{
373 int err;
374 void *mmaped_file;
375 struct stat st;
376 int fd;
377 const char *args = "";
378
379 if (mod == NULL)
380 return -ENOENT;
381
382 if (mod->path == NULL) {
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200383 ERR(mod->ctx, "Not supported to load a module by name yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200384 return -ENOSYS;
385 }
386
387 if (flags != 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200388 INFO(mod->ctx, "Flags are not implemented yet\n");
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200389
390 if ((fd = open(mod->path, O_RDONLY)) < 0) {
391 err = -errno;
392 return err;
393 }
394
Lucas De Marchib418a822011-12-01 23:13:27 -0200395 fstat(fd, &st);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200396
397 if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
398 MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
399 close(fd);
400 return -errno;
401 }
402
403 err = init_module(mmaped_file, st.st_size, args);
404 if (err < 0)
Lucas De Marchi1b2e26a2011-11-25 01:28:39 -0200405 ERR(mod->ctx, "Failed to insert module '%s'\n", mod->path);
Lucas De Marchi8f788d52011-11-25 01:22:56 -0200406
407 munmap(mmaped_file, st.st_size);
408 close(fd);
409
410 return err;
411}
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200412
413KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate state)
414{
415 switch (state) {
416 case KMOD_MODULE_BUILTIN:
417 return "builtin";
418 case KMOD_MODULE_LIVE:
419 return "live";
420 case KMOD_MODULE_COMING:
421 return "coming";
422 case KMOD_MODULE_GOING:
423 return "going";
424 default:
425 return NULL;
426 }
427}
428
429KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod)
430{
431 char path[PATH_MAX], buf[32];
432 int fd, err, pathlen;
433
434 pathlen = snprintf(path, sizeof(path),
435 "/sys/module/%s/initstate", mod->name);
436 fd = open(path, O_RDONLY);
437 if (fd < 0) {
438 err = -errno;
439
440 if (pathlen > (int)sizeof("/initstate") - 1) {
441 struct stat st;
442 path[pathlen - (sizeof("/initstate") - 1)] = '\0';
443 if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
444 return KMOD_MODULE_BUILTIN;
445 }
446
447 ERR(mod->ctx, "could not open '%s': %s\n",
448 path, strerror(-err));
449 return err;
450 }
451
452 err = read_str_safe(fd, buf, sizeof(buf));
453 close(fd);
454 if (err < 0) {
455 ERR(mod->ctx, "could not read from '%s': %s\n",
456 path, strerror(-err));
457 return err;
458 }
459
460 if (strcmp(buf, "live\n") == 0)
461 return KMOD_MODULE_LIVE;
462 else if (strcmp(buf, "coming\n") == 0)
463 return KMOD_MODULE_COMING;
464 else if (strcmp(buf, "going\n") == 0)
465 return KMOD_MODULE_GOING;
466
467 ERR(mod->ctx, "unknown %s: '%s'\n", path, buf);
468 return -EINVAL;
469}
470
471KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
472{
473 char path[PATH_MAX];
474 long refcnt;
475 int fd, err;
476
477 snprintf(path, sizeof(path), "/sys/module/%s/refcnt", mod->name);
478 fd = open(path, O_RDONLY);
479 if (fd < 0) {
480 err = -errno;
481 ERR(mod->ctx, "could not open '%s': %s\n",
482 path, strerror(errno));
483 return err;
484 }
485
486 err = read_str_long(fd, &refcnt, 10);
487 close(fd);
488 if (err < 0) {
489 ERR(mod->ctx, "could not read integer from '%s': '%s'\n",
490 path, strerror(-err));
491 return err;
492 }
493
494 return (int)refcnt;
495}
496
497KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module *mod)
498{
499 char dname[PATH_MAX];
500 struct kmod_list *list = NULL;
501 DIR *d;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200502
503 if (mod == NULL)
504 return NULL;
505 snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name);
506
507 d = opendir(dname);
508 if (d == NULL) {
509 ERR(mod->ctx, "could not open '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200510 dname, strerror(errno));
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200511 return NULL;
512 }
513
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200514 for (;;) {
515 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200516 struct kmod_module *holder;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200517 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200518 int err;
519
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200520 err = readdir_r(d, &de, &entp);
521 if (err != 0) {
522 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
523 mod->name, strerror(-err));
524 goto fail;
525 }
526
527 if (entp == NULL)
528 break;
529
530 if (de.d_name[0] == '.') {
531 if (de.d_name[1] == '\0' ||
532 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200533 continue;
534 }
535
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200536 err = kmod_module_new_from_name(mod->ctx, de.d_name, &holder);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200537 if (err < 0) {
538 ERR(mod->ctx, "could not create module for '%s': %s\n",
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200539 de.d_name, strerror(-err));
540 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200541 }
542
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200543 l = kmod_list_append(list, holder);
544 if (l != NULL) {
545 list = l;
546 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200547 ERR(mod->ctx, "out of memory\n");
548 kmod_module_unref(holder);
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200549 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200550 }
551 }
552
553 closedir(d);
554 return list;
Lucas De Marchi53886dd2011-12-05 13:24:23 -0200555
556fail:
557 closedir(d);
558 kmod_module_unref_list(list);
559 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200560}
561
562struct kmod_module_section {
563 unsigned long address;
564 char name[];
565};
566
567static void kmod_module_section_free(struct kmod_module_section *section)
568{
569 free(section);
570}
571
572KMOD_EXPORT struct kmod_list *kmod_module_get_sections(const struct kmod_module *mod)
573{
574 char dname[PATH_MAX];
575 struct kmod_list *list = NULL;
576 DIR *d;
577 int dfd;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200578
579 if (mod == NULL)
580 return NULL;
581 snprintf(dname, sizeof(dname), "/sys/module/%s/sections", mod->name);
582
583 d = opendir(dname);
584 if (d == NULL) {
585 ERR(mod->ctx, "could not open '%s': %s\n",
586 dname, strerror(errno));
587 return NULL;
588 }
589
590 dfd = dirfd(d);
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200591
592 for (;;) {
593 struct dirent de, *entp;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200594 struct kmod_module_section *section;
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200595 struct kmod_list *l;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200596 unsigned long address;
597 size_t namesz;
598 int fd, err;
599
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200600 err = readdir_r(d, &de, &entp);
601 if (err != 0) {
602 ERR(mod->ctx, "could not iterate for module '%s': %s\n",
603 mod->name, strerror(-err));
604 goto fail;
605 }
606
607 if (de.d_name[0] == '.') {
608 if (de.d_name[1] == '\0' ||
609 (de.d_name[1] == '.' && de.d_name[2] == '\0'))
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200610 continue;
611 }
612
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200613 fd = openat(dfd, de.d_name, O_RDONLY);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200614 if (fd < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200615 ERR(mod->ctx, "could not open '%s/%s': %m\n",
616 dname, de.d_name);
617 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200618 }
619
620 err = read_str_ulong(fd, &address, 16);
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200621 close(fd);
622
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200623 if (err < 0) {
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200624 ERR(mod->ctx, "could not read long from '%s/%s': %m\n",
625 dname, de.d_name);
626 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200627 }
628
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200629 namesz = strlen(de.d_name) + 1;
630 section = malloc(sizeof(*section) + namesz);
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200631
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200632 if (section == NULL) {
633 ERR(mod->ctx, "out of memory\n");
634 goto fail;
635 }
636
637 section->address = address;
638 memcpy(section->name, de.d_name, namesz);
639
640 l = kmod_list_append(list, section);
641 if (l != NULL) {
642 list = l;
643 } else {
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200644 ERR(mod->ctx, "out of memory\n");
645 free(section);
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200646 goto fail;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200647 }
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200648 }
649
650 closedir(d);
651 return list;
Lucas De Marchi40923bd2011-12-05 13:40:16 -0200652
653fail:
654 closedir(d);
655 kmod_module_unref_list(list);
656 return NULL;
Gustavo Sverzut Barbierif12ae3c2011-12-04 12:40:00 -0200657}
658
659KMOD_EXPORT const char *kmod_module_section_get_name(const struct kmod_list *entry)
660{
661 struct kmod_module_section *section;
662 if (entry == NULL)
663 return NULL;
664 section = entry->data;
665 return section->name;
666}
667
668KMOD_EXPORT unsigned long kmod_module_section_get_address(const struct kmod_list *entry)
669{
670 struct kmod_module_section *section;
671 if (entry == NULL)
672 return (unsigned long)-1;
673 section = entry->data;
674 return section->address;
675}
676
677KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list)
678{
679 while (list) {
680 kmod_module_section_free(list->data);
681 list = kmod_list_remove(list);
682 }
683}