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.
24 #include "libudev-private.h"
28 struct udev_device
*parent_device
;
42 size_t monitor_buf_len
;
43 struct udev_list_node devlinks_list
;
44 struct udev_list_node properties_list
;
45 struct udev_list_node sysattr_list
;
46 unsigned long long int seqnum
;
49 int num_fake_partitions
;
54 unsigned int parent_set
:1;
55 unsigned int subsystem_set
:1;
56 unsigned int devtype_set
:1;
57 unsigned int devlinks_uptodate
:1;
58 unsigned int envp_uptodate
:1;
59 unsigned int driver_set
:1;
60 unsigned int info_loaded
:1;
61 unsigned int ignore_remove
:1;
64 static size_t devpath_to_db_path(struct udev
*udev
, const char *devpath
, char *filename
, size_t len
)
68 /* translate to location of db file */
69 util_strlcpy(filename
, udev_get_dev_path(udev
), len
);
70 start
= util_strlcat(filename
, "/.udev/db/", len
);
71 util_strlcat(filename
, devpath
, len
);
72 return util_path_encode(&filename
[start
], len
- start
);
75 int udev_device_read_db(struct udev_device
*udev_device
)
78 char filename
[UTIL_PATH_SIZE
];
79 char line
[UTIL_LINE_SIZE
];
82 devpath_to_db_path(udev_device
->udev
, udev_device
->devpath
, filename
, sizeof(filename
));
84 if (lstat(filename
, &stats
) != 0) {
85 dbg(udev_device
->udev
, "no db file to read %s: %m\n", filename
);
88 if ((stats
.st_mode
& S_IFMT
) == S_IFLNK
) {
89 char target
[UTIL_PATH_SIZE
];
90 char devnode
[UTIL_PATH_SIZE
];
94 target_len
= readlink(filename
, target
, sizeof(target
));
96 target
[target_len
] = '\0';
98 dbg(udev_device
->udev
, "error reading db link %s: %m\n", filename
);
102 next
= strchr(target
, ' ');
107 util_strlcpy(devnode
, udev_get_dev_path(udev_device
->udev
), sizeof(devnode
));
108 util_strlcat(devnode
, "/", sizeof(devnode
));
109 util_strlcat(devnode
, target
, sizeof(devnode
));
110 udev_device_set_devnode(udev_device
, devnode
);
111 while (next
!= NULL
) {
112 char devlink
[UTIL_PATH_SIZE
];
116 next
= strchr(next
, ' ');
121 util_strlcpy(devlink
, udev_get_dev_path(udev_device
->udev
), sizeof(devlink
));
122 util_strlcat(devlink
, "/", sizeof(devlink
));
123 util_strlcat(devlink
, lnk
, sizeof(devlink
));
124 udev_device_add_devlink(udev_device
, devlink
);
126 info(udev_device
->udev
, "device %p filled with db symlink data '%s'\n", udev_device
, udev_device
->devnode
);
130 f
= fopen(filename
, "r");
132 dbg(udev_device
->udev
, "error reading db file %s: %m\n", filename
);
135 while (fgets(line
, sizeof(line
), f
)) {
146 util_strlcpy(filename
, udev_get_dev_path(udev_device
->udev
), sizeof(filename
));
147 util_strlcat(filename
, "/", sizeof(filename
));
148 util_strlcat(filename
, val
, sizeof(filename
));
149 udev_device_set_devnode(udev_device
, filename
);
152 util_strlcpy(filename
, udev_get_dev_path(udev_device
->udev
), sizeof(filename
));
153 util_strlcat(filename
, "/", sizeof(filename
));
154 util_strlcat(filename
, val
, sizeof(filename
));
155 udev_device_add_devlink(udev_device
, filename
);
158 udev_device_set_devlink_priority(udev_device
, atoi(val
));
161 udev_device_set_event_timeout(udev_device
, atoi(val
));
164 udev_device_set_num_fake_partitions(udev_device
, atoi(val
));
167 udev_device_set_ignore_remove(udev_device
, atoi(val
));
170 udev_device_add_property_from_string(udev_device
, val
);
173 udev_device_set_watch_handle(udev_device
, atoi(val
));
179 info(udev_device
->udev
, "device %p filled with db file data\n", udev_device
);
183 int udev_device_read_uevent_file(struct udev_device
*udev_device
)
185 char filename
[UTIL_PATH_SIZE
];
187 char line
[UTIL_LINE_SIZE
];
191 util_strlcpy(filename
, udev_device
->syspath
, sizeof(filename
));
192 util_strlcat(filename
, "/uevent", sizeof(filename
));
193 f
= fopen(filename
, "r");
197 while (fgets(line
, sizeof(line
), f
)) {
200 pos
= strchr(line
, '\n');
205 if (strncmp(line
, "DEVTYPE=", 8) == 0)
206 udev_device_set_devtype(udev_device
, &line
[8]);
207 else if (strncmp(line
, "MAJOR=", 6) == 0)
208 maj
= strtoull(&line
[6], NULL
, 10);
209 else if (strncmp(line
, "MINOR=", 6) == 0)
210 min
= strtoull(&line
[6], NULL
, 10);
212 udev_device_add_property_from_string(udev_device
, line
);
215 udev_device
->devnum
= makedev(maj
, min
);
221 static void device_load_info(struct udev_device
*device
)
223 device
->info_loaded
= 1;
224 udev_device_read_uevent_file(device
);
225 udev_device_read_db(device
);
228 void udev_device_set_info_loaded(struct udev_device
*device
)
230 device
->info_loaded
= 1;
233 struct udev_device
*device_new(struct udev
*udev
)
235 struct udev_device
*udev_device
;
236 struct udev_list_entry
*list_entry
;
241 udev_device
= calloc(1, sizeof(struct udev_device
));
242 if (udev_device
== NULL
)
244 udev_device
->refcount
= 1;
245 udev_device
->udev
= udev
;
246 udev_list_init(&udev_device
->devlinks_list
);
247 udev_list_init(&udev_device
->properties_list
);
248 udev_list_init(&udev_device
->sysattr_list
);
249 udev_device
->event_timeout
= -1;
250 udev_device
->watch_handle
= -1;
251 /* copy global properties */
252 udev_list_entry_foreach(list_entry
, udev_get_properties_list_entry(udev
))
253 udev_device_add_property(udev_device
,
254 udev_list_entry_get_name(list_entry
),
255 udev_list_entry_get_value(list_entry
));
256 dbg(udev_device
->udev
, "udev_device: %p created\n", udev_device
);
261 * udev_device_new_from_syspath:
262 * @udev: udev library context
263 * @syspath: sys device path including sys directory
265 * Create new udev device, and fill in information from the sys
266 * device and the udev database entry. The sypath is the absolute
267 * path to the device, including the sys mount point.
269 * The initial refcount is 1, and needs to be decremented to
270 * release the resources of the udev device.
272 * Returns: a new udev device, or #NULL, if it does not exist
274 struct udev_device
*udev_device_new_from_syspath(struct udev
*udev
, const char *syspath
)
278 char path
[UTIL_PATH_SIZE
];
281 struct udev_device
*udev_device
;
288 /* path starts in sys */
289 len
= strlen(udev_get_sys_path(udev
));
290 if (strncmp(syspath
, udev_get_sys_path(udev
), len
) != 0) {
291 info(udev
, "not in sys :%s\n", syspath
);
295 /* path is not a root directory */
296 subdir
= &syspath
[len
+1];
297 pos
= strrchr(subdir
, '/');
298 if (pos
== NULL
|| pos
[1] == '\0' || pos
< &subdir
[2]) {
299 dbg(udev
, "not a subdir :%s\n", syspath
);
303 /* resolve possible symlink to real path */
304 util_strlcpy(path
, syspath
, sizeof(path
));
305 util_resolve_sys_link(udev
, path
, sizeof(path
));
307 /* try to resolve the silly block layout if needed */
308 if (strncmp(&path
[len
], "/block/", 7) == 0) {
309 char block
[UTIL_PATH_SIZE
];
310 char part
[UTIL_PATH_SIZE
];
312 util_strlcpy(block
, path
, sizeof(block
));
313 pos
= strrchr(block
, '/');
316 util_strlcpy(part
, pos
, sizeof(part
));
318 if (util_resolve_sys_link(udev
, block
, sizeof(block
)) == 0) {
319 util_strlcpy(path
, block
, sizeof(path
));
320 util_strlcat(path
, part
, sizeof(path
));
324 /* path exists in sys */
325 if (strncmp(&syspath
[len
], "/devices/", 9) == 0 ||
326 strncmp(&syspath
[len
], "/class/", 7) == 0 ||
327 strncmp(&syspath
[len
], "/block/", 7) == 0) {
328 char file
[UTIL_PATH_SIZE
];
330 /* all "devices" require a "uevent" file */
331 util_strlcpy(file
, path
, sizeof(file
));
332 util_strlcat(file
, "/uevent", sizeof(file
));
333 if (stat(file
, &statbuf
) != 0) {
334 dbg(udev
, "not a device: %s\n", syspath
);
338 /* everything else just needs to be a directory */
339 if (stat(path
, &statbuf
) != 0 || !S_ISDIR(statbuf
.st_mode
)) {
340 dbg(udev
, "directory not found: %s\n", syspath
);
345 udev_device
= device_new(udev
);
346 if (udev_device
== NULL
)
349 udev_device_set_syspath(udev_device
, path
);
350 info(udev
, "device %p has devpath '%s'\n", udev_device
, udev_device_get_devpath(udev_device
));
355 struct udev_device
*udev_device_new_from_devnum(struct udev
*udev
, char type
, dev_t devnum
)
357 char path
[UTIL_PATH_SIZE
];
358 const char *type_str
;
359 struct udev_enumerate
*udev_enumerate
;
360 struct udev_list_entry
*list_entry
;
361 struct udev_device
*device
= NULL
;
365 else if (type
== 'c')
370 /* /sys/dev/{block,char}/<maj>:<min> link */
371 snprintf(path
, sizeof(path
), "%s/dev/%s/%u:%u", udev_get_sys_path(udev
),
372 type_str
, major(devnum
), minor(devnum
));
373 if (util_resolve_sys_link(udev
, path
, sizeof(path
)) == 0)
374 return udev_device_new_from_syspath(udev
, path
);
376 udev_enumerate
= udev_enumerate_new(udev
);
377 if (udev_enumerate
== NULL
)
380 /* fallback to search sys devices for the major/minor */
382 udev_enumerate_add_match_subsystem(udev_enumerate
, "block");
383 else if (type
== 'c')
384 udev_enumerate_add_nomatch_subsystem(udev_enumerate
, "block");
385 udev_enumerate_scan_devices(udev_enumerate
);
386 udev_list_entry_foreach(list_entry
, udev_enumerate_get_list_entry(udev_enumerate
)) {
387 struct udev_device
*device_loop
;
389 device_loop
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(list_entry
));
390 if (device_loop
!= NULL
) {
391 if (udev_device_get_devnum(device_loop
) == devnum
) {
392 if (type
== 'b' && strcmp(udev_device_get_subsystem(device_loop
), "block") != 0)
394 if (type
== 'c' && strcmp(udev_device_get_subsystem(device_loop
), "block") == 0)
396 device
= device_loop
;
399 udev_device_unref(device_loop
);
402 udev_enumerate_unref(udev_enumerate
);
406 struct udev_device
*udev_device_new_from_subsystem_sysname(struct udev
*udev
, const char *subsystem
, const char *sysname
)
409 char path_full
[UTIL_PATH_SIZE
];
413 sys_path_len
= util_strlcpy(path_full
, udev_get_sys_path(udev
), sizeof(path_full
));
414 path
= &path_full
[sys_path_len
];
416 if (strcmp(subsystem
, "subsystem") == 0) {
417 util_strlcpy(path
, "/subsystem/", sizeof(path_full
) - sys_path_len
);
418 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
419 if (stat(path_full
, &statbuf
) == 0)
422 util_strlcpy(path
, "/bus/", sizeof(path_full
) - sys_path_len
);
423 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
424 if (stat(path_full
, &statbuf
) == 0)
427 util_strlcpy(path
, "/class/", sizeof(path_full
) - sys_path_len
);
428 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
429 if (stat(path_full
, &statbuf
) == 0)
434 if (strcmp(subsystem
, "module") == 0) {
435 util_strlcpy(path
, "/module/", sizeof(path_full
) - sys_path_len
);
436 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
437 if (stat(path_full
, &statbuf
) == 0)
442 if (strcmp(subsystem
, "drivers") == 0) {
443 char subsys
[UTIL_NAME_SIZE
];
446 util_strlcpy(subsys
, sysname
, sizeof(subsys
));
447 driver
= strchr(subsys
, ':');
448 if (driver
!= NULL
) {
451 util_strlcpy(path
, "/subsystem/", sizeof(path_full
) - sys_path_len
);
452 util_strlcat(path
, subsys
, sizeof(path_full
) - sys_path_len
);
453 util_strlcat(path
, "/drivers/", sizeof(path_full
) - sys_path_len
);
454 util_strlcat(path
, driver
, sizeof(path_full
) - sys_path_len
);
455 if (stat(path_full
, &statbuf
) == 0)
458 util_strlcpy(path
, "/bus/", sizeof(path_full
) - sys_path_len
);
459 util_strlcat(path
, subsys
, sizeof(path_full
) - sys_path_len
);
460 util_strlcat(path
, "/drivers/", sizeof(path_full
) - sys_path_len
);
461 util_strlcat(path
, driver
, sizeof(path_full
) - sys_path_len
);
462 if (stat(path_full
, &statbuf
) == 0)
468 util_strlcpy(path
, "/subsystem/", sizeof(path_full
) - sys_path_len
);
469 util_strlcat(path
, subsystem
, sizeof(path_full
) - sys_path_len
);
470 util_strlcat(path
, "/devices/", sizeof(path_full
) - sys_path_len
);
471 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
472 if (stat(path_full
, &statbuf
) == 0)
475 util_strlcpy(path
, "/bus/", sizeof(path_full
) - sys_path_len
);
476 util_strlcat(path
, subsystem
, sizeof(path_full
) - sys_path_len
);
477 util_strlcat(path
, "/devices/", sizeof(path_full
) - sys_path_len
);
478 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
479 if (stat(path_full
, &statbuf
) == 0)
482 util_strlcpy(path
, "/class/", sizeof(path_full
) - sys_path_len
);
483 util_strlcat(path
, subsystem
, sizeof(path_full
) - sys_path_len
);
484 util_strlcat(path
, "/", sizeof(path_full
) - sys_path_len
);
485 util_strlcat(path
, sysname
, sizeof(path_full
) - sys_path_len
);
486 if (stat(path_full
, &statbuf
) == 0)
491 return udev_device_new_from_syspath(udev
, path_full
);
494 static struct udev_device
*device_new_from_parent(struct udev_device
*udev_device
)
496 struct udev_device
*udev_device_parent
= NULL
;
497 char path
[UTIL_PATH_SIZE
];
500 /* follow "device" link in deprecated sys layout */
501 if (strncmp(udev_device
->devpath
, "/class/", 7) == 0 ||
502 strncmp(udev_device
->devpath
, "/block/", 7) == 0) {
503 util_strlcpy(path
, udev_device
->syspath
, sizeof(path
));
504 util_strlcat(path
, "/device", sizeof(path
));
505 if (util_resolve_sys_link(udev_device
->udev
, path
, sizeof(path
)) == 0) {
506 udev_device_parent
= udev_device_new_from_syspath(udev_device
->udev
, path
);
507 if (udev_device_parent
!= NULL
)
508 return udev_device_parent
;
512 util_strlcpy(path
, udev_device
->syspath
, sizeof(path
));
513 subdir
= &path
[strlen(udev_get_sys_path(udev_device
->udev
))+1];
517 pos
= strrchr(subdir
, '/');
518 if (pos
== NULL
|| pos
< &subdir
[2])
521 udev_device_parent
= udev_device_new_from_syspath(udev_device
->udev
, path
);
522 if (udev_device_parent
!= NULL
)
523 return udev_device_parent
;
528 struct udev_device
*udev_device_get_parent(struct udev_device
*udev_device
)
530 if (udev_device
== NULL
)
532 if (!udev_device
->parent_set
) {
533 udev_device
->parent_set
= 1;
534 udev_device
->parent_device
= device_new_from_parent(udev_device
);
536 if (udev_device
->parent_device
!= NULL
)
537 dbg(udev_device
->udev
, "returning existing parent %p\n", udev_device
->parent_device
);
538 return udev_device
->parent_device
;
541 struct udev_device
*udev_device_get_parent_with_subsystem_devtype(struct udev_device
*udev_device
, const char *subsystem
, const char *devtype
)
543 struct udev_device
*parent
;
545 if (subsystem
== NULL
)
548 parent
= udev_device_get_parent(udev_device
);
549 while (parent
!= NULL
) {
550 const char *parent_subsystem
;
551 const char *parent_devtype
;
553 parent_subsystem
= udev_device_get_subsystem(parent
);
554 if (parent_subsystem
!= NULL
&& strcmp(parent_subsystem
, subsystem
) == 0) {
557 parent_devtype
= udev_device_get_devtype(parent
);
558 if (parent_devtype
!= NULL
&& strcmp(parent_devtype
, devtype
) == 0)
561 parent
= udev_device_get_parent(parent
);
567 * udev_device_get_udev:
568 * @udev_device: udev device
570 * Retrieve the udev library context the device was created with.
572 * Returns: the udev library context
574 struct udev
*udev_device_get_udev(struct udev_device
*udev_device
)
576 if (udev_device
== NULL
)
578 return udev_device
->udev
;
583 * @udev_device: udev device
585 * Take a reference of a udev device.
587 * Returns: the passed udev device
589 struct udev_device
*udev_device_ref(struct udev_device
*udev_device
)
591 if (udev_device
== NULL
)
593 udev_device
->refcount
++;
599 * @udev_device: udev device
601 * Drop a reference of a udev device. If the refcount reaches zero,
602 * the resources of the device will be released.
605 void udev_device_unref(struct udev_device
*udev_device
)
607 if (udev_device
== NULL
)
609 udev_device
->refcount
--;
610 if (udev_device
->refcount
> 0)
612 if (udev_device
->parent_device
!= NULL
)
613 udev_device_unref(udev_device
->parent_device
);
614 free(udev_device
->syspath
);
615 free(udev_device
->sysname
);
616 free(udev_device
->devnode
);
617 free(udev_device
->subsystem
);
618 free(udev_device
->devtype
);
619 udev_list_cleanup_entries(udev_device
->udev
, &udev_device
->devlinks_list
);
620 udev_list_cleanup_entries(udev_device
->udev
, &udev_device
->properties_list
);
621 free(udev_device
->action
);
622 free(udev_device
->driver
);
623 free(udev_device
->devpath_old
);
624 free(udev_device
->physdevpath
);
625 udev_list_cleanup_entries(udev_device
->udev
, &udev_device
->sysattr_list
);
626 free(udev_device
->envp
);
627 free(udev_device
->monitor_buf
);
628 dbg(udev_device
->udev
, "udev_device: %p released\n", udev_device
);
633 * udev_device_get_devpath:
634 * @udev_device: udev device
636 * Retrieve the kernel devpath value of the udev device. The path
637 * does not contain the sys mount point, and starts with a '/'.
639 * Returns: the devpath of the udev device
641 const char *udev_device_get_devpath(struct udev_device
*udev_device
)
643 if (udev_device
== NULL
)
645 return udev_device
->devpath
;
649 * udev_device_get_syspath:
650 * @udev_device: udev device
652 * Retrieve the sys path of the udev device. The path is an
653 * absolute path and starts with the sys mount point.
655 * Returns: the sys path of the udev device
657 const char *udev_device_get_syspath(struct udev_device
*udev_device
)
659 if (udev_device
== NULL
)
661 return udev_device
->syspath
;
664 const char *udev_device_get_sysname(struct udev_device
*udev_device
)
666 if (udev_device
== NULL
)
668 return udev_device
->sysname
;
671 const char *udev_device_get_sysnum(struct udev_device
*udev_device
)
673 if (udev_device
== NULL
)
675 return udev_device
->sysnum
;
679 * udev_device_get_devnode:
680 * @udev_device: udev device
682 * Retrieve the device node file name belonging to the udev device.
683 * The path is an absolute path, and starts with the device directory.
685 * Returns: the device node file name of the udev device, or #NULL if no device node exists
687 const char *udev_device_get_devnode(struct udev_device
*udev_device
)
689 if (udev_device
== NULL
)
691 if (!udev_device
->info_loaded
)
692 device_load_info(udev_device
);
693 return udev_device
->devnode
;
697 * udev_device_get_subsystem:
698 * @udev_device: udev device
700 * Retrieve the subsystem string of the udev device. The string does not
703 * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
705 const char *udev_device_get_subsystem(struct udev_device
*udev_device
)
707 char subsystem
[UTIL_NAME_SIZE
];
709 if (udev_device
== NULL
)
711 if (!udev_device
->subsystem_set
) {
712 udev_device
->subsystem_set
= 1;
713 /* read "subsytem" link */
714 if (util_get_sys_subsystem(udev_device
->udev
, udev_device
->syspath
, subsystem
, sizeof(subsystem
)) > 0) {
715 udev_device_set_subsystem(udev_device
, subsystem
);
716 return udev_device
->subsystem
;
719 if (strncmp(udev_device
->devpath
, "/module/", 8) == 0) {
720 udev_device_set_subsystem(udev_device
, "module");
721 return udev_device
->subsystem
;
723 if (strstr(udev_device
->devpath
, "/drivers/") != NULL
) {
724 udev_device_set_subsystem(udev_device
, "drivers");
725 return udev_device
->subsystem
;
727 if (strncmp(udev_device
->devpath
, "/subsystem/", 11) == 0 ||
728 strncmp(udev_device
->devpath
, "/class/", 7) == 0 ||
729 strncmp(udev_device
->devpath
, "/bus/", 5) == 0) {
730 udev_device_set_subsystem(udev_device
, "subsystem");
731 return udev_device
->subsystem
;
734 return udev_device
->subsystem
;
738 * udev_device_get_devtype:
739 * @udev_device: udev device
741 * Retrieve the devtype string of the udev device.
743 * Returns: the devtype name of the udev device, or #NULL if it can not be determined
745 const char *udev_device_get_devtype(struct udev_device
*udev_device
)
747 if (udev_device
== NULL
)
749 if (!udev_device
->devtype_set
) {
750 udev_device
->devtype_set
= 1;
751 if (!udev_device
->info_loaded
)
752 udev_device_read_uevent_file(udev_device
);
754 return udev_device
->devtype
;
758 * udev_device_get_devlinks_list_entry:
759 * @udev_device: udev device
761 * Retrieve the list of device links pointing to the device file of
762 * the udev device. The next list entry can be retrieved with
763 * udev_list_entry_next(), which returns #NULL if no more entries exist.
764 * The devlink path can be retrieved from the list entry by
765 * udev_list_entry_get_name(). The path is an absolute path, and starts with
766 * the device directory.
768 * Returns: the first entry of the device node link list
770 struct udev_list_entry
*udev_device_get_devlinks_list_entry(struct udev_device
*udev_device
)
772 if (udev_device
== NULL
)
774 if (!udev_device
->info_loaded
)
775 device_load_info(udev_device
);
776 return udev_list_get_entry(&udev_device
->devlinks_list
);
779 void udev_device_cleanup_devlinks_list(struct udev_device
*udev_device
)
781 udev_device
->devlinks_uptodate
= 0;
782 udev_list_cleanup_entries(udev_device
->udev
, &udev_device
->devlinks_list
);
786 * udev_device_get_properties_list_entry:
787 * @udev_device: udev device
789 * Retrieve the list of key/value device properties of the udev
790 * device. The next list entry can be retrieved with udev_list_entry_next(),
791 * which returns #NULL if no more entries exist. The property name
792 * can be retrieved from the list entry by udev_list_get_name(),
793 * the property value by udev_list_get_value().
795 * Returns: the first entry of the property list
797 struct udev_list_entry
*udev_device_get_properties_list_entry(struct udev_device
*udev_device
)
799 if (udev_device
== NULL
)
801 if (!udev_device
->info_loaded
)
802 device_load_info(udev_device
);
803 if (!udev_device
->devlinks_uptodate
) {
804 char symlinks
[UTIL_PATH_SIZE
];
805 struct udev_list_entry
*list_entry
;
807 udev_device
->devlinks_uptodate
= 1;
808 list_entry
= udev_device_get_devlinks_list_entry(udev_device
);
809 if (list_entry
!= NULL
) {
810 util_strlcpy(symlinks
, udev_list_entry_get_name(list_entry
), sizeof(symlinks
));
811 udev_list_entry_foreach(list_entry
, udev_list_entry_get_next(list_entry
)) {
812 util_strlcat(symlinks
, " ", sizeof(symlinks
));
813 util_strlcat(symlinks
, udev_list_entry_get_name(list_entry
), sizeof(symlinks
));
815 udev_device_add_property(udev_device
, "DEVLINKS", symlinks
);
818 return udev_list_get_entry(&udev_device
->properties_list
);
821 const char *udev_device_get_driver(struct udev_device
*udev_device
)
823 char driver
[UTIL_NAME_SIZE
];
825 if (udev_device
== NULL
)
827 if (!udev_device
->driver_set
) {
828 udev_device
->driver_set
= 1;
829 if (util_get_sys_driver(udev_device
->udev
, udev_device
->syspath
, driver
, sizeof(driver
)) > 0)
830 udev_device
->driver
= strdup(driver
);
832 return udev_device
->driver
;
835 dev_t
udev_device_get_devnum(struct udev_device
*udev_device
)
837 if (udev_device
== NULL
)
838 return makedev(0, 0);
839 if (!udev_device
->info_loaded
)
840 device_load_info(udev_device
);
841 return udev_device
->devnum
;
844 const char *udev_device_get_action(struct udev_device
*udev_device
)
846 if (udev_device
== NULL
)
848 return udev_device
->action
;
851 unsigned long long int udev_device_get_seqnum(struct udev_device
*udev_device
)
853 if (udev_device
== NULL
)
855 return udev_device
->seqnum
;
858 const char *udev_device_get_sysattr_value(struct udev_device
*udev_device
, const char *sysattr
)
860 struct udev_list_entry
*list_entry
;
861 char path
[UTIL_PATH_SIZE
];
866 const char *val
= NULL
;
868 if (udev_device
== NULL
)
873 /* look for possibly already cached result */
874 udev_list_entry_foreach(list_entry
, udev_list_get_entry(&udev_device
->sysattr_list
)) {
875 if (strcmp(udev_list_entry_get_name(list_entry
), sysattr
) == 0) {
876 dbg(udev_device
->udev
, "got '%s' (%s) from cache\n",
877 sysattr
, udev_list_entry_get_value(list_entry
));
878 return udev_list_entry_get_value(list_entry
);
882 util_strlcpy(path
, udev_device_get_syspath(udev_device
), sizeof(path
));
883 util_strlcat(path
, "/", sizeof(path
));
884 util_strlcat(path
, sysattr
, sizeof(path
));
886 if (lstat(path
, &statbuf
) != 0) {
887 dbg(udev_device
->udev
, "no attribute '%s', keep negative entry\n", path
);
888 udev_list_entry_add(udev_device
->udev
, &udev_device
->sysattr_list
, sysattr
, NULL
, 0, 0);
892 if (S_ISLNK(statbuf
.st_mode
)) {
893 char target
[UTIL_NAME_SIZE
];
897 /* some core links return the last element of the target path */
898 if (strcmp(sysattr
, "driver") != 0 &&
899 strcmp(sysattr
, "subsystem") != 0 &&
900 strcmp(sysattr
, "module") != 0)
903 len
= readlink(path
, target
, sizeof(target
));
906 pos
= strrchr(target
, '/');
909 dbg(udev_device
->udev
, "cache '%s' with link value '%s'\n", sysattr
, pos
);
910 list_entry
= udev_list_entry_add(udev_device
->udev
, &udev_device
->sysattr_list
, sysattr
, pos
, 0, 0);
911 val
= udev_list_entry_get_value(list_entry
);
917 /* skip directories */
918 if (S_ISDIR(statbuf
.st_mode
))
921 /* skip non-readable files */
922 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
925 /* read attribute value */
926 fd
= open(path
, O_RDONLY
);
928 dbg(udev_device
->udev
, "attribute '%s' can not be opened\n", path
);
931 size
= read(fd
, value
, sizeof(value
));
935 if (size
== sizeof(value
))
938 /* got a valid value, store it in cache and return it */
940 util_remove_trailing_chars(value
, '\n');
941 dbg(udev_device
->udev
, "'%s' has attribute value '%s'\n", path
, value
);
942 list_entry
= udev_list_entry_add(udev_device
->udev
, &udev_device
->sysattr_list
, sysattr
, value
, 0, 0);
943 val
= udev_list_entry_get_value(list_entry
);
948 int udev_device_set_syspath(struct udev_device
*udev_device
, const char *syspath
)
953 free(udev_device
->syspath
);
954 udev_device
->syspath
= strdup(syspath
);
955 if (udev_device
->syspath
== NULL
)
957 udev_device
->devpath
= &udev_device
->syspath
[strlen(udev_get_sys_path(udev_device
->udev
))];
958 udev_device_add_property(udev_device
, "DEVPATH", udev_device
->devpath
);
960 pos
= strrchr(udev_device
->syspath
, '/');
963 udev_device
->sysname
= strdup(&pos
[1]);
964 if (udev_device
->sysname
== NULL
)
967 /* some devices have '!' in their name, change that to '/' */
969 while (udev_device
->sysname
[len
] != '\0') {
970 if (udev_device
->sysname
[len
] == '!')
971 udev_device
->sysname
[len
] = '/';
975 /* trailing number */
976 while (len
> 0 && isdigit(udev_device
->sysname
[--len
]))
977 udev_device
->sysnum
= &udev_device
->sysname
[len
];
979 /* sysname is completely numeric */
981 udev_device
->sysnum
= NULL
;
986 int udev_device_set_subsystem(struct udev_device
*udev_device
, const char *subsystem
)
988 free(udev_device
->subsystem
);
989 udev_device
->subsystem
= strdup(subsystem
);
990 if (udev_device
->subsystem
== NULL
)
992 udev_device
->subsystem_set
= 1;
993 udev_device_add_property(udev_device
, "SUBSYSTEM", udev_device
->subsystem
);
997 int udev_device_set_devtype(struct udev_device
*udev_device
, const char *devtype
)
999 free(udev_device
->devtype
);
1000 udev_device
->devtype
= strdup(devtype
);
1001 if (udev_device
->devtype
== NULL
)
1003 udev_device
->devtype_set
= 1;
1004 udev_device_add_property(udev_device
, "DEVTYPE", udev_device
->devtype
);
1008 int udev_device_set_devnode(struct udev_device
*udev_device
, const char *devnode
)
1010 free(udev_device
->devnode
);
1011 udev_device
->devnode
= strdup(devnode
);
1012 if (devnode
== NULL
)
1014 if (udev_device
->devnode
== NULL
)
1016 udev_device_add_property(udev_device
, "DEVNAME", udev_device
->devnode
);
1020 int udev_device_add_devlink(struct udev_device
*udev_device
, const char *devlink
)
1022 udev_device
->devlinks_uptodate
= 0;
1023 if (udev_list_entry_add(udev_device
->udev
, &udev_device
->devlinks_list
, devlink
, NULL
, 1, 0) == NULL
)
1028 struct udev_list_entry
*udev_device_add_property(struct udev_device
*udev_device
, const char *key
, const char *value
)
1030 udev_device
->envp_uptodate
= 0;
1031 if (value
== NULL
) {
1032 struct udev_list_entry
*list_entry
;
1034 list_entry
= udev_device_get_properties_list_entry(udev_device
);
1035 list_entry
= udev_list_entry_get_by_name(list_entry
, key
);
1036 if (list_entry
!= NULL
)
1037 udev_list_entry_delete(list_entry
);
1040 return udev_list_entry_add(udev_device
->udev
, &udev_device
->properties_list
, key
, value
, 1, 0);
1043 struct udev_list_entry
*udev_device_add_property_from_string(struct udev_device
*udev_device
, const char *property
)
1045 char name
[UTIL_PATH_SIZE
];
1048 util_strlcpy(name
, property
, sizeof(name
));
1049 val
= strchr(name
, '=');
1056 return udev_device_add_property(udev_device
, name
, val
);
1059 const char *udev_device_get_property_value(struct udev_device
*udev_device
, const char *key
)
1061 struct udev_list_entry
*list_entry
;
1063 if (udev_device
== NULL
)
1068 list_entry
= udev_device_get_properties_list_entry(udev_device
);
1069 list_entry
= udev_list_entry_get_by_name(list_entry
, key
);
1070 return udev_list_entry_get_value(list_entry
);
1073 #define ENVP_SIZE 128
1074 #define MONITOR_BUF_SIZE 4096
1075 static int update_envp_monitor_buf(struct udev_device
*udev_device
)
1077 struct udev_list_entry
*list_entry
;
1082 /* monitor buffer of property strings */
1083 free(udev_device
->monitor_buf
);
1084 udev_device
->monitor_buf_len
= 0;
1085 udev_device
->monitor_buf
= malloc(MONITOR_BUF_SIZE
);
1086 if (udev_device
->monitor_buf
== NULL
)
1089 /* envp array, strings will point into monitor buffer */
1090 if (udev_device
->envp
== NULL
)
1091 udev_device
->envp
= malloc(sizeof(char *) * ENVP_SIZE
);
1092 if (udev_device
->envp
== NULL
)
1097 udev_list_entry_foreach(list_entry
, udev_device_get_properties_list_entry(udev_device
)) {
1098 /* add string to envp array */
1099 udev_device
->envp
[i
++] = &udev_device
->monitor_buf
[bufpos
];
1100 if (i
+1 >= ENVP_SIZE
)
1103 /* add property string to monitor buffer */
1104 len
= util_strlcpy(&udev_device
->monitor_buf
[bufpos
],
1105 udev_list_entry_get_name(list_entry
), MONITOR_BUF_SIZE
-bufpos
);
1106 if (len
>= MONITOR_BUF_SIZE
-bufpos
)
1109 len
= util_strlcpy(&udev_device
->monitor_buf
[bufpos
], "=", MONITOR_BUF_SIZE
-bufpos
);
1110 if (len
>= MONITOR_BUF_SIZE
-bufpos
)
1113 len
= util_strlcpy(&udev_device
->monitor_buf
[bufpos
], udev_list_entry_get_value(list_entry
),
1114 MONITOR_BUF_SIZE
-bufpos
);
1115 if (len
+1 >= MONITOR_BUF_SIZE
-bufpos
)
1119 udev_device
->envp
[i
] = NULL
;
1120 udev_device
->monitor_buf_len
= bufpos
;
1121 udev_device
->envp_uptodate
= 1;
1122 dbg(udev_device
->udev
, "filled envp/monitor buffer, %u properties, %zu bytes\n", i
, bufpos
);
1126 char **udev_device_get_properties_envp(struct udev_device
*udev_device
)
1128 if (!udev_device
->envp_uptodate
)
1129 if (update_envp_monitor_buf(udev_device
) != 0)
1131 return udev_device
->envp
;
1134 ssize_t
udev_device_get_properties_monitor_buf(struct udev_device
*udev_device
, const char **buf
)
1136 if (!udev_device
->envp_uptodate
)
1137 if (update_envp_monitor_buf(udev_device
) != 0)
1139 *buf
= udev_device
->monitor_buf
;
1140 return udev_device
->monitor_buf_len
;
1143 int udev_device_set_action(struct udev_device
*udev_device
, const char *action
)
1145 free(udev_device
->action
);
1146 udev_device
->action
= strdup(action
);
1147 if (udev_device
->action
== NULL
)
1149 udev_device_add_property(udev_device
, "ACTION", udev_device
->action
);
1153 int udev_device_set_driver(struct udev_device
*udev_device
, const char *driver
)
1155 free(udev_device
->driver
);
1156 udev_device
->driver
= strdup(driver
);
1157 if (udev_device
->driver
== NULL
)
1159 udev_device
->driver_set
= 1;
1160 udev_device_add_property(udev_device
, "DRIVER", udev_device
->driver
);
1164 const char *udev_device_get_devpath_old(struct udev_device
*udev_device
)
1166 return udev_device
->devpath_old
;
1169 int udev_device_set_devpath_old(struct udev_device
*udev_device
, const char *devpath_old
)
1171 udev_device
->devpath_old
= strdup(devpath_old
);
1172 if (udev_device
->devpath_old
== NULL
)
1174 udev_device_add_property(udev_device
, "DEVPATH_OLD", udev_device
->devpath_old
);
1178 const char *udev_device_get_physdevpath(struct udev_device
*udev_device
)
1180 return udev_device
->physdevpath
;
1183 int udev_device_set_physdevpath(struct udev_device
*udev_device
, const char *physdevpath
)
1185 udev_device
->physdevpath
= strdup(physdevpath
);
1186 if (udev_device
->physdevpath
== NULL
)
1191 int udev_device_get_timeout(struct udev_device
*udev_device
)
1193 return udev_device
->timeout
;
1196 int udev_device_set_timeout(struct udev_device
*udev_device
, int timeout
)
1198 udev_device
->timeout
= timeout
;
1201 int udev_device_get_event_timeout(struct udev_device
*udev_device
)
1203 if (!udev_device
->info_loaded
)
1204 device_load_info(udev_device
);
1205 return udev_device
->event_timeout
;
1208 int udev_device_set_event_timeout(struct udev_device
*udev_device
, int event_timeout
)
1210 udev_device
->event_timeout
= event_timeout
;
1214 int udev_device_set_seqnum(struct udev_device
*udev_device
, unsigned long long int seqnum
)
1218 udev_device
->seqnum
= seqnum
;
1219 snprintf(num
, sizeof(num
), "%llu", seqnum
);
1220 udev_device_add_property(udev_device
, "SEQNUM", num
);
1224 int udev_device_set_devnum(struct udev_device
*udev_device
, dev_t devnum
)
1228 udev_device
->devnum
= devnum
;
1230 snprintf(num
, sizeof(num
), "%u", major(devnum
));
1231 udev_device_add_property(udev_device
, "MAJOR", num
);
1232 snprintf(num
, sizeof(num
), "%u", minor(devnum
));
1233 udev_device_add_property(udev_device
, "MINOR", num
);
1237 int udev_device_get_num_fake_partitions(struct udev_device
*udev_device
)
1239 if (!udev_device
->info_loaded
)
1240 device_load_info(udev_device
);
1241 return udev_device
->num_fake_partitions
;
1244 int udev_device_set_num_fake_partitions(struct udev_device
*udev_device
, int num
)
1246 udev_device
->num_fake_partitions
= num
;
1250 int udev_device_get_devlink_priority(struct udev_device
*udev_device
)
1252 if (!udev_device
->info_loaded
)
1253 device_load_info(udev_device
);
1254 return udev_device
->devlink_priority
;
1257 int udev_device_set_devlink_priority(struct udev_device
*udev_device
, int prio
)
1259 udev_device
->devlink_priority
= prio
;
1263 int udev_device_get_ignore_remove(struct udev_device
*udev_device
)
1265 if (!udev_device
->info_loaded
)
1266 device_load_info(udev_device
);
1267 return udev_device
->ignore_remove
;
1270 int udev_device_set_ignore_remove(struct udev_device
*udev_device
, int ignore
)
1272 udev_device
->ignore_remove
= ignore
;
1276 int udev_device_get_watch_handle(struct udev_device
*udev_device
)
1278 if (!udev_device
->info_loaded
)
1279 device_load_info(udev_device
);
1280 return udev_device
->watch_handle
;
1283 int udev_device_set_watch_handle(struct udev_device
*udev_device
, int handle
)
1285 udev_device
->watch_handle
= handle
;