1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
10 #include "alloc-util.h"
12 #include "device-internal.h"
13 #include "device-private.h"
14 #include "device-util.h"
15 #include "devnum-util.h"
16 #include "dirent-util.h"
20 #include "format-util.h"
23 #include "id128-util.h"
25 #include "missing_magic.h"
26 #include "netlink-util.h"
27 #include "parse-util.h"
28 #include "path-util.h"
30 #include "socket-util.h"
31 #include "stdio-util.h"
32 #include "string-util.h"
35 #include "user-util.h"
37 int device_new_aux(sd_device
**ret
) {
42 device
= new(sd_device
, 1);
46 *device
= (sd_device
) {
48 .devmode
= MODE_INVALID
,
49 .devuid
= UID_INVALID
,
50 .devgid
= GID_INVALID
,
51 .action
= _SD_DEVICE_ACTION_INVALID
,
58 static sd_device
*device_free(sd_device
*device
) {
61 sd_device_unref(device
->parent
);
62 free(device
->syspath
);
63 free(device
->sysname
);
64 free(device
->devtype
);
65 free(device
->devname
);
66 free(device
->subsystem
);
67 free(device
->driver_subsystem
);
69 free(device
->device_id
);
70 free(device
->properties_strv
);
71 free(device
->properties_nulstr
);
73 ordered_hashmap_free(device
->properties
);
74 ordered_hashmap_free(device
->properties_db
);
75 hashmap_free(device
->sysattr_values
);
76 set_free(device
->sysattrs
);
77 set_free(device
->all_tags
);
78 set_free(device
->current_tags
);
79 set_free(device
->devlinks
);
80 hashmap_free(device
->children
);
85 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device
, sd_device
, device_free
);
87 int device_add_property_aux(sd_device
*device
, const char *key
, const char *value
, bool db
) {
88 OrderedHashmap
**properties
;
94 properties
= &device
->properties_db
;
96 properties
= &device
->properties
;
99 _unused_ _cleanup_free_
char *old_value
= NULL
;
100 _cleanup_free_
char *new_key
= NULL
, *new_value
= NULL
, *old_key
= NULL
;
103 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops_free_free
);
107 new_key
= strdup(key
);
111 new_value
= strdup(value
);
115 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
117 /* ordered_hashmap_replace() does not fail when the hashmap already has the entry. */
118 r
= ordered_hashmap_replace(*properties
, new_key
, new_value
);
125 _unused_ _cleanup_free_
char *old_value
= NULL
;
126 _cleanup_free_
char *old_key
= NULL
;
128 old_value
= ordered_hashmap_remove2(*properties
, key
, (void**) &old_key
);
132 device
->properties_generation
++;
133 device
->properties_buf_outdated
= true;
139 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
140 _cleanup_free_
char *syspath
= NULL
;
148 _cleanup_close_
int fd
= -EBADF
;
150 /* The input path maybe a symlink located outside of /sys. Let's try to chase the symlink at first.
151 * The primary use case is that e.g. /proc/device-tree is a symlink to /sys/firmware/devicetree/base.
152 * By chasing symlinks in the path at first, we can call sd_device_new_from_path() with such path. */
153 r
= chase(_syspath
, NULL
, 0, &syspath
, &fd
);
155 /* the device does not exist (any more?) */
156 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
157 "sd-device: Failed to chase symlinks in \"%s\".", _syspath
);
159 return log_debug_errno(r
, "sd-device: Failed to get target of '%s': %m", _syspath
);
161 if (!path_startswith(syspath
, "/sys")) {
162 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
165 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
166 r
= chase("/sys", NULL
, 0, &real_sys
, NULL
);
168 return log_debug_errno(r
, "sd-device: Failed to chase symlink /sys: %m");
170 p
= path_startswith(syspath
, real_sys
);
172 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
173 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
176 new_syspath
= path_join("/sys", p
);
178 return log_oom_debug();
180 free_and_replace(syspath
, new_syspath
);
181 path_simplify(syspath
);
184 if (path_startswith(syspath
, "/sys/devices/")) {
185 /* For proper devices, stricter rules apply: they must have a 'uevent' file,
186 * otherwise we won't allow them */
188 if (faccessat(fd
, "uevent", F_OK
, 0) < 0) {
190 /* This is not a valid device. Note, this condition is quite often
191 * satisfied when enumerating devices or finding a parent device.
192 * Hence, use log_trace_errno() here. */
193 return log_trace_errno(SYNTHETIC_ERRNO(ENODEV
),
194 "sd-device: the uevent file \"%s/uevent\" does not exist.", syspath
);
195 if (errno
== ENOTDIR
)
196 /* Not actually a directory. */
197 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
198 "sd-device: the syspath \"%s\" is not a directory.", syspath
);
200 return log_debug_errno(errno
, "sd-device: cannot find uevent file for %s: %m", syspath
);
205 /* For everything else lax rules apply: they just need to be a directory */
207 if (fstat(fd
, &st
) < 0)
208 return log_debug_errno(errno
, "sd-device: failed to check if syspath \"%s\" is a directory: %m", syspath
);
209 if (!S_ISDIR(st
.st_mode
))
210 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
211 "sd-device: the syspath \"%s\" is not a directory.", syspath
);
214 /* Only operate on sysfs, i.e. refuse going down into /sys/fs/cgroup/ or similar places where
215 * things are not arranged as kobjects in kernel, and hence don't necessarily have
216 * kobject/attribute structure. */
217 r
= getenv_bool_secure("SYSTEMD_DEVICE_VERIFY_SYSFS");
218 if (r
< 0 && r
!= -ENXIO
)
219 log_debug_errno(r
, "Failed to parse $SYSTEMD_DEVICE_VERIFY_SYSFS value: %m");
221 r
= fd_is_fs_type(fd
, SYSFS_MAGIC
);
223 return log_debug_errno(r
, "sd-device: failed to check if syspath \"%s\" is backed by sysfs.", syspath
);
225 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
226 "sd-device: the syspath \"%s\" is outside of sysfs, refusing.", syspath
);
229 /* must be a subdirectory of /sys */
230 if (!path_startswith(_syspath
, "/sys/"))
231 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
232 "sd-device: Syspath '%s' is not a subdirectory of /sys",
235 r
= path_simplify_alloc(_syspath
, &syspath
);
240 assert_se(devpath
= startswith(syspath
, "/sys"));
241 if (devpath
[0] != '/')
242 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
), "sd-device: \"/sys\" alone is not a valid device path.");
244 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
246 return log_debug_errno(r
, "sd-device: Failed to add \"DEVPATH\" property for device \"%s\": %m", syspath
);
248 free_and_replace(device
->syspath
, syspath
);
249 device
->devpath
= devpath
;
251 /* Unset sysname and sysnum, they will be assigned when requested. */
252 device
->sysnum
= NULL
;
253 device
->sysname
= mfree(device
->sysname
);
257 static int device_new_from_syspath(sd_device
**ret
, const char *syspath
, bool strict
) {
258 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
261 assert_return(ret
, -EINVAL
);
262 assert_return(syspath
, -EINVAL
);
264 if (strict
&& !path_startswith(syspath
, "/sys/"))
267 r
= device_new_aux(&device
);
271 r
= device_set_syspath(device
, syspath
, /* verify= */ true);
275 *ret
= TAKE_PTR(device
);
279 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
280 return device_new_from_syspath(ret
, syspath
, /* strict = */ true);
283 int device_new_from_mode_and_devnum(sd_device
**ret
, mode_t mode
, dev_t devnum
) {
284 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
285 _cleanup_free_
char *syspath
= NULL
;
286 const char *t
, *subsystem
= NULL
;
294 else if (S_ISBLK(mode
))
299 if (major(devnum
) == 0)
302 if (asprintf(&syspath
, "/sys/dev/%s/" DEVNUM_FORMAT_STR
, t
, DEVNUM_FORMAT_VAL(devnum
)) < 0)
305 r
= sd_device_new_from_syspath(&dev
, syspath
);
309 r
= sd_device_get_devnum(dev
, &n
);
317 r
= sd_device_get_subsystem(dev
, &subsystem
);
318 if (r
< 0 && r
!= -ENOENT
)
320 if (streq_ptr(subsystem
, "block") != !!S_ISBLK(mode
))
323 *ret
= TAKE_PTR(dev
);
327 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
328 assert_return(ret
, -EINVAL
);
329 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
331 return device_new_from_mode_and_devnum(ret
, type
== 'b' ? S_IFBLK
: S_IFCHR
, devnum
);
334 static int device_new_from_main_ifname(sd_device
**ret
, const char *ifname
) {
340 syspath
= strjoina("/sys/class/net/", ifname
);
341 return sd_device_new_from_syspath(ret
, syspath
);
344 _public_
int sd_device_new_from_ifname(sd_device
**ret
, const char *ifname
) {
345 _cleanup_free_
char *main_name
= NULL
;
348 assert_return(ret
, -EINVAL
);
349 assert_return(ifname
, -EINVAL
);
351 r
= parse_ifindex(ifname
);
353 return sd_device_new_from_ifindex(ret
, r
);
355 if (ifname_valid(ifname
)) {
356 r
= device_new_from_main_ifname(ret
, ifname
);
361 r
= rtnl_resolve_link_alternative_name(NULL
, ifname
, &main_name
);
365 return device_new_from_main_ifname(ret
, main_name
);
368 _public_
int sd_device_new_from_ifindex(sd_device
**ret
, int ifindex
) {
369 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
370 char ifname
[IF_NAMESIZE
];
373 assert_return(ret
, -EINVAL
);
374 assert_return(ifindex
> 0, -EINVAL
);
376 if (format_ifname(ifindex
, ifname
) < 0)
379 r
= device_new_from_main_ifname(&dev
, ifname
);
383 r
= sd_device_get_ifindex(dev
, &i
);
391 *ret
= TAKE_PTR(dev
);
395 static int device_strjoin_new(
405 p
= strjoina(a
, b
, c
, d
);
406 if (access(p
, F_OK
) < 0)
407 return IN_SET(errno
, ENOENT
, ENAMETOOLONG
) ? 0 : -errno
; /* If this sysfs is too long then it doesn't exist either */
409 r
= sd_device_new_from_syspath(ret
, p
);
416 _public_
int sd_device_new_from_subsystem_sysname(
418 const char *subsystem
,
419 const char *sysname
) {
424 assert_return(ret
, -EINVAL
);
425 assert_return(path_is_normalized(subsystem
), -EINVAL
);
426 assert_return(path_is_normalized(sysname
), -EINVAL
);
428 /* translate sysname back to sysfs filename */
429 name
= strdupa_safe(sysname
);
430 string_replace_char(name
, '/', '!');
432 if (streq(subsystem
, "subsystem")) {
433 FOREACH_STRING(s
, "/sys/bus/", "/sys/class/") {
434 r
= device_strjoin_new(s
, name
, NULL
, NULL
, ret
);
441 } else if (streq(subsystem
, "module")) {
442 r
= device_strjoin_new("/sys/module/", name
, NULL
, NULL
, ret
);
448 } else if (streq(subsystem
, "drivers")) {
451 sep
= strchr(name
, ':');
452 if (sep
&& sep
[1] != '\0') { /* Require ":" and something non-empty after that. */
454 const char *subsys
= memdupa_suffix0(name
, sep
- name
);
457 if (streq(sep
, "drivers")) /* If the sysname is "drivers", then it's the drivers directory itself that is meant. */
458 r
= device_strjoin_new("/sys/bus/", subsys
, "/drivers", NULL
, ret
);
460 r
= device_strjoin_new("/sys/bus/", subsys
, "/drivers/", sep
, ret
);
468 r
= device_strjoin_new("/sys/bus/", subsystem
, "/devices/", name
, ret
);
474 r
= device_strjoin_new("/sys/class/", subsystem
, "/", name
, ret
);
480 r
= device_strjoin_new("/sys/firmware/", subsystem
, "/", name
, ret
);
489 _public_
int sd_device_new_from_stat_rdev(sd_device
**ret
, const struct stat
*st
) {
490 assert_return(ret
, -EINVAL
);
491 assert_return(st
, -EINVAL
);
493 return device_new_from_mode_and_devnum(ret
, st
->st_mode
, st
->st_rdev
);
496 _public_
int sd_device_new_from_devname(sd_device
**ret
, const char *devname
) {
501 assert_return(ret
, -EINVAL
);
502 assert_return(devname
, -EINVAL
);
504 /* This function actually accepts both devlinks and devnames, i.e. both symlinks and device
505 * nodes below /dev/. */
507 /* Also ignore when the specified path is "/dev". */
508 if (isempty(path_startswith(devname
, "/dev")))
511 if (device_path_parse_major_minor(devname
, &mode
, &devnum
) >= 0)
512 /* Let's shortcut when "/dev/block/maj:min" or "/dev/char/maj:min" is specified.
513 * In that case, we can directly convert the path to syspath, hence it is not necessary
514 * that the specified path exists. So, this works fine without udevd being running. */
515 return device_new_from_mode_and_devnum(ret
, mode
, devnum
);
517 if (stat(devname
, &st
) < 0)
518 return ERRNO_IS_DEVICE_ABSENT(errno
) ? -ENODEV
: -errno
;
520 return sd_device_new_from_stat_rdev(ret
, &st
);
523 _public_
int sd_device_new_from_path(sd_device
**ret
, const char *path
) {
524 assert_return(ret
, -EINVAL
);
525 assert_return(path
, -EINVAL
);
527 if (path_startswith(path
, "/dev"))
528 return sd_device_new_from_devname(ret
, path
);
530 return device_new_from_syspath(ret
, path
, /* strict = */ false);
533 int device_set_devtype(sd_device
*device
, const char *devtype
) {
534 _cleanup_free_
char *t
= NULL
;
544 r
= device_add_property_internal(device
, "DEVTYPE", t
);
548 return free_and_replace(device
->devtype
, t
);
551 int device_set_ifindex(sd_device
*device
, const char *name
) {
557 ifindex
= parse_ifindex(name
);
561 r
= device_add_property_internal(device
, "IFINDEX", name
);
565 device
->ifindex
= ifindex
;
570 static int mangle_devname(const char *p
, char **ret
) {
576 if (!path_is_safe(p
))
579 /* When the path is absolute, it must start with "/dev/", but ignore "/dev/" itself. */
580 if (path_is_absolute(p
)) {
581 if (isempty(path_startswith(p
, "/dev/")))
586 q
= path_join("/dev/", p
);
596 int device_set_devname(sd_device
*device
, const char *devname
) {
597 _cleanup_free_
char *t
= NULL
;
603 r
= mangle_devname(devname
, &t
);
607 r
= device_add_property_internal(device
, "DEVNAME", t
);
611 return free_and_replace(device
->devname
, t
);
614 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
621 r
= safe_atou(_devmode
, &devmode
);
628 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
632 device
->devmode
= devmode
;
637 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
638 unsigned maj
, min
= 0;
644 r
= safe_atou(major
, &maj
);
649 if (!DEVICE_MAJOR_VALID(maj
))
653 r
= safe_atou(minor
, &min
);
656 if (!DEVICE_MINOR_VALID(min
))
660 r
= device_add_property_internal(device
, "MAJOR", major
);
665 r
= device_add_property_internal(device
, "MINOR", minor
);
670 device
->devnum
= makedev(maj
, min
);
675 int device_set_diskseq(sd_device
*device
, const char *str
) {
682 r
= safe_atou64(str
, &diskseq
);
688 r
= device_add_property_internal(device
, "DISKSEQ", str
);
692 device
->diskseq
= diskseq
;
697 static int handle_uevent_line(
702 const char **minor
) {
710 if (streq(key
, "DEVTYPE"))
711 return device_set_devtype(device
, value
);
712 if (streq(key
, "IFINDEX"))
713 return device_set_ifindex(device
, value
);
714 if (streq(key
, "DEVNAME"))
715 return device_set_devname(device
, value
);
716 if (streq(key
, "DEVMODE"))
717 return device_set_devmode(device
, value
);
718 if (streq(key
, "DISKSEQ"))
719 return device_set_diskseq(device
, value
);
720 if (streq(key
, "MAJOR"))
722 else if (streq(key
, "MINOR"))
725 return device_add_property_internal(device
, key
, value
);
730 int device_read_uevent_file(sd_device
*device
) {
731 _cleanup_free_
char *uevent
= NULL
;
732 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
747 if (device
->uevent_loaded
|| device
->sealed
)
750 r
= sd_device_get_syspath(device
, &syspath
);
754 device
->uevent_loaded
= true;
756 path
= strjoina(syspath
, "/uevent");
758 r
= read_full_virtual_file(path
, &uevent
, &uevent_len
);
759 if (r
== -EACCES
|| ERRNO_IS_NEG_DEVICE_ABSENT(r
))
760 /* The uevent files may be write-only, the device may be already removed, or the device
761 * may not have the uevent file. */
764 return log_device_debug_errno(device
, r
, "sd-device: Failed to read uevent file '%s': %m", path
);
766 for (size_t i
= 0; i
< uevent_len
; i
++)
769 if (!strchr(NEWLINE
, uevent
[i
])) {
777 if (uevent
[i
] == '=') {
781 } else if (strchr(NEWLINE
, uevent
[i
])) {
783 log_device_debug(device
, "sd-device: Invalid uevent line '%s', ignoring", key
);
793 _fallthrough_
; /* to handle empty property */
795 if (strchr(NEWLINE
, uevent
[i
])) {
798 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
800 log_device_debug_errno(device
, r
, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key
, value
);
807 assert_not_reached();
811 r
= device_set_devnum(device
, major
, minor
);
813 log_device_debug_errno(device
, r
, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major
, strna(minor
), path
);
819 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
822 assert_return(device
, -EINVAL
);
824 r
= device_read_uevent_file(device
);
828 if (device
->ifindex
<= 0)
832 *ifindex
= device
->ifindex
;
837 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
840 assert_return(ret
, -EINVAL
);
841 assert_return(id
, -EINVAL
);
851 r
= parse_devnum(id
+ 1, &devt
);
855 return sd_device_new_from_devnum(ret
, id
[0], devt
);
861 ifindex
= parse_ifindex(id
+ 1);
865 return sd_device_new_from_ifindex(ret
, ifindex
);
869 const char *subsys
, *sep
;
871 sep
= strchr(id
+ 1, ':');
872 if (!sep
|| sep
- id
- 1 > NAME_MAX
)
875 subsys
= memdupa_suffix0(id
+ 1, sep
- id
- 1);
877 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sep
+ 1);
885 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
886 assert_return(device
, -EINVAL
);
888 assert(path_startswith(device
->syspath
, "/sys/"));
891 *ret
= device
->syspath
;
896 DEFINE_PRIVATE_HASH_OPS_FULL(
897 device_by_path_hash_ops
,
898 char, path_hash_func
, path_compare
, free
,
899 sd_device
, sd_device_unref
);
901 static int device_enumerate_children_internal(sd_device
*device
, const char *subdir
, Set
**stack
, Hashmap
**children
) {
902 _cleanup_closedir_
DIR *dir
= NULL
;
909 r
= device_opendir(device
, subdir
, &dir
);
913 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
914 _cleanup_(sd_device_unrefp
) sd_device
*child
= NULL
;
915 _cleanup_free_
char *p
= NULL
;
917 if (dot_or_dot_dot(de
->d_name
))
920 if (!IN_SET(de
->d_type
, DT_LNK
, DT_DIR
))
924 p
= path_join(subdir
, de
->d_name
);
926 p
= strdup(de
->d_name
);
930 /* Try to create child device. */
931 r
= sd_device_new_child(&child
, device
, p
);
933 /* OK, this is a child device, saving it. */
934 r
= hashmap_ensure_put(children
, &device_by_path_hash_ops
, p
, child
);
940 } else if (r
== -ENODEV
) {
941 /* This is not a child device. Push the sub-directory into stack, and read it later. */
943 if (de
->d_type
== DT_LNK
)
944 /* Do not follow symlinks, otherwise, we will enter an infinite loop, e.g.,
945 * /sys/class/block/nvme0n1/subsystem/nvme0n1/subsystem/nvme0n1/subsystem/… */
948 r
= set_ensure_consume(stack
, &path_hash_ops_free
, TAKE_PTR(p
));
958 static int device_enumerate_children(sd_device
*device
) {
959 _cleanup_hashmap_free_ Hashmap
*children
= NULL
;
960 _cleanup_set_free_ Set
*stack
= NULL
;
965 if (device
->children_enumerated
)
966 return 0; /* Already enumerated. */
968 r
= device_enumerate_children_internal(device
, NULL
, &stack
, &children
);
973 _cleanup_free_
char *subdir
= NULL
;
975 subdir
= set_steal_first(stack
);
979 r
= device_enumerate_children_internal(device
, subdir
, &stack
, &children
);
984 device
->children_enumerated
= true;
985 device
->children
= TAKE_PTR(children
);
986 return 1; /* Enumerated. */
989 _public_ sd_device
*sd_device_get_child_first(sd_device
*device
, const char **ret_suffix
) {
994 r
= device_enumerate_children(device
);
996 log_device_debug_errno(device
, r
, "sd-device: failed to enumerate child devices: %m");
1002 device
->children_iterator
= ITERATOR_FIRST
;
1004 return sd_device_get_child_next(device
, ret_suffix
);
1007 _public_ sd_device
*sd_device_get_child_next(sd_device
*device
, const char **ret_suffix
) {
1012 (void) hashmap_iterate(device
->children
, &device
->children_iterator
, (void**) &child
, (const void**) ret_suffix
);
1016 _public_
int sd_device_new_child(sd_device
**ret
, sd_device
*device
, const char *suffix
) {
1017 _cleanup_free_
char *path
= NULL
;
1022 assert_return(ret
, -EINVAL
);
1023 assert_return(device
, -EINVAL
);
1024 assert_return(suffix
, -EINVAL
);
1026 if (!path_is_safe(suffix
))
1029 /* If we have already enumerated children, try to find the child from the cache. */
1030 child
= hashmap_get(device
->children
, suffix
);
1032 *ret
= sd_device_ref(child
);
1036 r
= sd_device_get_syspath(device
, &s
);
1040 path
= path_join(s
, suffix
);
1044 return sd_device_new_from_syspath(ret
, path
);
1047 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
1048 _cleanup_free_
char *path
= NULL
;
1049 const char *syspath
;
1055 r
= sd_device_get_syspath(child
, &syspath
);
1060 _cleanup_free_
char *p
= NULL
;
1062 r
= path_extract_directory(path
?: syspath
, &p
);
1066 if (path_equal(p
, "/sys"))
1069 r
= sd_device_new_from_syspath(ret
, p
);
1073 free_and_replace(path
, p
);
1077 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
1080 assert_return(child
, -EINVAL
);
1082 if (!child
->parent_set
) {
1083 r
= device_new_from_child(&child
->parent
, child
);
1084 if (r
< 0 && r
!= -ENODEV
)
1087 child
->parent_set
= true;
1094 *ret
= child
->parent
;
1098 int device_set_subsystem(sd_device
*device
, const char *subsystem
) {
1099 _cleanup_free_
char *s
= NULL
;
1105 s
= strdup(subsystem
);
1110 r
= device_add_property_internal(device
, "SUBSYSTEM", s
);
1114 device
->subsystem_set
= true;
1115 return free_and_replace(device
->subsystem
, s
);
1118 int device_set_drivers_subsystem(sd_device
*device
) {
1119 _cleanup_free_
char *subsystem
= NULL
;
1120 const char *devpath
, *drivers
, *p
;
1125 r
= sd_device_get_devpath(device
, &devpath
);
1129 drivers
= strstr(devpath
, "/drivers/");
1131 drivers
= endswith(devpath
, "/drivers");
1135 /* Find the path component immediately before the "/drivers/" string */
1136 r
= path_find_last_component(devpath
, /* accept_dot_dot= */ false, &drivers
, &p
);
1142 subsystem
= strndup(p
, r
);
1146 r
= device_set_subsystem(device
, "drivers");
1150 return free_and_replace(device
->driver_subsystem
, subsystem
);
1153 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
1156 assert_return(device
, -EINVAL
);
1158 if (!device
->subsystem_set
) {
1159 _cleanup_free_
char *subsystem
= NULL
;
1160 const char *syspath
;
1163 r
= sd_device_get_syspath(device
, &syspath
);
1167 /* read 'subsystem' link */
1168 path
= strjoina(syspath
, "/subsystem");
1169 r
= readlink_value(path
, &subsystem
);
1170 if (r
< 0 && r
!= -ENOENT
)
1171 return log_device_debug_errno(device
, r
,
1172 "sd-device: Failed to read subsystem for %s: %m",
1176 r
= device_set_subsystem(device
, subsystem
);
1177 /* use implicit names */
1178 else if (!isempty(path_startswith(device
->devpath
, "/module/")))
1179 r
= device_set_subsystem(device
, "module");
1180 else if (strstr(syspath
, "/drivers/") || endswith(syspath
, "/drivers"))
1181 r
= device_set_drivers_subsystem(device
);
1182 else if (!isempty(PATH_STARTSWITH_SET(device
->devpath
, "/class/", "/bus/")))
1183 r
= device_set_subsystem(device
, "subsystem");
1185 device
->subsystem_set
= true;
1189 return log_device_debug_errno(device
, r
,
1190 "sd-device: Failed to set subsystem for %s: %m",
1194 if (!device
->subsystem
)
1198 *ret
= device
->subsystem
;
1202 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
1205 assert_return(device
, -EINVAL
);
1207 r
= device_read_uevent_file(device
);
1211 if (!device
->devtype
)
1215 *devtype
= device
->devtype
;
1217 return !!device
->devtype
;
1220 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
1221 sd_device
*parent
= NULL
;
1224 assert_return(child
, -EINVAL
);
1225 assert_return(subsystem
, -EINVAL
);
1227 r
= sd_device_get_parent(child
, &parent
);
1229 const char *parent_subsystem
= NULL
;
1231 (void) sd_device_get_subsystem(parent
, &parent_subsystem
);
1232 if (streq_ptr(parent_subsystem
, subsystem
)) {
1233 const char *parent_devtype
= NULL
;
1238 (void) sd_device_get_devtype(parent
, &parent_devtype
);
1239 if (streq_ptr(parent_devtype
, devtype
))
1242 r
= sd_device_get_parent(parent
, &parent
);
1253 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
1256 assert_return(device
, -EINVAL
);
1258 r
= device_read_uevent_file(device
);
1262 if (major(device
->devnum
) <= 0)
1266 *devnum
= device
->devnum
;
1271 int device_set_driver(sd_device
*device
, const char *driver
) {
1272 _cleanup_free_
char *d
= NULL
;
1283 r
= device_add_property_internal(device
, "DRIVER", d
);
1287 device
->driver_set
= true;
1288 return free_and_replace(device
->driver
, d
);
1291 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
1292 assert_return(device
, -EINVAL
);
1294 if (!device
->driver_set
) {
1295 _cleanup_free_
char *driver
= NULL
;
1296 const char *syspath
;
1300 r
= sd_device_get_syspath(device
, &syspath
);
1304 path
= strjoina(syspath
, "/driver");
1305 r
= readlink_value(path
, &driver
);
1306 if (r
< 0 && r
!= -ENOENT
)
1307 return log_device_debug_errno(device
, r
,
1308 "sd-device: readlink(\"%s\") failed: %m", path
);
1310 r
= device_set_driver(device
, driver
);
1312 return log_device_debug_errno(device
, r
,
1313 "sd-device: Failed to set driver \"%s\": %m", driver
);
1316 if (!device
->driver
)
1320 *ret
= device
->driver
;
1324 _public_
int sd_device_get_devpath(sd_device
*device
, const char **ret
) {
1325 assert_return(device
, -EINVAL
);
1327 assert(device
->devpath
);
1328 assert(device
->devpath
[0] == '/');
1331 *ret
= device
->devpath
;
1336 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
1339 assert_return(device
, -EINVAL
);
1341 r
= device_read_uevent_file(device
);
1345 if (!device
->devname
)
1348 assert(!isempty(path_startswith(device
->devname
, "/dev/")));
1351 *devname
= device
->devname
;
1355 static int device_set_sysname_and_sysnum(sd_device
*device
) {
1356 _cleanup_free_
char *sysname
= NULL
;
1362 r
= path_extract_filename(device
->devpath
, &sysname
);
1365 if (r
== O_DIRECTORY
)
1368 /* some devices have '!' in their name, change that to '/' */
1369 string_replace_char(sysname
, '!', '/');
1371 n
= strspn_from_end(sysname
, DIGITS
);
1372 len
= strlen(sysname
);
1375 n
= 0; /* Do not set sysnum for number only sysname. */
1377 device
->sysnum
= n
> 0 ? sysname
+ len
- n
: NULL
;
1378 return free_and_replace(device
->sysname
, sysname
);
1381 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1384 assert_return(device
, -EINVAL
);
1386 if (!device
->sysname
) {
1387 r
= device_set_sysname_and_sysnum(device
);
1393 *ret
= device
->sysname
;
1397 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1400 assert_return(device
, -EINVAL
);
1402 if (!device
->sysname
) {
1403 r
= device_set_sysname_and_sysnum(device
);
1408 if (!device
->sysnum
)
1412 *ret
= device
->sysnum
;
1416 _public_
int sd_device_get_action(sd_device
*device
, sd_device_action_t
*ret
) {
1417 assert_return(device
, -EINVAL
);
1419 if (device
->action
< 0)
1423 *ret
= device
->action
;
1428 _public_
int sd_device_get_seqnum(sd_device
*device
, uint64_t *ret
) {
1429 assert_return(device
, -EINVAL
);
1431 if (device
->seqnum
== 0)
1435 *ret
= device
->seqnum
;
1440 _public_
int sd_device_get_diskseq(sd_device
*device
, uint64_t *ret
) {
1443 assert_return(device
, -EINVAL
);
1445 r
= device_read_uevent_file(device
);
1449 if (device
->diskseq
== 0)
1453 *ret
= device
->diskseq
;
1458 static bool is_valid_tag(const char *tag
) {
1461 return in_charset(tag
, ALPHANUMERICAL
"-_") && filename_is_valid(tag
);
1464 int device_add_tag(sd_device
*device
, const char *tag
, bool both
) {
1470 if (!is_valid_tag(tag
))
1473 /* Definitely add to the "all" list of tags (i.e. the sticky list) */
1474 added
= set_put_strdup(&device
->all_tags
, tag
);
1478 /* And optionally, also add it to the current list of tags */
1480 r
= set_put_strdup(&device
->current_tags
, tag
);
1483 (void) set_remove(device
->all_tags
, tag
);
1489 device
->tags_generation
++;
1490 device
->property_tags_outdated
= true;
1495 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1502 r
= mangle_devname(devlink
, &p
);
1506 r
= set_ensure_consume(&device
->devlinks
, &path_hash_ops_free
, p
);
1510 device
->devlinks_generation
++;
1511 device
->property_devlinks_outdated
= true;
1513 return r
; /* return 1 when newly added, 0 when already exists */
1516 int device_remove_devlink(sd_device
*device
, const char *devlink
) {
1517 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
1523 r
= mangle_devname(devlink
, &p
);
1527 s
= set_remove(device
->devlinks
, p
);
1529 return 0; /* does not exist */
1531 device
->devlinks_generation
++;
1532 device
->property_devlinks_outdated
= true;
1533 return 1; /* removed */
1536 bool device_has_devlink(sd_device
*device
, const char *devlink
) {
1540 return set_contains(device
->devlinks
, devlink
);
1543 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1544 _cleanup_free_
char *key
= NULL
;
1555 value
= strchr(key
, '=');
1561 if (isempty(++value
))
1564 /* Add the property to both sd_device::properties and sd_device::properties_db,
1565 * as this is called by only handle_db_line(). */
1566 r
= device_add_property_aux(device
, key
, value
, false);
1570 return device_add_property_aux(device
, key
, value
, true);
1573 int device_set_usec_initialized(sd_device
*device
, usec_t when
) {
1574 char s
[DECIMAL_STR_MAX(usec_t
)];
1579 xsprintf(s
, USEC_FMT
, when
);
1581 r
= device_add_property_internal(device
, "USEC_INITIALIZED", s
);
1585 device
->usec_initialized
= when
;
1589 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1596 case 'G': /* Any tag */
1597 case 'Q': /* Current tag */
1598 return device_add_tag(device
, value
, key
== 'Q');
1603 path
= strjoina("/dev/", value
);
1604 return device_add_devlink(device
, path
);
1607 return device_add_property_internal_from_string(device
, value
);
1612 r
= safe_atou64(value
, &t
);
1616 return device_set_usec_initialized(device
, t
);
1619 return safe_atoi(value
, &device
->devlink_priority
);
1622 /* Deprecated. Previously, watch handle is both saved in database and /run/udev/watch.
1623 * However, the handle saved in database may not be updated when the handle is updated
1624 * or removed. Moreover, it is not necessary to store the handle within the database,
1625 * as its value becomes meaningless when udevd is restarted. */
1629 return safe_atou(value
, &device
->database_version
);
1632 log_device_debug(device
, "sd-device: Unknown key '%c' in device db, ignoring", key
);
1637 int device_get_device_id(sd_device
*device
, const char **ret
) {
1641 if (!device
->device_id
) {
1642 _cleanup_free_
char *id
= NULL
;
1643 const char *subsystem
;
1647 r
= sd_device_get_subsystem(device
, &subsystem
);
1651 if (sd_device_get_devnum(device
, &devnum
) >= 0) {
1652 /* use dev_t — b259:131072, c254:0 */
1653 if (asprintf(&id
, "%c" DEVNUM_FORMAT_STR
,
1654 streq(subsystem
, "block") ? 'b' : 'c',
1655 DEVNUM_FORMAT_VAL(devnum
)) < 0)
1657 } else if (sd_device_get_ifindex(device
, &ifindex
) >= 0) {
1658 /* use netdev ifindex — n3 */
1659 if (asprintf(&id
, "n%u", (unsigned) ifindex
) < 0)
1662 _cleanup_free_
char *sysname
= NULL
;
1664 /* use $subsys:$sysname — pci:0000:00:1f.2
1665 * sd_device_get_sysname() has '!' translated, get it from devpath */
1666 r
= path_extract_filename(device
->devpath
, &sysname
);
1669 if (r
== O_DIRECTORY
)
1672 if (streq(subsystem
, "drivers")) {
1673 /* the 'drivers' pseudo-subsystem is special, and needs the real
1674 * subsystem encoded as well */
1675 assert(device
->driver_subsystem
);
1676 id
= strjoin("+drivers:", device
->driver_subsystem
, ":", sysname
);
1678 id
= strjoin("+", subsystem
, ":", sysname
);
1683 if (!filename_is_valid(id
))
1686 device
->device_id
= TAKE_PTR(id
);
1689 *ret
= device
->device_id
;
1693 int device_read_db_internal_filename(sd_device
*device
, const char *filename
) {
1694 _cleanup_free_
char *db
= NULL
;
1697 char key
= '\0'; /* Unnecessary initialization to appease gcc-12.0.0-0.4.fc36 */
1711 r
= read_full_file(filename
, &db
, &db_len
);
1716 return log_device_debug_errno(device
, r
, "sd-device: Failed to read db '%s': %m", filename
);
1719 /* devices with a database entry are initialized */
1720 device
->is_initialized
= true;
1722 device
->db_loaded
= true;
1724 for (size_t i
= 0; i
< db_len
; i
++)
1727 if (!strchr(NEWLINE
, db
[i
])) {
1736 log_device_debug(device
, "sd-device: Invalid db entry with key '%c', ignoring", key
);
1738 state
= INVALID_LINE
;
1753 if (strchr(NEWLINE
, db
[i
]))
1758 if (strchr(NEWLINE
, db
[i
])) {
1760 r
= handle_db_line(device
, key
, value
);
1762 log_device_debug_errno(device
, r
, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m",
1770 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
), "sd-device: invalid db syntax.");
1776 int device_read_db_internal(sd_device
*device
, bool force
) {
1777 const char *id
, *path
;
1782 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1785 r
= device_get_device_id(device
, &id
);
1789 path
= strjoina("/run/udev/data/", id
);
1791 return device_read_db_internal_filename(device
, path
);
1794 _public_
int sd_device_get_is_initialized(sd_device
*device
) {
1797 assert_return(device
, -EINVAL
);
1799 r
= device_read_db(device
);
1801 /* The device may be already removed or renamed. */
1806 return device
->is_initialized
;
1809 _public_
int sd_device_get_usec_initialized(sd_device
*device
, uint64_t *ret
) {
1812 assert_return(device
, -EINVAL
);
1814 r
= sd_device_get_is_initialized(device
);
1820 if (device
->usec_initialized
== 0)
1824 *ret
= device
->usec_initialized
;
1829 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *ret
) {
1833 assert_return(device
, -EINVAL
);
1835 r
= sd_device_get_usec_initialized(device
, &ts
);
1839 now_ts
= now(CLOCK_MONOTONIC
);
1845 *ret
= usec_sub_unsigned(now_ts
, ts
);
1850 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1853 assert_return(device
, NULL
);
1855 (void) device_read_db(device
);
1857 device
->all_tags_iterator_generation
= device
->tags_generation
;
1858 device
->all_tags_iterator
= ITERATOR_FIRST
;
1860 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1864 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1867 assert_return(device
, NULL
);
1869 (void) device_read_db(device
);
1871 if (device
->all_tags_iterator_generation
!= device
->tags_generation
)
1874 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1878 static bool device_database_supports_current_tags(sd_device
*device
) {
1881 (void) device_read_db(device
);
1883 /* The current tags (saved in Q field) feature is implemented in database version 1.
1884 * If the database version is 0, then the tags (NOT current tags, saved in G field) are not
1885 * sticky. Thus, we can safely bypass the operations for the current tags (Q) to tags (G). */
1887 return device
->database_version
>= 1;
1890 _public_
const char *sd_device_get_current_tag_first(sd_device
*device
) {
1893 assert_return(device
, NULL
);
1895 if (!device_database_supports_current_tags(device
))
1896 return sd_device_get_tag_first(device
);
1898 (void) device_read_db(device
);
1900 device
->current_tags_iterator_generation
= device
->tags_generation
;
1901 device
->current_tags_iterator
= ITERATOR_FIRST
;
1903 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1907 _public_
const char *sd_device_get_current_tag_next(sd_device
*device
) {
1910 assert_return(device
, NULL
);
1912 if (!device_database_supports_current_tags(device
))
1913 return sd_device_get_tag_next(device
);
1915 (void) device_read_db(device
);
1917 if (device
->current_tags_iterator_generation
!= device
->tags_generation
)
1920 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1924 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1927 assert_return(device
, NULL
);
1929 (void) device_read_db(device
);
1931 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1932 device
->devlinks_iterator
= ITERATOR_FIRST
;
1934 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1938 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1941 assert_return(device
, NULL
);
1943 (void) device_read_db(device
);
1945 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1948 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1952 int device_properties_prepare(sd_device
*device
) {
1957 r
= device_read_uevent_file(device
);
1961 r
= device_read_db(device
);
1965 if (device
->property_devlinks_outdated
) {
1966 _cleanup_free_
char *devlinks
= NULL
;
1968 r
= set_strjoin(device
->devlinks
, " ", false, &devlinks
);
1972 if (!isempty(devlinks
)) {
1973 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1978 device
->property_devlinks_outdated
= false;
1981 if (device
->property_tags_outdated
) {
1982 _cleanup_free_
char *tags
= NULL
;
1984 r
= set_strjoin(device
->all_tags
, ":", true, &tags
);
1988 if (!isempty(tags
)) {
1989 r
= device_add_property_internal(device
, "TAGS", tags
);
1995 r
= set_strjoin(device
->current_tags
, ":", true, &tags
);
1999 if (!isempty(tags
)) {
2000 r
= device_add_property_internal(device
, "CURRENT_TAGS", tags
);
2005 device
->property_tags_outdated
= false;
2011 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
2015 assert_return(device
, NULL
);
2017 r
= device_properties_prepare(device
);
2021 device
->properties_iterator_generation
= device
->properties_generation
;
2022 device
->properties_iterator
= ITERATOR_FIRST
;
2024 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
2028 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
2032 assert_return(device
, NULL
);
2034 r
= device_properties_prepare(device
);
2038 if (device
->properties_iterator_generation
!= device
->properties_generation
)
2041 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
2045 static int device_sysattrs_read_all_internal(sd_device
*device
, const char *subdir
, Set
**stack
) {
2046 _cleanup_closedir_
DIR *dir
= NULL
;
2052 r
= device_opendir(device
, subdir
, &dir
);
2053 if (r
== -ENOENT
&& subdir
)
2054 return 0; /* Maybe, this is a child device, and is already removed. */
2059 if (faccessat(dirfd(dir
), "uevent", F_OK
, 0) >= 0)
2060 return 0; /* this is a child device, skipping */
2061 if (errno
!= ENOENT
) {
2062 log_device_debug_errno(device
, errno
,
2063 "sd-device: Failed to access %s/uevent, ignoring sub-directory %s: %m",
2069 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
2070 _cleanup_free_
char *p
= NULL
;
2071 struct stat statbuf
;
2073 if (dot_or_dot_dot(de
->d_name
))
2076 /* only handle symlinks, regular files, and directories */
2077 if (!IN_SET(de
->d_type
, DT_LNK
, DT_REG
, DT_DIR
))
2081 p
= path_join(subdir
, de
->d_name
);
2086 if (de
->d_type
== DT_DIR
) {
2087 /* push the sub-directory into the stack, and read it later. */
2089 r
= set_ensure_consume(stack
, &path_hash_ops_free
, TAKE_PTR(p
));
2091 r
= set_put_strdup_full(stack
, &path_hash_ops_free
, de
->d_name
);
2098 if (fstatat(dirfd(dir
), de
->d_name
, &statbuf
, AT_SYMLINK_NOFOLLOW
) < 0)
2101 if ((statbuf
.st_mode
& (S_IRUSR
| S_IWUSR
)) == 0)
2105 r
= set_ensure_consume(&device
->sysattrs
, &path_hash_ops_free
, TAKE_PTR(p
));
2107 r
= set_put_strdup_full(&device
->sysattrs
, &path_hash_ops_free
, de
->d_name
);
2115 static int device_sysattrs_read_all(sd_device
*device
) {
2116 _cleanup_set_free_ Set
*stack
= NULL
;
2121 if (device
->sysattrs_read
)
2124 r
= device_sysattrs_read_all_internal(device
, NULL
, &stack
);
2129 _cleanup_free_
char *subdir
= NULL
;
2131 subdir
= set_steal_first(stack
);
2135 r
= device_sysattrs_read_all_internal(device
, subdir
, &stack
);
2140 device
->sysattrs_read
= true;
2145 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
2149 assert_return(device
, NULL
);
2151 if (!device
->sysattrs_read
) {
2152 r
= device_sysattrs_read_all(device
);
2159 device
->sysattrs_iterator
= ITERATOR_FIRST
;
2161 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
2165 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
2168 assert_return(device
, NULL
);
2170 if (!device
->sysattrs_read
)
2173 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
2177 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
2178 assert_return(device
, -EINVAL
);
2179 assert_return(tag
, -EINVAL
);
2181 (void) device_read_db(device
);
2183 return set_contains(device
->all_tags
, tag
);
2186 _public_
int sd_device_has_current_tag(sd_device
*device
, const char *tag
) {
2187 assert_return(device
, -EINVAL
);
2188 assert_return(tag
, -EINVAL
);
2190 if (!device_database_supports_current_tags(device
))
2191 return sd_device_has_tag(device
, tag
);
2193 (void) device_read_db(device
);
2195 return set_contains(device
->current_tags
, tag
);
2198 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **ret_value
) {
2202 assert_return(device
, -EINVAL
);
2203 assert_return(key
, -EINVAL
);
2205 r
= device_properties_prepare(device
);
2209 value
= ordered_hashmap_get(device
->properties
, key
);
2218 int device_get_property_bool(sd_device
*device
, const char *key
) {
2225 r
= sd_device_get_property_value(device
, key
, &value
);
2229 return parse_boolean(value
);
2232 int device_get_property_int(sd_device
*device
, const char *key
, int *ret
) {
2239 r
= sd_device_get_property_value(device
, key
, &value
);
2243 r
= safe_atoi(value
, &v
);
2252 _public_
int sd_device_get_trigger_uuid(sd_device
*device
, sd_id128_t
*ret
) {
2257 assert_return(device
, -EINVAL
);
2259 /* Retrieves the UUID attached to a uevent when triggering it from userspace via
2260 * sd_device_trigger_with_uuid() or an equivalent interface. Returns -ENOENT if the record is not
2261 * caused by a synthetic event and -ENODATA if it was but no UUID was specified */
2263 r
= sd_device_get_property_value(device
, "SYNTH_UUID", &s
);
2267 if (streq(s
, "0")) /* SYNTH_UUID=0 is set whenever a device is triggered by userspace without specifying a UUID */
2270 r
= sd_id128_from_string(s
, &id
);
2280 void device_clear_sysattr_cache(sd_device
*device
) {
2281 device
->sysattr_values
= hashmap_free(device
->sysattr_values
);
2284 int device_cache_sysattr_value(sd_device
*device
, const char *key
, char *value
) {
2285 _unused_ _cleanup_free_
char *old_value
= NULL
;
2286 _cleanup_free_
char *new_key
= NULL
;
2292 /* This takes the reference of the input value. The input value may be NULL.
2293 * This replaces the value if it already exists. */
2295 /* First, remove the old cache entry. So, we do not need to clear cache on error. */
2296 old_value
= hashmap_remove2(device
->sysattr_values
, key
, (void **) &new_key
);
2298 new_key
= strdup(key
);
2303 r
= hashmap_ensure_put(&device
->sysattr_values
, &path_hash_ops_free_free
, new_key
, value
);
2312 int device_get_cached_sysattr_value(sd_device
*device
, const char *key
, const char **ret_value
) {
2313 const char *k
= NULL
, *value
;
2318 value
= hashmap_get2(device
->sysattr_values
, key
, (void **) &k
);
2320 return -ESTALE
; /* We have not read the attribute. */
2322 return -ENOENT
; /* We have looked up the attribute before and it did not exist. */
2328 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
2329 * with a NULL value in the cache, otherwise the returned string is stored */
2330 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **ret_value
) {
2331 _cleanup_free_
char *value
= NULL
, *path
= NULL
;
2332 const char *syspath
;
2333 struct stat statbuf
;
2336 assert_return(device
, -EINVAL
);
2337 assert_return(sysattr
, -EINVAL
);
2339 /* look for possibly already cached result */
2340 r
= device_get_cached_sysattr_value(device
, sysattr
, ret_value
);
2344 r
= sd_device_get_syspath(device
, &syspath
);
2348 path
= path_join(syspath
, sysattr
);
2352 if (lstat(path
, &statbuf
) < 0) {
2357 /* remember that we could not access the sysattr */
2358 k
= device_cache_sysattr_value(device
, sysattr
, NULL
);
2360 log_device_debug_errno(device
, k
,
2361 "sd-device: failed to cache attribute '%s' with NULL, ignoring: %m",
2365 } else if (S_ISLNK(statbuf
.st_mode
)) {
2366 /* Some core links return only the last element of the target path,
2367 * these are just values, the paths should not be exposed. */
2368 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
2369 r
= readlink_value(path
, &value
);
2374 } else if (S_ISDIR(statbuf
.st_mode
))
2375 /* skip directories */
2377 else if (!(statbuf
.st_mode
& S_IRUSR
))
2378 /* skip non-readable files */
2383 /* Read attribute value, Some attributes contain embedded '\0'. So, it is necessary to
2384 * also get the size of the result. See issue #20025. */
2385 r
= read_full_virtual_file(path
, &value
, &size
);
2389 /* drop trailing newlines */
2390 while (size
> 0 && strchr(NEWLINE
, value
[--size
]))
2394 /* Unfortunately, we need to return 'const char*' instead of 'char*'. Hence, failure in caching
2395 * sysattr value is critical unlike the other places. */
2396 r
= device_cache_sysattr_value(device
, sysattr
, value
);
2398 log_device_debug_errno(device
, r
,
2399 "sd-device: failed to cache attribute '%s' with '%s'%s: %m",
2400 sysattr
, value
, ret_value
? "" : ", ignoring");
2414 int device_get_sysattr_int(sd_device
*device
, const char *sysattr
, int *ret_value
) {
2418 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2423 r
= safe_atoi(value
, &v
);
2425 return log_device_debug_errno(device
, r
, "Failed to parse '%s' attribute: %m", sysattr
);
2429 /* We return "true" if the value is positive. */
2433 int device_get_sysattr_unsigned(sd_device
*device
, const char *sysattr
, unsigned *ret_value
) {
2437 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2442 r
= safe_atou(value
, &v
);
2444 return log_device_debug_errno(device
, r
, "Failed to parse '%s' attribute: %m", sysattr
);
2448 /* We return "true" if the value is positive. */
2452 int device_get_sysattr_bool(sd_device
*device
, const char *sysattr
) {
2459 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
2463 return parse_boolean(value
);
2466 static void device_remove_cached_sysattr_value(sd_device
*device
, const char *_key
) {
2467 _cleanup_free_
char *key
= NULL
;
2472 free(hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
));
2475 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, const char *_value
) {
2476 _cleanup_free_
char *value
= NULL
, *path
= NULL
;
2477 const char *syspath
;
2481 assert_return(device
, -EINVAL
);
2482 assert_return(sysattr
, -EINVAL
);
2484 /* Set the attribute and save it in the cache. */
2487 /* If input value is NULL, then clear cache and not write anything. */
2488 device_remove_cached_sysattr_value(device
, sysattr
);
2492 r
= sd_device_get_syspath(device
, &syspath
);
2496 path
= path_join(syspath
, sysattr
);
2500 len
= strlen(_value
);
2502 /* drop trailing newlines */
2503 while (len
> 0 && strchr(NEWLINE
, _value
[len
- 1]))
2506 /* value length is limited to 4k */
2510 value
= strndup(_value
, len
);
2514 r
= write_string_file(path
, value
, WRITE_STRING_FILE_DISABLE_BUFFER
| WRITE_STRING_FILE_NOFOLLOW
);
2516 /* On failure, clear cache entry, as we do not know how it fails. */
2517 device_remove_cached_sysattr_value(device
, sysattr
);
2521 /* Do not cache action string written into uevent file. */
2522 if (streq(sysattr
, "uevent"))
2525 r
= device_cache_sysattr_value(device
, sysattr
, value
);
2527 log_device_debug_errno(device
, r
,
2528 "sd-device: failed to cache attribute '%s' with '%s', ignoring: %m",
2536 _public_
int sd_device_set_sysattr_valuef(sd_device
*device
, const char *sysattr
, const char *format
, ...) {
2537 _cleanup_free_
char *value
= NULL
;
2541 assert_return(device
, -EINVAL
);
2542 assert_return(sysattr
, -EINVAL
);
2545 device_remove_cached_sysattr_value(device
, sysattr
);
2549 va_start(ap
, format
);
2550 r
= vasprintf(&value
, format
, ap
);
2556 return sd_device_set_sysattr_value(device
, sysattr
, value
);
2559 _public_
int sd_device_trigger(sd_device
*device
, sd_device_action_t action
) {
2562 assert_return(device
, -EINVAL
);
2564 s
= device_action_to_string(action
);
2568 /* This uses the simple no-UUID interface of kernel < 4.13 */
2569 return sd_device_set_sysattr_value(device
, "uevent", s
);
2572 _public_
int sd_device_trigger_with_uuid(
2574 sd_device_action_t action
,
2575 sd_id128_t
*ret_uuid
) {
2581 assert_return(device
, -EINVAL
);
2583 /* If no one wants to know the UUID, use the simple interface from pre-4.13 times */
2585 return sd_device_trigger(device
, action
);
2587 s
= device_action_to_string(action
);
2591 r
= sd_id128_randomize(&u
);
2595 j
= strjoina(s
, " ", SD_ID128_TO_UUID_STRING(u
));
2597 r
= sd_device_set_sysattr_value(device
, "uevent", j
);
2605 _public_
int sd_device_open(sd_device
*device
, int flags
) {
2606 _cleanup_close_
int fd
= -EBADF
, fd2
= -EBADF
;
2607 const char *devname
, *subsystem
= NULL
;
2608 uint64_t q
, diskseq
= 0;
2613 assert_return(device
, -EINVAL
);
2614 assert_return(FLAGS_SET(flags
, O_PATH
) || !FLAGS_SET(flags
, O_NOFOLLOW
), -EINVAL
);
2616 r
= sd_device_get_devname(device
, &devname
);
2622 r
= sd_device_get_devnum(device
, &devnum
);
2628 r
= sd_device_get_subsystem(device
, &subsystem
);
2629 if (r
< 0 && r
!= -ENOENT
)
2632 fd
= open(devname
, FLAGS_SET(flags
, O_PATH
) ? flags
: O_CLOEXEC
|O_NOFOLLOW
|O_PATH
);
2636 if (fstat(fd
, &st
) < 0)
2639 if (st
.st_rdev
!= devnum
)
2642 if (streq_ptr(subsystem
, "block") ? !S_ISBLK(st
.st_mode
) : !S_ISCHR(st
.st_mode
))
2645 /* If flags has O_PATH, then we cannot check diskseq. Let's return earlier. */
2646 if (FLAGS_SET(flags
, O_PATH
))
2649 /* If the device is not initialized, then we cannot determine if we should check diskseq through
2650 * ID_IGNORE_DISKSEQ property. Let's skip to check diskseq in that case. */
2651 r
= sd_device_get_is_initialized(device
);
2655 r
= device_get_property_bool(device
, "ID_IGNORE_DISKSEQ");
2656 if (r
< 0 && r
!= -ENOENT
)
2659 r
= sd_device_get_diskseq(device
, &diskseq
);
2660 if (r
< 0 && r
!= -ENOENT
)
2665 fd2
= fd_reopen(fd
, flags
);
2670 return TAKE_FD(fd2
);
2672 r
= fd_get_diskseq(fd2
, &q
);
2679 return TAKE_FD(fd2
);
2682 int device_opendir(sd_device
*device
, const char *subdir
, DIR **ret
) {
2683 _cleanup_closedir_
DIR *d
= NULL
;
2684 _cleanup_free_
char *path
= NULL
;
2685 const char *syspath
;
2691 r
= sd_device_get_syspath(device
, &syspath
);
2696 if (!path_is_safe(subdir
))
2699 path
= path_join(syspath
, subdir
);
2704 d
= opendir(path
?: syspath
);