]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libudev/libudev.c
libudev: do not accept invalid log levels
[thirdparty/systemd.git] / src / libudev / libudev.c
CommitLineData
88a6477e
KS
1/***
2 This file is part of systemd.
3
4 Copyright 2008-2012 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***/
33a5cc29 19
33a5cc29
KS
20#include <stdio.h>
21#include <stdlib.h>
22#include <stddef.h>
4cf23685 23#include <stdarg.h>
33a5cc29
KS
24#include <unistd.h>
25#include <errno.h>
26#include <string.h>
7d563a17 27#include <ctype.h>
4f1795cc 28#include <time.h>
33a5cc29
KS
29
30#include "libudev.h"
31#include "libudev-private.h"
4db17f29 32#include "missing.h"
33a5cc29 33
ce1d6d7f
KS
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
1e511322
KS
42/**
43 * udev:
44 *
ce1d6d7f 45 * Opaque object representing the library context.
1e511322 46 */
ba6929f6 47struct udev {
912541b0
KS
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;
912541b0
KS
53 struct udev_list properties_list;
54 int log_priority;
ba6929f6
KS
55};
56
33a5cc29 57void udev_log(struct udev *udev,
912541b0
KS
58 int priority, const char *file, int line, const char *fn,
59 const char *format, ...)
33a5cc29 60{
912541b0 61 va_list args;
33a5cc29 62
912541b0
KS
63 va_start(args, format);
64 udev->log_fn(udev, priority, file, line, fn, format, args);
65 va_end(args);
33a5cc29
KS
66}
67
9091e686 68_printf_(6,0)
33a5cc29 69static void log_stderr(struct udev *udev,
912541b0
KS
70 int priority, const char *file, int line, const char *fn,
71 const char *format, va_list args)
33a5cc29 72{
912541b0
KS
73 fprintf(stderr, "libudev: %s: ", fn);
74 vfprintf(stderr, format, args);
33a5cc29 75}
33a5cc29 76
1e511322
KS
77/**
78 * udev_get_userdata:
79 * @udev: udev library context
80 *
81 * Retrieve stored data pointer from library context. This might be useful
dbba7e40 82 * to access from callbacks like a custom logging function.
1e511322
KS
83 *
84 * Returns: stored userdata
85 **/
54cf0b7f 86_public_ void *udev_get_userdata(struct udev *udev)
c8e32461 87{
912541b0
KS
88 if (udev == NULL)
89 return NULL;
90 return udev->userdata;
c8e32461
KS
91}
92
1e511322
KS
93/**
94 * udev_set_userdata:
95 * @udev: udev library context
96 * @userdata: data pointer
97 *
98 * Store custom @userdata in the library context.
99 **/
54cf0b7f 100_public_ void udev_set_userdata(struct udev *udev, void *userdata)
c8e32461 101{
912541b0
KS
102 if (udev == NULL)
103 return;
104 udev->userdata = userdata;
c8e32461
KS
105}
106
33a5cc29
KS
107/**
108 * udev_new:
109 *
1e511322
KS
110 * Create udev library context. This reads the udev configuration
111 * file, and fills in the default values.
33a5cc29
KS
112 *
113 * The initial refcount is 1, and needs to be decremented to
be7de409 114 * release the resources of the udev library context.
33a5cc29
KS
115 *
116 * Returns: a new udev library context
117 **/
54cf0b7f 118_public_ struct udev *udev_new(void)
33a5cc29 119{
912541b0
KS
120 struct udev *udev;
121 const char *env;
fe756ed9 122 _cleanup_free_ FILE *f = NULL;
912541b0 123
955d98c9 124 udev = new0(struct udev, 1);
912541b0
KS
125 if (udev == NULL)
126 return NULL;
127 udev->refcount = 1;
128 udev->log_fn = log_stderr;
2004d23a 129 udev->log_priority = LOG_INFO;
912541b0
KS
130 udev_list_init(udev, &udev->properties_list, true);
131
ff944daa 132 f = fopen("/etc/udev/udev.conf", "re");
912541b0
KS
133 if (f != NULL) {
134 char line[UTIL_LINE_SIZE];
fe756ed9 135 unsigned line_nr = 0;
912541b0
KS
136
137 while (fgets(line, sizeof(line), f)) {
138 size_t len;
139 char *key;
140 char *val;
141
142 line_nr++;
143
144 /* find key */
145 key = line;
146 while (isspace(key[0]))
147 key++;
148
149 /* comment or empty line */
150 if (key[0] == '#' || key[0] == '\0')
151 continue;
152
153 /* split key/value */
154 val = strchr(key, '=');
155 if (val == NULL) {
fe756ed9 156 udev_err(udev, "/etc/udev/udev.conf:%u: missing assignment, skipping line.\n", line_nr);
912541b0
KS
157 continue;
158 }
159 val[0] = '\0';
160 val++;
161
162 /* find value */
163 while (isspace(val[0]))
164 val++;
165
166 /* terminate key */
167 len = strlen(key);
168 if (len == 0)
169 continue;
170 while (isspace(key[len-1]))
171 len--;
172 key[len] = '\0';
173
174 /* terminate value */
175 len = strlen(val);
176 if (len == 0)
177 continue;
178 while (isspace(val[len-1]))
179 len--;
180 val[len] = '\0';
181
182 if (len == 0)
183 continue;
184
185 /* unquote */
186 if (val[0] == '"' || val[0] == '\'') {
187 if (val[len-1] != val[0]) {
fe756ed9 188 udev_err(udev, "/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.\n", line_nr);
912541b0
KS
189 continue;
190 }
191 val[len-1] = '\0';
192 val++;
193 }
194
090be865 195 if (streq(key, "udev_log")) {
ee7122c0
ZJS
196 int prio;
197
198 prio = util_log_priority(val);
199 if (prio < 0)
200 udev_err(udev, "/etc/udev/udev.conf:%u: invalid logging level '%s', ignoring.\n", line_nr, val);
201 else
202 udev_set_log_priority(udev, prio);
912541b0
KS
203 continue;
204 }
912541b0 205 }
912541b0
KS
206 }
207
91418155 208 /* environment overrides config */
4db17f29 209 env = secure_getenv("UDEV_LOG");
ee7122c0
ZJS
210 if (env != NULL) {
211 int prio;
212
213 prio = util_log_priority(env);
214 if (prio < 0)
215 udev_err(udev, "$UDEV_LOG specifies invalid logging level '%s', ignoring.\n", env);
216 else
217 udev_set_log_priority(udev, prio);
218 }
912541b0 219
912541b0 220 return udev;
33a5cc29
KS
221}
222
223/**
224 * udev_ref:
225 * @udev: udev library context
226 *
227 * Take a reference of the udev library context.
228 *
229 * Returns: the passed udev library context
230 **/
54cf0b7f 231_public_ struct udev *udev_ref(struct udev *udev)
33a5cc29 232{
912541b0
KS
233 if (udev == NULL)
234 return NULL;
235 udev->refcount++;
236 return udev;
33a5cc29
KS
237}
238
239/**
240 * udev_unref:
241 * @udev: udev library context
242 *
243 * Drop a reference of the udev library context. If the refcount
be7de409 244 * reaches zero, the resources of the context will be released.
33a5cc29 245 *
c1959569 246 * Returns: the passed udev library context if it has still an active reference, or #NULL otherwise.
33a5cc29 247 **/
20bbd54f 248_public_ struct udev *udev_unref(struct udev *udev)
33a5cc29 249{
912541b0 250 if (udev == NULL)
20bbd54f 251 return NULL;
912541b0
KS
252 udev->refcount--;
253 if (udev->refcount > 0)
20bbd54f 254 return udev;
912541b0 255 udev_list_cleanup(&udev->properties_list);
912541b0 256 free(udev);
20bbd54f 257 return NULL;
33a5cc29
KS
258}
259
260/**
261 * udev_set_log_fn:
262 * @udev: udev library context
263 * @log_fn: function to be called for logging messages
264 *
be7de409 265 * The built-in logging writes to stderr. It can be
33a5cc29 266 * overridden by a custom function, to plug log messages
be7de409 267 * into the users' logging functionality.
33a5cc29
KS
268 *
269 **/
54cf0b7f 270_public_ void udev_set_log_fn(struct udev *udev,
912541b0
KS
271 void (*log_fn)(struct udev *udev,
272 int priority, const char *file, int line, const char *fn,
273 const char *format, va_list args))
33a5cc29 274{
912541b0 275 udev->log_fn = log_fn;
c8f8394a 276 udev_dbg(udev, "custom logging function %p registered\n", log_fn);
7d563a17
KS
277}
278
1e511322
KS
279/**
280 * udev_get_log_priority:
281 * @udev: udev library context
282 *
dbba7e40 283 * The initial logging priority is read from the udev config file
1e511322
KS
284 * at startup.
285 *
dbba7e40 286 * Returns: the current logging priority
1e511322 287 **/
54cf0b7f 288_public_ int udev_get_log_priority(struct udev *udev)
7d563a17 289{
912541b0 290 return udev->log_priority;
7d563a17
KS
291}
292
1e511322
KS
293/**
294 * udev_set_log_priority:
295 * @udev: udev library context
dbba7e40 296 * @priority: the new logging priority
1e511322 297 *
dbba7e40
KS
298 * Set the current logging priority. The value controls which messages
299 * are logged.
1e511322 300 **/
54cf0b7f 301_public_ void udev_set_log_priority(struct udev *udev, int priority)
7d563a17 302{
912541b0 303 char num[32];
f183b6ed 304
912541b0
KS
305 udev->log_priority = priority;
306 snprintf(num, sizeof(num), "%u", udev->log_priority);
307 udev_add_property(udev, "UDEV_LOG", num);
7d563a17
KS
308}
309
f183b6ed
KS
310struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value)
311{
912541b0
KS
312 if (value == NULL) {
313 struct udev_list_entry *list_entry;
314
315 list_entry = udev_get_properties_list_entry(udev);
316 list_entry = udev_list_entry_get_by_name(list_entry, key);
317 if (list_entry != NULL)
318 udev_list_entry_delete(list_entry);
319 return NULL;
320 }
321 return udev_list_entry_add(&udev->properties_list, key, value);
f183b6ed
KS
322}
323
324struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev)
325{
912541b0 326 return udev_list_get_entry(&udev->properties_list);
f183b6ed 327}