1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
6 Copyright 2014 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
26 #include "sd-device.h"
28 #include "alloc-util.h"
29 #include "device-internal.h"
30 #include "device-private.h"
31 #include "device-util.h"
32 #include "dirent-util.h"
38 #include "parse-util.h"
39 #include "path-util.h"
41 #include "socket-util.h"
42 #include "stat-util.h"
43 #include "string-util.h"
48 int device_new_aux(sd_device
**ret
) {
49 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
53 device
= new0(sd_device
, 1);
58 device
->watch_handle
= -1;
66 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
68 assert_se(++ device
->n_ref
>= 2);
73 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
74 if (device
&& -- device
->n_ref
== 0) {
75 sd_device_unref(device
->parent
);
76 free(device
->syspath
);
77 free(device
->sysname
);
78 free(device
->devtype
);
79 free(device
->devname
);
80 free(device
->subsystem
);
81 free(device
->driver_subsystem
);
83 free(device
->id_filename
);
84 free(device
->properties_strv
);
85 free(device
->properties_nulstr
);
87 ordered_hashmap_free_free_free(device
->properties
);
88 ordered_hashmap_free_free_free(device
->properties_db
);
89 hashmap_free_free_free(device
->sysattr_values
);
90 set_free_free(device
->sysattrs
);
91 set_free_free(device
->tags
);
92 set_free_free(device
->devlinks
);
100 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
101 OrderedHashmap
**properties
;
107 properties
= &device
->properties_db
;
109 properties
= &device
->properties
;
112 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
115 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
123 value
= strdup(_value
);
127 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
129 r
= ordered_hashmap_replace(*properties
, key
, value
);
136 _cleanup_free_
char *key
= NULL
;
137 _cleanup_free_
char *value
= NULL
;
139 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
143 device
->properties_generation
++;
144 device
->properties_buf_outdated
= true;
150 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
151 return device_add_property_aux(device
, key
, value
, false);
154 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
155 _cleanup_free_
char *syspath
= NULL
;
162 /* must be a subdirectory of /sys */
163 if (!path_startswith(_syspath
, "/sys/")) {
164 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
169 r
= readlink_and_canonicalize(_syspath
, NULL
, &syspath
);
171 /* the device does not exist (any more?) */
173 else if (r
== -EINVAL
) {
175 syspath
= canonicalize_file_name(_syspath
);
178 /* the device does not exist (any more?) */
181 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
184 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
188 if (path_startswith(syspath
, "/sys/devices/")) {
191 /* all 'devices' require an 'uevent' file */
192 path
= strjoina(syspath
, "/uevent");
193 r
= access(path
, F_OK
);
196 /* this is not a valid device */
199 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
202 /* everything else just needs to be a directory */
203 if (!is_dir(syspath
, false))
207 syspath
= strdup(_syspath
);
212 devpath
= syspath
+ strlen("/sys");
214 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
218 free(device
->syspath
);
219 device
->syspath
= syspath
;
222 device
->devpath
= devpath
;
227 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
228 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
231 assert_return(ret
, -EINVAL
);
232 assert_return(syspath
, -EINVAL
);
234 r
= device_new_aux(&device
);
238 r
= device_set_syspath(device
, syspath
, true);
248 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
250 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
252 assert_return(ret
, -EINVAL
);
253 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
255 /* use /sys/dev/{block,char}/<maj>:<min> link */
256 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
258 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
260 return sd_device_new_from_syspath(ret
, syspath
);
263 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
264 char *name
, *syspath
;
267 assert_return(ret
, -EINVAL
);
268 assert_return(subsystem
, -EINVAL
);
269 assert_return(sysname
, -EINVAL
);
271 if (streq(subsystem
, "subsystem")) {
272 syspath
= strjoina("/sys/subsystem/", sysname
);
273 if (access(syspath
, F_OK
) >= 0)
274 return sd_device_new_from_syspath(ret
, syspath
);
276 syspath
= strjoina("/sys/bus/", sysname
);
277 if (access(syspath
, F_OK
) >= 0)
278 return sd_device_new_from_syspath(ret
, syspath
);
280 syspath
= strjoina("/sys/class/", sysname
);
281 if (access(syspath
, F_OK
) >= 0)
282 return sd_device_new_from_syspath(ret
, syspath
);
283 } else if (streq(subsystem
, "module")) {
284 syspath
= strjoina("/sys/module/", sysname
);
285 if (access(syspath
, F_OK
) >= 0)
286 return sd_device_new_from_syspath(ret
, syspath
);
287 } else if (streq(subsystem
, "drivers")) {
288 char subsys
[PATH_MAX
];
291 strscpy(subsys
, sizeof(subsys
), sysname
);
292 driver
= strchr(subsys
, ':');
297 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
298 if (access(syspath
, F_OK
) >= 0)
299 return sd_device_new_from_syspath(ret
, syspath
);
301 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
302 if (access(syspath
, F_OK
) >= 0)
303 return sd_device_new_from_syspath(ret
, syspath
);
307 /* translate sysname back to sysfs filename */
308 name
= strdupa(sysname
);
309 while (name
[len
] != '\0') {
310 if (name
[len
] == '/')
316 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
317 if (access(syspath
, F_OK
) >= 0)
318 return sd_device_new_from_syspath(ret
, syspath
);
320 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
321 if (access(syspath
, F_OK
) >= 0)
322 return sd_device_new_from_syspath(ret
, syspath
);
324 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
325 if (access(syspath
, F_OK
) >= 0)
326 return sd_device_new_from_syspath(ret
, syspath
);
328 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
329 if (access(syspath
, F_OK
) >= 0)
330 return sd_device_new_from_syspath(ret
, syspath
);
335 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
336 _cleanup_free_
char *devtype
= NULL
;
342 devtype
= strdup(_devtype
);
346 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
350 free(device
->devtype
);
351 device
->devtype
= devtype
;
357 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
363 r
= parse_ifindex(_ifindex
, &ifindex
);
367 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
371 device
->ifindex
= ifindex
;
376 int device_set_devname(sd_device
*device
, const char *_devname
) {
377 _cleanup_free_
char *devname
= NULL
;
383 if (_devname
[0] != '/') {
384 r
= asprintf(&devname
, "/dev/%s", _devname
);
388 devname
= strdup(_devname
);
393 r
= device_add_property_internal(device
, "DEVNAME", devname
);
397 free(device
->devname
);
398 device
->devname
= devname
;
404 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
411 r
= safe_atou(_devmode
, &devmode
);
418 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
422 device
->devmode
= devmode
;
427 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
428 unsigned maj
= 0, min
= 0;
434 r
= safe_atou(major
, &maj
);
441 r
= safe_atou(minor
, &min
);
446 r
= device_add_property_internal(device
, "MAJOR", major
);
451 r
= device_add_property_internal(device
, "MINOR", minor
);
456 device
->devnum
= makedev(maj
, min
);
461 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
470 if (streq(key
, "DEVTYPE")) {
471 r
= device_set_devtype(device
, value
);
474 } else if (streq(key
, "IFINDEX")) {
475 r
= device_set_ifindex(device
, value
);
478 } else if (streq(key
, "DEVNAME")) {
479 r
= device_set_devname(device
, value
);
482 } else if (streq(key
, "DEVMODE")) {
483 r
= device_set_devmode(device
, value
);
486 } else if (streq(key
, "MAJOR"))
488 else if (streq(key
, "MINOR"))
491 r
= device_add_property_internal(device
, key
, value
);
499 int device_read_uevent_file(sd_device
*device
) {
500 _cleanup_free_
char *uevent
= NULL
;
501 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
517 if (device
->uevent_loaded
|| device
->sealed
)
520 device
->uevent_loaded
= true;
522 r
= sd_device_get_syspath(device
, &syspath
);
526 path
= strjoina(syspath
, "/uevent");
528 r
= read_full_file(path
, &uevent
, &uevent_len
);
530 /* empty uevent files may be write-only */
532 else if (r
== -ENOENT
)
533 /* some devices may not have uevent files, see set_syspath() */
536 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
540 for (i
= 0; i
< uevent_len
; i
++)
543 if (!strchr(NEWLINE
, uevent
[i
])) {
551 if (uevent
[i
] == '=') {
555 } else if (strchr(NEWLINE
, uevent
[i
])) {
557 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
567 /* fall through */ /* to handle empty property */
569 if (strchr(NEWLINE
, uevent
[i
])) {
572 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
574 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
581 assert_not_reached("invalid state when parsing uevent file");
585 r
= device_set_devnum(device
, major
, minor
);
587 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
593 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
596 assert_return(device
, -EINVAL
);
597 assert_return(ifindex
, -EINVAL
);
599 r
= device_read_uevent_file(device
);
603 *ifindex
= device
->ifindex
;
608 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
611 assert_return(ret
, -EINVAL
);
612 assert_return(id
, -EINVAL
);
621 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
625 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
629 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
630 _cleanup_close_
int sk
= -1;
631 struct ifreq ifr
= {};
634 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
638 sk
= socket_ioctl_fd();
642 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
646 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
650 r
= sd_device_get_ifindex(device
, &ifindex
);
654 /* this is racey, so we might end up with the wrong device */
655 if (ifr
.ifr_ifindex
!= ifindex
)
665 char subsys
[PATH_MAX
];
668 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
669 sysname
= strchr(subsys
, ':');
676 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
683 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
684 assert_return(device
, -EINVAL
);
685 assert_return(ret
, -EINVAL
);
687 assert(path_startswith(device
->syspath
, "/sys/"));
689 *ret
= device
->syspath
;
694 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
695 _cleanup_free_
char *path
= NULL
;
696 const char *subdir
, *syspath
;
702 r
= sd_device_get_syspath(child
, &syspath
);
706 path
= strdup(syspath
);
709 subdir
= path
+ strlen("/sys");
714 pos
= strrchr(subdir
, '/');
715 if (!pos
|| pos
< subdir
+ 2)
720 r
= sd_device_new_from_syspath(ret
, path
);
730 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
732 assert_return(ret
, -EINVAL
);
733 assert_return(child
, -EINVAL
);
735 if (!child
->parent_set
) {
736 child
->parent_set
= true;
738 (void)device_new_from_child(&child
->parent
, child
);
744 *ret
= child
->parent
;
749 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
750 _cleanup_free_
char *subsystem
= NULL
;
756 subsystem
= strdup(_subsystem
);
760 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
764 free(device
->subsystem
);
765 device
->subsystem
= subsystem
;
768 device
->subsystem_set
= true;
773 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
774 _cleanup_free_
char *subsystem
= NULL
;
781 subsystem
= strdup(_subsystem
);
785 r
= device_set_subsystem(device
, "drivers");
789 free(device
->driver_subsystem
);
790 device
->driver_subsystem
= subsystem
;
796 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
797 const char *syspath
, *drivers
= NULL
;
800 assert_return(ret
, -EINVAL
);
801 assert_return(device
, -EINVAL
);
803 r
= sd_device_get_syspath(device
, &syspath
);
807 if (!device
->subsystem_set
) {
808 _cleanup_free_
char *subsystem
= NULL
;
811 /* read 'subsystem' link */
812 path
= strjoina(syspath
, "/subsystem");
813 r
= readlink_value(path
, &subsystem
);
815 r
= device_set_subsystem(device
, subsystem
);
816 /* use implicit names */
817 else if (path_startswith(device
->devpath
, "/module/"))
818 r
= device_set_subsystem(device
, "module");
819 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
820 (path_startswith(device
->devpath
, "/subsystem/") ||
821 path_startswith(device
->devpath
, "/class/") ||
822 path_startswith(device
->devpath
, "/bus/")))
823 r
= device_set_subsystem(device
, "subsystem");
824 if (r
< 0 && r
!= -ENOENT
)
825 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
827 device
->subsystem_set
= true;
828 } else if (!device
->driver_subsystem_set
)
829 drivers
= strstr(syspath
, "/drivers/");
831 if (!device
->driver_subsystem_set
) {
833 _cleanup_free_
char *subpath
= NULL
;
835 subpath
= strndup(syspath
, drivers
- syspath
);
841 subsys
= strrchr(subpath
, '/');
845 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
847 if (r
< 0 && r
!= -ENOENT
)
848 return log_debug_errno(r
, "sd-device: could not set subsystem for driver %s: %m", device
->devpath
);
851 device
->driver_subsystem_set
= true;
854 if (!device
->subsystem
)
857 *ret
= device
->subsystem
;
862 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
868 r
= device_read_uevent_file(device
);
872 *devtype
= device
->devtype
;
877 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
878 sd_device
*parent
= NULL
;
881 assert_return(child
, -EINVAL
);
882 assert_return(subsystem
, -EINVAL
);
884 r
= sd_device_get_parent(child
, &parent
);
886 const char *parent_subsystem
= NULL
;
887 const char *parent_devtype
= NULL
;
889 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
890 if (streq_ptr(parent_subsystem
, subsystem
)) {
894 (void)sd_device_get_devtype(parent
, &parent_devtype
);
895 if (streq_ptr(parent_devtype
, devtype
))
898 r
= sd_device_get_parent(parent
, &parent
);
909 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
912 assert_return(device
, -EINVAL
);
913 assert_return(devnum
, -EINVAL
);
915 r
= device_read_uevent_file(device
);
919 *devnum
= device
->devnum
;
924 int device_set_driver(sd_device
*device
, const char *_driver
) {
925 _cleanup_free_
char *driver
= NULL
;
931 driver
= strdup(_driver
);
935 r
= device_add_property_internal(device
, "DRIVER", driver
);
939 free(device
->driver
);
940 device
->driver
= driver
;
943 device
->driver_set
= true;
948 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
949 assert_return(device
, -EINVAL
);
950 assert_return(ret
, -EINVAL
);
952 if (!device
->driver_set
) {
953 _cleanup_free_
char *driver
= NULL
;
958 r
= sd_device_get_syspath(device
, &syspath
);
962 path
= strjoina(syspath
, "/driver");
963 r
= readlink_value(path
, &driver
);
965 r
= device_set_driver(device
, driver
);
967 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
968 } else if (r
== -ENOENT
)
969 device
->driver_set
= true;
971 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
977 *ret
= device
->driver
;
982 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
983 assert_return(device
, -EINVAL
);
984 assert_return(devpath
, -EINVAL
);
986 assert(device
->devpath
);
987 assert(device
->devpath
[0] == '/');
989 *devpath
= device
->devpath
;
994 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
997 assert_return(device
, -EINVAL
);
998 assert_return(devname
, -EINVAL
);
1000 r
= device_read_uevent_file(device
);
1004 if (!device
->devname
)
1007 assert(path_startswith(device
->devname
, "/dev/"));
1009 *devname
= device
->devname
;
1014 static int device_set_sysname(sd_device
*device
) {
1015 _cleanup_free_
char *sysname
= NULL
;
1016 const char *sysnum
= NULL
;
1020 pos
= strrchr(device
->devpath
, '/');
1025 /* devpath is not a root directory */
1026 if (*pos
== '\0' || pos
<= device
->devpath
)
1029 sysname
= strdup(pos
);
1033 /* some devices have '!' in their name, change that to '/' */
1034 while (sysname
[len
] != '\0') {
1035 if (sysname
[len
] == '!')
1041 /* trailing number */
1042 while (len
> 0 && isdigit(sysname
[--len
]))
1043 sysnum
= &sysname
[len
];
1048 free(device
->sysname
);
1049 device
->sysname
= sysname
;
1052 device
->sysnum
= sysnum
;
1054 device
->sysname_set
= true;
1059 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1062 assert_return(device
, -EINVAL
);
1063 assert_return(ret
, -EINVAL
);
1065 if (!device
->sysname_set
) {
1066 r
= device_set_sysname(device
);
1071 assert_return(device
->sysname
, -ENOENT
);
1073 *ret
= device
->sysname
;
1078 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1081 assert_return(device
, -EINVAL
);
1082 assert_return(ret
, -EINVAL
);
1084 if (!device
->sysname_set
) {
1085 r
= device_set_sysname(device
);
1090 *ret
= device
->sysnum
;
1095 static bool is_valid_tag(const char *tag
) {
1098 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1101 int device_add_tag(sd_device
*device
, const char *tag
) {
1107 if (!is_valid_tag(tag
))
1110 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1114 r
= set_put_strdup(device
->tags
, tag
);
1118 device
->tags_generation
++;
1119 device
->property_tags_outdated
= true;
1124 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1130 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1134 r
= set_put_strdup(device
->devlinks
, devlink
);
1138 device
->devlinks_generation
++;
1139 device
->property_devlinks_outdated
= true;
1144 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1145 _cleanup_free_
char *key
= NULL
;
1155 value
= strchr(key
, '=');
1161 if (isempty(++value
))
1164 return device_add_property_internal(device
, key
, value
);
1167 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1168 uint64_t usec_initialized
;
1172 assert(initialized
);
1174 r
= safe_atou64(initialized
, &usec_initialized
);
1178 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1182 device
->usec_initialized
= usec_initialized
;
1187 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1196 r
= device_add_tag(device
, value
);
1202 path
= strjoina("/dev/", value
);
1203 r
= device_add_devlink(device
, path
);
1209 r
= device_add_property_internal_from_string(device
, value
);
1215 r
= device_set_usec_initialized(device
, value
);
1221 r
= safe_atoi(value
, &device
->devlink_priority
);
1227 r
= safe_atoi(value
, &device
->watch_handle
);
1233 log_debug("device db: unknown key '%c'", key
);
1239 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1243 if (!device
->id_filename
) {
1244 _cleanup_free_
char *id
= NULL
;
1245 const char *subsystem
;
1249 r
= sd_device_get_subsystem(device
, &subsystem
);
1253 r
= sd_device_get_devnum(device
, &devnum
);
1257 r
= sd_device_get_ifindex(device
, &ifindex
);
1261 if (major(devnum
) > 0) {
1264 /* use dev_t — b259:131072, c254:0 */
1265 r
= asprintf(&id
, "%c%u:%u",
1266 streq(subsystem
, "block") ? 'b' : 'c',
1267 major(devnum
), minor(devnum
));
1270 } else if (ifindex
> 0) {
1271 /* use netdev ifindex — n3 */
1272 r
= asprintf(&id
, "n%u", ifindex
);
1276 /* use $subsys:$sysname — pci:0000:00:1f.2
1277 * sysname() has '!' translated, get it from devpath
1279 const char *sysname
;
1281 sysname
= basename(device
->devpath
);
1288 if (streq(subsystem
, "drivers")) {
1289 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1290 * encoded as well */
1291 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1295 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1301 device
->id_filename
= id
;
1305 *ret
= device
->id_filename
;
1310 int device_read_db_aux(sd_device
*device
, bool force
) {
1311 _cleanup_free_
char *db
= NULL
;
1313 const char *id
, *value
;
1327 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1330 device
->db_loaded
= true;
1332 r
= device_get_id_filename(device
, &id
);
1336 path
= strjoina("/run/udev/data/", id
);
1338 r
= read_full_file(path
, &db
, &db_len
);
1343 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1346 /* devices with a database entry are initialized */
1347 device
->is_initialized
= true;
1349 for (i
= 0; i
< db_len
; i
++) {
1352 if (!strchr(NEWLINE
, db
[i
])) {
1361 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1363 state
= INVALID_LINE
;
1378 if (strchr(NEWLINE
, db
[i
]))
1383 if (strchr(NEWLINE
, db
[i
])) {
1385 r
= handle_db_line(device
, key
, value
);
1387 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1394 assert_not_reached("invalid state when parsing db");
1401 static int device_read_db(sd_device
*device
) {
1402 return device_read_db_aux(device
, false);
1405 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1408 assert_return(device
, -EINVAL
);
1409 assert_return(initialized
, -EINVAL
);
1411 r
= device_read_db(device
);
1415 *initialized
= device
->is_initialized
;
1420 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1424 assert_return(device
, -EINVAL
);
1425 assert_return(usec
, -EINVAL
);
1427 r
= device_read_db(device
);
1431 if (!device
->is_initialized
)
1434 if (!device
->usec_initialized
)
1437 now_ts
= now(clock_boottime_or_monotonic());
1439 if (now_ts
< device
->usec_initialized
)
1442 *usec
= now_ts
- device
->usec_initialized
;
1447 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1450 assert_return(device
, NULL
);
1452 (void) device_read_db(device
);
1454 device
->tags_iterator_generation
= device
->tags_generation
;
1455 device
->tags_iterator
= ITERATOR_FIRST
;
1457 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1461 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1464 assert_return(device
, NULL
);
1466 (void) device_read_db(device
);
1468 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1471 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1475 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1478 assert_return(device
, NULL
);
1480 (void) device_read_db(device
);
1482 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1483 device
->devlinks_iterator
= ITERATOR_FIRST
;
1485 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1489 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1492 assert_return(device
, NULL
);
1494 (void) device_read_db(device
);
1496 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1499 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1503 static int device_properties_prepare(sd_device
*device
) {
1508 r
= device_read_uevent_file(device
);
1512 r
= device_read_db(device
);
1516 if (device
->property_devlinks_outdated
) {
1517 _cleanup_free_
char *devlinks
= NULL
;
1518 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1519 const char *devlink
;
1521 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1524 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1526 if (devlinks_len
> 0)
1527 stpcpy(devlinks
+ devlinks_len
++, " ");
1528 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1529 devlinks_len
= e
- devlinks
;
1532 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1536 device
->property_devlinks_outdated
= false;
1539 if (device
->property_tags_outdated
) {
1540 _cleanup_free_
char *tags
= NULL
;
1541 size_t tags_allocated
= 0, tags_len
= 0;
1544 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1549 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1552 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1554 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1555 tags_len
= e
- tags
;
1558 r
= device_add_property_internal(device
, "TAGS", tags
);
1562 device
->property_tags_outdated
= false;
1568 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1573 assert_return(device
, NULL
);
1575 r
= device_properties_prepare(device
);
1579 device
->properties_iterator_generation
= device
->properties_generation
;
1580 device
->properties_iterator
= ITERATOR_FIRST
;
1582 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1590 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1595 assert_return(device
, NULL
);
1597 r
= device_properties_prepare(device
);
1601 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1604 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1612 static int device_sysattrs_read_all(sd_device
*device
) {
1613 _cleanup_closedir_
DIR *dir
= NULL
;
1614 const char *syspath
;
1615 struct dirent
*dent
;
1620 if (device
->sysattrs_read
)
1623 r
= sd_device_get_syspath(device
, &syspath
);
1627 dir
= opendir(syspath
);
1631 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1635 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1637 struct stat statbuf
;
1639 /* only handle symlinks and regular files */
1640 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
))
1643 path
= strjoina(syspath
, "/", dent
->d_name
);
1645 if (lstat(path
, &statbuf
) != 0)
1648 if (!(statbuf
.st_mode
& S_IRUSR
))
1651 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1656 device
->sysattrs_read
= true;
1661 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1665 assert_return(device
, NULL
);
1667 if (!device
->sysattrs_read
) {
1668 r
= device_sysattrs_read_all(device
);
1675 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1677 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1681 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1684 assert_return(device
, NULL
);
1686 if (!device
->sysattrs_read
)
1689 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1693 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1694 assert_return(device
, -EINVAL
);
1695 assert_return(tag
, -EINVAL
);
1697 (void) device_read_db(device
);
1699 return !!set_contains(device
->tags
, tag
);
1702 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1706 assert_return(device
, -EINVAL
);
1707 assert_return(key
, -EINVAL
);
1708 assert_return(_value
, -EINVAL
);
1710 r
= device_properties_prepare(device
);
1714 value
= ordered_hashmap_get(device
->properties
, key
);
1723 /* replaces the value if it already exists */
1724 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1725 _cleanup_free_
char *key
= NULL
;
1726 _cleanup_free_
char *value_old
= NULL
;
1732 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1736 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1743 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
);
1768 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1769 * with a NULL value in the cache, otherwise the returned string is stored */
1770 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1771 _cleanup_free_
char *value
= NULL
;
1772 const char *syspath
, *cached_value
= NULL
;
1774 struct stat statbuf
;
1777 assert_return(device
, -EINVAL
);
1778 assert_return(sysattr
, -EINVAL
);
1780 /* look for possibly already cached result */
1781 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1787 /* we looked up the sysattr before and it did not exist */
1791 *_value
= cached_value
;
1796 r
= sd_device_get_syspath(device
, &syspath
);
1800 path
= strjoina(syspath
, "/", sysattr
);
1801 r
= lstat(path
, &statbuf
);
1803 /* remember that we could not access the sysattr */
1804 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1809 } else if (S_ISLNK(statbuf
.st_mode
)) {
1810 /* Some core links return only the last element of the target path,
1811 * these are just values, the paths should not be exposed. */
1812 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1813 r
= readlink_value(path
, &value
);
1818 } else if (S_ISDIR(statbuf
.st_mode
)) {
1819 /* skip directories */
1821 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1822 /* skip non-readable files */
1827 /* read attribute value */
1828 r
= read_full_file(path
, &value
, &size
);
1832 /* drop trailing newlines */
1833 while (size
> 0 && value
[--size
] == '\n')
1837 r
= device_add_sysattr_value(device
, sysattr
, value
);
1847 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1848 _cleanup_free_
char *key
= NULL
;
1849 _cleanup_free_
char *value
= NULL
;
1854 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1859 /* set the attribute and save it in the cache. If a NULL value is passed the
1860 * attribute is cleared from the cache */
1861 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1862 _cleanup_close_
int fd
= -1;
1863 _cleanup_free_
char *value
= NULL
;
1864 const char *syspath
;
1870 assert_return(device
, -EINVAL
);
1871 assert_return(sysattr
, -EINVAL
);
1874 device_remove_sysattr_value(device
, sysattr
);
1879 r
= sd_device_get_syspath(device
, &syspath
);
1883 path
= strjoina(syspath
, "/", sysattr
);
1885 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
1889 if (errno
== EISDIR
)
1896 r
= device_add_sysattr_value(device
, sysattr
, value
);
1904 len
= strlen(_value
);
1906 /* drop trailing newlines */
1907 while (len
> 0 && _value
[len
- 1] == '\n')
1910 /* value length is limited to 4k */
1914 value
= strndup(_value
, len
);
1918 size
= write(fd
, value
, len
);
1922 if ((size_t)size
!= len
)
1925 r
= device_add_sysattr_value(device
, sysattr
, value
);