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 struct udev_list_node properties_list;
50 void udev_log(struct udev *udev,
51 int priority, const char *file, int line, const char *fn,
52 const char *format, ...)
56 va_start(args, format);
57 udev->log_fn(udev, priority, file, line, fn, format, args);
61 static void log_stderr(struct udev *udev,
62 int priority, const char *file, int line, const char *fn,
63 const char *format, va_list args)
65 fprintf(stderr, "libudev: %s: ", fn);
66 vfprintf(stderr, format, args);
71 * @udev: udev library context
73 * Retrieve stored data pointer from library context. This might be useful
74 * to access from callbacks like a custom logging function.
76 * Returns: stored userdata
78 void *udev_get_userdata(struct udev *udev)
82 return udev->userdata;
87 * @udev: udev library context
88 * @userdata: data pointer
90 * Store custom @userdata in the library context.
92 void udev_set_userdata(struct udev *udev, void *userdata)
96 udev->userdata = userdata;
102 * Create udev library context. This reads the udev configuration
103 * file, and fills in the default values.
105 * The initial refcount is 1, and needs to be decremented to
106 * release the resources of the udev library context.
108 * Returns: a new udev library context
110 struct udev *udev_new(void)
117 udev = calloc(1, sizeof(struct udev));
121 udev->log_fn = log_stderr;
122 udev->log_priority = LOG_ERR;
123 udev_list_init(&udev->properties_list);
124 udev->dev_path = strdup("/dev");
125 udev->sys_path = strdup("/sys");
126 config_file = strdup(SYSCONFDIR "/udev/udev.conf");
127 if (udev->dev_path == NULL ||
128 udev->sys_path == NULL ||
132 /* settings by environment and config file */
133 env = getenv("SYSFS_PATH");
135 free(udev->sys_path);
136 udev->sys_path = strdup(env);
137 util_remove_trailing_chars(udev->sys_path, '/');
138 udev_add_property(udev, "SYSFS_PATH", udev->sys_path);
141 env = getenv("UDEV_CONFIG_FILE");
144 config_file = strdup(env);
145 util_remove_trailing_chars(config_file, '/');
147 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 free(udev->dev_path);
218 udev->dev_path = strdup(val);
219 util_remove_trailing_chars(udev->dev_path, '/');
222 if (strcmp(key, "udev_rules") == 0) {
223 free(udev->rules_path);
224 udev->rules_path = strdup(val);
225 util_remove_trailing_chars(udev->rules_path, '/');
232 env = getenv("UDEV_ROOT");
234 free(udev->dev_path);
235 udev->dev_path = strdup(env);
236 util_remove_trailing_chars(udev->dev_path, '/');
237 udev_add_property(udev, "UDEV_ROOT", udev->dev_path);
240 env = getenv("UDEV_LOG");
242 udev_set_log_priority(udev, util_log_priority(env));
244 if (udev->dev_path == NULL || udev->sys_path == NULL)
246 dbg(udev, "context %p created\n", udev);
247 dbg(udev, "log_priority=%d\n", udev->log_priority);
248 dbg(udev, "config_file='%s'\n", config_file);
249 dbg(udev, "dev_path='%s'\n", udev->dev_path);
250 dbg(udev, "sys_path='%s'\n", udev->sys_path);
251 if (udev->rules_path != NULL)
252 dbg(udev, "rules_path='%s'\n", udev->rules_path);
257 err(udev, "context creation failed\n");
264 * @udev: udev library context
266 * Take a reference of the udev library context.
268 * Returns: the passed udev library context
270 struct udev *udev_ref(struct udev *udev)
280 * @udev: udev library context
282 * Drop a reference of the udev library context. If the refcount
283 * reaches zero, the resources of the context will be released.
286 void udev_unref(struct udev *udev)
291 if (udev->refcount > 0)
293 udev_list_cleanup_entries(udev, &udev->properties_list);
294 free(udev->dev_path);
295 free(udev->sys_path);
296 free(udev->rules_path);
297 dbg(udev, "context %p released\n", udev);
303 * @udev: udev library context
304 * @log_fn: function to be called for logging messages
306 * The built-in logging writes to stderr. It can be
307 * overridden by a custom function, to plug log messages
308 * into the users' logging functionality.
311 void udev_set_log_fn(struct udev *udev,
312 void (*log_fn)(struct udev *udev,
313 int priority, const char *file, int line, const char *fn,
314 const char *format, va_list args))
316 udev->log_fn = log_fn;
317 info(udev, "custom logging function %p registered\n", udev);
321 * udev_get_log_priority:
322 * @udev: udev library context
324 * The initial logging priority is read from the udev config file
327 * Returns: the current logging priority
329 int udev_get_log_priority(struct udev *udev)
331 return udev->log_priority;
335 * udev_set_log_priority:
336 * @udev: udev library context
337 * @priority: the new logging priority
339 * Set the current logging priority. The value controls which messages
342 void udev_set_log_priority(struct udev *udev, int priority)
346 udev->log_priority = priority;
347 snprintf(num, sizeof(num), "%u", udev->log_priority);
348 udev_add_property(udev, "UDEV_LOG", num);
351 const char *udev_get_rules_path(struct udev *udev)
353 return udev->rules_path;
358 * @udev: udev library context
360 * Retrieve the sysfs mount point. The default is "/sys". For
361 * testing purposes, it can be overridden with the environment
362 * variable SYSFS_PATH.
364 * Returns: the sys mount point
366 const char *udev_get_sys_path(struct udev *udev)
370 return udev->sys_path;
375 * @udev: udev library context
377 * Retrieve the device directory path. The default value is "/dev",
378 * the actual value may be overridden in the udev configuration
381 * Returns: the device directory path
383 const char *udev_get_dev_path(struct udev *udev)
387 return udev->dev_path;
390 struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value)
393 struct udev_list_entry *list_entry;
395 list_entry = udev_get_properties_list_entry(udev);
396 list_entry = udev_list_entry_get_by_name(list_entry, key);
397 if (list_entry != NULL)
398 udev_list_entry_delete(list_entry);
401 return udev_list_entry_add(udev, &udev->properties_list, key, value, 1, 0);
404 struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev)
406 return udev_list_get_entry(&udev->properties_list);