]> git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod.c
Import skeleton from libabc
[thirdparty/kmod.git] / libkmod / libkmod.c
1 /*
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
30 #include "libkmod.h"
31 #include "libkmod-private.h"
32
33 /**
34 * SECTION:libkmod
35 * @short_description: libkmod context
36 *
37 * The context contains the default values for the library user,
38 * and is passed to all library operations.
39 */
40
41 /**
42 * kmod_ctx:
43 *
44 * Opaque object representing the library context.
45 */
46 struct kmod_ctx {
47 int refcount;
48 void (*log_fn)(struct kmod_ctx *ctx,
49 int priority, const char *file, int line, const char *fn,
50 const char *format, va_list args);
51 void *userdata;
52 int log_priority;
53 };
54
55 void kmod_log(struct kmod_ctx *ctx,
56 int priority, const char *file, int line, const char *fn,
57 const char *format, ...)
58 {
59 va_list args;
60
61 va_start(args, format);
62 ctx->log_fn(ctx, priority, file, line, fn, format, args);
63 va_end(args);
64 }
65
66 static void log_stderr(struct kmod_ctx *ctx,
67 int priority, const char *file, int line, const char *fn,
68 const char *format, va_list args)
69 {
70 fprintf(stderr, "libkmod: %s: ", fn);
71 vfprintf(stderr, format, args);
72 }
73
74 /**
75 * kmod_get_userdata:
76 * @ctx: kmod library context
77 *
78 * Retrieve stored data pointer from library context. This might be useful
79 * to access from callbacks like a custom logging function.
80 *
81 * Returns: stored userdata
82 **/
83 KMOD_EXPORT void *kmod_get_userdata(struct kmod_ctx *ctx)
84 {
85 if (ctx == NULL)
86 return NULL;
87 return ctx->userdata;
88 }
89
90 /**
91 * kmod_set_userdata:
92 * @ctx: kmod library context
93 * @userdata: data pointer
94 *
95 * Store custom @userdata in the library context.
96 **/
97 KMOD_EXPORT void kmod_set_userdata(struct kmod_ctx *ctx, void *userdata)
98 {
99 if (ctx == NULL)
100 return;
101 ctx->userdata = userdata;
102 }
103
104 static int log_priority(const char *priority)
105 {
106 char *endptr;
107 int prio;
108
109 prio = strtol(priority, &endptr, 10);
110 if (endptr[0] == '\0' || isspace(endptr[0]))
111 return prio;
112 if (strncmp(priority, "err", 3) == 0)
113 return LOG_ERR;
114 if (strncmp(priority, "info", 4) == 0)
115 return LOG_INFO;
116 if (strncmp(priority, "debug", 5) == 0)
117 return LOG_DEBUG;
118 return 0;
119 }
120
121 /**
122 * kmod_new:
123 *
124 * Create kmod library context. This reads the kmod configuration
125 * and fills in the default values.
126 *
127 * The initial refcount is 1, and needs to be decremented to
128 * release the resources of the kmod library context.
129 *
130 * Returns: a new kmod library context
131 **/
132 KMOD_EXPORT int kmod_new(struct kmod_ctx **ctx)
133 {
134 const char *env;
135 struct kmod_ctx *c;
136
137 c = calloc(1, sizeof(struct kmod_ctx));
138 if (!c)
139 return -ENOMEM;
140
141 c->refcount = 1;
142 c->log_fn = log_stderr;
143 c->log_priority = LOG_ERR;
144
145 /* environment overwrites config */
146 env = getenv("KMOD_LOG");
147 if (env != NULL)
148 kmod_set_log_priority(c, log_priority(env));
149
150 info(c, "ctx %p created\n", c);
151 dbg(c, "log_priority=%d\n", c->log_priority);
152 *ctx = c;
153 return 0;
154 }
155
156 /**
157 * kmod_ref:
158 * @ctx: kmod library context
159 *
160 * Take a reference of the kmod library context.
161 *
162 * Returns: the passed kmod library context
163 **/
164 KMOD_EXPORT struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx)
165 {
166 if (ctx == NULL)
167 return NULL;
168 ctx->refcount++;
169 return ctx;
170 }
171
172 /**
173 * kmod_unref:
174 * @ctx: kmod library context
175 *
176 * Drop a reference of the kmod library context. If the refcount
177 * reaches zero, the resources of the context will be released.
178 *
179 **/
180 KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx)
181 {
182 if (ctx == NULL)
183 return NULL;
184 ctx->refcount--;
185 if (ctx->refcount > 0)
186 return ctx;
187 info(ctx, "context %p released\n", ctx);
188 free(ctx);
189 return NULL;
190 }
191
192 /**
193 * kmod_set_log_fn:
194 * @ctx: kmod library context
195 * @log_fn: function to be called for logging messages
196 *
197 * The built-in logging writes to stderr. It can be
198 * overridden by a custom function, to plug log messages
199 * into the user's logging functionality.
200 *
201 **/
202 KMOD_EXPORT void kmod_set_log_fn(struct kmod_ctx *ctx,
203 void (*log_fn)(struct kmod_ctx *ctx,
204 int priority, const char *file,
205 int line, const char *fn,
206 const char *format, va_list args))
207 {
208 ctx->log_fn = log_fn;
209 info(ctx, "custom logging function %p registered\n", log_fn);
210 }
211
212 /**
213 * kmod_get_log_priority:
214 * @ctx: kmod library context
215 *
216 * Returns: the current logging priority
217 **/
218 KMOD_EXPORT int kmod_get_log_priority(struct kmod_ctx *ctx)
219 {
220 return ctx->log_priority;
221 }
222
223 /**
224 * kmod_set_log_priority:
225 * @ctx: kmod library context
226 * @priority: the new logging priority
227 *
228 * Set the current logging priority. The value controls which messages
229 * are logged.
230 **/
231 KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority)
232 {
233 ctx->log_priority = priority;
234 }
235
236 struct kmod_list_entry;
237 struct kmod_list_entry *kmod_list_entry_get_next(struct kmod_list_entry *list_entry);
238 const char *kmod_list_entry_get_name(struct kmod_list_entry *list_entry);
239 const char *kmod_list_entry_get_value(struct kmod_list_entry *list_entry);
240
241 struct kmod_thing {
242 struct kmod_ctx *ctx;
243 int refcount;
244 };
245
246 KMOD_EXPORT struct kmod_thing *kmod_thing_ref(struct kmod_thing *thing)
247 {
248 if (!thing)
249 return NULL;
250 thing->refcount++;
251 return thing;
252 }
253
254 KMOD_EXPORT struct kmod_thing *kmod_thing_unref(struct kmod_thing *thing)
255 {
256 if (thing == NULL)
257 return NULL;
258 thing->refcount--;
259 if (thing->refcount > 0)
260 return thing;
261 dbg(thing->ctx, "context %p released\n", thing);
262 free(thing);
263 return NULL;
264 }
265
266 KMOD_EXPORT struct kmod_ctx *kmod_thing_get_ctx(struct kmod_thing *thing)
267 {
268 return thing->ctx;
269 }
270
271 KMOD_EXPORT int kmod_thing_new_from_string(struct kmod_ctx *ctx, const char *string, struct kmod_thing **thing)
272 {
273 struct kmod_thing *t;
274
275 t = calloc(1, sizeof(struct kmod_thing));
276 if (!t)
277 return -ENOMEM;
278
279 t->refcount = 1;
280 t->ctx = ctx;
281 *thing = t;
282 return 0;
283 }
284
285 KMOD_EXPORT struct kmod_list_entry *kmod_thing_get_some_list_entry(struct kmod_thing *thing)
286 {
287 return NULL;
288 }