1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
10 #include "alloc-util.h"
11 #include "device-internal.h"
12 #include "device-private.h"
13 #include "device-util.h"
14 #include "dirent-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
23 #include "socket-util.h"
24 #include "stat-util.h"
25 #include "stdio-util.h"
26 #include "string-util.h"
29 #include "user-util.h"
32 int device_new_aux(sd_device
**ret
) {
37 device
= new(sd_device
, 1);
41 *device
= (sd_device
) {
44 .devmode
= MODE_INVALID
,
45 .devuid
= UID_INVALID
,
46 .devgid
= GID_INVALID
,
47 .action
= _SD_DEVICE_ACTION_INVALID
,
54 static sd_device
*device_free(sd_device
*device
) {
57 sd_device_unref(device
->parent
);
58 free(device
->syspath
);
59 free(device
->sysname
);
60 free(device
->devtype
);
61 free(device
->devname
);
62 free(device
->subsystem
);
63 free(device
->driver_subsystem
);
65 free(device
->id_filename
);
66 free(device
->properties_strv
);
67 free(device
->properties_nulstr
);
69 ordered_hashmap_free(device
->properties
);
70 ordered_hashmap_free(device
->properties_db
);
71 hashmap_free(device
->sysattr_values
);
72 set_free(device
->sysattrs
);
73 set_free(device
->all_tags
);
74 set_free(device
->current_tags
);
75 set_free(device
->devlinks
);
80 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device
, sd_device
, device_free
);
82 int device_add_property_aux(sd_device
*device
, const char *key
, const char *value
, bool db
) {
83 OrderedHashmap
**properties
;
89 properties
= &device
->properties_db
;
91 properties
= &device
->properties
;
94 _cleanup_free_
char *new_key
= NULL
, *new_value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
97 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops_free_free
);
101 new_key
= strdup(key
);
105 new_value
= strdup(value
);
109 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
111 /* ordered_hashmap_replace() does not fail when the hashmap already has the entry. */
112 r
= ordered_hashmap_replace(*properties
, new_key
, new_value
);
119 _cleanup_free_
char *old_key
= NULL
, *old_value
= NULL
;
121 old_value
= ordered_hashmap_remove2(*properties
, key
, (void**) &old_key
);
125 device
->properties_generation
++;
126 device
->properties_buf_outdated
= true;
132 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
133 _cleanup_free_
char *syspath
= NULL
;
140 /* must be a subdirectory of /sys */
141 if (!path_startswith(_syspath
, "/sys/"))
142 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
143 "sd-device: Syspath '%s' is not a subdirectory of /sys",
147 r
= chase_symlinks(_syspath
, NULL
, 0, &syspath
, NULL
);
149 return -ENODEV
; /* the device does not exist (any more?) */
151 return log_debug_errno(r
, "sd-device: Failed to get target of '%s': %m", _syspath
);
153 if (!path_startswith(syspath
, "/sys")) {
154 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
157 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
158 r
= chase_symlinks("/sys", NULL
, 0, &real_sys
, NULL
);
160 return log_debug_errno(r
, "sd-device: Failed to chase symlink /sys: %m");
162 p
= path_startswith(syspath
, real_sys
);
164 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
165 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
168 new_syspath
= path_join("/sys", p
);
172 free_and_replace(syspath
, new_syspath
);
173 path_simplify(syspath
, false);
176 if (path_startswith(syspath
, "/sys/devices/")) {
179 /* all 'devices' require an 'uevent' file */
180 path
= strjoina(syspath
, "/uevent");
181 r
= access(path
, F_OK
);
184 /* this is not a valid device */
187 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
190 /* everything else just needs to be a directory */
191 if (!is_dir(syspath
, false))
195 syspath
= strdup(_syspath
);
200 devpath
= syspath
+ STRLEN("/sys");
202 if (devpath
[0] != '/')
203 /* '/sys' alone is not a valid device path */
206 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
210 free_and_replace(device
->syspath
, syspath
);
211 device
->devpath
= devpath
;
215 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
216 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
219 assert_return(ret
, -EINVAL
);
220 assert_return(syspath
, -EINVAL
);
222 r
= device_new_aux(&device
);
226 r
= device_set_syspath(device
, syspath
, true);
230 *ret
= TAKE_PTR(device
);
234 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
235 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1], *syspath
;
237 assert_return(ret
, -EINVAL
);
238 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
240 /* use /sys/dev/{block,char}/<maj>:<min> link */
241 xsprintf(id
, "%u:%u", major(devnum
), minor(devnum
));
243 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
245 return sd_device_new_from_syspath(ret
, syspath
);
248 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
249 char *name
, *syspath
;
252 assert_return(ret
, -EINVAL
);
253 assert_return(subsystem
, -EINVAL
);
254 assert_return(sysname
, -EINVAL
);
256 if (streq(subsystem
, "subsystem")) {
257 syspath
= strjoina("/sys/subsystem/", sysname
);
258 if (access(syspath
, F_OK
) >= 0)
259 return sd_device_new_from_syspath(ret
, syspath
);
261 syspath
= strjoina("/sys/bus/", sysname
);
262 if (access(syspath
, F_OK
) >= 0)
263 return sd_device_new_from_syspath(ret
, syspath
);
265 syspath
= strjoina("/sys/class/", sysname
);
266 if (access(syspath
, F_OK
) >= 0)
267 return sd_device_new_from_syspath(ret
, syspath
);
268 } else if (streq(subsystem
, "module")) {
269 syspath
= strjoina("/sys/module/", sysname
);
270 if (access(syspath
, F_OK
) >= 0)
271 return sd_device_new_from_syspath(ret
, syspath
);
272 } else if (streq(subsystem
, "drivers")) {
273 char subsys
[PATH_MAX
];
276 strscpy(subsys
, sizeof(subsys
), sysname
);
277 driver
= strchr(subsys
, ':');
282 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
283 if (access(syspath
, F_OK
) >= 0)
284 return sd_device_new_from_syspath(ret
, syspath
);
286 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
287 if (access(syspath
, F_OK
) >= 0)
288 return sd_device_new_from_syspath(ret
, syspath
);
292 /* translate sysname back to sysfs filename */
293 name
= strdupa(sysname
);
294 while (name
[len
] != '\0') {
295 if (name
[len
] == '/')
301 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
302 if (access(syspath
, F_OK
) >= 0)
303 return sd_device_new_from_syspath(ret
, syspath
);
305 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
306 if (access(syspath
, F_OK
) >= 0)
307 return sd_device_new_from_syspath(ret
, syspath
);
309 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
310 if (access(syspath
, F_OK
) >= 0)
311 return sd_device_new_from_syspath(ret
, syspath
);
313 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
314 if (access(syspath
, F_OK
) >= 0)
315 return sd_device_new_from_syspath(ret
, syspath
);
320 _public_
int sd_device_new_from_stat_rdev(sd_device
**ret
, const struct stat
*st
) {
323 assert_return(ret
, -EINVAL
);
324 assert_return(st
, -EINVAL
);
326 if (S_ISBLK(st
->st_mode
))
328 else if (S_ISCHR(st
->st_mode
))
333 return sd_device_new_from_devnum(ret
, type
, st
->st_rdev
);
336 int device_set_devtype(sd_device
*device
, const char *devtype
) {
337 _cleanup_free_
char *t
= NULL
;
347 r
= device_add_property_internal(device
, "DEVTYPE", t
);
351 return free_and_replace(device
->devtype
, t
);
354 int device_set_ifindex(sd_device
*device
, const char *name
) {
360 ifindex
= parse_ifindex(name
);
364 r
= device_add_property_internal(device
, "IFINDEX", name
);
368 device
->ifindex
= ifindex
;
373 int device_set_devname(sd_device
*device
, const char *devname
) {
374 _cleanup_free_
char *t
= NULL
;
380 if (devname
[0] != '/')
381 t
= strjoin("/dev/", devname
);
387 r
= device_add_property_internal(device
, "DEVNAME", t
);
391 return free_and_replace(device
->devname
, t
);
394 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
401 r
= safe_atou(_devmode
, &devmode
);
408 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
412 device
->devmode
= devmode
;
417 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
418 unsigned maj
, min
= 0;
424 r
= safe_atou(major
, &maj
);
431 r
= safe_atou(minor
, &min
);
436 r
= device_add_property_internal(device
, "MAJOR", major
);
441 r
= device_add_property_internal(device
, "MINOR", minor
);
446 device
->devnum
= makedev(maj
, min
);
451 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
460 if (streq(key
, "DEVTYPE")) {
461 r
= device_set_devtype(device
, value
);
464 } else if (streq(key
, "IFINDEX")) {
465 r
= device_set_ifindex(device
, value
);
468 } else if (streq(key
, "DEVNAME")) {
469 r
= device_set_devname(device
, value
);
472 } else if (streq(key
, "DEVMODE")) {
473 r
= device_set_devmode(device
, value
);
476 } else if (streq(key
, "MAJOR"))
478 else if (streq(key
, "MINOR"))
481 r
= device_add_property_internal(device
, key
, value
);
489 int device_read_uevent_file(sd_device
*device
) {
490 _cleanup_free_
char *uevent
= NULL
;
491 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
507 if (device
->uevent_loaded
|| device
->sealed
)
510 r
= sd_device_get_syspath(device
, &syspath
);
514 path
= strjoina(syspath
, "/uevent");
516 r
= read_full_file(path
, &uevent
, &uevent_len
);
518 /* empty uevent files may be write-only */
519 device
->uevent_loaded
= true;
523 /* some devices may not have uevent files, see device_set_syspath() */
526 return log_device_debug_errno(device
, r
, "sd-device: Failed to read uevent file '%s': %m", path
);
528 device
->uevent_loaded
= true;
530 for (i
= 0; i
< uevent_len
; i
++)
533 if (!strchr(NEWLINE
, uevent
[i
])) {
541 if (uevent
[i
] == '=') {
545 } else if (strchr(NEWLINE
, uevent
[i
])) {
547 log_device_debug(device
, "sd-device: Invalid uevent line '%s', ignoring", key
);
557 _fallthrough_
; /* to handle empty property */
559 if (strchr(NEWLINE
, uevent
[i
])) {
562 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
564 log_device_debug_errno(device
, r
, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key
, value
);
571 assert_not_reached("Invalid state when parsing uevent file");
575 r
= device_set_devnum(device
, major
, minor
);
577 log_device_debug_errno(device
, r
, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major
, minor
, path
);
583 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
586 assert_return(device
, -EINVAL
);
588 r
= device_read_uevent_file(device
);
592 if (device
->ifindex
<= 0)
596 *ifindex
= device
->ifindex
;
601 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
604 assert_return(ret
, -EINVAL
);
605 assert_return(id
, -EINVAL
);
615 r
= parse_dev(id
+ 1, &devt
);
619 return sd_device_new_from_devnum(ret
, id
[0], devt
);
623 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
624 _cleanup_close_
int sk
= -1;
625 struct ifreq ifr
= {};
628 r
= ifr
.ifr_ifindex
= parse_ifindex(&id
[1]);
632 sk
= socket_ioctl_fd();
636 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
640 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
644 r
= sd_device_get_ifindex(device
, &ifindex
);
648 /* this is racey, so we might end up with the wrong device */
649 if (ifr
.ifr_ifindex
!= ifindex
)
652 *ret
= TAKE_PTR(device
);
657 char subsys
[PATH_MAX
];
660 (void) strscpy(subsys
, sizeof(subsys
), id
+ 1);
661 sysname
= strchr(subsys
, ':');
668 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
676 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
677 assert_return(device
, -EINVAL
);
679 assert(path_startswith(device
->syspath
, "/sys/"));
682 *ret
= device
->syspath
;
687 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
688 _cleanup_free_
char *path
= NULL
;
689 const char *subdir
, *syspath
;
695 r
= sd_device_get_syspath(child
, &syspath
);
699 path
= strdup(syspath
);
702 subdir
= path
+ STRLEN("/sys");
707 pos
= strrchr(subdir
, '/');
708 if (!pos
|| pos
< subdir
+ 2)
713 r
= sd_device_new_from_syspath(ret
, path
);
723 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
724 assert_return(child
, -EINVAL
);
726 if (!child
->parent_set
) {
727 child
->parent_set
= true;
729 (void) device_new_from_child(&child
->parent
, child
);
736 *ret
= child
->parent
;
740 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
741 _cleanup_free_
char *subsystem
= NULL
;
747 subsystem
= strdup(_subsystem
);
751 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
755 device
->subsystem_set
= true;
756 return free_and_replace(device
->subsystem
, subsystem
);
759 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
760 _cleanup_free_
char *subsystem
= NULL
;
767 subsystem
= strdup(_subsystem
);
771 r
= device_set_subsystem(device
, "drivers");
775 return free_and_replace(device
->driver_subsystem
, subsystem
);
778 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
779 const char *syspath
, *drivers
= NULL
;
782 assert_return(device
, -EINVAL
);
784 r
= sd_device_get_syspath(device
, &syspath
);
788 if (!device
->subsystem_set
) {
789 _cleanup_free_
char *subsystem
= NULL
;
792 /* read 'subsystem' link */
793 path
= strjoina(syspath
, "/subsystem");
794 r
= readlink_value(path
, &subsystem
);
796 r
= device_set_subsystem(device
, subsystem
);
797 /* use implicit names */
798 else if (path_startswith(device
->devpath
, "/module/"))
799 r
= device_set_subsystem(device
, "module");
800 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
801 PATH_STARTSWITH_SET(device
->devpath
, "/subsystem/",
804 r
= device_set_subsystem(device
, "subsystem");
805 if (r
< 0 && r
!= -ENOENT
)
806 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem for %s: %m", device
->devpath
);
808 device
->subsystem_set
= true;
809 } else if (!device
->driver_subsystem_set
)
810 drivers
= strstr(syspath
, "/drivers/");
812 if (!device
->driver_subsystem_set
) {
814 _cleanup_free_
char *subpath
= NULL
;
816 subpath
= strndup(syspath
, drivers
- syspath
);
822 subsys
= strrchr(subpath
, '/');
826 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
828 if (r
< 0 && r
!= -ENOENT
)
829 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem for driver %s: %m", device
->devpath
);
832 device
->driver_subsystem_set
= true;
835 if (!device
->subsystem
)
839 *ret
= device
->subsystem
;
843 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
846 assert_return(device
, -EINVAL
);
848 r
= device_read_uevent_file(device
);
852 if (!device
->devtype
)
856 *devtype
= device
->devtype
;
858 return !!device
->devtype
;
861 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
862 sd_device
*parent
= NULL
;
865 assert_return(child
, -EINVAL
);
866 assert_return(subsystem
, -EINVAL
);
868 r
= sd_device_get_parent(child
, &parent
);
870 const char *parent_subsystem
= NULL
;
872 (void) sd_device_get_subsystem(parent
, &parent_subsystem
);
873 if (streq_ptr(parent_subsystem
, subsystem
)) {
874 const char *parent_devtype
= NULL
;
879 (void) sd_device_get_devtype(parent
, &parent_devtype
);
880 if (streq_ptr(parent_devtype
, devtype
))
883 r
= sd_device_get_parent(parent
, &parent
);
894 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
897 assert_return(device
, -EINVAL
);
899 r
= device_read_uevent_file(device
);
903 if (major(device
->devnum
) <= 0)
907 *devnum
= device
->devnum
;
912 int device_set_driver(sd_device
*device
, const char *_driver
) {
913 _cleanup_free_
char *driver
= NULL
;
919 driver
= strdup(_driver
);
923 r
= device_add_property_internal(device
, "DRIVER", driver
);
927 device
->driver_set
= true;
928 return free_and_replace(device
->driver
, driver
);
931 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
932 assert_return(device
, -EINVAL
);
934 if (!device
->driver_set
) {
935 _cleanup_free_
char *driver
= NULL
;
940 r
= sd_device_get_syspath(device
, &syspath
);
944 path
= strjoina(syspath
, "/driver");
945 r
= readlink_value(path
, &driver
);
947 r
= device_set_driver(device
, driver
);
949 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver for %s: %m", device
->devpath
);
950 } else if (r
== -ENOENT
)
951 device
->driver_set
= true;
953 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver for %s: %m", device
->devpath
);
960 *ret
= device
->driver
;
964 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
965 assert_return(device
, -EINVAL
);
967 assert(device
->devpath
);
968 assert(device
->devpath
[0] == '/');
971 *devpath
= device
->devpath
;
975 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
978 assert_return(device
, -EINVAL
);
980 r
= device_read_uevent_file(device
);
984 if (!device
->devname
)
987 assert(path_startswith(device
->devname
, "/dev/"));
990 *devname
= device
->devname
;
994 static int device_set_sysname(sd_device
*device
) {
995 _cleanup_free_
char *sysname
= NULL
;
996 const char *sysnum
= NULL
;
1000 if (!device
->devpath
)
1003 pos
= strrchr(device
->devpath
, '/');
1008 /* devpath is not a root directory */
1009 if (*pos
== '\0' || pos
<= device
->devpath
)
1012 sysname
= strdup(pos
);
1016 /* some devices have '!' in their name, change that to '/' */
1017 while (sysname
[len
] != '\0') {
1018 if (sysname
[len
] == '!')
1024 /* trailing number */
1025 while (len
> 0 && isdigit(sysname
[--len
]))
1026 sysnum
= &sysname
[len
];
1031 device
->sysname_set
= true;
1032 device
->sysnum
= sysnum
;
1033 return free_and_replace(device
->sysname
, sysname
);
1036 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1039 assert_return(device
, -EINVAL
);
1041 if (!device
->sysname_set
) {
1042 r
= device_set_sysname(device
);
1047 assert_return(device
->sysname
, -ENOENT
);
1050 *ret
= device
->sysname
;
1054 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1057 assert_return(device
, -EINVAL
);
1059 if (!device
->sysname_set
) {
1060 r
= device_set_sysname(device
);
1065 if (!device
->sysnum
)
1069 *ret
= device
->sysnum
;
1073 _public_
int sd_device_get_action(sd_device
*device
, sd_device_action_t
*ret
) {
1074 assert_return(device
, -EINVAL
);
1076 if (device
->action
< 0)
1080 *ret
= device
->action
;
1085 _public_
int sd_device_get_seqnum(sd_device
*device
, uint64_t *ret
) {
1086 assert_return(device
, -EINVAL
);
1088 if (device
->seqnum
== 0)
1092 *ret
= device
->seqnum
;
1097 static bool is_valid_tag(const char *tag
) {
1100 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1103 int device_add_tag(sd_device
*device
, const char *tag
, bool both
) {
1109 if (!is_valid_tag(tag
))
1112 /* Definitely add to the "all" list of tags (i.e. the sticky list) */
1113 added
= set_put_strdup(&device
->all_tags
, tag
);
1117 /* And optionally, also add it to the current list of tags */
1119 r
= set_put_strdup(&device
->current_tags
, tag
);
1122 (void) set_remove(device
->all_tags
, tag
);
1128 device
->tags_generation
++;
1129 device
->property_tags_outdated
= true;
1134 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1140 r
= set_put_strdup(&device
->devlinks
, devlink
);
1144 device
->devlinks_generation
++;
1145 device
->property_devlinks_outdated
= true;
1150 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1151 _cleanup_free_
char *key
= NULL
;
1162 value
= strchr(key
, '=');
1168 if (isempty(++value
))
1171 /* Add the property to both sd_device::properties and sd_device::properties_db,
1172 * as this is called by only handle_db_line(). */
1173 r
= device_add_property_aux(device
, key
, value
, false);
1177 return device_add_property_aux(device
, key
, value
, true);
1180 int device_set_usec_initialized(sd_device
*device
, usec_t when
) {
1181 char s
[DECIMAL_STR_MAX(usec_t
)];
1186 xsprintf(s
, USEC_FMT
, when
);
1188 r
= device_add_property_internal(device
, "USEC_INITIALIZED", s
);
1192 device
->usec_initialized
= when
;
1196 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1204 case 'G': /* Any tag */
1205 case 'Q': /* Current tag */
1206 r
= device_add_tag(device
, value
, key
== 'Q');
1212 path
= strjoina("/dev/", value
);
1213 r
= device_add_devlink(device
, path
);
1219 r
= device_add_property_internal_from_string(device
, value
);
1227 r
= safe_atou64(value
, &t
);
1231 r
= device_set_usec_initialized(device
, t
);
1238 r
= safe_atoi(value
, &device
->devlink_priority
);
1244 r
= safe_atoi(value
, &device
->watch_handle
);
1250 r
= safe_atou(value
, &device
->database_version
);
1256 log_device_debug(device
, "sd-device: Unknown key '%c' in device db, ignoring", key
);
1262 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1266 if (!device
->id_filename
) {
1267 _cleanup_free_
char *id
= NULL
;
1268 const char *subsystem
;
1272 r
= sd_device_get_subsystem(device
, &subsystem
);
1276 if (sd_device_get_devnum(device
, &devnum
) >= 0) {
1279 /* use dev_t — b259:131072, c254:0 */
1280 r
= asprintf(&id
, "%c%u:%u",
1281 streq(subsystem
, "block") ? 'b' : 'c',
1282 major(devnum
), minor(devnum
));
1285 } else if (sd_device_get_ifindex(device
, &ifindex
) >= 0) {
1286 /* use netdev ifindex — n3 */
1287 r
= asprintf(&id
, "n%u", (unsigned) ifindex
);
1291 /* use $subsys:$sysname — pci:0000:00:1f.2
1292 * sysname() has '!' translated, get it from devpath
1294 const char *sysname
;
1296 sysname
= basename(device
->devpath
);
1304 if (streq(subsystem
, "drivers"))
1305 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1306 * encoded as well */
1307 id
= strjoin("+drivers:", device
->driver_subsystem
, ":", sysname
);
1309 id
= strjoin("+", subsystem
, ":", sysname
);
1314 device
->id_filename
= TAKE_PTR(id
);
1317 *ret
= device
->id_filename
;
1321 int device_read_db_internal_filename(sd_device
*device
, const char *filename
) {
1322 _cleanup_free_
char *db
= NULL
;
1339 r
= read_full_file(filename
, &db
, &db_len
);
1344 return log_device_debug_errno(device
, r
, "sd-device: Failed to read db '%s': %m", filename
);
1347 /* devices with a database entry are initialized */
1348 device
->is_initialized
= true;
1350 device
->db_loaded
= true;
1352 for (i
= 0; i
< db_len
; i
++) {
1355 if (!strchr(NEWLINE
, db
[i
])) {
1364 log_device_debug(device
, "sd-device: Invalid db entry with key '%c', ignoring", key
);
1366 state
= INVALID_LINE
;
1381 if (strchr(NEWLINE
, db
[i
]))
1386 if (strchr(NEWLINE
, db
[i
])) {
1388 r
= handle_db_line(device
, key
, value
);
1390 log_device_debug_errno(device
, r
, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key
, value
);
1397 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
), "sd-device: invalid db syntax.");
1404 int device_read_db_internal(sd_device
*device
, bool force
) {
1405 const char *id
, *path
;
1410 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1413 r
= device_get_id_filename(device
, &id
);
1417 path
= strjoina("/run/udev/data/", id
);
1419 return device_read_db_internal_filename(device
, path
);
1422 _public_
int sd_device_get_is_initialized(sd_device
*device
) {
1425 assert_return(device
, -EINVAL
);
1427 r
= device_read_db(device
);
1431 return device
->is_initialized
;
1434 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1438 assert_return(device
, -EINVAL
);
1440 r
= device_read_db(device
);
1444 if (!device
->is_initialized
)
1447 if (!device
->usec_initialized
)
1450 now_ts
= now(clock_boottime_or_monotonic());
1452 if (now_ts
< device
->usec_initialized
)
1456 *usec
= now_ts
- device
->usec_initialized
;
1460 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1463 assert_return(device
, NULL
);
1465 (void) device_read_db(device
);
1467 device
->all_tags_iterator_generation
= device
->tags_generation
;
1468 device
->all_tags_iterator
= ITERATOR_FIRST
;
1470 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1474 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1477 assert_return(device
, NULL
);
1479 (void) device_read_db(device
);
1481 if (device
->all_tags_iterator_generation
!= device
->tags_generation
)
1484 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1488 static bool device_database_supports_current_tags(sd_device
*device
) {
1491 (void) device_read_db(device
);
1493 /* The current tags (saved in Q field) feature is implemented in database version 1.
1494 * If the database version is 0, then the tags (NOT current tags, saved in G field) are not
1495 * sticky. Thus, we can safely bypass the operations for the current tags (Q) to tags (G). */
1497 return device
->database_version
>= 1;
1500 _public_
const char *sd_device_get_current_tag_first(sd_device
*device
) {
1503 assert_return(device
, NULL
);
1505 if (!device_database_supports_current_tags(device
))
1506 return sd_device_get_tag_first(device
);
1508 (void) device_read_db(device
);
1510 device
->current_tags_iterator_generation
= device
->tags_generation
;
1511 device
->current_tags_iterator
= ITERATOR_FIRST
;
1513 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1517 _public_
const char *sd_device_get_current_tag_next(sd_device
*device
) {
1520 assert_return(device
, NULL
);
1522 if (!device_database_supports_current_tags(device
))
1523 return sd_device_get_tag_next(device
);
1525 (void) device_read_db(device
);
1527 if (device
->current_tags_iterator_generation
!= device
->tags_generation
)
1530 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1534 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1537 assert_return(device
, NULL
);
1539 (void) device_read_db(device
);
1541 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1542 device
->devlinks_iterator
= ITERATOR_FIRST
;
1544 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1548 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1551 assert_return(device
, NULL
);
1553 (void) device_read_db(device
);
1555 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1558 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1562 int device_properties_prepare(sd_device
*device
) {
1567 r
= device_read_uevent_file(device
);
1571 r
= device_read_db(device
);
1575 if (device
->property_devlinks_outdated
) {
1576 _cleanup_free_
char *devlinks
= NULL
;
1578 r
= set_strjoin(device
->devlinks
, " ", false, &devlinks
);
1582 if (!isempty(devlinks
)) {
1583 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1588 device
->property_devlinks_outdated
= false;
1591 if (device
->property_tags_outdated
) {
1592 _cleanup_free_
char *tags
= NULL
;
1594 r
= set_strjoin(device
->all_tags
, ":", true, &tags
);
1598 if (!isempty(tags
)) {
1599 r
= device_add_property_internal(device
, "TAGS", tags
);
1605 r
= set_strjoin(device
->current_tags
, ":", true, &tags
);
1609 if (!isempty(tags
)) {
1610 r
= device_add_property_internal(device
, "CURRENT_TAGS", tags
);
1615 device
->property_tags_outdated
= false;
1621 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1625 assert_return(device
, NULL
);
1627 r
= device_properties_prepare(device
);
1631 device
->properties_iterator_generation
= device
->properties_generation
;
1632 device
->properties_iterator
= ITERATOR_FIRST
;
1634 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
1638 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1642 assert_return(device
, NULL
);
1644 r
= device_properties_prepare(device
);
1648 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1651 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
1655 static int device_sysattrs_read_all_internal(sd_device
*device
, const char *subdir
) {
1656 _cleanup_free_
char *path_dir
= NULL
;
1657 _cleanup_closedir_
DIR *dir
= NULL
;
1658 struct dirent
*dent
;
1659 const char *syspath
;
1662 r
= sd_device_get_syspath(device
, &syspath
);
1667 _cleanup_free_
char *p
= NULL
;
1669 p
= path_join(syspath
, subdir
, "uevent");
1673 if (access(p
, F_OK
) >= 0)
1674 /* this is a child device, skipping */
1676 if (errno
!= ENOENT
) {
1677 log_device_debug_errno(device
, errno
, "sd-device: Failed to stat %s, ignoring subdir: %m", p
);
1681 path_dir
= path_join(syspath
, subdir
);
1686 dir
= opendir(path_dir
?: syspath
);
1690 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1691 _cleanup_free_
char *path
= NULL
, *p
= NULL
;
1692 struct stat statbuf
;
1694 if (dot_or_dot_dot(dent
->d_name
))
1697 /* only handle symlinks, regular files, and directories */
1698 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
, DT_DIR
))
1702 p
= path_join(subdir
, dent
->d_name
);
1707 if (dent
->d_type
== DT_DIR
) {
1708 /* read subdirectory */
1709 r
= device_sysattrs_read_all_internal(device
, p
?: dent
->d_name
);
1716 path
= path_join(syspath
, p
?: dent
->d_name
);
1720 if (lstat(path
, &statbuf
) != 0)
1723 if (!(statbuf
.st_mode
& S_IRUSR
))
1726 r
= set_put_strdup(&device
->sysattrs
, p
?: dent
->d_name
);
1734 static int device_sysattrs_read_all(sd_device
*device
) {
1739 if (device
->sysattrs_read
)
1742 r
= device_sysattrs_read_all_internal(device
, NULL
);
1746 device
->sysattrs_read
= true;
1751 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1755 assert_return(device
, NULL
);
1757 if (!device
->sysattrs_read
) {
1758 r
= device_sysattrs_read_all(device
);
1765 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1767 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1771 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1774 assert_return(device
, NULL
);
1776 if (!device
->sysattrs_read
)
1779 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1783 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1784 assert_return(device
, -EINVAL
);
1785 assert_return(tag
, -EINVAL
);
1787 (void) device_read_db(device
);
1789 return set_contains(device
->all_tags
, tag
);
1792 _public_
int sd_device_has_current_tag(sd_device
*device
, const char *tag
) {
1793 assert_return(device
, -EINVAL
);
1794 assert_return(tag
, -EINVAL
);
1796 if (!device_database_supports_current_tags(device
))
1797 return sd_device_has_tag(device
, tag
);
1799 (void) device_read_db(device
);
1801 return set_contains(device
->current_tags
, tag
);
1804 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **ret_value
) {
1808 assert_return(device
, -EINVAL
);
1809 assert_return(key
, -EINVAL
);
1811 r
= device_properties_prepare(device
);
1815 value
= ordered_hashmap_get(device
->properties
, key
);
1824 static int device_cache_sysattr_value(sd_device
*device
, const char *key
, char *value
) {
1825 _cleanup_free_
char *new_key
= NULL
, *old_value
= NULL
;
1831 /* This takes the reference of the input value. The input value may be NULL.
1832 * This replaces the value if it already exists. */
1834 /* First, remove the old cache entry. So, we do not need to clear cache on error. */
1835 old_value
= hashmap_remove2(device
->sysattr_values
, key
, (void **) &new_key
);
1837 new_key
= strdup(key
);
1842 r
= hashmap_ensure_put(&device
->sysattr_values
, &string_hash_ops_free_free
, new_key
, value
);
1851 static int device_get_cached_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1852 const char *key
= NULL
, *value
;
1857 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1866 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1867 * with a NULL value in the cache, otherwise the returned string is stored */
1868 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **ret_value
) {
1869 _cleanup_free_
char *value
= NULL
;
1870 const char *path
, *syspath
, *cached_value
= NULL
;
1871 struct stat statbuf
;
1874 assert_return(device
, -EINVAL
);
1875 assert_return(sysattr
, -EINVAL
);
1877 /* look for possibly already cached result */
1878 r
= device_get_cached_sysattr_value(device
, sysattr
, &cached_value
);
1884 /* we looked up the sysattr before and it did not exist */
1888 *ret_value
= cached_value
;
1893 r
= sd_device_get_syspath(device
, &syspath
);
1897 path
= prefix_roota(syspath
, sysattr
);
1898 r
= lstat(path
, &statbuf
);
1902 /* remember that we could not access the sysattr */
1903 k
= device_cache_sysattr_value(device
, sysattr
, NULL
);
1905 log_device_debug_errno(device
, k
,
1906 "sd-device: failed to cache attribute '%s' with NULL, ignoring: %m",
1910 } else if (S_ISLNK(statbuf
.st_mode
)) {
1911 /* Some core links return only the last element of the target path,
1912 * these are just values, the paths should not be exposed. */
1913 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1914 r
= readlink_value(path
, &value
);
1919 } else if (S_ISDIR(statbuf
.st_mode
))
1920 /* skip directories */
1922 else if (!(statbuf
.st_mode
& S_IRUSR
))
1923 /* skip non-readable files */
1926 /* read attribute value */
1927 r
= read_full_virtual_file(path
, &value
, NULL
);
1931 /* drop trailing newlines */
1932 delete_trailing_chars(value
, "\n");
1935 /* Unfortunately, we need to return 'const char*' instead of 'char*'. Hence, failure in caching
1936 * sysattr value is critical unlike the other places. */
1937 r
= device_cache_sysattr_value(device
, sysattr
, value
);
1939 log_device_debug_errno(device
, r
,
1940 "sd-device: failed to cache attribute '%s' with '%s'%s: %m",
1941 sysattr
, value
, ret_value
? "" : ", ignoring");
1944 } else if (ret_value
)
1945 *ret_value
= TAKE_PTR(value
);
1950 static void device_remove_cached_sysattr_value(sd_device
*device
, const char *_key
) {
1951 _cleanup_free_
char *key
= NULL
;
1956 free(hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
));
1959 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, const char *_value
) {
1960 _cleanup_free_
char *value
= NULL
;
1961 const char *syspath
, *path
;
1965 assert_return(device
, -EINVAL
);
1966 assert_return(sysattr
, -EINVAL
);
1968 /* Set the attribute and save it in the cache. */
1971 /* If input value is NULL, then clear cache and not write anything. */
1972 device_remove_cached_sysattr_value(device
, sysattr
);
1976 r
= sd_device_get_syspath(device
, &syspath
);
1980 path
= prefix_roota(syspath
, sysattr
);
1982 len
= strlen(_value
);
1984 /* drop trailing newlines */
1985 while (len
> 0 && strchr(NEWLINE
, _value
[len
- 1]))
1988 /* value length is limited to 4k */
1992 value
= strndup(_value
, len
);
1996 r
= write_string_file(path
, value
, WRITE_STRING_FILE_DISABLE_BUFFER
| WRITE_STRING_FILE_NOFOLLOW
);
1998 /* On failure, clear cache entry, as we do not know how it fails. */
1999 device_remove_cached_sysattr_value(device
, sysattr
);
2003 /* Do not cache action string written into uevent file. */
2004 if (streq(sysattr
, "uevent"))
2007 r
= device_cache_sysattr_value(device
, sysattr
, value
);
2009 log_device_debug_errno(device
, r
,
2010 "sd-device: failed to cache attribute '%s' with '%s', ignoring: %m",
2018 _public_
int sd_device_set_sysattr_valuef(sd_device
*device
, const char *sysattr
, const char *format
, ...) {
2019 _cleanup_free_
char *value
= NULL
;
2023 assert_return(device
, -EINVAL
);
2024 assert_return(sysattr
, -EINVAL
);
2027 device_remove_cached_sysattr_value(device
, sysattr
);
2031 va_start(ap
, format
);
2032 r
= vasprintf(&value
, format
, ap
);
2038 return sd_device_set_sysattr_value(device
, sysattr
, value
);
2041 _public_
int sd_device_trigger(sd_device
*device
, sd_device_action_t action
) {
2044 assert_return(device
, -EINVAL
);
2046 s
= device_action_to_string(action
);
2050 return sd_device_set_sysattr_value(device
, "uevent", s
);