2 * libudev - interface to udev device information
4 * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include "libudev-private.h"
34 void (*log_fn)(struct udev *udev,
35 int priority, const char *file, int line, const char *fn,
36 const char *format, va_list args);
41 struct udev_list_node properties_list;
46 void udev_log(struct udev *udev,
47 int priority, const char *file, int line, const char *fn,
48 const char *format, ...)
52 if (priority > udev->log_priority)
55 va_start(args, format);
56 udev->log_fn(udev, priority, file, line, fn, format, args);
60 static void log_stderr(struct udev *udev,
61 int priority, const char *file, int line, const char *fn,
62 const char *format, va_list args)
64 fprintf(stderr, "libudev: %s: ", fn);
65 vfprintf(stderr, format, args);
68 void *udev_get_userdata(struct udev *udev)
72 return udev->userdata;
75 void udev_set_userdata(struct udev *udev, void *userdata)
79 udev->userdata = userdata;
85 * Create udev library context.
87 * The initial refcount is 1, and needs to be decremented to
88 * release the resources of the udev library context.
90 * Returns: a new udev library context
92 struct udev *udev_new(void)
99 udev = calloc(1, sizeof(struct udev));
103 udev->log_fn = log_stderr;
104 udev->log_priority = LOG_ERR;
105 udev_list_init(&udev->properties_list);
107 udev->dev_path = strdup(UDEV_PREFIX "/dev");
108 udev->sys_path = strdup("/sys");
109 config_file = strdup(SYSCONFDIR "/udev/udev.conf");
110 if (udev->dev_path == NULL ||
111 udev->sys_path == NULL ||
115 /* settings by environment and config file */
116 env = getenv("SYSFS_PATH");
118 free(udev->sys_path);
119 udev->sys_path = strdup(env);
120 util_remove_trailing_chars(udev->sys_path, '/');
121 udev_add_property(udev, "SYSFS_PATH", udev->sys_path);
124 env = getenv("UDEV_RUN");
125 if (env != NULL && strcmp(env, "0") == 0)
128 env = getenv("UDEV_CONFIG_FILE");
131 config_file = strdup(env);
132 util_remove_trailing_chars(config_file, '/');
134 if (config_file == NULL)
136 f = fopen(config_file, "r");
138 char line[UTIL_LINE_SIZE];
141 while (fgets(line, sizeof(line), f)) {
150 while (isspace(key[0]))
153 /* comment or empty line */
154 if (key[0] == '#' || key[0] == '\0')
157 /* split key/value */
158 val = strchr(key, '=');
160 err(udev, "missing <key>=<value> in '%s'[%i], skip line\n", config_file, line_nr);
167 while (isspace(val[0]))
174 while (isspace(key[len-1]))
178 /* terminate value */
182 while (isspace(val[len-1]))
190 if (val[0] == '"' || val[0] == '\'') {
191 if (val[len-1] != val[0]) {
192 err(udev, "inconsistent quoting in '%s'[%i], skip line\n", config_file, line_nr);
199 if (strcasecmp(key, "udev_log") == 0) {
200 udev_set_log_priority(udev, util_log_priority(val));
203 if (strcasecmp(key, "udev_root") == 0) {
204 free(udev->dev_path);
205 udev->dev_path = strdup(val);
206 util_remove_trailing_chars(udev->dev_path, '/');
209 if (strcasecmp(key, "udev_rules") == 0) {
210 free(udev->rules_path);
211 udev->rules_path = strdup(val);
212 util_remove_trailing_chars(udev->rules_path, '/');
219 env = getenv("UDEV_ROOT");
221 free(udev->dev_path);
222 udev->dev_path = strdup(env);
223 util_remove_trailing_chars(udev->dev_path, '/');
224 udev_add_property(udev, "UDEV_ROOT", udev->dev_path);
227 env = getenv("UDEV_LOG");
229 udev_set_log_priority(udev, util_log_priority(env));
231 if (udev->dev_path == NULL || udev->sys_path == NULL)
233 dbg(udev, "context %p created\n", udev);
234 dbg(udev, "log_priority=%d\n", udev->log_priority);
235 dbg(udev, "config_file='%s'\n", config_file);
236 dbg(udev, "dev_path='%s'\n", udev->dev_path);
237 dbg(udev, "sys_path='%s'\n", udev->sys_path);
238 if (udev->rules_path != NULL)
239 dbg(udev, "rules_path='%s'\n", udev->rules_path);
244 err(udev, "context creation failed\n");
251 * @udev: udev library context
253 * Take a reference of the udev library context.
255 * Returns: the passed udev library context
257 struct udev *udev_ref(struct udev *udev)
267 * @udev: udev library context
269 * Drop a reference of the udev library context. If the refcount
270 * reaches zero, the resources of the context will be released.
273 void udev_unref(struct udev *udev)
278 if (udev->refcount > 0)
280 udev_list_cleanup_entries(udev, &udev->properties_list);
281 free(udev->dev_path);
282 free(udev->sys_path);
283 free(udev->rules_path);
284 dbg(udev, "context %p released\n", udev);
290 * @udev: udev library context
291 * @log_fn: function to be called for logging messages
293 * The built-in logging writes to stderr. It can be
294 * overridden by a custom function, to plug log messages
295 * into the users' logging functionality.
298 void udev_set_log_fn(struct udev *udev,
299 void (*log_fn)(struct udev *udev,
300 int priority, const char *file, int line, const char *fn,
301 const char *format, va_list args))
303 udev->log_fn = log_fn;
304 info(udev, "custom logging function %p registered\n", udev);
307 int udev_get_log_priority(struct udev *udev)
309 return udev->log_priority;
312 void udev_set_log_priority(struct udev *udev, int priority)
316 udev->log_priority = priority;
317 snprintf(num, sizeof(num), "%u", udev->log_priority);
318 udev_add_property(udev, "UDEV_LOG", num);
321 const char *udev_get_rules_path(struct udev *udev)
323 return udev->rules_path;
326 int udev_get_run(struct udev *udev)
333 * @udev: udev library context
335 * Retrieve the sysfs mount point. The default is "/sys". For
336 * testing purposes, it can be overridden with the environment
337 * variable SYSFS_PATH.
339 * Returns: the sys mount point
341 const char *udev_get_sys_path(struct udev *udev)
345 return udev->sys_path;
350 * @udev: udev library context
352 * Retrieve the device directory path. The default value is "/dev",
353 * the actual value may be overridden in the udev configuration
356 * Returns: the device directory path
358 const char *udev_get_dev_path(struct udev *udev)
362 return udev->dev_path;
365 struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value)
368 struct udev_list_entry *list_entry;
370 list_entry = udev_get_properties_list_entry(udev);
371 list_entry = udev_list_entry_get_by_name(list_entry, key);
372 if (list_entry != NULL)
373 udev_list_entry_delete(list_entry);
376 return udev_list_entry_add(udev, &udev->properties_list, key, value, 1, 0);
379 struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev)
381 return udev_list_get_entry(&udev->properties_list);