]>
Commit | Line | Data |
---|---|---|
ecd40ee4 | 1 | /* |
586fc304 LDM |
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 | */ | |
ecd40ee4 LDM |
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 | ||
586fc304 LDM |
30 | #include "libkmod.h" |
31 | #include "libkmod-private.h" | |
ecd40ee4 LDM |
32 | |
33 | /** | |
586fc304 LDM |
34 | * SECTION:libkmod |
35 | * @short_description: libkmod context | |
ecd40ee4 LDM |
36 | * |
37 | * The context contains the default values for the library user, | |
38 | * and is passed to all library operations. | |
39 | */ | |
40 | ||
41 | /** | |
586fc304 | 42 | * kmod_ctx: |
ecd40ee4 LDM |
43 | * |
44 | * Opaque object representing the library context. | |
45 | */ | |
586fc304 | 46 | struct kmod_ctx { |
ecd40ee4 | 47 | int refcount; |
586fc304 | 48 | void (*log_fn)(struct kmod_ctx *ctx, |
e4351b05 LDM |
49 | int priority, const char *file, int line, |
50 | const char *fn, const char *format, va_list args); | |
ecd40ee4 LDM |
51 | void *userdata; |
52 | int log_priority; | |
53 | }; | |
54 | ||
586fc304 | 55 | void kmod_log(struct kmod_ctx *ctx, |
e4351b05 LDM |
56 | int priority, const char *file, int line, const char *fn, |
57 | const char *format, ...) | |
ecd40ee4 LDM |
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 | ||
586fc304 | 66 | static void log_stderr(struct kmod_ctx *ctx, |
e4351b05 LDM |
67 | int priority, const char *file, int line, |
68 | const char *fn, const char *format, va_list args) | |
ecd40ee4 | 69 | { |
586fc304 | 70 | fprintf(stderr, "libkmod: %s: ", fn); |
ecd40ee4 LDM |
71 | vfprintf(stderr, format, args); |
72 | } | |
73 | ||
74 | /** | |
586fc304 LDM |
75 | * kmod_get_userdata: |
76 | * @ctx: kmod library context | |
ecd40ee4 LDM |
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 | **/ | |
586fc304 | 83 | KMOD_EXPORT void *kmod_get_userdata(struct kmod_ctx *ctx) |
ecd40ee4 LDM |
84 | { |
85 | if (ctx == NULL) | |
86 | return NULL; | |
87 | return ctx->userdata; | |
88 | } | |
89 | ||
90 | /** | |
586fc304 LDM |
91 | * kmod_set_userdata: |
92 | * @ctx: kmod library context | |
ecd40ee4 LDM |
93 | * @userdata: data pointer |
94 | * | |
95 | * Store custom @userdata in the library context. | |
96 | **/ | |
586fc304 | 97 | KMOD_EXPORT void kmod_set_userdata(struct kmod_ctx *ctx, void *userdata) |
ecd40ee4 LDM |
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 | /** | |
586fc304 | 122 | * kmod_new: |
ecd40ee4 | 123 | * |
586fc304 | 124 | * Create kmod library context. This reads the kmod configuration |
ecd40ee4 LDM |
125 | * and fills in the default values. |
126 | * | |
127 | * The initial refcount is 1, and needs to be decremented to | |
586fc304 | 128 | * release the resources of the kmod library context. |
ecd40ee4 | 129 | * |
586fc304 | 130 | * Returns: a new kmod library context |
ecd40ee4 | 131 | **/ |
586fc304 | 132 | KMOD_EXPORT int kmod_new(struct kmod_ctx **ctx) |
ecd40ee4 LDM |
133 | { |
134 | const char *env; | |
586fc304 | 135 | struct kmod_ctx *c; |
ecd40ee4 | 136 | |
586fc304 | 137 | c = calloc(1, sizeof(struct kmod_ctx)); |
ecd40ee4 LDM |
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 */ | |
586fc304 | 146 | env = getenv("KMOD_LOG"); |
ecd40ee4 | 147 | if (env != NULL) |
586fc304 | 148 | kmod_set_log_priority(c, log_priority(env)); |
ecd40ee4 LDM |
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 | /** | |
586fc304 LDM |
157 | * kmod_ref: |
158 | * @ctx: kmod library context | |
ecd40ee4 | 159 | * |
586fc304 | 160 | * Take a reference of the kmod library context. |
ecd40ee4 | 161 | * |
586fc304 | 162 | * Returns: the passed kmod library context |
ecd40ee4 | 163 | **/ |
586fc304 | 164 | KMOD_EXPORT struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx) |
ecd40ee4 LDM |
165 | { |
166 | if (ctx == NULL) | |
167 | return NULL; | |
168 | ctx->refcount++; | |
169 | return ctx; | |
170 | } | |
171 | ||
172 | /** | |
586fc304 LDM |
173 | * kmod_unref: |
174 | * @ctx: kmod library context | |
ecd40ee4 | 175 | * |
586fc304 | 176 | * Drop a reference of the kmod library context. If the refcount |
ecd40ee4 LDM |
177 | * reaches zero, the resources of the context will be released. |
178 | * | |
179 | **/ | |
586fc304 | 180 | KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx) |
ecd40ee4 LDM |
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 | /** | |
586fc304 LDM |
193 | * kmod_set_log_fn: |
194 | * @ctx: kmod library context | |
ecd40ee4 LDM |
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 | **/ | |
586fc304 | 202 | KMOD_EXPORT void kmod_set_log_fn(struct kmod_ctx *ctx, |
e4351b05 LDM |
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)) | |
ecd40ee4 LDM |
207 | { |
208 | ctx->log_fn = log_fn; | |
209 | info(ctx, "custom logging function %p registered\n", log_fn); | |
210 | } | |
211 | ||
212 | /** | |
586fc304 LDM |
213 | * kmod_get_log_priority: |
214 | * @ctx: kmod library context | |
ecd40ee4 LDM |
215 | * |
216 | * Returns: the current logging priority | |
217 | **/ | |
586fc304 | 218 | KMOD_EXPORT int kmod_get_log_priority(struct kmod_ctx *ctx) |
ecd40ee4 LDM |
219 | { |
220 | return ctx->log_priority; | |
221 | } | |
222 | ||
223 | /** | |
586fc304 LDM |
224 | * kmod_set_log_priority: |
225 | * @ctx: kmod library context | |
ecd40ee4 LDM |
226 | * @priority: the new logging priority |
227 | * | |
228 | * Set the current logging priority. The value controls which messages | |
229 | * are logged. | |
230 | **/ | |
586fc304 | 231 | KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority) |
ecd40ee4 LDM |
232 | { |
233 | ctx->log_priority = priority; | |
234 | } | |
235 | ||
586fc304 LDM |
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); | |
ecd40ee4 | 240 | |
586fc304 LDM |
241 | struct kmod_thing { |
242 | struct kmod_ctx *ctx; | |
ecd40ee4 LDM |
243 | int refcount; |
244 | }; | |
245 | ||
586fc304 | 246 | KMOD_EXPORT struct kmod_thing *kmod_thing_ref(struct kmod_thing *thing) |
ecd40ee4 LDM |
247 | { |
248 | if (!thing) | |
249 | return NULL; | |
250 | thing->refcount++; | |
251 | return thing; | |
252 | } | |
253 | ||
586fc304 | 254 | KMOD_EXPORT struct kmod_thing *kmod_thing_unref(struct kmod_thing *thing) |
ecd40ee4 LDM |
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 | ||
586fc304 | 266 | KMOD_EXPORT struct kmod_ctx *kmod_thing_get_ctx(struct kmod_thing *thing) |
ecd40ee4 LDM |
267 | { |
268 | return thing->ctx; | |
269 | } | |
270 | ||
586fc304 | 271 | KMOD_EXPORT int kmod_thing_new_from_string(struct kmod_ctx *ctx, const char *string, struct kmod_thing **thing) |
ecd40ee4 | 272 | { |
586fc304 | 273 | struct kmod_thing *t; |
ecd40ee4 | 274 | |
586fc304 | 275 | t = calloc(1, sizeof(struct kmod_thing)); |
ecd40ee4 LDM |
276 | if (!t) |
277 | return -ENOMEM; | |
278 | ||
279 | t->refcount = 1; | |
280 | t->ctx = ctx; | |
281 | *thing = t; | |
282 | return 0; | |
283 | } | |
284 | ||
586fc304 | 285 | KMOD_EXPORT struct kmod_list_entry *kmod_thing_get_some_list_entry(struct kmod_thing *thing) |
ecd40ee4 LDM |
286 | { |
287 | return NULL; | |
288 | } |