1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
10 #include "device-internal.h"
11 #include "device-private.h"
12 #include "device-util.h"
13 #include "devnum-util.h"
14 #include "dirent-util.h"
16 #include "errno-util.h"
17 #include "extract-word.h"
22 #include "missing_magic.h"
23 #include "netlink-util.h"
24 #include "parse-util.h"
25 #include "path-util.h"
27 #include "socket-util.h"
28 #include "stat-util.h"
29 #include "stdio-util.h"
30 #include "string-util.h"
32 #include "time-util.h"
34 int device_new_aux(sd_device
**ret
) {
39 device
= new(sd_device
, 1);
43 *device
= (sd_device
) {
45 .devmode
= MODE_INVALID
,
46 .devuid
= UID_INVALID
,
47 .devgid
= GID_INVALID
,
48 .action
= _SD_DEVICE_ACTION_INVALID
,
55 static sd_device
*device_free(sd_device
*device
) {
58 sd_device_unref(device
->parent
);
59 free(device
->syspath
);
60 free(device
->sysname
);
61 free(device
->devtype
);
62 free(device
->devname
);
63 free(device
->subsystem
);
64 free(device
->driver_subsystem
);
66 free(device
->device_id
);
67 free(device
->properties_strv
);
68 free(device
->properties_nulstr
);
70 ordered_hashmap_free(device
->properties
);
71 ordered_hashmap_free(device
->properties_db
);
72 hashmap_free(device
->sysattr_values
);
73 set_free(device
->sysattrs
);
74 set_free(device
->all_tags
);
75 set_free(device
->current_tags
);
76 set_free(device
->devlinks
);
77 hashmap_free(device
->children
);
82 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device
, sd_device
, device_free
);
84 int device_add_property_aux(sd_device
*device
, const char *key
, const char *value
, bool db
) {
85 OrderedHashmap
**properties
;
91 properties
= &device
->properties_db
;
93 properties
= &device
->properties
;
96 _unused_ _cleanup_free_
char *old_value
= NULL
;
97 _cleanup_free_
char *new_key
= NULL
, *new_value
= NULL
, *old_key
= NULL
;
100 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops_free_free
);
104 new_key
= strdup(key
);
108 new_value
= strdup(value
);
112 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
114 /* ordered_hashmap_replace() does not fail when the hashmap already has the entry. */
115 r
= ordered_hashmap_replace(*properties
, new_key
, new_value
);
122 _unused_ _cleanup_free_
char *old_value
= NULL
;
123 _cleanup_free_
char *old_key
= NULL
;
125 old_value
= ordered_hashmap_remove2(*properties
, key
, (void**) &old_key
);
129 device
->properties_generation
++;
130 device
->properties_buf_outdated
= true;
136 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
137 _cleanup_free_
char *syspath
= NULL
;
145 _cleanup_close_
int fd
= -EBADF
;
147 /* The input path maybe a symlink located outside of /sys. Let's try to chase the symlink at first.
148 * The primary use case is that e.g. /proc/device-tree is a symlink to /sys/firmware/devicetree/base.
149 * By chasing symlinks in the path at first, we can call sd_device_new_from_path() with such path. */
150 r
= chase(_syspath
, NULL
, 0, &syspath
, &fd
);
152 /* the device does not exist (any more?) */
153 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
154 "sd-device: Failed to chase symlinks in \"%s\".", _syspath
);
156 return log_debug_errno(r
, "sd-device: Failed to get target of '%s': %m", _syspath
);
158 if (!path_startswith(syspath
, "/sys")) {
159 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
162 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
163 r
= chase("/sys", NULL
, 0, &real_sys
, NULL
);
165 return log_debug_errno(r
, "sd-device: Failed to chase symlink /sys: %m");
167 p
= path_startswith(syspath
, real_sys
);
169 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
170 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
173 new_syspath
= path_join("/sys", p
);
175 return log_oom_debug();
177 free_and_replace(syspath
, new_syspath
);
178 path_simplify(syspath
);
181 if (path_startswith(syspath
, "/sys/devices/")) {
182 /* For proper devices, stricter rules apply: they must have a 'uevent' file,
183 * otherwise we won't allow them */
185 if (faccessat(fd
, "uevent", F_OK
, 0) < 0) {
187 /* This is not a valid device. Note, this condition is quite often
188 * satisfied when enumerating devices or finding a parent device.
189 * Hence, use log_trace_errno() here. */
190 return log_trace_errno(SYNTHETIC_ERRNO(ENODEV
),
191 "sd-device: the uevent file \"%s/uevent\" does not exist.", syspath
);
192 if (errno
== ENOTDIR
)
193 /* Not actually a directory. */
194 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
195 "sd-device: the syspath \"%s\" is not a directory.", syspath
);
197 return log_debug_errno(errno
, "sd-device: cannot find uevent file for %s: %m", syspath
);
202 /* For everything else lax rules apply: they just need to be a directory */
204 if (fstat(fd
, &st
) < 0)
205 return log_debug_errno(errno
, "sd-device: failed to check if syspath \"%s\" is a directory: %m", syspath
);
206 if (!S_ISDIR(st
.st_mode
))
207 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
208 "sd-device: the syspath \"%s\" is not a directory.", syspath
);
211 /* Only operate on sysfs, i.e. refuse going down into /sys/fs/cgroup/ or similar places where
212 * things are not arranged as kobjects in kernel, and hence don't necessarily have
213 * kobject/attribute structure. */
214 r
= secure_getenv_bool("SYSTEMD_DEVICE_VERIFY_SYSFS");
215 if (r
< 0 && r
!= -ENXIO
)
216 log_debug_errno(r
, "Failed to parse $SYSTEMD_DEVICE_VERIFY_SYSFS value: %m");
218 r
= fd_is_fs_type(fd
, SYSFS_MAGIC
);
220 return log_debug_errno(r
, "sd-device: failed to check if syspath \"%s\" is backed by sysfs.", syspath
);
222 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
223 "sd-device: the syspath \"%s\" is outside of sysfs, refusing.", syspath
);
226 /* must be a subdirectory of /sys */
227 if (!path_startswith(_syspath
, "/sys/"))
228 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
229 "sd-device: Syspath '%s' is not a subdirectory of /sys",
232 r
= path_simplify_alloc(_syspath
, &syspath
);
234 return log_oom_debug();
237 assert_se(devpath
= startswith(syspath
, "/sys"));
238 if (devpath
[0] != '/')
239 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "sd-device: \"/sys\" alone is not a valid device path.");
241 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
243 return log_debug_errno(r
, "sd-device: Failed to add \"DEVPATH\" property for device \"%s\": %m", syspath
);
245 free_and_replace(device
->syspath
, syspath
);
246 device
->devpath
= devpath
;
248 /* Unset sysname and sysnum, they will be assigned when requested. */
249 device
->sysnum
= NULL
;
250 device
->sysname
= mfree(device
->sysname
);
254 static int device_new_from_syspath(sd_device
**ret
, const char *syspath
, bool strict
) {
255 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
258 assert_return(ret
, -EINVAL
);
259 assert_return(syspath
, -EINVAL
);
261 if (strict
&& !path_startswith(syspath
, "/sys/"))
264 r
= device_new_aux(&device
);
268 r
= device_set_syspath(device
, syspath
, /* verify= */ true);
272 *ret
= TAKE_PTR(device
);
276 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
277 return device_new_from_syspath(ret
, syspath
, /* strict = */ true);
280 int device_new_from_mode_and_devnum(sd_device
**ret
, mode_t mode
, dev_t devnum
) {
281 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
282 _cleanup_free_
char *syspath
= NULL
;
291 else if (S_ISBLK(mode
))
296 if (major(devnum
) == 0)
299 if (asprintf(&syspath
, "/sys/dev/%s/" DEVNUM_FORMAT_STR
, t
, DEVNUM_FORMAT_VAL(devnum
)) < 0)
302 r
= sd_device_new_from_syspath(&dev
, syspath
);
306 r
= sd_device_get_devnum(dev
, &n
);
314 r
= device_in_subsystem(dev
, "block");
317 if (r
> 0 ? !S_ISBLK(mode
) : !S_ISCHR(mode
))
320 *ret
= TAKE_PTR(dev
);
324 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
325 assert_return(ret
, -EINVAL
);
326 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
328 return device_new_from_mode_and_devnum(ret
, type
== 'b' ? S_IFBLK
: S_IFCHR
, devnum
);
331 static int device_new_from_main_ifname(sd_device
**ret
, const char *ifname
) {
337 syspath
= strjoina("/sys/class/net/", ifname
);
338 return sd_device_new_from_syspath(ret
, syspath
);
341 _public_
int sd_device_new_from_ifname(sd_device
**ret
, const char *ifname
) {
342 _cleanup_free_
char *main_name
= NULL
;
345 assert_return(ret
, -EINVAL
);
346 assert_return(ifname
, -EINVAL
);
348 if (ifname_valid(ifname
)) {
349 r
= device_new_from_main_ifname(ret
, ifname
);
354 r
= rtnl_resolve_ifname_full(NULL
, RESOLVE_IFNAME_ALTERNATIVE
| RESOLVE_IFNAME_NUMERIC
, ifname
, &main_name
, NULL
);
358 return device_new_from_main_ifname(ret
, main_name
);
361 _public_
int sd_device_new_from_ifindex(sd_device
**ret
, int ifindex
) {
362 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
363 _cleanup_free_
char *ifname
= NULL
;
366 assert_return(ret
, -EINVAL
);
367 assert_return(ifindex
> 0, -EINVAL
);
369 r
= rtnl_get_ifname(NULL
, ifindex
, &ifname
);
373 r
= device_new_from_main_ifname(&dev
, ifname
);
377 r
= sd_device_get_ifindex(dev
, &i
);
385 *ret
= TAKE_PTR(dev
);
389 static int device_new_from_path_join(
391 const char *subsystem
,
392 const char *driver_subsystem
,
399 _cleanup_(sd_device_unrefp
) sd_device
*new_device
= NULL
;
400 _cleanup_free_
char *p
= NULL
;
406 p
= path_join(a
, b
, c
, d
);
410 r
= sd_device_new_from_syspath(&new_device
, p
);
416 /* Check if the found device really has the expected subsystem and sysname, for safety. */
417 r
= device_in_subsystem(new_device
, subsystem
);
421 const char *new_driver_subsystem
= NULL
;
422 (void) sd_device_get_driver_subsystem(new_device
, &new_driver_subsystem
);
424 if (!streq_ptr(driver_subsystem
, new_driver_subsystem
))
427 const char *new_sysname
;
428 r
= sd_device_get_sysname(new_device
, &new_sysname
);
432 if (!streq(sysname
, new_sysname
))
435 /* If this is the first device we found, then take it. */
437 *device
= TAKE_PTR(new_device
);
441 /* Unfortunately, (subsystem, sysname) pair is not unique. For examples,
442 * - /sys/bus/gpio and /sys/class/gpio, both have gpiochip%N. However, these point to different devpaths.
443 * - /sys/bus/mdio_bus and /sys/class/mdio_bus,
444 * - /sys/bus/mei and /sys/class/mei,
445 * - /sys/bus/typec and /sys/class/typec, and so on.
446 * Hence, if we already know a device, then we need to check if it is equivalent to the newly found one. */
448 const char *devpath
, *new_devpath
;
449 r
= sd_device_get_devpath(*device
, &devpath
);
453 r
= sd_device_get_devpath(new_device
, &new_devpath
);
457 if (!streq(devpath
, new_devpath
))
458 return log_debug_errno(SYNTHETIC_ERRNO(ETOOMANYREFS
),
459 "sd-device: found multiple devices for subsystem=%s and sysname=%s, refusing: %s, %s",
460 subsystem
, sysname
, devpath
, new_devpath
);
462 return 1; /* Fortunately, they are consistent. */
465 _public_
int sd_device_new_from_subsystem_sysname(
467 const char *subsystem
,
468 const char *sysname
) {
470 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
474 assert_return(ret
, -EINVAL
);
475 assert_return(subsystem
, -EINVAL
);
476 assert_return(sysname
, -EINVAL
);
478 if (!path_is_normalized(subsystem
))
480 if (!path_is_normalized(sysname
))
483 /* translate sysname back to sysfs filename */
484 name
= strdupa_safe(sysname
);
485 string_replace_char(name
, '/', '!');
487 if (streq(subsystem
, "subsystem")) {
488 FOREACH_STRING(s
, "/sys/bus/", "/sys/class/") {
489 r
= device_new_from_path_join(&device
, subsystem
, /* driver_subsystem = */ NULL
, sysname
, s
, name
, NULL
, NULL
);
494 } else if (streq(subsystem
, "module")) {
495 r
= device_new_from_path_join(&device
, subsystem
, /* driver_subsystem = */ NULL
, sysname
, "/sys/module/", name
, NULL
, NULL
);
499 } else if (streq(subsystem
, "drivers")) {
502 sep
= strchr(name
, ':');
503 if (sep
&& sep
[1] != '\0') { /* Require ":" and something non-empty after that. */
505 const char *subsys
= memdupa_suffix0(name
, sep
- name
);
508 if (streq(sep
, "drivers")) /* If the sysname is "drivers", then it's the drivers directory itself that is meant. */
509 r
= device_new_from_path_join(&device
, subsystem
, subsys
, "drivers", "/sys/bus/", subsys
, "/drivers", NULL
);
511 r
= device_new_from_path_join(&device
, subsystem
, subsys
, sysname
+ (sep
- name
), "/sys/bus/", subsys
, "/drivers/", sep
);
517 r
= device_new_from_path_join(&device
, subsystem
, /* driver_subsystem = */ NULL
, sysname
, "/sys/bus/", subsystem
, "/devices/", name
);
521 r
= device_new_from_path_join(&device
, subsystem
, /* driver_subsystem = */ NULL
, sysname
, "/sys/class/", subsystem
, name
, NULL
);
525 /* Note that devices under /sys/firmware/ (e.g. /sys/firmware/devicetree/base/) do not have
526 * subsystem. Hence, pass NULL for subsystem. See issue #35861. */
527 r
= device_new_from_path_join(&device
, /* subsystem = */ NULL
, /* driver_subsystem = */ NULL
, sysname
, "/sys/firmware/", subsystem
, name
, NULL
);
534 *ret
= TAKE_PTR(device
);
538 _public_
int sd_device_new_from_stat_rdev(sd_device
**ret
, const struct stat
*st
) {
539 assert_return(ret
, -EINVAL
);
540 assert_return(st
, -EINVAL
);
542 return device_new_from_mode_and_devnum(ret
, st
->st_mode
, st
->st_rdev
);
545 static int device_new_from_devname(sd_device
**ret
, const char *devname
, bool strict
) {
548 assert_return(ret
, -EINVAL
);
549 assert_return(devname
, -EINVAL
);
551 /* This function actually accepts both devlinks and devnames, i.e. both symlinks and device
552 * nodes below /dev/. */
554 if (strict
&& isempty(path_startswith(devname
, "/dev/")))
559 if (device_path_parse_major_minor(devname
, &mode
, &devnum
) >= 0)
560 /* Let's shortcut when "/dev/block/maj:min" or "/dev/char/maj:min" is specified.
561 * In that case, we can directly convert the path to syspath, hence it is not necessary
562 * that the specified path exists. So, this works fine without udevd being running. */
563 return device_new_from_mode_and_devnum(ret
, mode
, devnum
);
565 _cleanup_free_
char *resolved
= NULL
;
567 r
= chase_and_stat(devname
, /* root = */ NULL
, /* chase_flags = */ 0, &resolved
, &st
);
568 if (ERRNO_IS_NEG_DEVICE_ABSENT(r
))
573 if (isempty(path_startswith(resolved
, "/dev/")))
576 return sd_device_new_from_stat_rdev(ret
, &st
);
579 _public_
int sd_device_new_from_devname(sd_device
**ret
, const char *devname
) {
580 return device_new_from_devname(ret
, devname
, /* strict = */ true);
583 _public_
int sd_device_new_from_path(sd_device
**ret
, const char *path
) {
584 assert_return(ret
, -EINVAL
);
585 assert_return(path
, -EINVAL
);
587 if (device_new_from_devname(ret
, path
, /* strict = */ false) >= 0)
590 return device_new_from_syspath(ret
, path
, /* strict = */ false);
593 int device_set_devtype(sd_device
*device
, const char *devtype
) {
594 _cleanup_free_
char *t
= NULL
;
604 r
= device_add_property_internal(device
, "DEVTYPE", t
);
608 return free_and_replace(device
->devtype
, t
);
611 int device_set_ifindex(sd_device
*device
, const char *name
) {
617 ifindex
= parse_ifindex(name
);
621 r
= device_add_property_internal(device
, "IFINDEX", name
);
625 device
->ifindex
= ifindex
;
630 static int mangle_devname(const char *p
, char **ret
) {
636 if (!path_is_safe(p
))
639 /* When the path is absolute, it must start with "/dev/", but ignore "/dev/" itself. */
640 if (path_is_absolute(p
)) {
641 if (isempty(path_startswith(p
, "/dev/")))
646 q
= path_join("/dev/", p
);
656 int device_set_devname(sd_device
*device
, const char *devname
) {
657 _cleanup_free_
char *t
= NULL
;
663 r
= mangle_devname(devname
, &t
);
667 r
= device_add_property_internal(device
, "DEVNAME", t
);
671 return free_and_replace(device
->devname
, t
);
674 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
681 r
= safe_atou(_devmode
, &devmode
);
688 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
692 device
->devmode
= devmode
;
697 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
698 unsigned maj
, min
= 0;
704 r
= safe_atou(major
, &maj
);
709 if (!DEVICE_MAJOR_VALID(maj
))
713 r
= safe_atou(minor
, &min
);
716 if (!DEVICE_MINOR_VALID(min
))
720 r
= device_add_property_internal(device
, "MAJOR", major
);
725 r
= device_add_property_internal(device
, "MINOR", minor
);
730 device
->devnum
= makedev(maj
, min
);
735 int device_set_diskseq(sd_device
*device
, const char *str
) {
742 r
= safe_atou64(str
, &diskseq
);
748 r
= device_add_property_internal(device
, "DISKSEQ", str
);
752 device
->diskseq
= diskseq
;
757 static int handle_uevent_line(
762 const char **minor
) {
770 if (streq(key
, "SUBSYSTEM"))
771 return device_set_subsystem(device
, value
);
772 if (streq(key
, "DEVTYPE"))
773 return device_set_devtype(device
, value
);
774 if (streq(key
, "IFINDEX"))
775 return device_set_ifindex(device
, value
);
776 if (streq(key
, "DEVNAME"))
777 return device_set_devname(device
, value
);
778 if (streq(key
, "DEVUID"))
779 return device_set_devuid(device
, value
);
780 if (streq(key
, "DEVGID"))
781 return device_set_devgid(device
, value
);
782 if (streq(key
, "DEVMODE"))
783 return device_set_devmode(device
, value
);
784 if (streq(key
, "DISKSEQ"))
785 return device_set_diskseq(device
, value
);
786 if (streq(key
, "DRIVER"))
787 return device_set_driver(device
, value
);
788 if (streq(key
, "MAJOR"))
790 else if (streq(key
, "MINOR"))
793 return device_add_property_internal(device
, key
, value
);
798 int device_read_uevent_file(sd_device
*device
) {
803 if (device
->uevent_loaded
|| device
->sealed
)
806 device
->uevent_loaded
= true;
809 r
= sd_device_get_sysattr_value(device
, "uevent", &uevent
);
810 if (ERRNO_IS_NEG_PRIVILEGE(r
) || ERRNO_IS_NEG_DEVICE_ABSENT(r
))
811 /* The uevent files may be write-only, the device may be already removed, or the device
812 * may not have the uevent file. */
815 return log_device_debug_errno(device
, r
, "sd-device: Failed to read uevent file: %m");
817 _cleanup_strv_free_
char **v
= NULL
;
818 r
= strv_split_newlines_full(&v
, uevent
, EXTRACT_RETAIN_ESCAPE
);
820 return log_device_debug_errno(device
, r
, "sd-device: Failed to parse uevent file: %m");
822 const char *major
= NULL
, *minor
= NULL
;
824 char *eq
= strchr(*s
, '=');
826 log_device_debug(device
, "sd-device: Invalid uevent line, ignoring: %s", *s
);
832 r
= handle_uevent_line(device
, *s
, eq
+ 1, &major
, &minor
);
834 log_device_debug_errno(device
, r
,
835 "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m",
840 r
= device_set_devnum(device
, major
, minor
);
842 log_device_debug_errno(device
, r
,
843 "sd-device: Failed to set 'MAJOR=%s' and/or 'MINOR=%s' from uevent, ignoring: %m",
844 major
, strna(minor
));
847 r
= device_in_subsystem(device
, "drivers");
849 log_device_debug_errno(device
, r
, "Failed to check if the device is a driver, ignoring: %m");
851 r
= device_set_drivers_subsystem(device
);
853 log_device_debug_errno(device
, r
,
854 "sd-device: Failed to set driver subsystem, ignoring: %m");
860 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
863 assert_return(device
, -EINVAL
);
865 r
= device_read_uevent_file(device
);
869 if (device
->ifindex
<= 0)
873 *ifindex
= device
->ifindex
;
878 int device_get_ifname(sd_device
*device
, const char **ret
) {
881 assert_return(device
, -EINVAL
);
883 /* First, check if the device is a network interface. */
884 r
= sd_device_get_ifindex(device
, NULL
);
888 /* The sysname and ifname may be different, as '!' in sysname are replaced with '/'.
889 * For network interfaces, we can use INTERFACE property. */
890 return sd_device_get_property_value(device
, "INTERFACE", ret
);
893 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
896 assert_return(ret
, -EINVAL
);
897 assert_return(id
, -EINVAL
);
907 r
= parse_devnum(id
+ 1, &devt
);
911 return sd_device_new_from_devnum(ret
, id
[0], devt
);
917 ifindex
= parse_ifindex(id
+ 1);
921 return sd_device_new_from_ifindex(ret
, ifindex
);
925 const char *sep
= strchr(id
+ 1, ':');
926 if (!sep
|| sep
[1] == '\0')
929 _cleanup_free_
char *subsystem
= strndup(id
+ 1, sep
- id
- 1);
933 _cleanup_free_
char *sysname
= strdup(sep
+ 1);
937 /* Device ID uses device directory name as is, hence may contain '!', but
938 * sd_device_new_from_subsystem_sysname() expects that the input is sysname,
939 * that is, '!' must be replaced with '/'. */
940 string_replace_char(sysname
, '!', '/');
942 return sd_device_new_from_subsystem_sysname(ret
, subsystem
, sysname
);
950 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
951 assert_return(device
, -EINVAL
);
953 assert(path_startswith(device
->syspath
, "/sys/"));
956 *ret
= device
->syspath
;
961 DEFINE_PRIVATE_HASH_OPS_FULL(
962 device_by_path_hash_ops
,
963 char, path_hash_func
, path_compare
, free
,
964 sd_device
, sd_device_unref
);
966 static int device_enumerate_children_internal(sd_device
*device
, const char *subdir
, Set
**stack
, Hashmap
**children
) {
967 _cleanup_closedir_
DIR *dir
= NULL
;
974 r
= device_opendir(device
, subdir
, &dir
);
978 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
979 _cleanup_(sd_device_unrefp
) sd_device
*child
= NULL
;
980 _cleanup_free_
char *p
= NULL
;
982 if (dot_or_dot_dot(de
->d_name
))
985 if (!IN_SET(de
->d_type
, DT_LNK
, DT_DIR
))
989 p
= path_join(subdir
, de
->d_name
);
991 p
= strdup(de
->d_name
);
995 /* Try to create child device. */
996 r
= sd_device_new_child(&child
, device
, p
);
998 /* OK, this is a child device, saving it. */
999 r
= hashmap_ensure_put(children
, &device_by_path_hash_ops
, p
, child
);
1005 } else if (r
== -ENODEV
) {
1006 /* This is not a child device. Push the sub-directory into stack, and read it later. */
1008 if (de
->d_type
== DT_LNK
)
1009 /* Do not follow symlinks, otherwise, we will enter an infinite loop, e.g.,
1010 * /sys/class/block/nvme0n1/subsystem/nvme0n1/subsystem/nvme0n1/subsystem/… */
1013 r
= set_ensure_consume(stack
, &path_hash_ops_free
, TAKE_PTR(p
));
1023 static int device_enumerate_children(sd_device
*device
) {
1024 _cleanup_hashmap_free_ Hashmap
*children
= NULL
;
1025 _cleanup_set_free_ Set
*stack
= NULL
;
1030 if (device
->children_enumerated
)
1031 return 0; /* Already enumerated. */
1033 r
= device_enumerate_children_internal(device
, NULL
, &stack
, &children
);
1038 _cleanup_free_
char *subdir
= NULL
;
1040 subdir
= set_steal_first(stack
);
1044 r
= device_enumerate_children_internal(device
, subdir
, &stack
, &children
);
1049 device
->children_enumerated
= true;
1050 device
->children
= TAKE_PTR(children
);
1051 return 1; /* Enumerated. */
1054 _public_ sd_device
*sd_device_get_child_first(sd_device
*device
, const char **ret_suffix
) {
1059 r
= device_enumerate_children(device
);
1061 log_device_debug_errno(device
, r
, "sd-device: failed to enumerate child devices: %m");
1067 device
->children_iterator
= ITERATOR_FIRST
;
1069 return sd_device_get_child_next(device
, ret_suffix
);
1072 _public_ sd_device
*sd_device_get_child_next(sd_device
*device
, const char **ret_suffix
) {
1077 (void) hashmap_iterate(device
->children
, &device
->children_iterator
, (void**) &child
, (const void**) ret_suffix
);
1081 _public_
int sd_device_new_child(sd_device
**ret
, sd_device
*device
, const char *suffix
) {
1082 _cleanup_free_
char *path
= NULL
;
1087 assert_return(ret
, -EINVAL
);
1088 assert_return(device
, -EINVAL
);
1089 assert_return(suffix
, -EINVAL
);
1091 if (!path_is_safe(suffix
))
1094 /* If we have already enumerated children, try to find the child from the cache. */
1095 child
= hashmap_get(device
->children
, suffix
);
1097 *ret
= sd_device_ref(child
);
1101 r
= sd_device_get_syspath(device
, &s
);
1105 path
= path_join(s
, suffix
);
1109 return sd_device_new_from_syspath(ret
, path
);
1112 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
1113 _cleanup_free_
char *path
= NULL
;
1114 const char *syspath
;
1120 r
= sd_device_get_syspath(child
, &syspath
);
1125 _cleanup_free_
char *p
= NULL
;
1127 r
= path_extract_directory(path
?: syspath
, &p
);
1131 if (path_equal(p
, "/sys"))
1134 r
= sd_device_new_from_syspath(ret
, p
);
1138 free_and_replace(path
, p
);
1142 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
1145 assert_return(child
, -EINVAL
);
1147 if (!child
->parent_set
) {
1148 r
= device_new_from_child(&child
->parent
, child
);
1149 if (r
< 0 && r
!= -ENODEV
)
1152 child
->parent_set
= true;
1159 *ret
= child
->parent
;
1163 int device_set_subsystem(sd_device
*device
, const char *subsystem
) {
1164 _cleanup_free_
char *s
= NULL
;
1170 s
= strdup(subsystem
);
1175 r
= device_add_property_internal(device
, "SUBSYSTEM", s
);
1179 device
->subsystem_set
= true;
1180 return free_and_replace(device
->subsystem
, s
);
1183 int device_set_drivers_subsystem(sd_device
*device
) {
1184 _cleanup_free_
char *subsystem
= NULL
;
1185 const char *devpath
, *drivers
, *p
;
1190 r
= sd_device_get_devpath(device
, &devpath
);
1194 drivers
= strstr(devpath
, "/drivers/");
1196 drivers
= endswith(devpath
, "/drivers");
1200 /* Find the path component immediately before the "/drivers/" string */
1201 r
= path_find_last_component(devpath
, /* accept_dot_dot= */ false, &drivers
, &p
);
1207 subsystem
= strndup(p
, r
);
1211 r
= device_set_subsystem(device
, "drivers");
1215 return free_and_replace(device
->driver_subsystem
, subsystem
);
1218 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
1221 assert_return(device
, -EINVAL
);
1223 r
= device_read_uevent_file(device
);
1227 if (!device
->subsystem_set
) {
1228 const char *subsystem
;
1230 r
= sd_device_get_sysattr_value(device
, "subsystem", &subsystem
);
1231 if (r
< 0 && r
!= -ENOENT
)
1232 return log_device_debug_errno(device
, r
,
1233 "sd-device: Failed to read subsystem for %s: %m",
1236 r
= device_set_subsystem(device
, subsystem
);
1237 /* use implicit names */
1238 else if (!isempty(path_startswith(device
->devpath
, "/module/")))
1239 r
= device_set_subsystem(device
, "module");
1240 else if (strstr(device
->devpath
, "/drivers/") || endswith(device
->devpath
, "/drivers"))
1241 r
= device_set_drivers_subsystem(device
);
1242 else if (!isempty(PATH_STARTSWITH_SET(device
->devpath
, "/class/", "/bus/")))
1243 r
= device_set_subsystem(device
, "subsystem");
1245 r
= device_set_subsystem(device
, NULL
);
1247 return log_device_debug_errno(device
, r
,
1248 "sd-device: Failed to set subsystem for %s: %m",
1252 if (!device
->subsystem
)
1256 *ret
= device
->subsystem
;
1260 _public_
int sd_device_get_driver_subsystem(sd_device
*device
, const char **ret
) {
1263 assert_return(device
, -EINVAL
);
1265 r
= device_in_subsystem(device
, "drivers");
1271 assert(device
->driver_subsystem
);
1274 *ret
= device
->driver_subsystem
;
1279 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
1282 assert_return(device
, -EINVAL
);
1284 r
= device_read_uevent_file(device
);
1288 if (!device
->devtype
)
1292 *devtype
= device
->devtype
;
1297 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*device
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
1300 assert_return(device
, -EINVAL
);
1301 assert_return(subsystem
, -EINVAL
);
1304 r
= sd_device_get_parent(device
, &device
);
1308 r
= device_is_subsystem_devtype(device
, subsystem
, devtype
);
1320 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
1323 assert_return(device
, -EINVAL
);
1325 r
= device_read_uevent_file(device
);
1329 if (major(device
->devnum
) <= 0)
1333 *devnum
= device
->devnum
;
1338 int device_set_driver(sd_device
*device
, const char *driver
) {
1339 _cleanup_free_
char *d
= NULL
;
1350 r
= device_add_property_internal(device
, "DRIVER", d
);
1354 device
->driver_set
= true;
1355 return free_and_replace(device
->driver
, d
);
1358 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
1361 assert_return(device
, -EINVAL
);
1363 r
= device_read_uevent_file(device
);
1367 if (!device
->driver_set
) {
1368 const char *driver
= NULL
;
1370 r
= sd_device_get_sysattr_value(device
, "driver", &driver
);
1371 if (r
< 0 && r
!= -ENOENT
)
1372 return log_device_debug_errno(device
, r
,
1373 "sd-device: Failed to read driver: %m");
1375 r
= device_set_driver(device
, driver
);
1377 return log_device_debug_errno(device
, r
,
1378 "sd-device: Failed to set driver \"%s\": %m", driver
);
1381 if (!device
->driver
)
1385 *ret
= device
->driver
;
1389 _public_
int sd_device_get_devpath(sd_device
*device
, const char **ret
) {
1390 assert_return(device
, -EINVAL
);
1392 assert(device
->devpath
);
1393 assert(device
->devpath
[0] == '/');
1396 *ret
= device
->devpath
;
1401 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
1404 assert_return(device
, -EINVAL
);
1406 r
= device_read_uevent_file(device
);
1410 if (!device
->devname
)
1413 assert(!isempty(path_startswith(device
->devname
, "/dev/")));
1416 *devname
= device
->devname
;
1420 static int device_set_sysname_and_sysnum(sd_device
*device
) {
1421 _cleanup_free_
char *sysname
= NULL
;
1427 r
= path_extract_filename(device
->devpath
, &sysname
);
1430 if (r
== O_DIRECTORY
)
1433 /* some devices have '!' in their name, change that to '/' */
1434 string_replace_char(sysname
, '!', '/');
1436 n
= strspn_from_end(sysname
, DIGITS
);
1437 len
= strlen(sysname
);
1440 n
= 0; /* Do not set sysnum for number only sysname. */
1442 device
->sysnum
= n
> 0 ? sysname
+ len
- n
: NULL
;
1443 return free_and_replace(device
->sysname
, sysname
);
1446 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1449 assert_return(device
, -EINVAL
);
1451 if (!device
->sysname
) {
1452 r
= device_set_sysname_and_sysnum(device
);
1458 *ret
= device
->sysname
;
1462 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1465 assert_return(device
, -EINVAL
);
1467 if (!device
->sysname
) {
1468 r
= device_set_sysname_and_sysnum(device
);
1473 if (!device
->sysnum
)
1477 *ret
= device
->sysnum
;
1481 int device_get_sysnum_unsigned(sd_device
*device
, unsigned *ret
) {
1487 r
= sd_device_get_sysnum(device
, &s
);
1492 r
= safe_atou_full(s
, SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_WHITESPACE
| 10, &n
);
1501 _public_
int sd_device_get_action(sd_device
*device
, sd_device_action_t
*ret
) {
1502 assert_return(device
, -EINVAL
);
1504 if (device
->action
< 0)
1508 *ret
= device
->action
;
1513 _public_
int sd_device_get_seqnum(sd_device
*device
, uint64_t *ret
) {
1514 assert_return(device
, -EINVAL
);
1516 if (device
->seqnum
== 0)
1520 *ret
= device
->seqnum
;
1525 _public_
int sd_device_get_diskseq(sd_device
*device
, uint64_t *ret
) {
1528 assert_return(device
, -EINVAL
);
1530 r
= device_read_uevent_file(device
);
1534 if (device
->diskseq
== 0)
1538 *ret
= device
->diskseq
;
1543 static bool is_valid_tag(const char *tag
) {
1546 return in_charset(tag
, ALPHANUMERICAL
"-_") && filename_is_valid(tag
);
1549 int device_add_tag(sd_device
*device
, const char *tag
, bool both
) {
1555 if (!is_valid_tag(tag
))
1558 /* Definitely add to the "all" list of tags (i.e. the sticky list) */
1559 added
= set_put_strdup(&device
->all_tags
, tag
);
1563 /* And optionally, also add it to the current list of tags */
1565 r
= set_put_strdup(&device
->current_tags
, tag
);
1568 (void) set_remove(device
->all_tags
, tag
);
1574 device
->tags_generation
++;
1575 device
->property_tags_outdated
= true;
1580 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1587 r
= mangle_devname(devlink
, &p
);
1591 r
= set_ensure_consume(&device
->devlinks
, &path_hash_ops_free
, p
);
1595 device
->devlinks_generation
++;
1596 device
->property_devlinks_outdated
= true;
1598 return r
; /* return 1 when newly added, 0 when already exists */
1601 int device_remove_devlink(sd_device
*device
, const char *devlink
) {
1602 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
1608 r
= mangle_devname(devlink
, &p
);
1612 s
= set_remove(device
->devlinks
, p
);
1614 return 0; /* does not exist */
1616 device
->devlinks_generation
++;
1617 device
->property_devlinks_outdated
= true;
1618 return 1; /* removed */
1621 bool device_has_devlink(sd_device
*device
, const char *devlink
) {
1625 return set_contains(device
->devlinks
, devlink
);
1628 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1629 _cleanup_free_
char *key
= NULL
;
1640 value
= strchr(key
, '=');
1646 if (isempty(++value
))
1649 /* Add the property to both sd_device::properties and sd_device::properties_db,
1650 * as this is called by only handle_db_line(). */
1651 r
= device_add_property_aux(device
, key
, value
, false);
1655 return device_add_property_aux(device
, key
, value
, true);
1658 int device_set_usec_initialized(sd_device
*device
, usec_t when
) {
1659 char s
[DECIMAL_STR_MAX(usec_t
)];
1664 xsprintf(s
, USEC_FMT
, when
);
1666 r
= device_add_property_internal(device
, "USEC_INITIALIZED", s
);
1670 device
->usec_initialized
= when
;
1674 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1681 case 'G': /* Any tag */
1682 case 'Q': /* Current tag */
1683 return device_add_tag(device
, value
, key
== 'Q');
1688 path
= strjoina("/dev/", value
);
1689 return device_add_devlink(device
, path
);
1692 return device_add_property_internal_from_string(device
, value
);
1697 r
= safe_atou64(value
, &t
);
1701 return device_set_usec_initialized(device
, t
);
1704 return safe_atoi(value
, &device
->devlink_priority
);
1707 /* Deprecated. Previously, watch handle is both saved in database and /run/udev/watch.
1708 * However, the handle saved in database may not be updated when the handle is updated
1709 * or removed. Moreover, it is not necessary to store the handle within the database,
1710 * as its value becomes meaningless when udevd is restarted. */
1714 return safe_atou(value
, &device
->database_version
);
1717 log_device_debug(device
, "sd-device: Unknown key '%c' in device db, ignoring", key
);
1722 _public_
int sd_device_get_device_id(sd_device
*device
, const char **ret
) {
1723 assert_return(device
, -EINVAL
);
1725 if (!device
->device_id
) {
1726 _cleanup_free_
char *id
= NULL
;
1730 if (sd_device_get_devnum(device
, &devnum
) >= 0) {
1731 r
= device_in_subsystem(device
, "block");
1734 char t
= r
> 0 ? 'b' : 'c';
1736 /* use dev_t — b259:131072, c254:0 */
1737 if (asprintf(&id
, "%c" DEVNUM_FORMAT_STR
, t
, DEVNUM_FORMAT_VAL(devnum
)) < 0)
1740 } else if (sd_device_get_ifindex(device
, &ifindex
) >= 0) {
1741 /* use netdev ifindex — n3 */
1742 if (asprintf(&id
, "n%u", (unsigned) ifindex
) < 0)
1746 _cleanup_free_
char *sysname
= NULL
;
1748 /* use $subsys:$sysname — pci:0000:00:1f.2
1749 * sd_device_get_sysname() has '!' translated, get it from devpath */
1750 r
= path_extract_filename(device
->devpath
, &sysname
);
1753 if (r
== O_DIRECTORY
)
1756 r
= device_in_subsystem(device
, "drivers");
1760 /* the 'drivers' pseudo-subsystem is special, and needs the real
1761 * subsystem encoded as well */
1762 id
= strjoin("+drivers:", ASSERT_PTR(device
->driver_subsystem
), ":", sysname
);
1764 const char *subsystem
;
1765 r
= sd_device_get_subsystem(device
, &subsystem
);
1769 id
= strjoin("+", subsystem
, ":", sysname
);
1775 if (!filename_is_valid(id
))
1778 device
->device_id
= TAKE_PTR(id
);
1782 *ret
= device
->device_id
;
1786 int device_read_db_internal_filename(sd_device
*device
, const char *filename
) {
1787 _cleanup_free_
char *db
= NULL
;
1790 char key
= '\0'; /* Unnecessary initialization to appease gcc-12.0.0-0.4.fc36 */
1804 r
= read_full_file(filename
, &db
, &db_len
);
1809 return log_device_debug_errno(device
, r
, "sd-device: Failed to read db '%s': %m", filename
);
1812 /* devices with a database entry are initialized */
1813 device
->is_initialized
= true;
1815 device
->db_loaded
= true;
1817 for (size_t i
= 0; i
< db_len
; i
++)
1820 if (!strchr(NEWLINE
, db
[i
])) {
1829 log_device_debug(device
, "sd-device: Invalid db entry with key '%c', ignoring", key
);
1831 state
= INVALID_LINE
;
1846 if (strchr(NEWLINE
, db
[i
]))
1851 if (strchr(NEWLINE
, db
[i
])) {
1853 r
= handle_db_line(device
, key
, value
);
1855 log_device_debug_errno(device
, r
, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m",
1863 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
), "sd-device: invalid db syntax.");
1869 _public_
int sd_device_get_is_initialized(sd_device
*device
) {
1872 assert_return(device
, -EINVAL
);
1874 r
= device_read_db(device
);
1876 /* The device may be already removed or renamed. */
1881 return device
->is_initialized
;
1884 _public_
int sd_device_get_usec_initialized(sd_device
*device
, uint64_t *ret
) {
1887 assert_return(device
, -EINVAL
);
1889 r
= sd_device_get_is_initialized(device
);
1895 if (device
->usec_initialized
== 0)
1899 *ret
= device
->usec_initialized
;
1904 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *ret
) {
1908 assert_return(device
, -EINVAL
);
1910 r
= sd_device_get_usec_initialized(device
, &ts
);
1914 now_ts
= now(CLOCK_MONOTONIC
);
1920 *ret
= usec_sub_unsigned(now_ts
, ts
);
1925 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1928 assert_return(device
, NULL
);
1930 (void) device_read_db(device
);
1932 device
->all_tags_iterator_generation
= device
->tags_generation
;
1933 device
->all_tags_iterator
= ITERATOR_FIRST
;
1935 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1939 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1942 assert_return(device
, NULL
);
1944 (void) device_read_db(device
);
1946 if (device
->all_tags_iterator_generation
!= device
->tags_generation
)
1949 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1953 static bool device_database_supports_current_tags(sd_device
*device
) {
1956 (void) device_read_db(device
);
1958 /* The current tags (saved in Q field) feature is implemented in database version 1.
1959 * If the database version is 0, then the tags (NOT current tags, saved in G field) are not
1960 * sticky. Thus, we can safely bypass the operations for the current tags (Q) to tags (G). */
1962 return device
->database_version
>= 1;
1965 _public_
const char *sd_device_get_current_tag_first(sd_device
*device
) {
1968 assert_return(device
, NULL
);
1970 if (!device_database_supports_current_tags(device
))
1971 return sd_device_get_tag_first(device
);
1973 (void) device_read_db(device
);
1975 device
->current_tags_iterator_generation
= device
->tags_generation
;
1976 device
->current_tags_iterator
= ITERATOR_FIRST
;
1978 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1982 _public_
const char *sd_device_get_current_tag_next(sd_device
*device
) {
1985 assert_return(device
, NULL
);
1987 if (!device_database_supports_current_tags(device
))
1988 return sd_device_get_tag_next(device
);
1990 (void) device_read_db(device
);
1992 if (device
->current_tags_iterator_generation
!= device
->tags_generation
)
1995 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1999 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
2002 assert_return(device
, NULL
);
2004 (void) device_read_db(device
);
2006 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
2007 device
->devlinks_iterator
= ITERATOR_FIRST
;
2009 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
2013 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
2016 assert_return(device
, NULL
);
2018 (void) device_read_db(device
);
2020 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
2023 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
2027 int device_properties_prepare(sd_device
*device
) {
2032 r
= device_read_uevent_file(device
);
2036 r
= device_read_db(device
);
2040 if (device
->property_devlinks_outdated
) {
2041 _cleanup_free_
char *devlinks
= NULL
;
2043 r
= set_strjoin(device
->devlinks
, " ", false, &devlinks
);
2047 if (!isempty(devlinks
)) {
2048 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
2053 device
->property_devlinks_outdated
= false;
2056 if (device
->property_tags_outdated
) {
2057 _cleanup_free_
char *tags
= NULL
;
2059 r
= set_strjoin(device
->all_tags
, ":", true, &tags
);
2063 if (!isempty(tags
)) {
2064 r
= device_add_property_internal(device
, "TAGS", tags
);
2070 r
= set_strjoin(device
->current_tags
, ":", true, &tags
);
2074 if (!isempty(tags
)) {
2075 r
= device_add_property_internal(device
, "CURRENT_TAGS", tags
);
2080 device
->property_tags_outdated
= false;
2086 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
2090 assert_return(device
, NULL
);
2092 r
= device_properties_prepare(device
);
2096 device
->properties_iterator_generation
= device
->properties_generation
;
2097 device
->properties_iterator
= ITERATOR_FIRST
;
2099 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
2103 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
2107 assert_return(device
, NULL
);
2109 r
= device_properties_prepare(device
);
2113 if (device
->properties_iterator_generation
!= device
->properties_generation
)
2116 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
2120 static int device_sysattrs_read_all_internal(sd_device
*device
, const char *subdir
, Set
**stack
) {
2121 _cleanup_closedir_
DIR *dir
= NULL
;
2127 r
= device_opendir(device
, subdir
, &dir
);
2128 if (r
== -ENOENT
&& subdir
)
2129 return 0; /* Maybe, this is a child device, and is already removed. */
2134 if (faccessat(dirfd(dir
), "uevent", F_OK
, 0) >= 0)
2135 return 0; /* this is a child device, skipping */
2136 if (errno
!= ENOENT
) {
2137 log_device_debug_errno(device
, errno
,
2138 "sd-device: Failed to access %s/uevent, ignoring sub-directory %s: %m",
2144 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
2145 _cleanup_free_
char *p
= NULL
;
2146 struct stat statbuf
;
2148 if (dot_or_dot_dot(de
->d_name
))
2151 /* only handle symlinks, regular files, and directories */
2152 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
, DT_DIR
))
2156 p
= path_join(subdir
, de
->d_name
);
2161 if (de
->d_type
== DT_DIR
) {
2162 /* push the sub-directory into the stack, and read it later. */
2164 r
= set_ensure_consume(stack
, &path_hash_ops_free
, TAKE_PTR(p
));
2166 r
= set_put_strdup_full(stack
, &path_hash_ops_free
, de
->d_name
);
2173 if (fstatat(dirfd(dir
), de
->d_name
, &statbuf
, AT_SYMLINK_NOFOLLOW
) < 0)
2176 if ((statbuf
.st_mode
& (S_IRUSR
| S_IWUSR
)) == 0)
2180 r
= set_ensure_consume(&device
->sysattrs
, &path_hash_ops_free
, TAKE_PTR(p
));
2182 r
= set_put_strdup_full(&device
->sysattrs
, &path_hash_ops_free
, de
->d_name
);
2190 static int device_sysattrs_read_all(sd_device
*device
) {
2191 _cleanup_set_free_ Set
*stack
= NULL
;
2196 if (device
->sysattrs_read
)
2199 r
= device_sysattrs_read_all_internal(device
, NULL
, &stack
);
2204 _cleanup_free_
char *subdir
= NULL
;
2206 subdir
= set_steal_first(stack
);
2210 r
= device_sysattrs_read_all_internal(device
, subdir
, &stack
);
2215 device
->sysattrs_read
= true;
2220 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
2224 assert_return(device
, NULL
);
2226 if (!device
->sysattrs_read
) {
2227 r
= device_sysattrs_read_all(device
);
2234 device
->sysattrs_iterator
= ITERATOR_FIRST
;
2236 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
2240 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
2243 assert_return(device
, NULL
);
2245 if (!device
->sysattrs_read
)
2248 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
2252 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
2253 assert_return(device
, -EINVAL
);
2254 assert_return(tag
, -EINVAL
);
2256 (void) device_read_db(device
);
2258 return set_contains(device
->all_tags
, tag
);
2261 _public_
int sd_device_has_current_tag(sd_device
*device
, const char *tag
) {
2262 assert_return(device
, -EINVAL
);
2263 assert_return(tag
, -EINVAL
);
2265 if (!device_database_supports_current_tags(device
))
2266 return sd_device_has_tag(device
, tag
);
2268 (void) device_read_db(device
);
2270 return set_contains(device
->current_tags
, tag
);
2273 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **ret_value
) {
2277 assert_return(device
, -EINVAL
);
2278 assert_return(key
, -EINVAL
);
2280 r
= device_properties_prepare(device
);
2284 value
= ordered_hashmap_get(device
->properties
, key
);
2293 int device_get_property_bool(sd_device
*device
, const char *key
) {
2300 r
= sd_device_get_property_value(device
, key
, &value
);
2304 return parse_boolean(value
);
2307 int device_get_property_int(sd_device
*device
, const char *key
, int *ret
) {
2314 r
= sd_device_get_property_value(device
, key
, &value
);
2318 r
= safe_atoi(value
, &v
);
2327 _public_
int sd_device_get_trigger_uuid(sd_device
*device
, sd_id128_t
*ret
) {
2332 assert_return(device
, -EINVAL
);
2334 /* Retrieves the UUID attached to a uevent when triggering it from userspace via
2335 * sd_device_trigger_with_uuid() or an equivalent interface. Returns -ENOENT if the record is not
2336 * caused by a synthetic event and -ENODATA if it was but no UUID was specified */
2338 r
= sd_device_get_property_value(device
, "SYNTH_UUID", &s
);
2342 if (streq(s
, "0")) /* SYNTH_UUID=0 is set whenever a device is triggered by userspace without specifying a UUID */
2345 r
= sd_id128_from_string(s
, &id
);
2355 void device_clear_sysattr_cache(sd_device
*device
) {
2356 device
->sysattr_values
= hashmap_free(device
->sysattr_values
);
2359 typedef struct SysAttrCacheEntry
{
2362 char *value_stripped
;
2365 } SysAttrCacheEntry
;
2367 static SysAttrCacheEntry
* sysattr_cache_entry_free(SysAttrCacheEntry
*p
) {
2373 free(p
->value_stripped
);
2377 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
2378 sysattr_cache_hash_ops
,
2379 char, path_hash_func
, path_compare
,
2380 SysAttrCacheEntry
, sysattr_cache_entry_free
);
2382 static int device_cache_sysattr_value_full(sd_device
*device
, char *key
, char *value
, size_t size
, int error
, bool ignore_uevent
) {
2387 assert(value
|| error
> 0);
2389 /* This takes the reference of the input arguments when cached, hence the caller must not free them
2390 * when a positive return value is returned. The input value may be NULL. This replaces an already
2391 * existing entry. */
2393 if (ignore_uevent
&& streq(last_path_component(key
), "uevent"))
2394 return 0; /* not cached */
2396 /* Remove the old cache entry. So, we do not need to clear cache on error. */
2397 sysattr_cache_entry_free(hashmap_remove(device
->sysattr_values
, key
));
2399 /* We use ENOANO as a recognizable error code when we have not read the attribute. */
2400 if (error
== ENOANO
)
2403 _cleanup_free_ SysAttrCacheEntry
*entry
= new(SysAttrCacheEntry
, 1);
2407 _cleanup_free_
char *value_stripped
= NULL
;
2410 value_stripped
= memdup_suffix0(value
, size
);
2411 if (!value_stripped
)
2413 delete_trailing_chars(value_stripped
, NEWLINE
);
2416 *entry
= (SysAttrCacheEntry
) {
2419 .value_stripped
= value_stripped
,
2424 r
= hashmap_ensure_put(&device
->sysattr_values
, &sysattr_cache_hash_ops
, entry
->key
, entry
);
2429 TAKE_PTR(value_stripped
);
2430 return 1; /* cached */
2433 int device_cache_sysattr_value(sd_device
*device
, char *key
, char *value
, int error
) {
2434 return device_cache_sysattr_value_full(device
, key
, value
, strlen(value
), error
, /* ignore_uevent = */ true);
2437 static int device_get_cached_sysattr_value(sd_device
*device
, const char *key
, const char **ret_value
, size_t *ret_size
) {
2438 SysAttrCacheEntry
*entry
;
2443 entry
= hashmap_get(device
->sysattr_values
, key
);
2445 return -ENOANO
; /* We have not read the attribute. */
2446 if (!entry
->value
) {
2447 /* We have looked up the attribute before and failed. Return the cached error code. */
2448 assert(entry
->error
> 0);
2449 return -entry
->error
;
2452 *ret_value
= ret_size
? entry
->value
: entry
->value_stripped
;
2454 *ret_size
= entry
->size
;
2458 int device_chase(sd_device
*device
, const char *path
, ChaseFlags flags
, char **ret_resolved
, int *ret_fd
) {
2464 const char *syspath
;
2465 r
= sd_device_get_syspath(device
, &syspath
);
2469 /* Here, CHASE_PREFIX_ROOT is borrowed. If the flag is set or the specified path is relative, then
2470 * the path will be prefixed with the syspath. Note, we do not pass CHASE_PREFIX_ROOT flag with
2471 * syspath as root to chase(), but we manually concatenate the specified path with syspath before
2472 * calling chase(). Otherwise, we cannot set/get attributes of parent or sibling devices. */
2473 _cleanup_free_
char *prefixed
= NULL
;
2474 if (FLAGS_SET(flags
, CHASE_PREFIX_ROOT
) || !path_is_absolute(path
)) {
2475 prefixed
= path_join(syspath
, path
);
2479 flags
&= ~CHASE_PREFIX_ROOT
;
2482 _cleanup_free_
char *resolved
= NULL
;
2483 _cleanup_close_
int fd
= -EBADF
;
2484 r
= chase(path
, /* root = */ NULL
, CHASE_NO_AUTOFS
| flags
, &resolved
, ret_fd
? &fd
: NULL
);
2488 /* Refuse to reading/writing files outside of sysfs. */
2489 if (!path_startswith(resolved
, "/sys/"))
2493 /* Always return relative path. */
2494 r
= path_make_relative(syspath
, resolved
, ret_resolved
);
2500 *ret_fd
= TAKE_FD(fd
);
2505 _public_
int sd_device_get_sysattr_value_with_size(sd_device
*device
, const char *sysattr
, const char **ret_value
, size_t *ret_size
) {
2506 _cleanup_free_
char *resolved
= NULL
, *value
= NULL
;
2507 _cleanup_close_
int fd
= -EBADF
;
2511 assert_return(device
, -EINVAL
);
2512 assert_return(sysattr
, -EINVAL
);
2514 /* Look for possibly already cached result. */
2515 r
= device_get_cached_sysattr_value(device
, sysattr
, ret_value
, ret_size
);
2519 /* Special cases: read the symlink and return the last component of the value. Some core links return
2520 * only the last element of the target path, these are just values, the paths should not be exposed. */
2521 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
2522 _cleanup_free_
char *prefixed
= NULL
;
2523 const char *syspath
;
2525 r
= sd_device_get_syspath(device
, &syspath
);
2529 prefixed
= path_join(syspath
, sysattr
);
2533 r
= readlink_value(prefixed
, &value
);
2535 size
= strlen(value
);
2537 if (r
!= -EINVAL
) /* -EINVAL means the path is not a symlink. */
2541 r
= device_chase(device
, sysattr
, CHASE_PREFIX_ROOT
, &resolved
, &fd
);
2545 /* Look for cached result again with the resolved path. */
2546 r
= device_get_cached_sysattr_value(device
, resolved
, ret_value
, ret_size
);
2550 /* Read attribute value, Some attributes contain embedded '\0'. So, it is necessary to also get the
2551 * size of the result. See issue #20025. */
2552 r
= read_virtual_file_fd(fd
, SIZE_MAX
, &value
, &size
);
2560 return r
; /* Do not cache -ENOMEM, as the failure may be transient. */
2563 /* If we have not or could not chase the path, assume 'sysattr' is normalized. */
2564 resolved
= strdup(sysattr
);
2566 return RET_GATHER(r
, -ENOMEM
);
2569 int k
= device_cache_sysattr_value_full(device
, resolved
, value
, size
, -r
, /* ignore_uevent = */ false);
2572 log_device_debug_errno(device
, k
,
2573 "sd-device: failed to cache error code (%i) in reading attribute '%s', ignoring: %m",
2576 /* Unfortunately, we need to return 'const char*' instead of 'char*'. Hence, failure in caching
2577 * sysattr value is critical unlike the other places. */
2578 log_device_debug_errno(device
, k
,
2579 "sd-device: failed to cache attribute '%s' with '%s'%s: %m",
2580 resolved
, value
, ret_value
? "" : ", ignoring");
2589 /* device_cache_sysattr_value_full() takes 'resolved' and 'value' on success. */
2590 sysattr
= TAKE_PTR(resolved
);
2596 return device_get_cached_sysattr_value(device
, sysattr
, ret_value
, ret_size
);
2599 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **ret_value
) {
2600 return sd_device_get_sysattr_value_with_size(device
, sysattr
, ret_value
, NULL
);
2603 int device_get_sysattr_int(sd_device
*device
, const char *sysattr
, int *ret_value
) {
2607 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2612 r
= safe_atoi(value
, &v
);
2614 return log_device_debug_errno(device
, r
, "Failed to parse '%s' attribute: %m", sysattr
);
2618 /* We return "true" if the value is positive. */
2622 int device_get_sysattr_unsigned_full(sd_device
*device
, const char *sysattr
, unsigned base
, unsigned *ret_value
) {
2626 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2631 r
= safe_atou_full(value
, base
, &v
);
2633 return log_device_debug_errno(device
, r
, "Failed to parse '%s' attribute: %m", sysattr
);
2637 /* We return "true" if the value is positive. */
2641 int device_get_sysattr_u32(sd_device
*device
, const char *sysattr
, uint32_t *ret_value
) {
2645 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2650 r
= safe_atou32(value
, &v
);
2652 return log_device_debug_errno(device
, r
, "Failed to parse '%s' attribute: %m", sysattr
);
2656 /* We return "true" if the value is positive. */
2660 int device_get_sysattr_bool(sd_device
*device
, const char *sysattr
) {
2667 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2671 return parse_boolean(value
);
2674 static int device_remove_cached_sysattr_value(sd_device
*device
, const char *sysattr
) {
2680 _cleanup_free_
char *resolved
= NULL
;
2681 r
= device_chase(device
, sysattr
, CHASE_PREFIX_ROOT
| CHASE_NONEXISTENT
, &resolved
, /* ret_fd = */ NULL
);
2685 sysattr_cache_entry_free(hashmap_remove(device
->sysattr_values
, resolved
));
2689 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, const char *value
) {
2692 assert_return(device
, -EINVAL
);
2693 assert_return(sysattr
, -EINVAL
);
2695 /* Set the attribute and save it in the cache. */
2698 /* If input value is NULL, then clear cache and not write anything. */
2699 return device_remove_cached_sysattr_value(device
, sysattr
);
2701 _cleanup_free_
char *resolved
= NULL
;
2702 _cleanup_close_
int fd
= -EBADF
;
2703 r
= device_chase(device
, sysattr
, CHASE_PREFIX_ROOT
, &resolved
, &fd
);
2705 /* On failure, clear cache entry, hopefully, 'sysattr' is normalized. */
2706 sysattr_cache_entry_free(hashmap_remove(device
->sysattr_values
, sysattr
));
2710 /* value length is limited to 4k */
2711 _cleanup_free_
char *copied
= strndup(value
, 4096);
2715 /* drop trailing newlines */
2716 delete_trailing_chars(copied
, NEWLINE
);
2718 r
= write_string_file_fd(fd
, copied
, WRITE_STRING_FILE_DISABLE_BUFFER
| WRITE_STRING_FILE_AVOID_NEWLINE
);
2720 /* On failure, clear cache entry, as we do not know how it fails. */
2721 sysattr_cache_entry_free(hashmap_remove(device
->sysattr_values
, resolved
));
2725 r
= device_cache_sysattr_value(device
, resolved
, copied
, 0);
2727 log_device_debug_errno(device
, r
,
2728 "sd-device: failed to cache written attribute '%s' with '%s', ignoring: %m",
2738 _public_
int sd_device_set_sysattr_valuef(sd_device
*device
, const char *sysattr
, const char *format
, ...) {
2739 _cleanup_free_
char *value
= NULL
;
2743 assert_return(device
, -EINVAL
);
2744 assert_return(sysattr
, -EINVAL
);
2747 return device_remove_cached_sysattr_value(device
, sysattr
);
2749 va_start(ap
, format
);
2750 r
= vasprintf(&value
, format
, ap
);
2756 return sd_device_set_sysattr_value(device
, sysattr
, value
);
2759 _public_
int sd_device_trigger(sd_device
*device
, sd_device_action_t action
) {
2760 return sd_device_trigger_with_uuid(device
, action
, NULL
);
2763 _public_
int sd_device_trigger_with_uuid(
2765 sd_device_action_t action
,
2766 sd_id128_t
*ret_uuid
) {
2772 assert_return(device
, -EINVAL
);
2774 s
= device_action_to_string(action
);
2778 r
= sd_id128_randomize(&u
);
2782 j
= strjoina(s
, " ", SD_ID128_TO_UUID_STRING(u
));
2784 r
= sd_device_set_sysattr_value(device
, "uevent", j
);
2793 _public_
int sd_device_open(sd_device
*device
, int flags
) {
2794 _cleanup_close_
int fd
= -EBADF
, fd2
= -EBADF
;
2795 const char *devname
;
2796 uint64_t q
, diskseq
= 0;
2801 assert_return(device
, -EINVAL
);
2802 assert_return(FLAGS_SET(flags
, O_PATH
) || !FLAGS_SET(flags
, O_NOFOLLOW
), -EINVAL
);
2804 r
= sd_device_get_devname(device
, &devname
);
2810 r
= sd_device_get_devnum(device
, &devnum
);
2816 fd
= open(devname
, FLAGS_SET(flags
, O_PATH
) ? flags
: O_CLOEXEC
|O_NOFOLLOW
|O_PATH
);
2820 if (fstat(fd
, &st
) < 0)
2823 if (st
.st_rdev
!= devnum
)
2826 r
= device_in_subsystem(device
, "block");
2829 if (r
> 0 ? !S_ISBLK(st
.st_mode
) : !S_ISCHR(st
.st_mode
))
2832 /* If flags has O_PATH, then we cannot check diskseq. Let's return earlier. */
2833 if (FLAGS_SET(flags
, O_PATH
))
2836 /* If the device is not initialized, then we cannot determine if we should check diskseq through
2837 * ID_IGNORE_DISKSEQ property. Let's skip to check diskseq in that case. */
2838 r
= sd_device_get_is_initialized(device
);
2842 r
= device_get_property_bool(device
, "ID_IGNORE_DISKSEQ");
2843 if (r
< 0 && r
!= -ENOENT
)
2846 r
= sd_device_get_diskseq(device
, &diskseq
);
2847 if (r
< 0 && r
!= -ENOENT
)
2852 fd2
= fd_reopen(fd
, flags
);
2857 return TAKE_FD(fd2
);
2859 r
= fd_get_diskseq(fd2
, &q
);
2866 return TAKE_FD(fd2
);
2869 int device_opendir(sd_device
*device
, const char *subdir
, DIR **ret
) {
2870 _cleanup_closedir_
DIR *d
= NULL
;
2871 _cleanup_free_
char *path
= NULL
;
2872 const char *syspath
;
2878 r
= sd_device_get_syspath(device
, &syspath
);
2883 if (!path_is_safe(subdir
))
2886 path
= path_join(syspath
, subdir
);
2891 d
= opendir(path
?: syspath
);