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