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"
31 int device_new_aux(sd_device
**ret
) {
36 device
= new(sd_device
, 1);
40 *device
= (sd_device
) {
43 .devmode
= (mode_t
) -1,
46 .action
= _DEVICE_ACTION_INVALID
,
53 static sd_device
*device_free(sd_device
*device
) {
56 sd_device_unref(device
->parent
);
57 free(device
->syspath
);
58 free(device
->sysname
);
59 free(device
->devtype
);
60 free(device
->devname
);
61 free(device
->subsystem
);
62 free(device
->driver_subsystem
);
64 free(device
->id_filename
);
65 free(device
->properties_strv
);
66 free(device
->properties_nulstr
);
68 ordered_hashmap_free_free_free(device
->properties
);
69 ordered_hashmap_free_free_free(device
->properties_db
);
70 hashmap_free_free_free(device
->sysattr_values
);
71 set_free(device
->sysattrs
);
72 set_free(device
->all_tags
);
73 set_free(device
->current_tags
);
74 set_free(device
->devlinks
);
79 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device
, sd_device
, device_free
);
81 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
82 OrderedHashmap
**properties
;
88 properties
= &device
->properties_db
;
90 properties
= &device
->properties
;
93 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
96 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
104 value
= strdup(_value
);
108 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
110 r
= ordered_hashmap_replace(*properties
, key
, value
);
117 _cleanup_free_
char *key
= NULL
;
118 _cleanup_free_
char *value
= NULL
;
120 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
124 device
->properties_generation
++;
125 device
->properties_buf_outdated
= true;
131 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
132 return device_add_property_aux(device
, key
, value
, false);
135 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
136 _cleanup_free_
char *syspath
= NULL
;
143 /* must be a subdirectory of /sys */
144 if (!path_startswith(_syspath
, "/sys/"))
145 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
146 "sd-device: Syspath '%s' is not a subdirectory of /sys",
150 r
= chase_symlinks(_syspath
, NULL
, 0, &syspath
, NULL
);
152 return -ENODEV
; /* the device does not exist (any more?) */
154 return log_debug_errno(r
, "sd-device: Failed to get target of '%s': %m", _syspath
);
156 if (!path_startswith(syspath
, "/sys")) {
157 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
160 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
161 r
= chase_symlinks("/sys", NULL
, 0, &real_sys
, NULL
);
163 return log_debug_errno(r
, "sd-device: Failed to chase symlink /sys: %m");
165 p
= path_startswith(syspath
, real_sys
);
167 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
168 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
171 new_syspath
= path_join("/sys", p
);
175 free_and_replace(syspath
, new_syspath
);
176 path_simplify(syspath
, false);
179 if (path_startswith(syspath
, "/sys/devices/")) {
182 /* all 'devices' require an 'uevent' file */
183 path
= strjoina(syspath
, "/uevent");
184 r
= access(path
, F_OK
);
187 /* this is not a valid device */
190 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
193 /* everything else just needs to be a directory */
194 if (!is_dir(syspath
, false))
198 syspath
= strdup(_syspath
);
203 devpath
= syspath
+ STRLEN("/sys");
205 if (devpath
[0] == '\0')
206 /* '/sys' alone is not a valid device path */
209 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
213 free_and_replace(device
->syspath
, syspath
);
214 device
->devpath
= devpath
;
218 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
219 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
222 assert_return(ret
, -EINVAL
);
223 assert_return(syspath
, -EINVAL
);
225 r
= device_new_aux(&device
);
229 r
= device_set_syspath(device
, syspath
, true);
233 *ret
= TAKE_PTR(device
);
237 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
239 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
241 assert_return(ret
, -EINVAL
);
242 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
244 /* use /sys/dev/{block,char}/<maj>:<min> link */
245 xsprintf(id
, "%u:%u", major(devnum
), minor(devnum
));
247 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
249 return sd_device_new_from_syspath(ret
, syspath
);
252 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
253 char *name
, *syspath
;
256 assert_return(ret
, -EINVAL
);
257 assert_return(subsystem
, -EINVAL
);
258 assert_return(sysname
, -EINVAL
);
260 if (streq(subsystem
, "subsystem")) {
261 syspath
= strjoina("/sys/subsystem/", sysname
);
262 if (access(syspath
, F_OK
) >= 0)
263 return sd_device_new_from_syspath(ret
, syspath
);
265 syspath
= strjoina("/sys/bus/", sysname
);
266 if (access(syspath
, F_OK
) >= 0)
267 return sd_device_new_from_syspath(ret
, syspath
);
269 syspath
= strjoina("/sys/class/", sysname
);
270 if (access(syspath
, F_OK
) >= 0)
271 return sd_device_new_from_syspath(ret
, syspath
);
272 } else if (streq(subsystem
, "module")) {
273 syspath
= strjoina("/sys/module/", sysname
);
274 if (access(syspath
, F_OK
) >= 0)
275 return sd_device_new_from_syspath(ret
, syspath
);
276 } else if (streq(subsystem
, "drivers")) {
277 char subsys
[PATH_MAX
];
280 strscpy(subsys
, sizeof(subsys
), sysname
);
281 driver
= strchr(subsys
, ':');
286 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
287 if (access(syspath
, F_OK
) >= 0)
288 return sd_device_new_from_syspath(ret
, syspath
);
290 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
291 if (access(syspath
, F_OK
) >= 0)
292 return sd_device_new_from_syspath(ret
, syspath
);
296 /* translate sysname back to sysfs filename */
297 name
= strdupa(sysname
);
298 while (name
[len
] != '\0') {
299 if (name
[len
] == '/')
305 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
306 if (access(syspath
, F_OK
) >= 0)
307 return sd_device_new_from_syspath(ret
, syspath
);
309 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
310 if (access(syspath
, F_OK
) >= 0)
311 return sd_device_new_from_syspath(ret
, syspath
);
313 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
314 if (access(syspath
, F_OK
) >= 0)
315 return sd_device_new_from_syspath(ret
, syspath
);
317 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
318 if (access(syspath
, F_OK
) >= 0)
319 return sd_device_new_from_syspath(ret
, syspath
);
324 int device_set_devtype(sd_device
*device
, const char *devtype
) {
325 _cleanup_free_
char *t
= NULL
;
335 r
= device_add_property_internal(device
, "DEVTYPE", t
);
339 return free_and_replace(device
->devtype
, t
);
342 int device_set_ifindex(sd_device
*device
, const char *name
) {
348 ifindex
= parse_ifindex(name
);
352 r
= device_add_property_internal(device
, "IFINDEX", name
);
356 device
->ifindex
= ifindex
;
361 int device_set_devname(sd_device
*device
, const char *devname
) {
362 _cleanup_free_
char *t
= NULL
;
368 if (devname
[0] != '/')
369 t
= strjoin("/dev/", devname
);
375 r
= device_add_property_internal(device
, "DEVNAME", t
);
379 return free_and_replace(device
->devname
, t
);
382 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
389 r
= safe_atou(_devmode
, &devmode
);
396 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
400 device
->devmode
= devmode
;
405 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
406 unsigned maj
= 0, min
= 0;
412 r
= safe_atou(major
, &maj
);
419 r
= safe_atou(minor
, &min
);
424 r
= device_add_property_internal(device
, "MAJOR", major
);
429 r
= device_add_property_internal(device
, "MINOR", minor
);
434 device
->devnum
= makedev(maj
, min
);
439 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
448 if (streq(key
, "DEVTYPE")) {
449 r
= device_set_devtype(device
, value
);
452 } else if (streq(key
, "IFINDEX")) {
453 r
= device_set_ifindex(device
, value
);
456 } else if (streq(key
, "DEVNAME")) {
457 r
= device_set_devname(device
, value
);
460 } else if (streq(key
, "DEVMODE")) {
461 r
= device_set_devmode(device
, value
);
464 } else if (streq(key
, "MAJOR"))
466 else if (streq(key
, "MINOR"))
469 r
= device_add_property_internal(device
, key
, value
);
477 int device_read_uevent_file(sd_device
*device
) {
478 _cleanup_free_
char *uevent
= NULL
;
479 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
495 if (device
->uevent_loaded
|| device
->sealed
)
498 r
= sd_device_get_syspath(device
, &syspath
);
502 path
= strjoina(syspath
, "/uevent");
504 r
= read_full_file(path
, &uevent
, &uevent_len
);
506 /* empty uevent files may be write-only */
507 device
->uevent_loaded
= true;
511 /* some devices may not have uevent files, see set_syspath() */
514 return log_device_debug_errno(device
, r
, "sd-device: Failed to read uevent file '%s': %m", path
);
516 device
->uevent_loaded
= true;
518 for (i
= 0; i
< uevent_len
; i
++)
521 if (!strchr(NEWLINE
, uevent
[i
])) {
529 if (uevent
[i
] == '=') {
533 } else if (strchr(NEWLINE
, uevent
[i
])) {
535 log_device_debug(device
, "sd-device: Invalid uevent line '%s', ignoring", key
);
545 _fallthrough_
; /* to handle empty property */
547 if (strchr(NEWLINE
, uevent
[i
])) {
550 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
552 log_device_debug_errno(device
, r
, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key
, value
);
559 assert_not_reached("Invalid state when parsing uevent file");
563 r
= device_set_devnum(device
, major
, minor
);
565 log_device_debug_errno(device
, r
, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major
, minor
, path
);
571 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
574 assert_return(device
, -EINVAL
);
576 r
= device_read_uevent_file(device
);
580 if (device
->ifindex
<= 0)
584 *ifindex
= device
->ifindex
;
589 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
592 assert_return(ret
, -EINVAL
);
593 assert_return(id
, -EINVAL
);
603 r
= parse_dev(id
+ 1, &devt
);
607 return sd_device_new_from_devnum(ret
, id
[0], devt
);
611 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
612 _cleanup_close_
int sk
= -1;
613 struct ifreq ifr
= {};
616 r
= ifr
.ifr_ifindex
= parse_ifindex(&id
[1]);
620 sk
= socket_ioctl_fd();
624 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
628 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
632 r
= sd_device_get_ifindex(device
, &ifindex
);
636 /* this is racey, so we might end up with the wrong device */
637 if (ifr
.ifr_ifindex
!= ifindex
)
640 *ret
= TAKE_PTR(device
);
645 char subsys
[PATH_MAX
];
648 (void) strscpy(subsys
, sizeof(subsys
), id
+ 1);
649 sysname
= strchr(subsys
, ':');
656 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
664 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
665 assert_return(device
, -EINVAL
);
666 assert_return(ret
, -EINVAL
);
668 assert(path_startswith(device
->syspath
, "/sys/"));
670 *ret
= device
->syspath
;
675 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
676 _cleanup_free_
char *path
= NULL
;
677 const char *subdir
, *syspath
;
683 r
= sd_device_get_syspath(child
, &syspath
);
687 path
= strdup(syspath
);
690 subdir
= path
+ STRLEN("/sys");
695 pos
= strrchr(subdir
, '/');
696 if (!pos
|| pos
< subdir
+ 2)
701 r
= sd_device_new_from_syspath(ret
, path
);
711 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
713 assert_return(ret
, -EINVAL
);
714 assert_return(child
, -EINVAL
);
716 if (!child
->parent_set
) {
717 child
->parent_set
= true;
719 (void) device_new_from_child(&child
->parent
, child
);
725 *ret
= child
->parent
;
729 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
730 _cleanup_free_
char *subsystem
= NULL
;
736 subsystem
= strdup(_subsystem
);
740 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
744 device
->subsystem_set
= true;
745 return free_and_replace(device
->subsystem
, subsystem
);
748 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
749 _cleanup_free_
char *subsystem
= NULL
;
756 subsystem
= strdup(_subsystem
);
760 r
= device_set_subsystem(device
, "drivers");
764 return free_and_replace(device
->driver_subsystem
, subsystem
);
767 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
768 const char *syspath
, *drivers
= NULL
;
771 assert_return(ret
, -EINVAL
);
772 assert_return(device
, -EINVAL
);
774 r
= sd_device_get_syspath(device
, &syspath
);
778 if (!device
->subsystem_set
) {
779 _cleanup_free_
char *subsystem
= NULL
;
782 /* read 'subsystem' link */
783 path
= strjoina(syspath
, "/subsystem");
784 r
= readlink_value(path
, &subsystem
);
786 r
= device_set_subsystem(device
, subsystem
);
787 /* use implicit names */
788 else if (path_startswith(device
->devpath
, "/module/"))
789 r
= device_set_subsystem(device
, "module");
790 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
791 PATH_STARTSWITH_SET(device
->devpath
, "/subsystem/",
794 r
= device_set_subsystem(device
, "subsystem");
795 if (r
< 0 && r
!= -ENOENT
)
796 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem for %s: %m", device
->devpath
);
798 device
->subsystem_set
= true;
799 } else if (!device
->driver_subsystem_set
)
800 drivers
= strstr(syspath
, "/drivers/");
802 if (!device
->driver_subsystem_set
) {
804 _cleanup_free_
char *subpath
= NULL
;
806 subpath
= strndup(syspath
, drivers
- syspath
);
812 subsys
= strrchr(subpath
, '/');
816 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
818 if (r
< 0 && r
!= -ENOENT
)
819 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem for driver %s: %m", device
->devpath
);
822 device
->driver_subsystem_set
= true;
825 if (!device
->subsystem
)
828 *ret
= device
->subsystem
;
832 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
835 assert_return(device
, -EINVAL
);
837 r
= device_read_uevent_file(device
);
841 if (!device
->devtype
)
845 *devtype
= device
->devtype
;
847 return !!device
->devtype
;
850 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
851 sd_device
*parent
= NULL
;
854 assert_return(child
, -EINVAL
);
855 assert_return(subsystem
, -EINVAL
);
857 r
= sd_device_get_parent(child
, &parent
);
859 const char *parent_subsystem
= NULL
;
860 const char *parent_devtype
= NULL
;
862 (void) sd_device_get_subsystem(parent
, &parent_subsystem
);
863 if (streq_ptr(parent_subsystem
, subsystem
)) {
867 (void) sd_device_get_devtype(parent
, &parent_devtype
);
868 if (streq_ptr(parent_devtype
, devtype
))
871 r
= sd_device_get_parent(parent
, &parent
);
881 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
884 assert_return(device
, -EINVAL
);
886 r
= device_read_uevent_file(device
);
890 if (major(device
->devnum
) <= 0)
894 *devnum
= device
->devnum
;
899 int device_set_driver(sd_device
*device
, const char *_driver
) {
900 _cleanup_free_
char *driver
= NULL
;
906 driver
= strdup(_driver
);
910 r
= device_add_property_internal(device
, "DRIVER", driver
);
914 device
->driver_set
= true;
915 return free_and_replace(device
->driver
, driver
);
918 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
919 assert_return(device
, -EINVAL
);
920 assert_return(ret
, -EINVAL
);
922 if (!device
->driver_set
) {
923 _cleanup_free_
char *driver
= NULL
;
928 r
= sd_device_get_syspath(device
, &syspath
);
932 path
= strjoina(syspath
, "/driver");
933 r
= readlink_value(path
, &driver
);
935 r
= device_set_driver(device
, driver
);
937 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver for %s: %m", device
->devpath
);
938 } else if (r
== -ENOENT
)
939 device
->driver_set
= true;
941 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver for %s: %m", device
->devpath
);
947 *ret
= device
->driver
;
951 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
952 assert_return(device
, -EINVAL
);
953 assert_return(devpath
, -EINVAL
);
955 assert(device
->devpath
);
956 assert(device
->devpath
[0] == '/');
958 *devpath
= device
->devpath
;
962 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
965 assert_return(device
, -EINVAL
);
966 assert_return(devname
, -EINVAL
);
968 r
= device_read_uevent_file(device
);
972 if (!device
->devname
)
975 assert(path_startswith(device
->devname
, "/dev/"));
977 *devname
= device
->devname
;
981 static int device_set_sysname(sd_device
*device
) {
982 _cleanup_free_
char *sysname
= NULL
;
983 const char *sysnum
= NULL
;
987 if (!device
->devpath
)
990 pos
= strrchr(device
->devpath
, '/');
995 /* devpath is not a root directory */
996 if (*pos
== '\0' || pos
<= device
->devpath
)
999 sysname
= strdup(pos
);
1003 /* some devices have '!' in their name, change that to '/' */
1004 while (sysname
[len
] != '\0') {
1005 if (sysname
[len
] == '!')
1011 /* trailing number */
1012 while (len
> 0 && isdigit(sysname
[--len
]))
1013 sysnum
= &sysname
[len
];
1018 device
->sysname_set
= true;
1019 device
->sysnum
= sysnum
;
1020 return free_and_replace(device
->sysname
, sysname
);
1023 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1026 assert_return(device
, -EINVAL
);
1027 assert_return(ret
, -EINVAL
);
1029 if (!device
->sysname_set
) {
1030 r
= device_set_sysname(device
);
1035 assert_return(device
->sysname
, -ENOENT
);
1037 *ret
= device
->sysname
;
1041 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1044 assert_return(device
, -EINVAL
);
1045 assert_return(ret
, -EINVAL
);
1047 if (!device
->sysname_set
) {
1048 r
= device_set_sysname(device
);
1053 if (!device
->sysnum
)
1056 *ret
= device
->sysnum
;
1060 static bool is_valid_tag(const char *tag
) {
1063 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1066 int device_add_tag(sd_device
*device
, const char *tag
, bool both
) {
1072 if (!is_valid_tag(tag
))
1075 /* Definitely add to the "all" list of tags (i.e. the sticky list) */
1076 added
= set_put_strdup(&device
->all_tags
, tag
);
1080 /* And optionally, also add it to the current list of tags */
1082 r
= set_put_strdup(&device
->current_tags
, tag
);
1085 (void) set_remove(device
->all_tags
, tag
);
1091 device
->tags_generation
++;
1092 device
->property_tags_outdated
= true;
1097 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1103 r
= set_put_strdup(&device
->devlinks
, devlink
);
1107 device
->devlinks_generation
++;
1108 device
->property_devlinks_outdated
= true;
1113 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1114 _cleanup_free_
char *key
= NULL
;
1125 value
= strchr(key
, '=');
1131 if (isempty(++value
))
1134 /* Add the property to both sd_device::properties and sd_device::properties_db,
1135 * as this is called by only handle_db_line(). */
1136 r
= device_add_property_aux(device
, key
, value
, false);
1140 return device_add_property_aux(device
, key
, value
, true);
1143 int device_set_usec_initialized(sd_device
*device
, usec_t when
) {
1144 char s
[DECIMAL_STR_MAX(usec_t
)];
1149 xsprintf(s
, USEC_FMT
, when
);
1151 r
= device_add_property_internal(device
, "USEC_INITIALIZED", s
);
1155 device
->usec_initialized
= when
;
1159 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1167 case 'G': /* Any tag */
1168 case 'Q': /* Current tag */
1169 r
= device_add_tag(device
, value
, key
== 'Q');
1175 path
= strjoina("/dev/", value
);
1176 r
= device_add_devlink(device
, path
);
1182 r
= device_add_property_internal_from_string(device
, value
);
1190 r
= safe_atou64(value
, &t
);
1194 r
= device_set_usec_initialized(device
, t
);
1201 r
= safe_atoi(value
, &device
->devlink_priority
);
1207 r
= safe_atoi(value
, &device
->watch_handle
);
1213 log_device_debug(device
, "sd-device: Unknown key '%c' in device db, ignoring", key
);
1219 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1223 if (!device
->id_filename
) {
1224 _cleanup_free_
char *id
= NULL
;
1225 const char *subsystem
;
1229 r
= sd_device_get_subsystem(device
, &subsystem
);
1233 if (sd_device_get_devnum(device
, &devnum
) >= 0) {
1236 /* use dev_t — b259:131072, c254:0 */
1237 r
= asprintf(&id
, "%c%u:%u",
1238 streq(subsystem
, "block") ? 'b' : 'c',
1239 major(devnum
), minor(devnum
));
1242 } else if (sd_device_get_ifindex(device
, &ifindex
) >= 0) {
1243 /* use netdev ifindex — n3 */
1244 r
= asprintf(&id
, "n%u", (unsigned) ifindex
);
1248 /* use $subsys:$sysname — pci:0000:00:1f.2
1249 * sysname() has '!' translated, get it from devpath
1251 const char *sysname
;
1253 sysname
= basename(device
->devpath
);
1261 if (streq(subsystem
, "drivers"))
1262 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1263 * encoded as well */
1264 id
= strjoin("+drivers:", device
->driver_subsystem
, ":", sysname
);
1266 id
= strjoin("+", subsystem
, ":", sysname
);
1271 device
->id_filename
= TAKE_PTR(id
);
1274 *ret
= device
->id_filename
;
1278 int device_read_db_internal_filename(sd_device
*device
, const char *filename
) {
1279 _cleanup_free_
char *db
= NULL
;
1296 r
= read_full_file(filename
, &db
, &db_len
);
1301 return log_device_debug_errno(device
, r
, "sd-device: Failed to read db '%s': %m", filename
);
1304 /* devices with a database entry are initialized */
1305 device
->is_initialized
= true;
1307 device
->db_loaded
= true;
1309 for (i
= 0; i
< db_len
; i
++) {
1312 if (!strchr(NEWLINE
, db
[i
])) {
1321 log_device_debug(device
, "sd-device: Invalid db entry with key '%c', ignoring", key
);
1323 state
= INVALID_LINE
;
1338 if (strchr(NEWLINE
, db
[i
]))
1343 if (strchr(NEWLINE
, db
[i
])) {
1345 r
= handle_db_line(device
, key
, value
);
1347 log_device_debug_errno(device
, r
, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key
, value
);
1354 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
), "sd-device: invalid db syntax.");
1361 int device_read_db_internal(sd_device
*device
, bool force
) {
1362 const char *id
, *path
;
1367 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1370 r
= device_get_id_filename(device
, &id
);
1374 path
= strjoina("/run/udev/data/", id
);
1376 return device_read_db_internal_filename(device
, path
);
1379 _public_
int sd_device_get_is_initialized(sd_device
*device
) {
1382 assert_return(device
, -EINVAL
);
1384 r
= device_read_db(device
);
1388 return device
->is_initialized
;
1391 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1395 assert_return(device
, -EINVAL
);
1396 assert_return(usec
, -EINVAL
);
1398 r
= device_read_db(device
);
1402 if (!device
->is_initialized
)
1405 if (!device
->usec_initialized
)
1408 now_ts
= now(clock_boottime_or_monotonic());
1410 if (now_ts
< device
->usec_initialized
)
1413 *usec
= now_ts
- device
->usec_initialized
;
1417 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1420 assert_return(device
, NULL
);
1422 (void) device_read_db(device
);
1424 device
->all_tags_iterator_generation
= device
->tags_generation
;
1425 device
->all_tags_iterator
= ITERATOR_FIRST
;
1427 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1431 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1434 assert_return(device
, NULL
);
1436 (void) device_read_db(device
);
1438 if (device
->all_tags_iterator_generation
!= device
->tags_generation
)
1441 (void) set_iterate(device
->all_tags
, &device
->all_tags_iterator
, &v
);
1445 _public_
const char *sd_device_get_current_tag_first(sd_device
*device
) {
1448 assert_return(device
, NULL
);
1450 (void) device_read_db(device
);
1452 device
->current_tags_iterator_generation
= device
->tags_generation
;
1453 device
->current_tags_iterator
= ITERATOR_FIRST
;
1455 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1459 _public_
const char *sd_device_get_current_tag_next(sd_device
*device
) {
1462 assert_return(device
, NULL
);
1464 (void) device_read_db(device
);
1466 if (device
->current_tags_iterator_generation
!= device
->tags_generation
)
1469 (void) set_iterate(device
->current_tags
, &device
->current_tags_iterator
, &v
);
1473 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1476 assert_return(device
, NULL
);
1478 (void) device_read_db(device
);
1480 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1481 device
->devlinks_iterator
= ITERATOR_FIRST
;
1483 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1487 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1490 assert_return(device
, NULL
);
1492 (void) device_read_db(device
);
1494 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1497 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1501 static char *join_string_set(Set
*s
) {
1502 size_t ret_allocated
= 0, ret_len
;
1503 _cleanup_free_
char *ret
= NULL
;
1506 if (!GREEDY_REALLOC(ret
, ret_allocated
, 2))
1512 SET_FOREACH(tag
, s
) {
1515 if (!GREEDY_REALLOC(ret
, ret_allocated
, ret_len
+ strlen(tag
) + 2))
1518 e
= stpcpy(stpcpy(ret
+ ret_len
, tag
), ":");
1522 return TAKE_PTR(ret
);
1525 int device_properties_prepare(sd_device
*device
) {
1530 r
= device_read_uevent_file(device
);
1534 r
= device_read_db(device
);
1538 if (device
->property_devlinks_outdated
) {
1539 _cleanup_free_
char *devlinks
= NULL
;
1540 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1541 const char *devlink
;
1543 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1546 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1548 if (devlinks_len
> 0)
1549 stpcpy(devlinks
+ devlinks_len
++, " ");
1550 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1551 devlinks_len
= e
- devlinks
;
1554 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1558 device
->property_devlinks_outdated
= false;
1561 if (device
->property_tags_outdated
) {
1562 _cleanup_free_
char *tags
= NULL
;
1564 tags
= join_string_set(device
->all_tags
);
1568 if (!streq(tags
, ":")) {
1569 r
= device_add_property_internal(device
, "TAGS", tags
);
1575 tags
= join_string_set(device
->current_tags
);
1579 if (!streq(tags
, ":")) {
1580 r
= device_add_property_internal(device
, "CURRENT_TAGS", tags
);
1585 device
->property_tags_outdated
= false;
1591 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1595 assert_return(device
, NULL
);
1597 r
= device_properties_prepare(device
);
1601 device
->properties_iterator_generation
= device
->properties_generation
;
1602 device
->properties_iterator
= ITERATOR_FIRST
;
1604 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
1608 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1612 assert_return(device
, NULL
);
1614 r
= device_properties_prepare(device
);
1618 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1621 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
1625 static int device_sysattrs_read_all_internal(sd_device
*device
, const char *subdir
) {
1626 _cleanup_free_
char *path_dir
= NULL
;
1627 _cleanup_closedir_
DIR *dir
= NULL
;
1628 struct dirent
*dent
;
1629 const char *syspath
;
1632 r
= sd_device_get_syspath(device
, &syspath
);
1637 _cleanup_free_
char *p
= NULL
;
1639 p
= path_join(syspath
, subdir
, "uevent");
1643 if (access(p
, F_OK
) >= 0)
1644 /* this is a child device, skipping */
1646 if (errno
!= ENOENT
) {
1647 log_device_debug_errno(device
, errno
, "sd-device: Failed to stat %s, ignoring subdir: %m", p
);
1651 path_dir
= path_join(syspath
, subdir
);
1656 dir
= opendir(path_dir
?: syspath
);
1660 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1661 _cleanup_free_
char *path
= NULL
, *p
= NULL
;
1662 struct stat statbuf
;
1664 if (dot_or_dot_dot(dent
->d_name
))
1667 /* only handle symlinks, regular files, and directories */
1668 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
, DT_DIR
))
1672 p
= path_join(subdir
, dent
->d_name
);
1677 if (dent
->d_type
== DT_DIR
) {
1678 /* read subdirectory */
1679 r
= device_sysattrs_read_all_internal(device
, p
?: dent
->d_name
);
1686 path
= path_join(syspath
, p
?: dent
->d_name
);
1690 if (lstat(path
, &statbuf
) != 0)
1693 if (!(statbuf
.st_mode
& S_IRUSR
))
1696 r
= set_put_strdup(&device
->sysattrs
, p
?: dent
->d_name
);
1704 static int device_sysattrs_read_all(sd_device
*device
) {
1709 if (device
->sysattrs_read
)
1712 r
= device_sysattrs_read_all_internal(device
, NULL
);
1716 device
->sysattrs_read
= true;
1721 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1725 assert_return(device
, NULL
);
1727 if (!device
->sysattrs_read
) {
1728 r
= device_sysattrs_read_all(device
);
1735 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1737 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1741 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1744 assert_return(device
, NULL
);
1746 if (!device
->sysattrs_read
)
1749 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1753 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1754 assert_return(device
, -EINVAL
);
1755 assert_return(tag
, -EINVAL
);
1757 (void) device_read_db(device
);
1759 return set_contains(device
->all_tags
, tag
);
1762 _public_
int sd_device_has_current_tag(sd_device
*device
, const char *tag
) {
1763 assert_return(device
, -EINVAL
);
1764 assert_return(tag
, -EINVAL
);
1766 (void) device_read_db(device
);
1768 return set_contains(device
->current_tags
, tag
);
1771 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1775 assert_return(device
, -EINVAL
);
1776 assert_return(key
, -EINVAL
);
1778 r
= device_properties_prepare(device
);
1782 value
= ordered_hashmap_get(device
->properties
, key
);
1791 /* replaces the value if it already exists */
1792 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1793 _cleanup_free_
char *key
= NULL
;
1794 _cleanup_free_
char *value_old
= NULL
;
1800 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1804 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1811 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1819 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1820 const char *key
= NULL
, *value
;
1825 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1834 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1835 * with a NULL value in the cache, otherwise the returned string is stored */
1836 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1837 _cleanup_free_
char *value
= NULL
;
1838 const char *path
, *syspath
, *cached_value
= NULL
;
1839 struct stat statbuf
;
1842 assert_return(device
, -EINVAL
);
1843 assert_return(sysattr
, -EINVAL
);
1845 /* look for possibly already cached result */
1846 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1852 /* we looked up the sysattr before and it did not exist */
1856 *_value
= cached_value
;
1861 r
= sd_device_get_syspath(device
, &syspath
);
1865 path
= prefix_roota(syspath
, sysattr
);
1866 r
= lstat(path
, &statbuf
);
1868 /* remember that we could not access the sysattr */
1869 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1874 } else if (S_ISLNK(statbuf
.st_mode
)) {
1875 /* Some core links return only the last element of the target path,
1876 * these are just values, the paths should not be exposed. */
1877 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1878 r
= readlink_value(path
, &value
);
1883 } else if (S_ISDIR(statbuf
.st_mode
)) {
1884 /* skip directories */
1886 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1887 /* skip non-readable files */
1892 /* read attribute value */
1893 r
= read_full_virtual_file(path
, &value
, &size
);
1897 /* drop trailing newlines */
1898 while (size
> 0 && value
[--size
] == '\n')
1902 r
= device_add_sysattr_value(device
, sysattr
, value
);
1906 *_value
= TAKE_PTR(value
);
1911 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1912 _cleanup_free_
char *key
= NULL
;
1917 free(hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
));
1920 /* set the attribute and save it in the cache. If a NULL value is passed the
1921 * attribute is cleared from the cache */
1922 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, const char *_value
) {
1923 _cleanup_free_
char *value
= NULL
;
1924 const char *syspath
, *path
;
1928 assert_return(device
, -EINVAL
);
1929 assert_return(sysattr
, -EINVAL
);
1932 device_remove_sysattr_value(device
, sysattr
);
1936 r
= sd_device_get_syspath(device
, &syspath
);
1940 path
= prefix_roota(syspath
, sysattr
);
1942 len
= strlen(_value
);
1944 /* drop trailing newlines */
1945 while (len
> 0 && _value
[len
- 1] == '\n')
1948 /* value length is limited to 4k */
1952 value
= strndup(_value
, len
);
1956 r
= write_string_file(path
, value
, WRITE_STRING_FILE_DISABLE_BUFFER
| WRITE_STRING_FILE_NOFOLLOW
);
1963 r
= free_and_strdup(&value
, "");
1967 r
= device_add_sysattr_value(device
, sysattr
, value
);
1975 r
= device_add_sysattr_value(device
, sysattr
, value
);
1983 _public_
int sd_device_set_sysattr_valuef(sd_device
*device
, const char *sysattr
, const char *format
, ...) {
1984 _cleanup_free_
char *value
= NULL
;
1988 assert_return(device
, -EINVAL
);
1989 assert_return(sysattr
, -EINVAL
);
1992 device_remove_sysattr_value(device
, sysattr
);
1996 va_start(ap
, format
);
1997 r
= vasprintf(&value
, format
, ap
);
2003 return sd_device_set_sysattr_value(device
, sysattr
, value
);