]>
git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-module.c
2 * libkmod - interface to kernel module operations
4 * Copyright (C) 2011 ProFUSION embedded systems
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.
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.
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
31 #include <sys/types.h>
36 #include "libkmod-private.h"
41 * Opaque object representing a module.
48 struct kmod_list
*dep
;
55 static char *path_to_modname(const char *path
, bool alloc
)
60 modname
= basename(path
);
61 if (modname
== NULL
|| modname
[0] == '\0')
65 modname
= strdup(modname
);
67 for (c
= modname
; *c
!= '\0' && *c
!= '.'; c
++) {
76 static const char *get_modname(struct kmod_module
*mod
)
78 if (mod
->name
== NULL
)
79 mod
->name
= path_to_modname(mod
->path
, true);
84 int kmod_module_parse_dep(struct kmod_module
*mod
, char *line
)
86 struct kmod_ctx
*ctx
= mod
->ctx
;
87 struct kmod_list
*list
= NULL
;
91 assert(!mod
->init
.dep
&& mod
->dep
== NULL
);
94 p
= strchr(line
, ':');
100 for (p
= strtok_r(p
, " \t", &saveptr
); p
!= NULL
;
101 p
= strtok_r(NULL
, " \t", &saveptr
)) {
102 const char *modname
= path_to_modname(p
, false);
103 struct kmod_module
*depmod
;
105 err
= kmod_module_new_from_name(ctx
, modname
, &depmod
);
107 ERR(ctx
, "ctx=%p modname=%s error=%s\n",
108 ctx
, modname
, strerror(-err
));
112 DBG(ctx
, "add dep: %s\n", modname
);
114 list
= kmod_list_append(list
, depmod
);
118 DBG(ctx
, "%d dependencies for %s\n", n
, mod
->name
);
124 kmod_module_unref_list(list
);
125 mod
->init
.dep
= false;
129 KMOD_EXPORT
int kmod_module_new_from_name(struct kmod_ctx
*ctx
,
131 struct kmod_module
**mod
)
133 struct kmod_module
*m
;
135 if (ctx
== NULL
|| name
== NULL
)
138 m
= calloc(1, sizeof(*m
));
144 m
->ctx
= kmod_ref(ctx
);
145 m
->name
= strdup(name
);
152 KMOD_EXPORT
int kmod_module_new_from_path(struct kmod_ctx
*ctx
,
154 struct kmod_module
**mod
)
156 struct kmod_module
*m
;
160 if (ctx
== NULL
|| path
== NULL
)
163 err
= stat(path
, &st
);
167 m
= calloc(1, sizeof(*m
));
173 m
->ctx
= kmod_ref(ctx
);
174 m
->path
= strdup(path
);
181 KMOD_EXPORT
struct kmod_module
*kmod_module_unref(struct kmod_module
*mod
)
186 if (--mod
->refcount
> 0)
189 DBG(mod
->ctx
, "kmod_module %p released\n", mod
);
191 kmod_module_unref_list(mod
->dep
);
192 kmod_unref(mod
->ctx
);
193 free((char *) mod
->path
);
194 free((char *) mod
->name
);
199 KMOD_EXPORT
struct kmod_module
*kmod_module_ref(struct kmod_module
*mod
)
209 #define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
213 if (*(_list) != NULL) \
217 KMOD_EXPORT
int kmod_module_new_from_lookup(struct kmod_ctx
*ctx
,
219 struct kmod_list
**list
)
223 if (ctx
== NULL
|| alias
== NULL
)
226 if (list
== NULL
|| *list
!= NULL
) {
227 ERR(ctx
, "An empty list is needed to create lookup\n");
231 /* Aliases from config file override all the others */
232 err
= kmod_lookup_alias_from_config(ctx
, alias
, list
);
233 CHECK_ERR_AND_FINISH(err
, fail
, list
, finish
);
235 err
= kmod_lookup_alias_from_moddep_file(ctx
, alias
, list
);
236 CHECK_ERR_AND_FINISH(err
, fail
, list
, finish
);
238 err
= kmod_lookup_alias_from_symbols_file(ctx
, alias
, list
);
239 CHECK_ERR_AND_FINISH(err
, fail
, list
, finish
);
241 err
= kmod_lookup_alias_from_aliases_file(ctx
, alias
, list
);
242 CHECK_ERR_AND_FINISH(err
, fail
, list
, finish
);
248 kmod_module_unref_list(*list
);
252 #undef CHECK_ERR_AND_FINISH
255 KMOD_EXPORT
int kmod_module_unref_list(struct kmod_list
*list
)
257 for (; list
!= NULL
; list
= kmod_list_remove(list
))
258 kmod_module_unref(list
->data
);
264 * We don't increase the refcount. Maybe we should.
266 KMOD_EXPORT
struct kmod_list
*kmod_module_get_dependency(const struct kmod_module
*mod
)
268 // FIXME calculate dependency if it's not initialized
272 KMOD_EXPORT
struct kmod_module
*kmod_module_get_module(const struct kmod_list
*l
)
274 struct kmod_module
*mod
= l
->data
;
275 return kmod_module_ref(mod
);
278 KMOD_EXPORT
const char *kmod_module_get_name(const struct kmod_module
*mod
)
280 // FIXME calculate name if name == NULL
284 KMOD_EXPORT
const char *kmod_module_get_path(const struct kmod_module
*mod
)
286 // FIXME calculate path if path == NULL
291 extern long delete_module(const char *name
, unsigned int flags
);
293 KMOD_EXPORT
int kmod_module_remove_module(struct kmod_module
*mod
,
302 /* Filter out other flags */
303 flags
&= (KMOD_REMOVE_FORCE
| KMOD_REMOVE_NOWAIT
);
305 modname
= get_modname(mod
);
306 err
= delete_module(modname
, flags
);
308 ERR(mod
->ctx
, "Removing '%s': %s\n", modname
,
316 extern long init_module(void *mem
, unsigned long len
, const char *args
);
318 KMOD_EXPORT
int kmod_module_insert_module(struct kmod_module
*mod
,
325 const char *args
= "";
330 if (mod
->path
== NULL
) {
331 ERR(mod
->ctx
, "Not supported to load a module by name yet\n");
336 INFO(mod
->ctx
, "Flags are not implemented yet\n");
338 if ((fd
= open(mod
->path
, O_RDONLY
)) < 0) {
345 if ((mmaped_file
= mmap(0, st
.st_size
, PROT_READ
,
346 MAP_PRIVATE
, fd
, 0)) == MAP_FAILED
) {
351 err
= init_module(mmaped_file
, st
.st_size
, args
);
353 ERR(mod
->ctx
, "Failed to insert module '%s'\n", mod
->path
);
355 munmap(mmaped_file
, st
.st_size
);