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_and_replace(device
->syspath
, syspath
);
220 device
->devpath
= devpath
;
225 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
226 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
229 assert_return(ret
, -EINVAL
);
230 assert_return(syspath
, -EINVAL
);
232 r
= device_new_aux(&device
);
236 r
= device_set_syspath(device
, syspath
, true);
246 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
248 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
250 assert_return(ret
, -EINVAL
);
251 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
253 /* use /sys/dev/{block,char}/<maj>:<min> link */
254 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
256 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
258 return sd_device_new_from_syspath(ret
, syspath
);
261 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
262 char *name
, *syspath
;
265 assert_return(ret
, -EINVAL
);
266 assert_return(subsystem
, -EINVAL
);
267 assert_return(sysname
, -EINVAL
);
269 if (streq(subsystem
, "subsystem")) {
270 syspath
= strjoina("/sys/subsystem/", sysname
);
271 if (access(syspath
, F_OK
) >= 0)
272 return sd_device_new_from_syspath(ret
, syspath
);
274 syspath
= strjoina("/sys/bus/", sysname
);
275 if (access(syspath
, F_OK
) >= 0)
276 return sd_device_new_from_syspath(ret
, syspath
);
278 syspath
= strjoina("/sys/class/", sysname
);
279 if (access(syspath
, F_OK
) >= 0)
280 return sd_device_new_from_syspath(ret
, syspath
);
281 } else if (streq(subsystem
, "module")) {
282 syspath
= strjoina("/sys/module/", sysname
);
283 if (access(syspath
, F_OK
) >= 0)
284 return sd_device_new_from_syspath(ret
, syspath
);
285 } else if (streq(subsystem
, "drivers")) {
286 char subsys
[PATH_MAX
];
289 strscpy(subsys
, sizeof(subsys
), sysname
);
290 driver
= strchr(subsys
, ':');
295 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
296 if (access(syspath
, F_OK
) >= 0)
297 return sd_device_new_from_syspath(ret
, syspath
);
299 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
300 if (access(syspath
, F_OK
) >= 0)
301 return sd_device_new_from_syspath(ret
, syspath
);
305 /* translate sysname back to sysfs filename */
306 name
= strdupa(sysname
);
307 while (name
[len
] != '\0') {
308 if (name
[len
] == '/')
314 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
315 if (access(syspath
, F_OK
) >= 0)
316 return sd_device_new_from_syspath(ret
, syspath
);
318 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
319 if (access(syspath
, F_OK
) >= 0)
320 return sd_device_new_from_syspath(ret
, syspath
);
322 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
323 if (access(syspath
, F_OK
) >= 0)
324 return sd_device_new_from_syspath(ret
, syspath
);
326 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
327 if (access(syspath
, F_OK
) >= 0)
328 return sd_device_new_from_syspath(ret
, syspath
);
333 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
334 _cleanup_free_
char *devtype
= NULL
;
340 devtype
= strdup(_devtype
);
344 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
348 free_and_replace(device
->devtype
, devtype
);
353 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
359 r
= parse_ifindex(_ifindex
, &ifindex
);
363 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
367 device
->ifindex
= ifindex
;
372 int device_set_devname(sd_device
*device
, const char *_devname
) {
373 _cleanup_free_
char *devname
= NULL
;
379 if (_devname
[0] != '/') {
380 r
= asprintf(&devname
, "/dev/%s", _devname
);
384 devname
= strdup(_devname
);
389 r
= device_add_property_internal(device
, "DEVNAME", devname
);
393 free_and_replace(device
->devname
, devname
);
398 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
405 r
= safe_atou(_devmode
, &devmode
);
412 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
416 device
->devmode
= devmode
;
421 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
422 unsigned maj
= 0, min
= 0;
428 r
= safe_atou(major
, &maj
);
435 r
= safe_atou(minor
, &min
);
440 r
= device_add_property_internal(device
, "MAJOR", major
);
445 r
= device_add_property_internal(device
, "MINOR", minor
);
450 device
->devnum
= makedev(maj
, min
);
455 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
464 if (streq(key
, "DEVTYPE")) {
465 r
= device_set_devtype(device
, value
);
468 } else if (streq(key
, "IFINDEX")) {
469 r
= device_set_ifindex(device
, value
);
472 } else if (streq(key
, "DEVNAME")) {
473 r
= device_set_devname(device
, value
);
476 } else if (streq(key
, "DEVMODE")) {
477 r
= device_set_devmode(device
, value
);
480 } else if (streq(key
, "MAJOR"))
482 else if (streq(key
, "MINOR"))
485 r
= device_add_property_internal(device
, key
, value
);
493 int device_read_uevent_file(sd_device
*device
) {
494 _cleanup_free_
char *uevent
= NULL
;
495 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
511 if (device
->uevent_loaded
|| device
->sealed
)
514 device
->uevent_loaded
= true;
516 r
= sd_device_get_syspath(device
, &syspath
);
520 path
= strjoina(syspath
, "/uevent");
522 r
= read_full_file(path
, &uevent
, &uevent_len
);
524 /* empty uevent files may be write-only */
526 else if (r
== -ENOENT
)
527 /* some devices may not have uevent files, see set_syspath() */
530 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
534 for (i
= 0; i
< uevent_len
; i
++)
537 if (!strchr(NEWLINE
, uevent
[i
])) {
545 if (uevent
[i
] == '=') {
549 } else if (strchr(NEWLINE
, uevent
[i
])) {
551 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
561 _fallthrough_
; /* to handle empty property */
563 if (strchr(NEWLINE
, uevent
[i
])) {
566 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
568 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
575 assert_not_reached("invalid state when parsing uevent file");
579 r
= device_set_devnum(device
, major
, minor
);
581 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
587 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
590 assert_return(device
, -EINVAL
);
591 assert_return(ifindex
, -EINVAL
);
593 r
= device_read_uevent_file(device
);
597 *ifindex
= device
->ifindex
;
602 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
605 assert_return(ret
, -EINVAL
);
606 assert_return(id
, -EINVAL
);
615 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
619 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
623 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
624 _cleanup_close_
int sk
= -1;
625 struct ifreq ifr
= {};
628 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
632 sk
= socket_ioctl_fd();
636 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
640 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
644 r
= sd_device_get_ifindex(device
, &ifindex
);
648 /* this is racey, so we might end up with the wrong device */
649 if (ifr
.ifr_ifindex
!= ifindex
)
659 char subsys
[PATH_MAX
];
662 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
663 sysname
= strchr(subsys
, ':');
670 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
677 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
678 assert_return(device
, -EINVAL
);
679 assert_return(ret
, -EINVAL
);
681 assert(path_startswith(device
->syspath
, "/sys/"));
683 *ret
= device
->syspath
;
688 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
689 _cleanup_free_
char *path
= NULL
;
690 const char *subdir
, *syspath
;
696 r
= sd_device_get_syspath(child
, &syspath
);
700 path
= strdup(syspath
);
703 subdir
= path
+ STRLEN("/sys");
708 pos
= strrchr(subdir
, '/');
709 if (!pos
|| pos
< subdir
+ 2)
714 r
= sd_device_new_from_syspath(ret
, path
);
724 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
726 assert_return(ret
, -EINVAL
);
727 assert_return(child
, -EINVAL
);
729 if (!child
->parent_set
) {
730 child
->parent_set
= true;
732 (void)device_new_from_child(&child
->parent
, child
);
738 *ret
= child
->parent
;
743 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
744 _cleanup_free_
char *subsystem
= NULL
;
750 subsystem
= strdup(_subsystem
);
754 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
758 free_and_replace(device
->subsystem
, subsystem
);
760 device
->subsystem_set
= true;
765 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
766 _cleanup_free_
char *subsystem
= NULL
;
773 subsystem
= strdup(_subsystem
);
777 r
= device_set_subsystem(device
, "drivers");
781 free_and_replace(device
->driver_subsystem
, subsystem
);
786 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
787 const char *syspath
, *drivers
= NULL
;
790 assert_return(ret
, -EINVAL
);
791 assert_return(device
, -EINVAL
);
793 r
= sd_device_get_syspath(device
, &syspath
);
797 if (!device
->subsystem_set
) {
798 _cleanup_free_
char *subsystem
= NULL
;
801 /* read 'subsystem' link */
802 path
= strjoina(syspath
, "/subsystem");
803 r
= readlink_value(path
, &subsystem
);
805 r
= device_set_subsystem(device
, subsystem
);
806 /* use implicit names */
807 else if (path_startswith(device
->devpath
, "/module/"))
808 r
= device_set_subsystem(device
, "module");
809 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
810 (path_startswith(device
->devpath
, "/subsystem/") ||
811 path_startswith(device
->devpath
, "/class/") ||
812 path_startswith(device
->devpath
, "/bus/")))
813 r
= device_set_subsystem(device
, "subsystem");
814 if (r
< 0 && r
!= -ENOENT
)
815 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
817 device
->subsystem_set
= true;
818 } else if (!device
->driver_subsystem_set
)
819 drivers
= strstr(syspath
, "/drivers/");
821 if (!device
->driver_subsystem_set
) {
823 _cleanup_free_
char *subpath
= NULL
;
825 subpath
= strndup(syspath
, drivers
- syspath
);
831 subsys
= strrchr(subpath
, '/');
835 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
837 if (r
< 0 && r
!= -ENOENT
)
838 return log_debug_errno(r
, "sd-device: could not set subsystem for driver %s: %m", device
->devpath
);
841 device
->driver_subsystem_set
= true;
844 if (!device
->subsystem
)
847 *ret
= device
->subsystem
;
852 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
858 r
= device_read_uevent_file(device
);
862 *devtype
= device
->devtype
;
867 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
868 sd_device
*parent
= NULL
;
871 assert_return(child
, -EINVAL
);
872 assert_return(subsystem
, -EINVAL
);
874 r
= sd_device_get_parent(child
, &parent
);
876 const char *parent_subsystem
= NULL
;
877 const char *parent_devtype
= NULL
;
879 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
880 if (streq_ptr(parent_subsystem
, subsystem
)) {
884 (void)sd_device_get_devtype(parent
, &parent_devtype
);
885 if (streq_ptr(parent_devtype
, devtype
))
888 r
= sd_device_get_parent(parent
, &parent
);
899 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
902 assert_return(device
, -EINVAL
);
903 assert_return(devnum
, -EINVAL
);
905 r
= device_read_uevent_file(device
);
909 *devnum
= device
->devnum
;
914 int device_set_driver(sd_device
*device
, const char *_driver
) {
915 _cleanup_free_
char *driver
= NULL
;
921 driver
= strdup(_driver
);
925 r
= device_add_property_internal(device
, "DRIVER", driver
);
929 free_and_replace(device
->driver
, driver
);
931 device
->driver_set
= true;
936 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
937 assert_return(device
, -EINVAL
);
938 assert_return(ret
, -EINVAL
);
940 if (!device
->driver_set
) {
941 _cleanup_free_
char *driver
= NULL
;
946 r
= sd_device_get_syspath(device
, &syspath
);
950 path
= strjoina(syspath
, "/driver");
951 r
= readlink_value(path
, &driver
);
953 r
= device_set_driver(device
, driver
);
955 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
956 } else if (r
== -ENOENT
)
957 device
->driver_set
= true;
959 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
965 *ret
= device
->driver
;
970 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
971 assert_return(device
, -EINVAL
);
972 assert_return(devpath
, -EINVAL
);
974 assert(device
->devpath
);
975 assert(device
->devpath
[0] == '/');
977 *devpath
= device
->devpath
;
982 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
985 assert_return(device
, -EINVAL
);
986 assert_return(devname
, -EINVAL
);
988 r
= device_read_uevent_file(device
);
992 if (!device
->devname
)
995 assert(path_startswith(device
->devname
, "/dev/"));
997 *devname
= device
->devname
;
1002 static int device_set_sysname(sd_device
*device
) {
1003 _cleanup_free_
char *sysname
= NULL
;
1004 const char *sysnum
= NULL
;
1008 pos
= strrchr(device
->devpath
, '/');
1013 /* devpath is not a root directory */
1014 if (*pos
== '\0' || pos
<= device
->devpath
)
1017 sysname
= strdup(pos
);
1021 /* some devices have '!' in their name, change that to '/' */
1022 while (sysname
[len
] != '\0') {
1023 if (sysname
[len
] == '!')
1029 /* trailing number */
1030 while (len
> 0 && isdigit(sysname
[--len
]))
1031 sysnum
= &sysname
[len
];
1036 free_and_replace(device
->sysname
, sysname
);
1038 device
->sysnum
= sysnum
;
1040 device
->sysname_set
= true;
1045 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1048 assert_return(device
, -EINVAL
);
1049 assert_return(ret
, -EINVAL
);
1051 if (!device
->sysname_set
) {
1052 r
= device_set_sysname(device
);
1057 assert_return(device
->sysname
, -ENOENT
);
1059 *ret
= device
->sysname
;
1064 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1067 assert_return(device
, -EINVAL
);
1068 assert_return(ret
, -EINVAL
);
1070 if (!device
->sysname_set
) {
1071 r
= device_set_sysname(device
);
1076 *ret
= device
->sysnum
;
1081 static bool is_valid_tag(const char *tag
) {
1084 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1087 int device_add_tag(sd_device
*device
, const char *tag
) {
1093 if (!is_valid_tag(tag
))
1096 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1100 r
= set_put_strdup(device
->tags
, tag
);
1104 device
->tags_generation
++;
1105 device
->property_tags_outdated
= true;
1110 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1116 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1120 r
= set_put_strdup(device
->devlinks
, devlink
);
1124 device
->devlinks_generation
++;
1125 device
->property_devlinks_outdated
= true;
1130 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1131 _cleanup_free_
char *key
= NULL
;
1141 value
= strchr(key
, '=');
1147 if (isempty(++value
))
1150 return device_add_property_internal(device
, key
, value
);
1153 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1154 uint64_t usec_initialized
;
1158 assert(initialized
);
1160 r
= safe_atou64(initialized
, &usec_initialized
);
1164 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1168 device
->usec_initialized
= usec_initialized
;
1173 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1182 r
= device_add_tag(device
, value
);
1188 path
= strjoina("/dev/", value
);
1189 r
= device_add_devlink(device
, path
);
1195 r
= device_add_property_internal_from_string(device
, value
);
1201 r
= device_set_usec_initialized(device
, value
);
1207 r
= safe_atoi(value
, &device
->devlink_priority
);
1213 r
= safe_atoi(value
, &device
->watch_handle
);
1219 log_debug("device db: unknown key '%c'", key
);
1225 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1229 if (!device
->id_filename
) {
1230 _cleanup_free_
char *id
= NULL
;
1231 const char *subsystem
;
1235 r
= sd_device_get_subsystem(device
, &subsystem
);
1239 r
= sd_device_get_devnum(device
, &devnum
);
1243 r
= sd_device_get_ifindex(device
, &ifindex
);
1247 if (major(devnum
) > 0) {
1250 /* use dev_t — b259:131072, c254:0 */
1251 r
= asprintf(&id
, "%c%u:%u",
1252 streq(subsystem
, "block") ? 'b' : 'c',
1253 major(devnum
), minor(devnum
));
1256 } else if (ifindex
> 0) {
1257 /* use netdev ifindex — n3 */
1258 r
= asprintf(&id
, "n%u", ifindex
);
1262 /* use $subsys:$sysname — pci:0000:00:1f.2
1263 * sysname() has '!' translated, get it from devpath
1265 const char *sysname
;
1267 sysname
= basename(device
->devpath
);
1274 if (streq(subsystem
, "drivers")) {
1275 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1276 * encoded as well */
1277 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1281 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1287 device
->id_filename
= id
;
1291 *ret
= device
->id_filename
;
1296 int device_read_db_aux(sd_device
*device
, bool force
) {
1297 _cleanup_free_
char *db
= NULL
;
1299 const char *id
, *value
;
1313 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1316 device
->db_loaded
= true;
1318 r
= device_get_id_filename(device
, &id
);
1322 path
= strjoina("/run/udev/data/", id
);
1324 r
= read_full_file(path
, &db
, &db_len
);
1329 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1332 /* devices with a database entry are initialized */
1333 device
->is_initialized
= true;
1335 for (i
= 0; i
< db_len
; i
++) {
1338 if (!strchr(NEWLINE
, db
[i
])) {
1347 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1349 state
= INVALID_LINE
;
1364 if (strchr(NEWLINE
, db
[i
]))
1369 if (strchr(NEWLINE
, db
[i
])) {
1371 r
= handle_db_line(device
, key
, value
);
1373 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1380 assert_not_reached("invalid state when parsing db");
1387 static int device_read_db(sd_device
*device
) {
1388 return device_read_db_aux(device
, false);
1391 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1394 assert_return(device
, -EINVAL
);
1395 assert_return(initialized
, -EINVAL
);
1397 r
= device_read_db(device
);
1401 *initialized
= device
->is_initialized
;
1406 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1410 assert_return(device
, -EINVAL
);
1411 assert_return(usec
, -EINVAL
);
1413 r
= device_read_db(device
);
1417 if (!device
->is_initialized
)
1420 if (!device
->usec_initialized
)
1423 now_ts
= now(clock_boottime_or_monotonic());
1425 if (now_ts
< device
->usec_initialized
)
1428 *usec
= now_ts
- device
->usec_initialized
;
1433 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1436 assert_return(device
, NULL
);
1438 (void) device_read_db(device
);
1440 device
->tags_iterator_generation
= device
->tags_generation
;
1441 device
->tags_iterator
= ITERATOR_FIRST
;
1443 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1447 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1450 assert_return(device
, NULL
);
1452 (void) device_read_db(device
);
1454 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1457 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1461 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1464 assert_return(device
, NULL
);
1466 (void) device_read_db(device
);
1468 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1469 device
->devlinks_iterator
= ITERATOR_FIRST
;
1471 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1475 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1478 assert_return(device
, NULL
);
1480 (void) device_read_db(device
);
1482 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1485 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1489 static int device_properties_prepare(sd_device
*device
) {
1494 r
= device_read_uevent_file(device
);
1498 r
= device_read_db(device
);
1502 if (device
->property_devlinks_outdated
) {
1503 _cleanup_free_
char *devlinks
= NULL
;
1504 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1505 const char *devlink
;
1507 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1510 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1512 if (devlinks_len
> 0)
1513 stpcpy(devlinks
+ devlinks_len
++, " ");
1514 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1515 devlinks_len
= e
- devlinks
;
1518 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1522 device
->property_devlinks_outdated
= false;
1525 if (device
->property_tags_outdated
) {
1526 _cleanup_free_
char *tags
= NULL
;
1527 size_t tags_allocated
= 0, tags_len
= 0;
1530 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1535 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1538 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1540 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1541 tags_len
= e
- tags
;
1544 r
= device_add_property_internal(device
, "TAGS", tags
);
1548 device
->property_tags_outdated
= false;
1554 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1559 assert_return(device
, NULL
);
1561 r
= device_properties_prepare(device
);
1565 device
->properties_iterator_generation
= device
->properties_generation
;
1566 device
->properties_iterator
= ITERATOR_FIRST
;
1568 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1576 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1581 assert_return(device
, NULL
);
1583 r
= device_properties_prepare(device
);
1587 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1590 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1598 static int device_sysattrs_read_all(sd_device
*device
) {
1599 _cleanup_closedir_
DIR *dir
= NULL
;
1600 const char *syspath
;
1601 struct dirent
*dent
;
1606 if (device
->sysattrs_read
)
1609 r
= sd_device_get_syspath(device
, &syspath
);
1613 dir
= opendir(syspath
);
1617 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1621 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1623 struct stat statbuf
;
1625 /* only handle symlinks and regular files */
1626 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
))
1629 path
= strjoina(syspath
, "/", dent
->d_name
);
1631 if (lstat(path
, &statbuf
) != 0)
1634 if (!(statbuf
.st_mode
& S_IRUSR
))
1637 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1642 device
->sysattrs_read
= true;
1647 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1651 assert_return(device
, NULL
);
1653 if (!device
->sysattrs_read
) {
1654 r
= device_sysattrs_read_all(device
);
1661 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1663 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1667 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1670 assert_return(device
, NULL
);
1672 if (!device
->sysattrs_read
)
1675 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1679 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1680 assert_return(device
, -EINVAL
);
1681 assert_return(tag
, -EINVAL
);
1683 (void) device_read_db(device
);
1685 return !!set_contains(device
->tags
, tag
);
1688 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1692 assert_return(device
, -EINVAL
);
1693 assert_return(key
, -EINVAL
);
1694 assert_return(_value
, -EINVAL
);
1696 r
= device_properties_prepare(device
);
1700 value
= ordered_hashmap_get(device
->properties
, key
);
1709 /* replaces the value if it already exists */
1710 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1711 _cleanup_free_
char *key
= NULL
;
1712 _cleanup_free_
char *value_old
= NULL
;
1718 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1722 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1729 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1738 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1739 const char *key
= NULL
, *value
;
1744 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1754 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1755 * with a NULL value in the cache, otherwise the returned string is stored */
1756 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1757 _cleanup_free_
char *value
= NULL
;
1758 const char *syspath
, *cached_value
= NULL
;
1760 struct stat statbuf
;
1763 assert_return(device
, -EINVAL
);
1764 assert_return(sysattr
, -EINVAL
);
1766 /* look for possibly already cached result */
1767 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1773 /* we looked up the sysattr before and it did not exist */
1777 *_value
= cached_value
;
1782 r
= sd_device_get_syspath(device
, &syspath
);
1786 path
= strjoina(syspath
, "/", sysattr
);
1787 r
= lstat(path
, &statbuf
);
1789 /* remember that we could not access the sysattr */
1790 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1795 } else if (S_ISLNK(statbuf
.st_mode
)) {
1796 /* Some core links return only the last element of the target path,
1797 * these are just values, the paths should not be exposed. */
1798 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1799 r
= readlink_value(path
, &value
);
1804 } else if (S_ISDIR(statbuf
.st_mode
)) {
1805 /* skip directories */
1807 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1808 /* skip non-readable files */
1813 /* read attribute value */
1814 r
= read_full_file(path
, &value
, &size
);
1818 /* drop trailing newlines */
1819 while (size
> 0 && value
[--size
] == '\n')
1823 r
= device_add_sysattr_value(device
, sysattr
, value
);
1833 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1834 _cleanup_free_
char *key
= NULL
;
1835 _cleanup_free_
char *value
= NULL
;
1840 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1845 /* set the attribute and save it in the cache. If a NULL value is passed the
1846 * attribute is cleared from the cache */
1847 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1848 _cleanup_close_
int fd
= -1;
1849 _cleanup_free_
char *value
= NULL
;
1850 const char *syspath
;
1856 assert_return(device
, -EINVAL
);
1857 assert_return(sysattr
, -EINVAL
);
1860 device_remove_sysattr_value(device
, sysattr
);
1865 r
= sd_device_get_syspath(device
, &syspath
);
1869 path
= strjoina(syspath
, "/", sysattr
);
1871 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
1875 if (errno
== EISDIR
)
1882 r
= device_add_sysattr_value(device
, sysattr
, value
);
1890 len
= strlen(_value
);
1892 /* drop trailing newlines */
1893 while (len
> 0 && _value
[len
- 1] == '\n')
1896 /* value length is limited to 4k */
1900 value
= strndup(_value
, len
);
1904 size
= write(fd
, value
, len
);
1908 if ((size_t)size
!= len
)
1911 r
= device_add_sysattr_value(device
, sysattr
, value
);