chiark / gitweb /
udev: switch to systemd logging functions
[elogind.git] / src / libudev / libudev.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2008-2014 Kay Sievers <kay@vrfy.org>
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   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 License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stddef.h>
23 #include <stdarg.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <time.h>
29
30 #include "libudev.h"
31 #include "libudev-private.h"
32 #include "missing.h"
33
34 /**
35  * SECTION:libudev
36  * @short_description: libudev context
37  *
38  * The context contains the default values read from the udev config file,
39  * and is passed to all library operations.
40  */
41
42 /**
43  * udev:
44  *
45  * Opaque object representing the library context.
46  */
47 struct udev {
48         int refcount;
49         void (*log_fn)(struct udev *udev,
50                        int priority, const char *file, int line, const char *fn,
51                        const char *format, va_list args);
52         void *userdata;
53         struct udev_list properties_list;
54 };
55
56 /**
57  * udev_get_userdata:
58  * @udev: udev library context
59  *
60  * Retrieve stored data pointer from library context. This might be useful
61  * to access from callbacks.
62  *
63  * Returns: stored userdata
64  **/
65 _public_ void *udev_get_userdata(struct udev *udev) {
66         if (udev == NULL)
67                 return NULL;
68         return udev->userdata;
69 }
70
71 /**
72  * udev_set_userdata:
73  * @udev: udev library context
74  * @userdata: data pointer
75  *
76  * Store custom @userdata in the library context.
77  **/
78 _public_ void udev_set_userdata(struct udev *udev, void *userdata) {
79         if (udev == NULL)
80                 return;
81         udev->userdata = userdata;
82 }
83
84 /**
85  * udev_new:
86  *
87  * Create udev library context. This reads the udev configuration
88  * file, and fills in the default values.
89  *
90  * The initial refcount is 1, and needs to be decremented to
91  * release the resources of the udev library context.
92  *
93  * Returns: a new udev library context
94  **/
95 _public_ struct udev *udev_new(void) {
96         struct udev *udev;
97         _cleanup_fclose_ FILE *f = NULL;
98
99         udev = new0(struct udev, 1);
100         if (udev == NULL)
101                 return NULL;
102         udev->refcount = 1;
103         udev_list_init(udev, &udev->properties_list, true);
104
105         f = fopen("/etc/udev/udev.conf", "re");
106         if (f != NULL) {
107                 char line[UTIL_LINE_SIZE];
108                 unsigned line_nr = 0;
109
110                 while (fgets(line, sizeof(line), f)) {
111                         size_t len;
112                         char *key;
113                         char *val;
114
115                         line_nr++;
116
117                         /* find key */
118                         key = line;
119                         while (isspace(key[0]))
120                                 key++;
121
122                         /* comment or empty line */
123                         if (key[0] == '#' || key[0] == '\0')
124                                 continue;
125
126                         /* split key/value */
127                         val = strchr(key, '=');
128                         if (val == NULL) {
129                                 log_debug("/etc/udev/udev.conf:%u: missing assignment,  skipping line.\n", line_nr);
130                                 continue;
131                         }
132                         val[0] = '\0';
133                         val++;
134
135                         /* find value */
136                         while (isspace(val[0]))
137                                 val++;
138
139                         /* terminate key */
140                         len = strlen(key);
141                         if (len == 0)
142                                 continue;
143                         while (isspace(key[len-1]))
144                                 len--;
145                         key[len] = '\0';
146
147                         /* terminate value */
148                         len = strlen(val);
149                         if (len == 0)
150                                 continue;
151                         while (isspace(val[len-1]))
152                                 len--;
153                         val[len] = '\0';
154
155                         if (len == 0)
156                                 continue;
157
158                         /* unquote */
159                         if (val[0] == '"' || val[0] == '\'') {
160                                 if (val[len-1] != val[0]) {
161                                         log_debug("/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.\n", line_nr);
162                                         continue;
163                                 }
164                                 val[len-1] = '\0';
165                                 val++;
166                         }
167
168                         if (streq(key, "udev_log")) {
169                                 int prio;
170
171                                 prio = util_log_priority(val);
172                                 if (prio < 0)
173                                         log_debug("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.\n", line_nr, val);
174                                 else
175                                         log_set_max_level(prio);
176                                 continue;
177                         }
178                 }
179         }
180
181         return udev;
182 }
183
184 /**
185  * udev_ref:
186  * @udev: udev library context
187  *
188  * Take a reference of the udev library context.
189  *
190  * Returns: the passed udev library context
191  **/
192 _public_ struct udev *udev_ref(struct udev *udev) {
193         if (udev == NULL)
194                 return NULL;
195         udev->refcount++;
196         return udev;
197 }
198
199 /**
200  * udev_unref:
201  * @udev: udev library context
202  *
203  * Drop a reference of the udev library context. If the refcount
204  * reaches zero, the resources of the context will be released.
205  *
206  * Returns: the passed udev library context if it has still an active reference, or #NULL otherwise.
207  **/
208 _public_ struct udev *udev_unref(struct udev *udev) {
209         if (udev == NULL)
210                 return NULL;
211         udev->refcount--;
212         if (udev->refcount > 0)
213                 return udev;
214         udev_list_cleanup(&udev->properties_list);
215         free(udev);
216         return NULL;
217 }
218
219 /**
220  * udev_set_log_fn:
221  * @udev: udev library context
222  * @log_fn: function to be called for log messages
223  *
224  * This function is deprecated.
225  *
226  **/
227 _public_ void udev_set_log_fn(struct udev *udev,
228                      void (*log_fn)(struct udev *udev,
229                                     int priority, const char *file, int line, const char *fn,
230                                     const char *format, va_list args)) {
231         return;
232 }
233
234 /**
235  * udev_get_log_priority:
236  * @udev: udev library context
237  *
238  * This function is deprecated.
239  *
240  **/
241 _public_ int udev_get_log_priority(struct udev *udev) {
242         return log_get_max_level();
243 }
244
245 /**
246  * udev_set_log_priority:
247  * @udev: udev library context
248  * @priority: the new log priority
249  *
250  * This function is deprecated.
251  *
252  **/
253 _public_ void udev_set_log_priority(struct udev *udev, int priority) {
254         log_set_max_level(priority);
255 }
256
257 struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value) {
258         if (value == NULL) {
259                 struct udev_list_entry *list_entry;
260
261                 list_entry = udev_get_properties_list_entry(udev);
262                 list_entry = udev_list_entry_get_by_name(list_entry, key);
263                 if (list_entry != NULL)
264                         udev_list_entry_delete(list_entry);
265                 return NULL;
266         }
267         return udev_list_entry_add(&udev->properties_list, key, value);
268 }
269
270 struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev) {
271         return udev_list_get_entry(&udev->properties_list);
272 }