1 /* SPDX-License-Identifier: LGPL-2.1+ */
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
->tags
);
73 set_free(device
->devlinks
);
78 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device
, sd_device
, device_free
);
80 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
81 OrderedHashmap
**properties
;
87 properties
= &device
->properties_db
;
89 properties
= &device
->properties
;
92 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
95 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
103 value
= strdup(_value
);
107 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
109 r
= ordered_hashmap_replace(*properties
, key
, value
);
116 _cleanup_free_
char *key
= NULL
;
117 _cleanup_free_
char *value
= NULL
;
119 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
123 device
->properties_generation
++;
124 device
->properties_buf_outdated
= true;
130 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
131 return device_add_property_aux(device
, key
, value
, false);
134 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
135 _cleanup_free_
char *syspath
= NULL
;
142 /* must be a subdirectory of /sys */
143 if (!path_startswith(_syspath
, "/sys/"))
144 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
145 "sd-device: Syspath '%s' is not a subdirectory of /sys",
149 r
= chase_symlinks(_syspath
, NULL
, 0, &syspath
, NULL
);
151 return -ENODEV
; /* the device does not exist (any more?) */
153 return log_debug_errno(r
, "sd-device: Failed to get target of '%s': %m", _syspath
);
155 if (!path_startswith(syspath
, "/sys")) {
156 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
159 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
160 r
= chase_symlinks("/sys", NULL
, 0, &real_sys
, NULL
);
162 return log_debug_errno(r
, "sd-device: Failed to chase symlink /sys: %m");
164 p
= path_startswith(syspath
, real_sys
);
166 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV
),
167 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
170 new_syspath
= path_join("/sys", p
);
174 free_and_replace(syspath
, new_syspath
);
175 path_simplify(syspath
, false);
178 if (path_startswith(syspath
, "/sys/devices/")) {
181 /* all 'devices' require an 'uevent' file */
182 path
= strjoina(syspath
, "/uevent");
183 r
= access(path
, F_OK
);
186 /* this is not a valid device */
189 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
192 /* everything else just needs to be a directory */
193 if (!is_dir(syspath
, false))
197 syspath
= strdup(_syspath
);
202 devpath
= syspath
+ STRLEN("/sys");
204 if (devpath
[0] == '\0')
205 /* '/sys' alone is not a valid device path */
208 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
212 free_and_replace(device
->syspath
, syspath
);
213 device
->devpath
= devpath
;
217 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
218 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
221 assert_return(ret
, -EINVAL
);
222 assert_return(syspath
, -EINVAL
);
224 r
= device_new_aux(&device
);
228 r
= device_set_syspath(device
, syspath
, true);
232 *ret
= TAKE_PTR(device
);
236 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
238 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
240 assert_return(ret
, -EINVAL
);
241 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
243 /* use /sys/dev/{block,char}/<maj>:<min> link */
244 xsprintf(id
, "%u:%u", major(devnum
), minor(devnum
));
246 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
248 return sd_device_new_from_syspath(ret
, syspath
);
251 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
252 char *name
, *syspath
;
255 assert_return(ret
, -EINVAL
);
256 assert_return(subsystem
, -EINVAL
);
257 assert_return(sysname
, -EINVAL
);
259 if (streq(subsystem
, "subsystem")) {
260 syspath
= strjoina("/sys/subsystem/", sysname
);
261 if (access(syspath
, F_OK
) >= 0)
262 return sd_device_new_from_syspath(ret
, syspath
);
264 syspath
= strjoina("/sys/bus/", sysname
);
265 if (access(syspath
, F_OK
) >= 0)
266 return sd_device_new_from_syspath(ret
, syspath
);
268 syspath
= strjoina("/sys/class/", sysname
);
269 if (access(syspath
, F_OK
) >= 0)
270 return sd_device_new_from_syspath(ret
, syspath
);
271 } else if (streq(subsystem
, "module")) {
272 syspath
= strjoina("/sys/module/", sysname
);
273 if (access(syspath
, F_OK
) >= 0)
274 return sd_device_new_from_syspath(ret
, syspath
);
275 } else if (streq(subsystem
, "drivers")) {
276 char subsys
[PATH_MAX
];
279 strscpy(subsys
, sizeof(subsys
), sysname
);
280 driver
= strchr(subsys
, ':');
285 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
286 if (access(syspath
, F_OK
) >= 0)
287 return sd_device_new_from_syspath(ret
, syspath
);
289 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
290 if (access(syspath
, F_OK
) >= 0)
291 return sd_device_new_from_syspath(ret
, syspath
);
295 /* translate sysname back to sysfs filename */
296 name
= strdupa(sysname
);
297 while (name
[len
] != '\0') {
298 if (name
[len
] == '/')
304 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
305 if (access(syspath
, F_OK
) >= 0)
306 return sd_device_new_from_syspath(ret
, syspath
);
308 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
309 if (access(syspath
, F_OK
) >= 0)
310 return sd_device_new_from_syspath(ret
, syspath
);
312 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
313 if (access(syspath
, F_OK
) >= 0)
314 return sd_device_new_from_syspath(ret
, syspath
);
316 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
317 if (access(syspath
, F_OK
) >= 0)
318 return sd_device_new_from_syspath(ret
, syspath
);
323 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
324 _cleanup_free_
char *devtype
= NULL
;
330 devtype
= strdup(_devtype
);
334 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
338 free_and_replace(device
->devtype
, devtype
);
343 int device_set_ifindex(sd_device
*device
, const char *name
) {
349 ifindex
= parse_ifindex(name
);
353 r
= device_add_property_internal(device
, "IFINDEX", name
);
357 device
->ifindex
= ifindex
;
362 int device_set_devname(sd_device
*device
, const char *_devname
) {
363 _cleanup_free_
char *devname
= NULL
;
369 if (_devname
[0] != '/') {
370 r
= asprintf(&devname
, "/dev/%s", _devname
);
374 devname
= strdup(_devname
);
379 r
= device_add_property_internal(device
, "DEVNAME", devname
);
383 free_and_replace(device
->devname
, devname
);
388 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
395 r
= safe_atou(_devmode
, &devmode
);
402 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
406 device
->devmode
= devmode
;
411 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
412 unsigned maj
= 0, min
= 0;
418 r
= safe_atou(major
, &maj
);
425 r
= safe_atou(minor
, &min
);
430 r
= device_add_property_internal(device
, "MAJOR", major
);
435 r
= device_add_property_internal(device
, "MINOR", minor
);
440 device
->devnum
= makedev(maj
, min
);
445 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
454 if (streq(key
, "DEVTYPE")) {
455 r
= device_set_devtype(device
, value
);
458 } else if (streq(key
, "IFINDEX")) {
459 r
= device_set_ifindex(device
, value
);
462 } else if (streq(key
, "DEVNAME")) {
463 r
= device_set_devname(device
, value
);
466 } else if (streq(key
, "DEVMODE")) {
467 r
= device_set_devmode(device
, value
);
470 } else if (streq(key
, "MAJOR"))
472 else if (streq(key
, "MINOR"))
475 r
= device_add_property_internal(device
, key
, value
);
483 int device_read_uevent_file(sd_device
*device
) {
484 _cleanup_free_
char *uevent
= NULL
;
485 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
501 if (device
->uevent_loaded
|| device
->sealed
)
504 r
= sd_device_get_syspath(device
, &syspath
);
508 path
= strjoina(syspath
, "/uevent");
510 r
= read_full_file(path
, &uevent
, &uevent_len
);
512 /* empty uevent files may be write-only */
513 device
->uevent_loaded
= true;
517 /* some devices may not have uevent files, see set_syspath() */
520 return log_device_debug_errno(device
, r
, "sd-device: Failed to read uevent file '%s': %m", path
);
522 device
->uevent_loaded
= true;
524 for (i
= 0; i
< uevent_len
; i
++)
527 if (!strchr(NEWLINE
, uevent
[i
])) {
535 if (uevent
[i
] == '=') {
539 } else if (strchr(NEWLINE
, uevent
[i
])) {
541 log_device_debug(device
, "sd-device: Invalid uevent line '%s', ignoring", key
);
551 _fallthrough_
; /* to handle empty property */
553 if (strchr(NEWLINE
, uevent
[i
])) {
556 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
558 log_device_debug_errno(device
, r
, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key
, value
);
565 assert_not_reached("Invalid state when parsing uevent file");
569 r
= device_set_devnum(device
, major
, minor
);
571 log_device_debug_errno(device
, r
, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major
, minor
, path
);
577 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
580 assert_return(device
, -EINVAL
);
582 r
= device_read_uevent_file(device
);
586 if (device
->ifindex
<= 0)
590 *ifindex
= device
->ifindex
;
595 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
598 assert_return(ret
, -EINVAL
);
599 assert_return(id
, -EINVAL
);
609 r
= parse_dev(id
+ 1, &devt
);
613 return sd_device_new_from_devnum(ret
, id
[0], devt
);
617 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
618 _cleanup_close_
int sk
= -1;
619 struct ifreq ifr
= {};
622 r
= ifr
.ifr_ifindex
= parse_ifindex(&id
[1]);
626 sk
= socket_ioctl_fd();
630 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
634 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
638 r
= sd_device_get_ifindex(device
, &ifindex
);
642 /* this is racey, so we might end up with the wrong device */
643 if (ifr
.ifr_ifindex
!= ifindex
)
646 *ret
= TAKE_PTR(device
);
651 char subsys
[PATH_MAX
];
654 (void) strscpy(subsys
, sizeof(subsys
), id
+ 1);
655 sysname
= strchr(subsys
, ':');
662 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
670 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
671 assert_return(device
, -EINVAL
);
672 assert_return(ret
, -EINVAL
);
674 assert(path_startswith(device
->syspath
, "/sys/"));
676 *ret
= device
->syspath
;
681 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
682 _cleanup_free_
char *path
= NULL
;
683 const char *subdir
, *syspath
;
689 r
= sd_device_get_syspath(child
, &syspath
);
693 path
= strdup(syspath
);
696 subdir
= path
+ STRLEN("/sys");
701 pos
= strrchr(subdir
, '/');
702 if (!pos
|| pos
< subdir
+ 2)
707 r
= sd_device_new_from_syspath(ret
, path
);
717 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
719 assert_return(ret
, -EINVAL
);
720 assert_return(child
, -EINVAL
);
722 if (!child
->parent_set
) {
723 child
->parent_set
= true;
725 (void) device_new_from_child(&child
->parent
, child
);
731 *ret
= child
->parent
;
735 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
736 _cleanup_free_
char *subsystem
= NULL
;
742 subsystem
= strdup(_subsystem
);
746 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
750 device
->subsystem_set
= true;
751 return free_and_replace(device
->subsystem
, subsystem
);
754 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
755 _cleanup_free_
char *subsystem
= NULL
;
762 subsystem
= strdup(_subsystem
);
766 r
= device_set_subsystem(device
, "drivers");
770 return free_and_replace(device
->driver_subsystem
, subsystem
);
773 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
774 const char *syspath
, *drivers
= NULL
;
777 assert_return(ret
, -EINVAL
);
778 assert_return(device
, -EINVAL
);
780 r
= sd_device_get_syspath(device
, &syspath
);
784 if (!device
->subsystem_set
) {
785 _cleanup_free_
char *subsystem
= NULL
;
788 /* read 'subsystem' link */
789 path
= strjoina(syspath
, "/subsystem");
790 r
= readlink_value(path
, &subsystem
);
792 r
= device_set_subsystem(device
, subsystem
);
793 /* use implicit names */
794 else if (path_startswith(device
->devpath
, "/module/"))
795 r
= device_set_subsystem(device
, "module");
796 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
797 PATH_STARTSWITH_SET(device
->devpath
, "/subsystem/",
800 r
= device_set_subsystem(device
, "subsystem");
801 if (r
< 0 && r
!= -ENOENT
)
802 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem for %s: %m", device
->devpath
);
804 device
->subsystem_set
= true;
805 } else if (!device
->driver_subsystem_set
)
806 drivers
= strstr(syspath
, "/drivers/");
808 if (!device
->driver_subsystem_set
) {
810 _cleanup_free_
char *subpath
= NULL
;
812 subpath
= strndup(syspath
, drivers
- syspath
);
818 subsys
= strrchr(subpath
, '/');
822 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
824 if (r
< 0 && r
!= -ENOENT
)
825 return log_device_debug_errno(device
, r
, "sd-device: Failed to set subsystem for driver %s: %m", device
->devpath
);
828 device
->driver_subsystem_set
= true;
831 if (!device
->subsystem
)
834 *ret
= device
->subsystem
;
838 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
841 assert_return(device
, -EINVAL
);
843 r
= device_read_uevent_file(device
);
847 if (!device
->devtype
)
851 *devtype
= device
->devtype
;
853 return !!device
->devtype
;
856 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
857 sd_device
*parent
= NULL
;
860 assert_return(child
, -EINVAL
);
861 assert_return(subsystem
, -EINVAL
);
863 r
= sd_device_get_parent(child
, &parent
);
865 const char *parent_subsystem
= NULL
;
866 const char *parent_devtype
= NULL
;
868 (void) sd_device_get_subsystem(parent
, &parent_subsystem
);
869 if (streq_ptr(parent_subsystem
, subsystem
)) {
873 (void) sd_device_get_devtype(parent
, &parent_devtype
);
874 if (streq_ptr(parent_devtype
, devtype
))
877 r
= sd_device_get_parent(parent
, &parent
);
887 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
890 assert_return(device
, -EINVAL
);
892 r
= device_read_uevent_file(device
);
896 if (major(device
->devnum
) <= 0)
900 *devnum
= device
->devnum
;
905 int device_set_driver(sd_device
*device
, const char *_driver
) {
906 _cleanup_free_
char *driver
= NULL
;
912 driver
= strdup(_driver
);
916 r
= device_add_property_internal(device
, "DRIVER", driver
);
920 device
->driver_set
= true;
921 return free_and_replace(device
->driver
, driver
);
924 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
925 assert_return(device
, -EINVAL
);
926 assert_return(ret
, -EINVAL
);
928 if (!device
->driver_set
) {
929 _cleanup_free_
char *driver
= NULL
;
934 r
= sd_device_get_syspath(device
, &syspath
);
938 path
= strjoina(syspath
, "/driver");
939 r
= readlink_value(path
, &driver
);
941 r
= device_set_driver(device
, driver
);
943 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver for %s: %m", device
->devpath
);
944 } else if (r
== -ENOENT
)
945 device
->driver_set
= true;
947 return log_device_debug_errno(device
, r
, "sd-device: Failed to set driver for %s: %m", device
->devpath
);
953 *ret
= device
->driver
;
957 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
958 assert_return(device
, -EINVAL
);
959 assert_return(devpath
, -EINVAL
);
961 assert(device
->devpath
);
962 assert(device
->devpath
[0] == '/');
964 *devpath
= device
->devpath
;
968 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
971 assert_return(device
, -EINVAL
);
972 assert_return(devname
, -EINVAL
);
974 r
= device_read_uevent_file(device
);
978 if (!device
->devname
)
981 assert(path_startswith(device
->devname
, "/dev/"));
983 *devname
= device
->devname
;
987 static int device_set_sysname(sd_device
*device
) {
988 _cleanup_free_
char *sysname
= NULL
;
989 const char *sysnum
= NULL
;
993 if (!device
->devpath
)
996 pos
= strrchr(device
->devpath
, '/');
1001 /* devpath is not a root directory */
1002 if (*pos
== '\0' || pos
<= device
->devpath
)
1005 sysname
= strdup(pos
);
1009 /* some devices have '!' in their name, change that to '/' */
1010 while (sysname
[len
] != '\0') {
1011 if (sysname
[len
] == '!')
1017 /* trailing number */
1018 while (len
> 0 && isdigit(sysname
[--len
]))
1019 sysnum
= &sysname
[len
];
1024 device
->sysname_set
= true;
1025 device
->sysnum
= sysnum
;
1026 return free_and_replace(device
->sysname
, sysname
);
1029 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1032 assert_return(device
, -EINVAL
);
1033 assert_return(ret
, -EINVAL
);
1035 if (!device
->sysname_set
) {
1036 r
= device_set_sysname(device
);
1041 assert_return(device
->sysname
, -ENOENT
);
1043 *ret
= device
->sysname
;
1047 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1050 assert_return(device
, -EINVAL
);
1051 assert_return(ret
, -EINVAL
);
1053 if (!device
->sysname_set
) {
1054 r
= device_set_sysname(device
);
1059 if (!device
->sysnum
)
1062 *ret
= device
->sysnum
;
1066 static bool is_valid_tag(const char *tag
) {
1069 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1072 int device_add_tag(sd_device
*device
, const char *tag
) {
1078 if (!is_valid_tag(tag
))
1081 r
= set_put_strdup(&device
->tags
, tag
);
1085 device
->tags_generation
++;
1086 device
->property_tags_outdated
= true;
1091 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1097 r
= set_put_strdup(&device
->devlinks
, devlink
);
1101 device
->devlinks_generation
++;
1102 device
->property_devlinks_outdated
= true;
1107 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1108 _cleanup_free_
char *key
= NULL
;
1119 value
= strchr(key
, '=');
1125 if (isempty(++value
))
1128 /* Add the property to both sd_device::properties and sd_device::properties_db,
1129 * as this is called by only handle_db_line(). */
1130 r
= device_add_property_aux(device
, key
, value
, false);
1134 return device_add_property_aux(device
, key
, value
, true);
1137 int device_set_usec_initialized(sd_device
*device
, usec_t when
) {
1138 char s
[DECIMAL_STR_MAX(usec_t
)];
1143 xsprintf(s
, USEC_FMT
, when
);
1145 r
= device_add_property_internal(device
, "USEC_INITIALIZED", s
);
1149 device
->usec_initialized
= when
;
1153 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1162 r
= device_add_tag(device
, value
);
1168 path
= strjoina("/dev/", value
);
1169 r
= device_add_devlink(device
, path
);
1175 r
= device_add_property_internal_from_string(device
, value
);
1183 r
= safe_atou64(value
, &t
);
1187 r
= device_set_usec_initialized(device
, t
);
1194 r
= safe_atoi(value
, &device
->devlink_priority
);
1200 r
= safe_atoi(value
, &device
->watch_handle
);
1206 log_device_debug(device
, "sd-device: Unknown key '%c' in device db, ignoring", key
);
1212 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1216 if (!device
->id_filename
) {
1217 _cleanup_free_
char *id
= NULL
;
1218 const char *subsystem
;
1222 r
= sd_device_get_subsystem(device
, &subsystem
);
1226 if (sd_device_get_devnum(device
, &devnum
) >= 0) {
1229 /* use dev_t — b259:131072, c254:0 */
1230 r
= asprintf(&id
, "%c%u:%u",
1231 streq(subsystem
, "block") ? 'b' : 'c',
1232 major(devnum
), minor(devnum
));
1235 } else if (sd_device_get_ifindex(device
, &ifindex
) >= 0) {
1236 /* use netdev ifindex — n3 */
1237 r
= asprintf(&id
, "n%u", (unsigned) ifindex
);
1241 /* use $subsys:$sysname — pci:0000:00:1f.2
1242 * sysname() has '!' translated, get it from devpath
1244 const char *sysname
;
1246 sysname
= basename(device
->devpath
);
1253 if (streq(subsystem
, "drivers")) {
1254 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1255 * encoded as well */
1256 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1260 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1266 device
->id_filename
= TAKE_PTR(id
);
1269 *ret
= device
->id_filename
;
1273 int device_read_db_internal_filename(sd_device
*device
, const char *filename
) {
1274 _cleanup_free_
char *db
= NULL
;
1291 r
= read_full_file(filename
, &db
, &db_len
);
1296 return log_device_debug_errno(device
, r
, "sd-device: Failed to read db '%s': %m", filename
);
1299 /* devices with a database entry are initialized */
1300 device
->is_initialized
= true;
1302 device
->db_loaded
= true;
1304 for (i
= 0; i
< db_len
; i
++) {
1307 if (!strchr(NEWLINE
, db
[i
])) {
1316 log_device_debug(device
, "sd-device: Invalid db entry with key '%c', ignoring", key
);
1318 state
= INVALID_LINE
;
1333 if (strchr(NEWLINE
, db
[i
]))
1338 if (strchr(NEWLINE
, db
[i
])) {
1340 r
= handle_db_line(device
, key
, value
);
1342 log_device_debug_errno(device
, r
, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key
, value
);
1349 return log_device_debug_errno(device
, SYNTHETIC_ERRNO(EINVAL
), "sd-device: invalid db syntax.");
1356 int device_read_db_internal(sd_device
*device
, bool force
) {
1357 const char *id
, *path
;
1362 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1365 r
= device_get_id_filename(device
, &id
);
1369 path
= strjoina("/run/udev/data/", id
);
1371 return device_read_db_internal_filename(device
, path
);
1374 _public_
int sd_device_get_is_initialized(sd_device
*device
) {
1377 assert_return(device
, -EINVAL
);
1379 r
= device_read_db(device
);
1383 return device
->is_initialized
;
1386 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1390 assert_return(device
, -EINVAL
);
1391 assert_return(usec
, -EINVAL
);
1393 r
= device_read_db(device
);
1397 if (!device
->is_initialized
)
1400 if (!device
->usec_initialized
)
1403 now_ts
= now(clock_boottime_or_monotonic());
1405 if (now_ts
< device
->usec_initialized
)
1408 *usec
= now_ts
- device
->usec_initialized
;
1412 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1415 assert_return(device
, NULL
);
1417 (void) device_read_db(device
);
1419 device
->tags_iterator_generation
= device
->tags_generation
;
1420 device
->tags_iterator
= ITERATOR_FIRST
;
1422 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1426 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1429 assert_return(device
, NULL
);
1431 (void) device_read_db(device
);
1433 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1436 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1440 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1443 assert_return(device
, NULL
);
1445 (void) device_read_db(device
);
1447 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1448 device
->devlinks_iterator
= ITERATOR_FIRST
;
1450 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1454 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1457 assert_return(device
, NULL
);
1459 (void) device_read_db(device
);
1461 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1464 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1468 int device_properties_prepare(sd_device
*device
) {
1473 r
= device_read_uevent_file(device
);
1477 r
= device_read_db(device
);
1481 if (device
->property_devlinks_outdated
) {
1482 _cleanup_free_
char *devlinks
= NULL
;
1483 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1484 const char *devlink
;
1486 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1489 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1491 if (devlinks_len
> 0)
1492 stpcpy(devlinks
+ devlinks_len
++, " ");
1493 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1494 devlinks_len
= e
- devlinks
;
1497 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1501 device
->property_devlinks_outdated
= false;
1504 if (device
->property_tags_outdated
) {
1505 _cleanup_free_
char *tags
= NULL
;
1506 size_t tags_allocated
= 0, tags_len
= 0;
1509 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1514 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1517 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1519 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1520 tags_len
= e
- tags
;
1523 r
= device_add_property_internal(device
, "TAGS", tags
);
1527 device
->property_tags_outdated
= false;
1533 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1537 assert_return(device
, NULL
);
1539 r
= device_properties_prepare(device
);
1543 device
->properties_iterator_generation
= device
->properties_generation
;
1544 device
->properties_iterator
= ITERATOR_FIRST
;
1546 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
1550 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1554 assert_return(device
, NULL
);
1556 r
= device_properties_prepare(device
);
1560 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1563 (void) ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)_value
, (const void**)&key
);
1567 static int device_sysattrs_read_all_internal(sd_device
*device
, const char *subdir
) {
1568 _cleanup_free_
char *path_dir
= NULL
;
1569 _cleanup_closedir_
DIR *dir
= NULL
;
1570 struct dirent
*dent
;
1571 const char *syspath
;
1574 r
= sd_device_get_syspath(device
, &syspath
);
1579 _cleanup_free_
char *p
= NULL
;
1581 p
= path_join(syspath
, subdir
, "uevent");
1585 if (access(p
, F_OK
) >= 0)
1586 /* this is a child device, skipping */
1588 if (errno
!= ENOENT
) {
1589 log_device_debug_errno(device
, errno
, "sd-device: Failed to stat %s, ignoring subdir: %m", p
);
1593 path_dir
= path_join(syspath
, subdir
);
1598 dir
= opendir(path_dir
?: syspath
);
1602 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1603 _cleanup_free_
char *path
= NULL
, *p
= NULL
;
1604 struct stat statbuf
;
1606 if (dot_or_dot_dot(dent
->d_name
))
1609 /* only handle symlinks, regular files, and directories */
1610 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
, DT_DIR
))
1614 p
= path_join(subdir
, dent
->d_name
);
1619 if (dent
->d_type
== DT_DIR
) {
1620 /* read subdirectory */
1621 r
= device_sysattrs_read_all_internal(device
, p
?: dent
->d_name
);
1628 path
= path_join(syspath
, p
?: dent
->d_name
);
1632 if (lstat(path
, &statbuf
) != 0)
1635 if (!(statbuf
.st_mode
& S_IRUSR
))
1638 r
= set_put_strdup(&device
->sysattrs
, p
?: dent
->d_name
);
1646 static int device_sysattrs_read_all(sd_device
*device
) {
1651 if (device
->sysattrs_read
)
1654 r
= device_sysattrs_read_all_internal(device
, NULL
);
1658 device
->sysattrs_read
= true;
1663 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1667 assert_return(device
, NULL
);
1669 if (!device
->sysattrs_read
) {
1670 r
= device_sysattrs_read_all(device
);
1677 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1679 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1683 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1686 assert_return(device
, NULL
);
1688 if (!device
->sysattrs_read
)
1691 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1695 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1696 assert_return(device
, -EINVAL
);
1697 assert_return(tag
, -EINVAL
);
1699 (void) device_read_db(device
);
1701 return !!set_contains(device
->tags
, tag
);
1704 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1708 assert_return(device
, -EINVAL
);
1709 assert_return(key
, -EINVAL
);
1711 r
= device_properties_prepare(device
);
1715 value
= ordered_hashmap_get(device
->properties
, key
);
1724 /* replaces the value if it already exists */
1725 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1726 _cleanup_free_
char *key
= NULL
;
1727 _cleanup_free_
char *value_old
= NULL
;
1733 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1737 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1744 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1752 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1753 const char *key
= NULL
, *value
;
1758 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1767 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1768 * with a NULL value in the cache, otherwise the returned string is stored */
1769 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1770 _cleanup_free_
char *value
= NULL
;
1771 const char *path
, *syspath
, *cached_value
= NULL
;
1772 struct stat statbuf
;
1775 assert_return(device
, -EINVAL
);
1776 assert_return(sysattr
, -EINVAL
);
1778 /* look for possibly already cached result */
1779 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1785 /* we looked up the sysattr before and it did not exist */
1789 *_value
= cached_value
;
1794 r
= sd_device_get_syspath(device
, &syspath
);
1798 path
= prefix_roota(syspath
, sysattr
);
1799 r
= lstat(path
, &statbuf
);
1801 /* remember that we could not access the sysattr */
1802 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1807 } else if (S_ISLNK(statbuf
.st_mode
)) {
1808 /* Some core links return only the last element of the target path,
1809 * these are just values, the paths should not be exposed. */
1810 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1811 r
= readlink_value(path
, &value
);
1816 } else if (S_ISDIR(statbuf
.st_mode
)) {
1817 /* skip directories */
1819 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1820 /* skip non-readable files */
1825 /* read attribute value */
1826 r
= read_full_virtual_file(path
, &value
, &size
);
1830 /* drop trailing newlines */
1831 while (size
> 0 && value
[--size
] == '\n')
1835 r
= device_add_sysattr_value(device
, sysattr
, value
);
1839 *_value
= TAKE_PTR(value
);
1844 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1845 _cleanup_free_
char *key
= NULL
;
1850 free(hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
));
1853 /* set the attribute and save it in the cache. If a NULL value is passed the
1854 * attribute is cleared from the cache */
1855 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, const char *_value
) {
1856 _cleanup_free_
char *value
= NULL
;
1857 const char *syspath
, *path
;
1861 assert_return(device
, -EINVAL
);
1862 assert_return(sysattr
, -EINVAL
);
1865 device_remove_sysattr_value(device
, sysattr
);
1869 r
= sd_device_get_syspath(device
, &syspath
);
1873 path
= prefix_roota(syspath
, sysattr
);
1875 len
= strlen(_value
);
1877 /* drop trailing newlines */
1878 while (len
> 0 && _value
[len
- 1] == '\n')
1881 /* value length is limited to 4k */
1885 value
= strndup(_value
, len
);
1889 r
= write_string_file(path
, value
, WRITE_STRING_FILE_DISABLE_BUFFER
| WRITE_STRING_FILE_NOFOLLOW
);
1896 r
= free_and_strdup(&value
, "");
1900 r
= device_add_sysattr_value(device
, sysattr
, value
);
1908 r
= device_add_sysattr_value(device
, sysattr
, value
);