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