2 * libudev - interface to udev device information
4 * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org>
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.
22 #include "libudev-private.h"
26 * @short_description: libudev context
28 * The context contains the default values read from the udev config file,
29 * and is passed to all library operations.
35 * Opaque object representing the library context.
39 void (*log_fn)(struct udev *udev,
40 int priority, const char *file, int line, const char *fn,
41 const char *format, va_list args);
46 char *run_config_path;
48 struct udev_list_node properties_list;
52 void udev_log(struct udev *udev,
53 int priority, const char *file, int line, const char *fn,
54 const char *format, ...)
58 va_start(args, format);
59 udev->log_fn(udev, priority, file, line, fn, format, args);
63 static void log_stderr(struct udev *udev,
64 int priority, const char *file, int line, const char *fn,
65 const char *format, va_list args)
67 fprintf(stderr, "libudev: %s: ", fn);
68 vfprintf(stderr, format, args);
73 * @udev: udev library context
75 * Retrieve stored data pointer from library context. This might be useful
76 * to access from callbacks like a custom logging function.
78 * Returns: stored userdata
80 UDEV_EXPORT void *udev_get_userdata(struct udev *udev)
84 return udev->userdata;
89 * @udev: udev library context
90 * @userdata: data pointer
92 * Store custom @userdata in the library context.
94 UDEV_EXPORT void udev_set_userdata(struct udev *udev, void *userdata)
98 udev->userdata = userdata;
101 static char *set_value(char **s, const char *v)
105 util_remove_trailing_chars(*s, '/');
112 * Create udev library context. This reads the udev configuration
113 * file, and fills in the default values.
115 * The initial refcount is 1, and needs to be decremented to
116 * release the resources of the udev library context.
118 * Returns: a new udev library context
120 UDEV_EXPORT struct udev *udev_new(void)
124 char *config_file = NULL;
127 udev = calloc(1, sizeof(struct udev));
131 udev->log_fn = log_stderr;
132 udev->log_priority = LOG_ERR;
133 udev_list_init(&udev->properties_list);
135 /* custom config file */
136 env = getenv("UDEV_CONFIG_FILE");
138 udev_add_property(udev, "UDEV_CONFIG_FILE", udev->dev_path);
139 if (set_value(&config_file, env) == NULL)
143 /* default config file */
144 if (config_file == NULL)
145 config_file = strdup(SYSCONFDIR "/udev/udev.conf");
146 if (config_file == NULL)
149 f = fopen(config_file, "re");
151 char line[UTIL_LINE_SIZE];
154 while (fgets(line, sizeof(line), f)) {
163 while (isspace(key[0]))
166 /* comment or empty line */
167 if (key[0] == '#' || key[0] == '\0')
170 /* split key/value */
171 val = strchr(key, '=');
173 err(udev, "missing <key>=<value> in '%s'[%i], skip line\n", config_file, line_nr);
180 while (isspace(val[0]))
187 while (isspace(key[len-1]))
191 /* terminate value */
195 while (isspace(val[len-1]))
203 if (val[0] == '"' || val[0] == '\'') {
204 if (val[len-1] != val[0]) {
205 err(udev, "inconsistent quoting in '%s'[%i], skip line\n", config_file, line_nr);
212 if (strcmp(key, "udev_log") == 0) {
213 udev_set_log_priority(udev, util_log_priority(val));
216 if (strcmp(key, "udev_root") == 0) {
217 set_value(&udev->dev_path, val);
220 if (strcmp(key, "udev_run") == 0) {
221 set_value(&udev->run_config_path, val);
224 if (strcmp(key, "udev_rules") == 0) {
225 set_value(&udev->rules_path, val);
232 /* environment overwrites config */
233 env = getenv("UDEV_LOG");
235 udev_set_log_priority(udev, util_log_priority(env));
237 env = getenv("UDEV_ROOT");
239 set_value(&udev->dev_path, env);
240 udev_add_property(udev, "UDEV_ROOT", udev->dev_path);
243 env = getenv("SYSFS_PATH");
245 set_value(&udev->sys_path, env);
246 udev_add_property(udev, "SYSFS_PATH", udev->sys_path);
250 if (udev->dev_path == NULL)
251 if (set_value(&udev->dev_path, "/dev") == NULL)
254 if (udev->sys_path == NULL)
255 if (set_value(&udev->sys_path, "/sys") == NULL)
258 if (udev->run_config_path == NULL)
259 if (set_value(&udev->run_config_path, "/run/udev") == NULL)
262 dbg(udev, "context %p created\n", udev);
263 dbg(udev, "log_priority=%d\n", udev->log_priority);
264 dbg(udev, "config_file='%s'\n", config_file);
265 dbg(udev, "dev_path='%s'\n", udev->dev_path);
266 dbg(udev, "sys_path='%s'\n", udev->sys_path);
267 dbg(udev, "run_path='%s'\n", udev->run_config_path);
268 if (udev->rules_path != NULL)
269 dbg(udev, "rules_path='%s'\n", udev->rules_path);
274 err(udev, "context creation failed\n");
281 * @udev: udev library context
283 * Take a reference of the udev library context.
285 * Returns: the passed udev library context
287 UDEV_EXPORT struct udev *udev_ref(struct udev *udev)
297 * @udev: udev library context
299 * Drop a reference of the udev library context. If the refcount
300 * reaches zero, the resources of the context will be released.
303 UDEV_EXPORT void udev_unref(struct udev *udev)
308 if (udev->refcount > 0)
310 udev_list_cleanup_entries(udev, &udev->properties_list);
311 free(udev->dev_path);
312 free(udev->sys_path);
313 free(udev->rules_path);
314 free(udev->run_path);
315 free(udev->run_config_path);
316 dbg(udev, "context %p released\n", udev);
322 * @udev: udev library context
323 * @log_fn: function to be called for logging messages
325 * The built-in logging writes to stderr. It can be
326 * overridden by a custom function, to plug log messages
327 * into the users' logging functionality.
330 UDEV_EXPORT void udev_set_log_fn(struct udev *udev,
331 void (*log_fn)(struct udev *udev,
332 int priority, const char *file, int line, const char *fn,
333 const char *format, va_list args))
335 udev->log_fn = log_fn;
336 info(udev, "custom logging function %p registered\n", udev);
340 * udev_get_log_priority:
341 * @udev: udev library context
343 * The initial logging priority is read from the udev config file
346 * Returns: the current logging priority
348 UDEV_EXPORT int udev_get_log_priority(struct udev *udev)
350 return udev->log_priority;
354 * udev_set_log_priority:
355 * @udev: udev library context
356 * @priority: the new logging priority
358 * Set the current logging priority. The value controls which messages
361 UDEV_EXPORT void udev_set_log_priority(struct udev *udev, int priority)
365 udev->log_priority = priority;
366 snprintf(num, sizeof(num), "%u", udev->log_priority);
367 udev_add_property(udev, "UDEV_LOG", num);
370 const char *udev_get_rules_path(struct udev *udev)
372 return udev->rules_path;
377 * @udev: udev library context
379 * Retrieve the sysfs mount point. The default is "/sys". For
380 * testing purposes, it can be overridden with the environment
381 * variable SYSFS_PATH.
383 * Returns: the sys mount point
385 UDEV_EXPORT const char *udev_get_sys_path(struct udev *udev)
389 return udev->sys_path;
394 * @udev: udev library context
396 * Retrieve the device directory path. The default value is "/dev",
397 * the actual value may be overridden in the udev configuration
400 * Returns: the device directory path
402 UDEV_EXPORT const char *udev_get_dev_path(struct udev *udev)
406 return udev->dev_path;
409 const char *udev_get_run_config_path(struct udev *udev)
411 return udev->run_config_path;
416 * @udev: udev library context
418 * Retrieve the udev runtime directory path. The default is "/run/udev".
420 * Returns: the runtime directory path
422 UDEV_EXPORT const char *udev_get_run_path(struct udev *udev)
424 if (udev->run_path != NULL)
425 return udev->run_path;
427 /* check if configured path exists */
428 if (access(udev->run_config_path, F_OK) < 0) {
429 char filename[UTIL_PATH_SIZE];
431 /* fall back to /dev/.udev if that exists */
432 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev", NULL);
433 if (access(filename, F_OK) >= 0)
434 if (set_value(&udev->run_path, filename) != NULL)
435 return udev->run_path;
438 /* use default path */
439 set_value(&udev->run_path, udev->run_config_path);
440 if (udev->run_path == NULL)
441 return udev->run_config_path;
442 return udev->run_path;
445 const char *udev_set_run_path(struct udev *udev, const char *path)
447 return set_value(&udev->run_path, path);
450 struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value)
453 struct udev_list_entry *list_entry;
455 list_entry = udev_get_properties_list_entry(udev);
456 list_entry = udev_list_entry_get_by_name(list_entry, key);
457 if (list_entry != NULL)
458 udev_list_entry_delete(list_entry);
461 return udev_list_entry_add(udev, &udev->properties_list, key, value, UDEV_LIST_UNIQUE);
464 struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev)
466 return udev_list_get_entry(&udev->properties_list);