chiark / gitweb /
libudev: prefix log macros with 'udev_'
[elogind.git] / src / libudev / libudev.c
1 /*
2  * libudev - interface to udev device information
3  *
4  * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org>
5  *
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; either
9  * version 2.1 of the License, or (at your option) any later version.
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 #include <stdarg.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <string.h>
19 #include <ctype.h>
20 #include <time.h>
21
22 #include "libudev.h"
23 #include "libudev-private.h"
24
25 /**
26  * SECTION:libudev
27  * @short_description: libudev context
28  *
29  * The context contains the default values read from the udev config file,
30  * and is passed to all library operations.
31  */
32
33 /**
34  * udev:
35  *
36  * Opaque object representing the library context.
37  */
38 struct udev {
39         int refcount;
40         void (*log_fn)(struct udev *udev,
41                        int priority, const char *file, int line, const char *fn,
42                        const char *format, va_list args);
43         void *userdata;
44         struct udev_list properties_list;
45         int log_priority;
46 };
47
48 void udev_log(struct udev *udev,
49               int priority, const char *file, int line, const char *fn,
50               const char *format, ...)
51 {
52         va_list args;
53
54         va_start(args, format);
55         udev->log_fn(udev, priority, file, line, fn, format, args);
56         va_end(args);
57 }
58
59 static void log_stderr(struct udev *udev,
60                        int priority, const char *file, int line, const char *fn,
61                        const char *format, va_list args)
62 {
63         fprintf(stderr, "libudev: %s: ", fn);
64         vfprintf(stderr, format, args);
65 }
66
67 /**
68  * udev_get_userdata:
69  * @udev: udev library context
70  *
71  * Retrieve stored data pointer from library context. This might be useful
72  * to access from callbacks like a custom logging function.
73  *
74  * Returns: stored userdata
75  **/
76 _public_ void *udev_get_userdata(struct udev *udev)
77 {
78         if (udev == NULL)
79                 return NULL;
80         return udev->userdata;
81 }
82
83 /**
84  * udev_set_userdata:
85  * @udev: udev library context
86  * @userdata: data pointer
87  *
88  * Store custom @userdata in the library context.
89  **/
90 _public_ void udev_set_userdata(struct udev *udev, void *userdata)
91 {
92         if (udev == NULL)
93                 return;
94         udev->userdata = userdata;
95 }
96
97 /**
98  * udev_new:
99  *
100  * Create udev library context. This reads the udev configuration
101  * file, and fills in the default values.
102  *
103  * The initial refcount is 1, and needs to be decremented to
104  * release the resources of the udev library context.
105  *
106  * Returns: a new udev library context
107  **/
108 _public_ struct udev *udev_new(void)
109 {
110         struct udev *udev;
111         const char *env;
112         FILE *f;
113
114         udev = calloc(1, sizeof(struct udev));
115         if (udev == NULL)
116                 return NULL;
117         udev->refcount = 1;
118         udev->log_fn = log_stderr;
119         udev->log_priority = LOG_ERR;
120         udev_list_init(udev, &udev->properties_list, true);
121
122         f = fopen(SYSCONFDIR "/udev/udev.conf", "re");
123         if (f != NULL) {
124                 char line[UTIL_LINE_SIZE];
125                 int line_nr = 0;
126
127                 while (fgets(line, sizeof(line), f)) {
128                         size_t len;
129                         char *key;
130                         char *val;
131
132                         line_nr++;
133
134                         /* find key */
135                         key = line;
136                         while (isspace(key[0]))
137                                 key++;
138
139                         /* comment or empty line */
140                         if (key[0] == '#' || key[0] == '\0')
141                                 continue;
142
143                         /* split key/value */
144                         val = strchr(key, '=');
145                         if (val == NULL) {
146                                 udev_err(udev, "missing <key>=<value> in " SYSCONFDIR "/udev/udev.conf[%i]; skip line\n", line_nr);
147                                 continue;
148                         }
149                         val[0] = '\0';
150                         val++;
151
152                         /* find value */
153                         while (isspace(val[0]))
154                                 val++;
155
156                         /* terminate key */
157                         len = strlen(key);
158                         if (len == 0)
159                                 continue;
160                         while (isspace(key[len-1]))
161                                 len--;
162                         key[len] = '\0';
163
164                         /* terminate value */
165                         len = strlen(val);
166                         if (len == 0)
167                                 continue;
168                         while (isspace(val[len-1]))
169                                 len--;
170                         val[len] = '\0';
171
172                         if (len == 0)
173                                 continue;
174
175                         /* unquote */
176                         if (val[0] == '"' || val[0] == '\'') {
177                                 if (val[len-1] != val[0]) {
178                                         udev_err(udev, "inconsistent quoting in " SYSCONFDIR "/udev/udev.conf[%i]; skip line\n", line_nr);
179                                         continue;
180                                 }
181                                 val[len-1] = '\0';
182                                 val++;
183                         }
184
185                         if (strcmp(key, "udev_log") == 0) {
186                                 udev_set_log_priority(udev, util_log_priority(val));
187                                 continue;
188                         }
189                 }
190                 fclose(f);
191         }
192
193         /* environment overrides config */
194         env = getenv("UDEV_LOG");
195         if (env != NULL)
196                 udev_set_log_priority(udev, util_log_priority(env));
197
198         return udev;
199 }
200
201 /**
202  * udev_ref:
203  * @udev: udev library context
204  *
205  * Take a reference of the udev library context.
206  *
207  * Returns: the passed udev library context
208  **/
209 _public_ struct udev *udev_ref(struct udev *udev)
210 {
211         if (udev == NULL)
212                 return NULL;
213         udev->refcount++;
214         return udev;
215 }
216
217 /**
218  * udev_unref:
219  * @udev: udev library context
220  *
221  * Drop a reference of the udev library context. If the refcount
222  * reaches zero, the resources of the context will be released.
223  *
224  **/
225 _public_ void udev_unref(struct udev *udev)
226 {
227         if (udev == NULL)
228                 return;
229         udev->refcount--;
230         if (udev->refcount > 0)
231                 return;
232         udev_list_cleanup(&udev->properties_list);
233         free(udev);
234 }
235
236 /**
237  * udev_set_log_fn:
238  * @udev: udev library context
239  * @log_fn: function to be called for logging messages
240  *
241  * The built-in logging writes to stderr. It can be
242  * overridden by a custom function, to plug log messages
243  * into the users' logging functionality.
244  *
245  **/
246 _public_ void udev_set_log_fn(struct udev *udev,
247                      void (*log_fn)(struct udev *udev,
248                                     int priority, const char *file, int line, const char *fn,
249                                     const char *format, va_list args))
250 {
251         udev->log_fn = log_fn;
252         udev_dbg(udev, "custom logging function %p registered\n", log_fn);
253 }
254
255 /**
256  * udev_get_log_priority:
257  * @udev: udev library context
258  *
259  * The initial logging priority is read from the udev config file
260  * at startup.
261  *
262  * Returns: the current logging priority
263  **/
264 _public_ int udev_get_log_priority(struct udev *udev)
265 {
266         return udev->log_priority;
267 }
268
269 /**
270  * udev_set_log_priority:
271  * @udev: udev library context
272  * @priority: the new logging priority
273  *
274  * Set the current logging priority. The value controls which messages
275  * are logged.
276  **/
277 _public_ void udev_set_log_priority(struct udev *udev, int priority)
278 {
279         char num[32];
280
281         udev->log_priority = priority;
282         snprintf(num, sizeof(num), "%u", udev->log_priority);
283         udev_add_property(udev, "UDEV_LOG", num);
284 }
285
286 /**
287  * udev_get_sys_path:
288  * @udev: udev library context
289  *
290  * Returns always "/sys"; deprecated, will be removed in a future version.
291  *
292  * Returns: the sys mount point
293  **/
294 _public_ const char *udev_get_sys_path(struct udev *udev)
295 {
296         if (udev == NULL)
297                 return NULL;
298         return "/sys";
299 }
300
301 /**
302  * udev_get_dev_path:
303  * @udev: udev library context
304  *
305  * Returns always "/dev"; deprecated, will be removed in a future version.
306  *
307  * Returns: the device directory path
308  **/
309 _public_ const char *udev_get_dev_path(struct udev *udev)
310 {
311         if (udev == NULL)
312                 return NULL;
313         return "/dev";
314 }
315
316 /**
317  * udev_get_run_path:
318  * @udev: udev library context
319  *
320  * Returns always "/run/udev"; deprecated, will be removed in a future version.
321  *
322  * Returns: the runtime directory path
323  **/
324 _public_ const char *udev_get_run_path(struct udev *udev)
325 {
326         if (udev == NULL)
327                 return NULL;
328         return "/run/udev";
329 }
330
331 struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value)
332 {
333         if (value == NULL) {
334                 struct udev_list_entry *list_entry;
335
336                 list_entry = udev_get_properties_list_entry(udev);
337                 list_entry = udev_list_entry_get_by_name(list_entry, key);
338                 if (list_entry != NULL)
339                         udev_list_entry_delete(list_entry);
340                 return NULL;
341         }
342         return udev_list_entry_add(&udev->properties_list, key, value);
343 }
344
345 struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev)
346 {
347         return udev_list_get_entry(&udev->properties_list);
348 }