2 * libudev - interface to udev device information
4 * Copyright (C) 2008 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"
27 * Library context, passed to all operations.
31 void (*log_fn)(struct udev *udev,
32 int priority, const char *file, int line, const char *fn,
33 const char *format, va_list args);
38 struct udev_list_node properties_list;
43 void udev_log(struct udev *udev,
44 int priority, const char *file, int line, const char *fn,
45 const char *format, ...)
49 va_start(args, format);
50 udev->log_fn(udev, priority, file, line, fn, format, args);
54 static void log_stderr(struct udev *udev,
55 int priority, const char *file, int line, const char *fn,
56 const char *format, va_list args)
58 fprintf(stderr, "libudev: %s: ", fn);
59 vfprintf(stderr, format, args);
64 * @udev: udev library context
66 * Retrieve stored data pointer from library context. This might be useful
67 * to access from callbacks.
69 * Returns: stored userdata
71 void *udev_get_userdata(struct udev *udev)
75 return udev->userdata;
80 * @udev: udev library context
81 * @userdata: data pointer
83 * Store custom @userdata in the library context.
85 void udev_set_userdata(struct udev *udev, void *userdata)
89 udev->userdata = userdata;
95 * Create udev library context. This reads the udev configuration
96 * file, and fills in the default values.
98 * The initial refcount is 1, and needs to be decremented to
99 * release the resources of the udev library context.
101 * Returns: a new udev library context
103 struct udev *udev_new(void)
110 udev = calloc(1, sizeof(struct udev));
114 udev->log_fn = log_stderr;
115 udev->log_priority = LOG_ERR;
116 udev_list_init(&udev->properties_list);
118 udev->dev_path = strdup(UDEV_PREFIX "/dev");
119 udev->sys_path = strdup("/sys");
120 config_file = strdup(SYSCONFDIR "/udev/udev.conf");
121 if (udev->dev_path == NULL ||
122 udev->sys_path == NULL ||
126 /* settings by environment and config file */
127 env = getenv("SYSFS_PATH");
129 free(udev->sys_path);
130 udev->sys_path = strdup(env);
131 util_remove_trailing_chars(udev->sys_path, '/');
132 udev_add_property(udev, "SYSFS_PATH", udev->sys_path);
135 env = getenv("UDEV_RUN");
136 if (env != NULL && strcmp(env, "0") == 0)
139 env = getenv("UDEV_CONFIG_FILE");
142 config_file = strdup(env);
143 util_remove_trailing_chars(config_file, '/');
145 if (config_file == NULL)
147 f = fopen(config_file, "r");
149 char line[UTIL_LINE_SIZE];
152 while (fgets(line, sizeof(line), f)) {
161 while (isspace(key[0]))
164 /* comment or empty line */
165 if (key[0] == '#' || key[0] == '\0')
168 /* split key/value */
169 val = strchr(key, '=');
171 err(udev, "missing <key>=<value> in '%s'[%i], skip line\n", config_file, line_nr);
178 while (isspace(val[0]))
185 while (isspace(key[len-1]))
189 /* terminate value */
193 while (isspace(val[len-1]))
201 if (val[0] == '"' || val[0] == '\'') {
202 if (val[len-1] != val[0]) {
203 err(udev, "inconsistent quoting in '%s'[%i], skip line\n", config_file, line_nr);
210 if (strcmp(key, "udev_log") == 0) {
211 udev_set_log_priority(udev, util_log_priority(val));
214 if (strcmp(key, "udev_root") == 0) {
215 free(udev->dev_path);
216 udev->dev_path = strdup(val);
217 util_remove_trailing_chars(udev->dev_path, '/');
220 if (strcmp(key, "udev_rules") == 0) {
221 free(udev->rules_path);
222 udev->rules_path = strdup(val);
223 util_remove_trailing_chars(udev->rules_path, '/');
230 env = getenv("UDEV_ROOT");
232 free(udev->dev_path);
233 udev->dev_path = strdup(env);
234 util_remove_trailing_chars(udev->dev_path, '/');
235 udev_add_property(udev, "UDEV_ROOT", udev->dev_path);
238 env = getenv("UDEV_LOG");
240 udev_set_log_priority(udev, util_log_priority(env));
242 if (udev->dev_path == NULL || udev->sys_path == NULL)
244 dbg(udev, "context %p created\n", udev);
245 dbg(udev, "log_priority=%d\n", udev->log_priority);
246 dbg(udev, "config_file='%s'\n", config_file);
247 dbg(udev, "dev_path='%s'\n", udev->dev_path);
248 dbg(udev, "sys_path='%s'\n", udev->sys_path);
249 if (udev->rules_path != NULL)
250 dbg(udev, "rules_path='%s'\n", udev->rules_path);
255 err(udev, "context creation failed\n");
262 * @udev: udev library context
264 * Take a reference of the udev library context.
266 * Returns: the passed udev library context
268 struct udev *udev_ref(struct udev *udev)
278 * @udev: udev library context
280 * Drop a reference of the udev library context. If the refcount
281 * reaches zero, the resources of the context will be released.
284 void udev_unref(struct udev *udev)
289 if (udev->refcount > 0)
291 udev_list_cleanup_entries(udev, &udev->properties_list);
292 free(udev->dev_path);
293 free(udev->sys_path);
294 free(udev->rules_path);
295 dbg(udev, "context %p released\n", udev);
301 * @udev: udev library context
302 * @log_fn: function to be called for logging messages
304 * The built-in logging writes to stderr. It can be
305 * overridden by a custom function, to plug log messages
306 * into the users' logging functionality.
309 void udev_set_log_fn(struct udev *udev,
310 void (*log_fn)(struct udev *udev,
311 int priority, const char *file, int line, const char *fn,
312 const char *format, va_list args))
314 udev->log_fn = log_fn;
315 info(udev, "custom logging function %p registered\n", udev);
319 * udev_get_log_priority:
320 * @udev: udev library context
322 * The initial syslog priortity is read from the udev config file
325 * Returns: the current syslog priority
327 int udev_get_log_priority(struct udev *udev)
329 return udev->log_priority;
333 * udev_set_log_priority:
334 * @udev: udev library context
335 * @priority: the new syslog priority
337 * Set the current syslog priority. The value controls which messages
338 * are send to syslog.
340 void udev_set_log_priority(struct udev *udev, int priority)
344 udev->log_priority = priority;
345 snprintf(num, sizeof(num), "%u", udev->log_priority);
346 udev_add_property(udev, "UDEV_LOG", num);
349 const char *udev_get_rules_path(struct udev *udev)
351 return udev->rules_path;
354 int udev_get_run(struct udev *udev)
361 * @udev: udev library context
363 * Retrieve the sysfs mount point. The default is "/sys". For
364 * testing purposes, it can be overridden with the environment
365 * variable SYSFS_PATH.
367 * Returns: the sys mount point
369 const char *udev_get_sys_path(struct udev *udev)
373 return udev->sys_path;
378 * @udev: udev library context
380 * Retrieve the device directory path. The default value is "/dev",
381 * the actual value may be overridden in the udev configuration
384 * Returns: the device directory path
386 const char *udev_get_dev_path(struct udev *udev)
390 return udev->dev_path;
393 struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value)
396 struct udev_list_entry *list_entry;
398 list_entry = udev_get_properties_list_entry(udev);
399 list_entry = udev_list_entry_get_by_name(list_entry, key);
400 if (list_entry != NULL)
401 udev_list_entry_delete(list_entry);
404 return udev_list_entry_add(udev, &udev->properties_list, key, value, 1, 0);
407 struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev)
409 return udev_list_get_entry(&udev->properties_list);