chiark / gitweb /
098ca8f602897b0af944b9a7888dc485e89a7e8a
[elogind.git] / udev / lib / libudev.c
1 /*
2  * libudev - interface to udev device information
3  *
4  * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <dirent.h>
29 #include <sys/stat.h>
30
31 #include "libudev.h"
32 #include "libudev-private.h"
33 #include "../udev.h"
34
35 void udev_log(struct udev *udev,
36               int priority, const char *file, int line, const char *fn,
37               const char *format, ...)
38 {
39         va_list args;
40
41         va_start(args, format);
42         udev->log_fn(udev, priority, file, line, fn, format, args);
43         va_end(args);
44 }
45
46 static void log_stderr(struct udev *udev,
47                        int priority, const char *file, int line, const char *fn,
48                        const char *format, va_list args)
49 {
50         static int log = -1;
51
52         if (log == -1) {
53                 if (getenv("LIBUDEV_DEBUG") != NULL)
54                         log = 1;
55                 else
56                         log = 0;
57         }
58
59         if (log == 1) {
60                 fprintf(stderr, "libudev: %s: ", fn);
61                 vfprintf(stderr, format, args);
62         }
63 }
64
65 /* glue to udev logging, needed until udev logging code is "fixed" */
66 #ifdef USE_LOG
67 void log_message(int priority, const char *format, ...)
68 {
69         va_list args;
70
71         va_start(args, format);
72         log_stderr(NULL, priority, NULL, 0, "", format, args);
73         va_end(args);
74 }
75 #endif
76
77 static ssize_t get_subsystem(struct udev *udev, const char *devpath, char *subsystem, size_t size)
78 {
79         char path[PATH_SIZE];
80         ssize_t len;
81         const char *pos;
82
83         strlcpy(path, udev_get_sys_path(udev), sizeof(path));
84         strlcat(path, devpath, sizeof(path));
85         strlcat(path, "/subsystem", sizeof(path));
86         len = readlink(path, path, sizeof(path));
87         if (len < 0 || len >= (ssize_t) sizeof(path))
88                 return -1;
89         path[len] = '\0';
90         pos = strrchr(path, '/');
91         if (pos == NULL)
92                 return -1;
93         pos = &pos[1];
94         return strlcpy(subsystem, pos, size);
95 }
96
97 /**
98  * udev_new:
99  *
100  * Create udev library context.
101  *
102  * The initial refcount is 1, and needs to be decremented to
103  * release the ressources of the udev library context.
104  *
105  * Returns: a new udev library context
106  **/
107 struct udev *udev_new(void)
108 {
109         struct udev *udev;
110
111         udev = malloc(sizeof(struct udev));
112         if (udev == NULL)
113                 return NULL;
114         memset(udev, 0x00, (sizeof(struct udev)));
115         udev->refcount = 1;
116         udev->log_fn = log_stderr;
117         udev_config_init();
118         sysfs_init();
119         log_info(udev, "context %p created\n", udev);
120         return udev;
121 }
122
123 /**
124  * udev_ref:
125  * @udev: udev library context
126  *
127  * Take a reference of the udev library context.
128  *
129  * Returns: the passed udev library context
130  **/
131 struct udev *udev_ref(struct udev *udev)
132 {
133         udev->refcount++;
134         return udev;
135 }
136
137 /**
138  * udev_unref:
139  * @udev: udev library context
140  *
141  * Drop a reference of the udev library context. If the refcount
142  * reaches zero, the ressources of the context will be released.
143  *
144  **/
145 void udev_unref(struct udev *udev)
146 {
147         udev->refcount--;
148         if (udev->refcount > 0)
149                 return;
150         sysfs_cleanup();
151         log_info(udev, "context %p released\n", udev);
152         free(udev);
153 }
154
155 /**
156  * udev_set_log_fn:
157  * @udev: udev library context
158  * @log_fn: function to be called for logging messages
159  *
160  * The built-in logging, which writes to stderr if the
161  * LIBUDEV_DEBUG environment variable is set, can be
162  * overridden by a custom function, to plug log messages
163  * into the users logging functionality.
164  *
165  **/
166 void udev_set_log_fn(struct udev *udev,
167                      void (*log_fn)(struct udev *udev,
168                                     int priority, const char *file, int line, const char *fn,
169                                     const char *format, va_list args))
170 {
171         udev->log_fn = log_fn;
172         log_info(udev, "custom logging function %p registered\n", udev);
173 }
174
175 /**
176  * udev_get_sys_path:
177  * @udev: udev library context
178  *
179  * Retrieve the sysfs mount point. The default is "/sys". For
180  * testing purposes, it can be overridden with the environment
181  * variable SYSFS_PATH.
182  *
183  * Returns: the sys mount point
184  **/
185 const char *udev_get_sys_path(struct udev *udev)
186 {
187         return sysfs_path;
188 }
189
190 /**
191  * udev_get_dev_path:
192  * @udev: udev library context
193  *
194  * Retrieve the device directory path. The default value is "/dev",
195  * the actual value may be overridden in the udev configuration
196  * file.
197  *
198  * Returns: the device directory path
199  **/
200 const char *udev_get_dev_path(struct udev *udev)
201 {
202         return udev_root;
203 }
204
205 static struct udev_device *device_init(struct udev *udev)
206 {
207         struct udev_device *udev_device;
208
209         udev_device = malloc(sizeof(struct udev_device));
210         if (udev_device == NULL)
211                 return NULL;
212         memset(udev_device, 0x00, sizeof(struct udev_device));
213         udev_device->refcount = 1;
214         udev_device->udev = udev;
215         return udev_device;
216 }
217
218 /**
219  * udev_device_new_from_devpath:
220  * @udev: udev library context
221  * @devpath: sys device path
222  *
223  * Create new udev device, and fill in information from the sysfs
224  * device and the udev database entry. The devpath must not contain
225  * the sysfs mount path, and must contain a leading '/'.
226  *
227  * The initial refcount is 1, and needs to be decremented to
228  * release the ressources of the udev device.
229  *
230  * Returns: a new udev device, or #NULL, if it does not exist
231  **/
232 struct udev_device *udev_device_new_from_devpath(struct udev *udev, const char *devpath)
233 {
234         char path[PATH_SIZE];
235         struct stat statbuf;
236         struct udev_device *udev_device;
237         int err;
238
239         strlcpy(path, udev_get_sys_path(udev), sizeof(path));
240         strlcat(path, devpath, sizeof(path));
241         if (stat(path, &statbuf) != 0)
242                 return NULL;
243         if (!S_ISDIR(statbuf.st_mode))
244                 return NULL;
245
246         udev_device = device_init(udev);
247         if (udev_device == NULL)
248                 return NULL;
249
250         udev_device->udevice = udev_device_init(NULL);
251         if (udev_device->udevice == NULL) {
252                 free(udev_device);
253                 return NULL;
254         }
255         log_info(udev, "device %p created\n", udev_device);
256
257         strlcpy(path, devpath, sizeof(path));
258         sysfs_resolve_link(path, sizeof(path));
259
260         err = udev_db_get_device(udev_device->udevice, path);
261         if (err >= 0)
262                 log_info(udev, "device %p filled with udev database data\n", udev_device);
263         log_info(udev, "device %p filled with %s data\n", udev_device, udev_device_get_devpath(udev_device));
264         return udev_device;
265 }
266
267 /**
268  * udev_device_get_udev:
269  *
270  * Retrieve the udev library context the device was created with.
271  *
272  * Returns: the udev library context
273  **/
274 struct udev *udev_device_get_udev(struct udev_device *udev_device)
275 {
276         return udev_device->udev;
277 }
278
279 /**
280  * udev_device_ref:
281  * @udev_device: udev device
282  *
283  * Take a reference of a udev device.
284  *
285  * Returns: the passed udev device
286  **/
287 struct udev_device *udev_device_ref(struct udev_device *udev_device)
288 {
289         udev_device->refcount++;
290         return udev_device;
291 }
292
293 /**
294  * udev_device_unref:
295  * @udev_device: udev device
296  *
297  * Drop a reference of a udev device. If the refcount reaches zero,
298  * the ressources of the device will be released.
299  *
300  **/
301 void udev_device_unref(struct udev_device *udev_device)
302 {
303         udev_device->refcount--;
304         if (udev_device->refcount > 0)
305                 return;
306         udev_device_cleanup(udev_device->udevice);
307         free(udev_device);
308 }
309
310 /**
311  * udev_device_get_devpath:
312  * @udev_device: udev device
313  *
314  * Retrieve the sys path of the udev device. The path does not contain
315  * the sys mount point.
316  *
317  * Returns: the sys path of the udev device
318  **/
319 const char *udev_device_get_devpath(struct udev_device *udev_device)
320 {
321         return udev_device->udevice->dev->devpath;
322 }
323
324 /**
325  * udev_device_get_devname:
326  * @udev_device: udev device
327  *
328  * Retrieve the device node file name belonging to the udev device.
329  * The path does not contain the device directory, and does not contain
330  * a leading '/'.
331  *
332  * Returns: the device node file name of the udev device, or #NULL if no device node exists
333  **/
334 const char *udev_device_get_devname(struct udev_device *udev_device)
335 {
336         if (udev_device->udevice->name[0] == '\0')
337                 return NULL;
338         return udev_device->udevice->name;
339 }
340
341 /**
342  * udev_device_get_subsystem:
343  * @udev_device: udev device
344  *
345  * Retrieve the subsystem string of the udev device. The string does not
346  * contain any "/".
347  *
348  * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
349  **/
350 const char *udev_device_get_subsystem(struct udev_device *udev_device)
351 {
352         struct sysfs_device *dev = udev_device->udevice->dev;
353         if (dev->subsystem[0] != '\0')
354                 return dev->subsystem;
355         if (get_subsystem(udev_device->udev, dev->devpath,
356                           dev->subsystem, sizeof(dev->subsystem)) < 2)
357                 return NULL;
358         return dev->subsystem;
359 }
360
361 /**
362  * udev_device_get_devlinks:
363  * @udev_device: udev device
364  * @cb: function to be called for every device link found
365  * @data: data to be passed to the function
366  *
367  * Retrieve the device links pointing to the device file of the
368  * udev device. For every device link, the passed function will be
369  * called with the device link string. If the function returns 1,
370  * remaning device links will be ignored. The device link path
371  * does not contain the device directory, and does not contain
372  * a leading '/'.
373  *
374  * Returns: the number of device links passed to the caller, or a negative value on error
375  **/
376 int udev_device_get_devlinks(struct udev_device *udev_device,
377                               int (*cb)(struct udev_device *udev_device, const char *value, void *data),
378                               void *data)
379 {
380         struct name_entry *name_loop;
381         int count = 0;
382
383         list_for_each_entry(name_loop, &udev_device->udevice->symlink_list, node) {
384                 count++;
385                 if (cb(udev_device, name_loop->name, data) != 0)
386                         break;
387         }
388         return count;
389 }
390
391 /**
392  * udev_device_get_properties:
393  * @udev_device: udev device
394  * @cb: function to be called for every property found
395  * @data: data to be passed to the function
396  *
397  * Retrieve the property key/value pairs belonging to the
398  * udev device. For every key/value pair, the passed function will be
399  * called. If the function returns 1, remaning properties will be
400  * ignored.
401  *
402  * Returns: the number of properties passed to the caller, or a negative value on error
403  **/
404 int udev_device_get_properties(struct udev_device *udev_device,
405                                 int (*cb)(struct udev_device *udev_device, const char *key, const char *value, void *data),
406                                 void *data)
407 {
408         struct name_entry *name_loop;
409         int count = 0;
410
411         list_for_each_entry(name_loop, &udev_device->udevice->env_list, node) {
412                 char name[PATH_SIZE];
413                 char *val;
414
415                 strncpy(name, name_loop->name, PATH_SIZE);
416                 name[PATH_SIZE-1] = '\0';
417                 val = strchr(name, '=');
418                 if (val == NULL)
419                         continue;
420                 val[0] = '\0';
421                 val = &val[1];
422                 if (cb(udev_device, name, val, data) != 0)
423                         break;
424         }
425         return count;
426 }
427
428 static int devices_scan_subsystem(struct udev *udev,
429                                   const char *basedir, const char *subsystem, const char *subdir,
430                                   struct list_head *device_list)
431 {
432         char path[PATH_SIZE];
433         DIR *dir;
434         struct dirent *dent;
435         size_t len;
436
437         len = strlcpy(path, udev_get_sys_path(udev), sizeof(path));
438         strlcat(path, basedir, sizeof(path));
439         strlcat(path, "/", sizeof(path));
440         strlcat(path, subsystem, sizeof(path));
441         if (subdir != NULL)
442                 strlcat(path, subdir, sizeof(path));
443         dir = opendir(path);
444         if (dir == NULL)
445                 return -1;
446         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
447                 char devpath[PATH_SIZE];
448
449                 if (dent->d_name[0] == '.')
450                         continue;
451                 strlcpy(devpath, &path[len], sizeof(devpath));
452                 strlcat(devpath, "/", sizeof(devpath));
453                 strlcat(devpath, dent->d_name, sizeof(devpath));
454                 sysfs_resolve_link(devpath, sizeof(devpath));
455                 name_list_add(device_list, devpath, 1);
456         }
457         closedir(dir);
458         return 0;
459 }
460
461 static int devices_scan_subsystems(struct udev *udev,
462                                    const char *basedir, const char *subsystem, const char *subdir,
463                                    struct list_head *device_list)
464 {
465         char path[PATH_SIZE];
466         DIR *dir;
467         struct dirent *dent;
468
469         if (subsystem != NULL)
470                 return devices_scan_subsystem(udev, basedir, subsystem, subdir, device_list);
471
472         strlcpy(path, udev_get_sys_path(udev), sizeof(path));
473         strlcat(path, basedir, sizeof(path));
474         dir = opendir(path);
475         if (dir == NULL)
476                 return -1;
477         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
478                 if (dent->d_name[0] == '.')
479                         continue;
480                 devices_scan_subsystem(udev, basedir, dent->d_name, subdir, device_list);
481         }
482         closedir(dir);
483         return 0;
484 }
485
486 static int devices_delay(struct udev *udev, const char *devpath)
487 {
488         static const char *delay_device_list[] = {
489                 "/block/md",
490                 "/block/dm-",
491                 NULL
492         };
493         int i;
494
495         for (i = 0; delay_device_list[i] != NULL; i++) {
496                 if (strstr(devpath, delay_device_list[i]) != NULL) {
497                         log_info(udev, "delaying: %s\n", devpath);
498                         return 1;
499                 }
500         }
501         return 0;
502 }
503
504 static int devices_call(struct udev *udev, const char *devpath,
505                         int (*cb)(struct udev *udev,
506                                   const char *devpath, const char *subsystem, const char *name,
507                                   void *data),
508                         void *data,
509                         int *cb_rc)
510 {
511         char subsystem[NAME_SIZE];
512         const char *name;
513
514         name = strrchr(devpath, '/');
515         if (name == NULL)
516                 return -1;
517         name++;
518
519         if (get_subsystem(udev, devpath, subsystem, sizeof(subsystem)) < 2)
520                 return -1;
521         *cb_rc = cb(udev, devpath, subsystem, name, data);
522         return 0;
523 }
524
525 /**
526  * udev_devices_enumerate:
527  * @udev_device: udev device
528  * @cb: function to be called for every property found
529  * @data: data to be passed to the function
530  *
531  * Retrieve the property key/value pairs belonging to the
532  * udev device. For every key/value pair, the passed function will be
533  * called. If the function returns 1, remaning properties will be
534  * ignored.
535  *
536  * Returns: the number of properties passed to the caller, or a negative value on error
537  **/
538 int udev_devices_enumerate(struct udev *udev, const char *subsystem,
539                            int (*cb)(struct udev *udev,
540                                      const char *devpath, const char *subsystem, const char *name, void *data),
541                            void *data)
542 {
543         char base[PATH_SIZE];
544         struct stat statbuf;
545         struct list_head device_list;
546         struct name_entry *loop_device;
547         struct name_entry *tmp_device;
548         int cb_rc = 0;
549         int count = 0;
550
551         INIT_LIST_HEAD(&device_list);
552
553         /* if we have /sys/subsystem/, forget all the old stuff */
554         strlcpy(base, sysfs_path, sizeof(base));
555         strlcat(base, "/subsystem", sizeof(base));
556         if (stat(base, &statbuf) == 0) {
557                 devices_scan_subsystems(udev, "/subsystem", subsystem, "/devices", &device_list);
558         } else {
559                 devices_scan_subsystems(udev, "/bus", subsystem, "/devices", &device_list);
560                 devices_scan_subsystems(udev, "/class", subsystem, NULL, &device_list);
561         }
562
563         list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) {
564                 if (devices_delay(udev, loop_device->name))
565                         continue;
566                 if (cb_rc == 0)
567                         if (devices_call(udev, loop_device->name, cb, data, &cb_rc) == 0)
568                                 count++;
569                 list_del(&loop_device->node);
570                 free(loop_device);
571         }
572
573         /* handle remaining delayed devices */
574         list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) {
575                 if (cb_rc == 0)
576                         if (devices_call(udev, loop_device->name, cb, data, &cb_rc) == 0)
577                                 count++;
578                 list_del(&loop_device->node);
579                 free(loop_device);
580         }
581
582         return count;
583 }