blob: 5e8ae73e618a7eb770ace048f8c7925210efc96c [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
5 * Copyright (C) 2011 Lucas De Marchi <lucas.de.marchi@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation version 2.1.
10 *
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
21#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>
30#include <sys/stat.h>
31#include <sys/types.h>
32#include <sys/mman.h>
33#include <string.h>
34
35#include "libkmod.h"
36#include "libkmod-private.h"
37
38/**
39 * kmod_module:
40 *
41 * Opaque object representing a module.
42 */
43struct kmod_module {
44 struct kmod_ctx *ctx;
45 int refcount;
46 const char *path;
47 const char *name;
48};
49
50static char *path_to_modname(const char *path)
51{
52 char *modname;
53 char *c;
54
55 modname = basename(path);
56 if (modname == NULL || modname[0] == '\0')
57 return NULL;
58
59 modname = strdup(modname);
60 for (c = modname; *c != '\0' && *c != '.'; c++) {
61 if (*c == '-')
62 *c = '_';
63 }
64
65 *c = '\0';
66 return modname;
67}
68
69static const char *get_modname(struct kmod_module *mod)
70{
71 if (mod->name == NULL)
72 mod->name = path_to_modname(mod->path);
73
74 return mod->name;
75}
76
77KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
78 const char *name,
79 struct kmod_module **mod)
80{
81 struct kmod_module *m;
82
83 if (ctx == NULL || name == NULL)
84 return -ENOENT;
85
86 m = calloc(1, sizeof(*m));
87 if (m == NULL) {
88 free(m);
89 return -ENOMEM;
90 }
91
92 m->ctx = kmod_ref(ctx);
93 m->name = strdup(name);
94
95 *mod = m;
96
97 return 0;
98}
99
100KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
101 const char *path,
102 struct kmod_module **mod)
103{
104 struct kmod_module *m;
105 int err;
106 struct stat st;
107
108 if (ctx == NULL || path == NULL)
109 return -ENOENT;
110
111 err = stat(path, &st);
112 if (err < 0)
113 return -errno;
114
115 m = calloc(1, sizeof(*m));
116 if (m == NULL) {
117 free(m);
118 return -ENOMEM;
119 }
120
121 m->ctx = kmod_ref(ctx);
122 m->path = strdup(path);
123
124 *mod = m;
125
126 return 0;
127}
128
129KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod)
130{
131 if (mod == NULL)
132 return NULL;
133
134 if (--mod->refcount > 0)
135 return mod;
136
137 DBG(mod->ctx, "kmod_module %p released\n", mod);
138
139 kmod_unref(mod->ctx);
140 free((char *) mod->path);
141 free((char *) mod->name);
142 free(mod);
143 return NULL;
144}
145
146KMOD_EXPORT struct kmod_module *kmod_module_ref(struct kmod_module *mod)
147{
148 if (mod == NULL)
149 return NULL;
150
151 mod->refcount++;
152
153 return mod;
154}
155
156extern long delete_module(const char *name, unsigned int flags);
157
158KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
159 unsigned int flags)
160{
161 int err;
162 const char *modname;
163
164 if (mod == NULL)
165 return -ENOENT;
166
167 /* Filter out other flags */
168 flags &= (KMOD_REMOVE_FORCE | KMOD_REMOVE_NOWAIT);
169
170 modname = get_modname(mod);
171 err = delete_module(modname, flags);
172 if (err != 0) {
173 ERR(mod->ctx, "Removing '%s': %s\n", modname,
174 strerror(-err));
175 return err;
176 }
177
178 return 0;
179}
180
181extern long init_module(void *mem, unsigned long len, const char *args);
182
183KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
184 unsigned int flags)
185{
186 int err;
187 void *mmaped_file;
188 struct stat st;
189 int fd;
190 const char *args = "";
191
192 if (mod == NULL)
193 return -ENOENT;
194
195 if (mod->path == NULL) {
196 ERR(mod->ctx, "Not supported to load a module by name yet");
197 return -ENOSYS;
198 }
199
200 if (flags != 0)
201 INFO(mod->ctx, "Flags are not implemented yet");
202
203 if ((fd = open(mod->path, O_RDONLY)) < 0) {
204 err = -errno;
205 return err;
206 }
207
208 stat(mod->path, &st);
209
210 if ((mmaped_file = mmap(0, st.st_size, PROT_READ,
211 MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
212 close(fd);
213 return -errno;
214 }
215
216 err = init_module(mmaped_file, st.st_size, args);
217 if (err < 0)
218 ERR(mod->ctx, "Failed to insert module '%s'", mod->path);
219
220 munmap(mmaped_file, st.st_size);
221 close(fd);
222
223 return err;
224}