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 sd_device
*device
= NULL
;
53 device
= new0(sd_device
, 1);
58 device
->watch_handle
= -1;
65 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
67 assert_se(++ device
->n_ref
>= 2);
72 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
73 if (device
&& -- device
->n_ref
== 0) {
74 sd_device_unref(device
->parent
);
75 free(device
->syspath
);
76 free(device
->sysname
);
77 free(device
->devtype
);
78 free(device
->devname
);
79 free(device
->subsystem
);
80 free(device
->driver_subsystem
);
82 free(device
->id_filename
);
83 free(device
->properties_strv
);
84 free(device
->properties_nulstr
);
86 ordered_hashmap_free_free_free(device
->properties
);
87 ordered_hashmap_free_free_free(device
->properties_db
);
88 hashmap_free_free_free(device
->sysattr_values
);
89 set_free_free(device
->sysattrs
);
90 set_free_free(device
->tags
);
91 set_free_free(device
->devlinks
);
99 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
100 OrderedHashmap
**properties
;
106 properties
= &device
->properties_db
;
108 properties
= &device
->properties
;
111 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
114 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
122 value
= strdup(_value
);
126 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
128 r
= ordered_hashmap_replace(*properties
, key
, value
);
135 _cleanup_free_
char *key
= NULL
;
136 _cleanup_free_
char *value
= NULL
;
138 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
142 device
->properties_generation
++;
143 device
->properties_buf_outdated
= true;
149 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
150 return device_add_property_aux(device
, key
, value
, false);
153 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
154 _cleanup_free_
char *syspath
= NULL
;
161 /* must be a subdirectory of /sys */
162 if (!path_startswith(_syspath
, "/sys/")) {
163 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
168 r
= chase_symlinks(_syspath
, NULL
, 0, &syspath
);
170 return -ENODEV
; /* the device does not exist (any more?) */
172 return log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
174 if (!path_startswith(syspath
, "/sys")) {
175 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
178 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
179 r
= chase_symlinks("/sys", NULL
, 0, &real_sys
);
181 return log_debug_errno(r
, "sd-device: could not chase symlink /sys: %m");
183 p
= path_startswith(syspath
, real_sys
);
185 log_debug("sd-device: canonicalized path '%s' does not starts with sysfs mount point '%s'", syspath
, real_sys
);
189 new_syspath
= strjoin("/sys/", p
);
193 free_and_replace(syspath
, new_syspath
);
194 path_kill_slashes(syspath
);
197 if (path_startswith(syspath
, "/sys/devices/")) {
200 /* all 'devices' require an 'uevent' file */
201 path
= strjoina(syspath
, "/uevent");
202 r
= access(path
, F_OK
);
205 /* this is not a valid device */
208 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
211 /* everything else just needs to be a directory */
212 if (!is_dir(syspath
, false))
216 syspath
= strdup(_syspath
);
221 devpath
= syspath
+ STRLEN("/sys");
223 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
227 free_and_replace(device
->syspath
, syspath
);
229 device
->devpath
= devpath
;
234 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
235 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
238 assert_return(ret
, -EINVAL
);
239 assert_return(syspath
, -EINVAL
);
241 r
= device_new_aux(&device
);
245 r
= device_set_syspath(device
, syspath
, true);
249 *ret
= TAKE_PTR(device
);
254 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
256 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
258 assert_return(ret
, -EINVAL
);
259 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
261 /* use /sys/dev/{block,char}/<maj>:<min> link */
262 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
264 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
266 return sd_device_new_from_syspath(ret
, syspath
);
269 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
270 char *name
, *syspath
;
273 assert_return(ret
, -EINVAL
);
274 assert_return(subsystem
, -EINVAL
);
275 assert_return(sysname
, -EINVAL
);
277 if (streq(subsystem
, "subsystem")) {
278 syspath
= strjoina("/sys/subsystem/", sysname
);
279 if (access(syspath
, F_OK
) >= 0)
280 return sd_device_new_from_syspath(ret
, syspath
);
282 syspath
= strjoina("/sys/bus/", sysname
);
283 if (access(syspath
, F_OK
) >= 0)
284 return sd_device_new_from_syspath(ret
, syspath
);
286 syspath
= strjoina("/sys/class/", sysname
);
287 if (access(syspath
, F_OK
) >= 0)
288 return sd_device_new_from_syspath(ret
, syspath
);
289 } else if (streq(subsystem
, "module")) {
290 syspath
= strjoina("/sys/module/", sysname
);
291 if (access(syspath
, F_OK
) >= 0)
292 return sd_device_new_from_syspath(ret
, syspath
);
293 } else if (streq(subsystem
, "drivers")) {
294 char subsys
[PATH_MAX
];
297 strscpy(subsys
, sizeof(subsys
), sysname
);
298 driver
= strchr(subsys
, ':');
303 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
304 if (access(syspath
, F_OK
) >= 0)
305 return sd_device_new_from_syspath(ret
, syspath
);
307 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
308 if (access(syspath
, F_OK
) >= 0)
309 return sd_device_new_from_syspath(ret
, syspath
);
313 /* translate sysname back to sysfs filename */
314 name
= strdupa(sysname
);
315 while (name
[len
] != '\0') {
316 if (name
[len
] == '/')
322 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
323 if (access(syspath
, F_OK
) >= 0)
324 return sd_device_new_from_syspath(ret
, syspath
);
326 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
327 if (access(syspath
, F_OK
) >= 0)
328 return sd_device_new_from_syspath(ret
, syspath
);
330 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
331 if (access(syspath
, F_OK
) >= 0)
332 return sd_device_new_from_syspath(ret
, syspath
);
334 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
335 if (access(syspath
, F_OK
) >= 0)
336 return sd_device_new_from_syspath(ret
, syspath
);
341 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
342 _cleanup_free_
char *devtype
= NULL
;
348 devtype
= strdup(_devtype
);
352 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
356 free_and_replace(device
->devtype
, devtype
);
361 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
367 r
= parse_ifindex(_ifindex
, &ifindex
);
371 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
375 device
->ifindex
= ifindex
;
380 int device_set_devname(sd_device
*device
, const char *_devname
) {
381 _cleanup_free_
char *devname
= NULL
;
387 if (_devname
[0] != '/') {
388 r
= asprintf(&devname
, "/dev/%s", _devname
);
392 devname
= strdup(_devname
);
397 r
= device_add_property_internal(device
, "DEVNAME", devname
);
401 free_and_replace(device
->devname
, devname
);
406 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
413 r
= safe_atou(_devmode
, &devmode
);
420 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
424 device
->devmode
= devmode
;
429 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
430 unsigned maj
= 0, min
= 0;
436 r
= safe_atou(major
, &maj
);
443 r
= safe_atou(minor
, &min
);
448 r
= device_add_property_internal(device
, "MAJOR", major
);
453 r
= device_add_property_internal(device
, "MINOR", minor
);
458 device
->devnum
= makedev(maj
, min
);
463 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
472 if (streq(key
, "DEVTYPE")) {
473 r
= device_set_devtype(device
, value
);
476 } else if (streq(key
, "IFINDEX")) {
477 r
= device_set_ifindex(device
, value
);
480 } else if (streq(key
, "DEVNAME")) {
481 r
= device_set_devname(device
, value
);
484 } else if (streq(key
, "DEVMODE")) {
485 r
= device_set_devmode(device
, value
);
488 } else if (streq(key
, "MAJOR"))
490 else if (streq(key
, "MINOR"))
493 r
= device_add_property_internal(device
, key
, value
);
501 int device_read_uevent_file(sd_device
*device
) {
502 _cleanup_free_
char *uevent
= NULL
;
503 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
519 if (device
->uevent_loaded
|| device
->sealed
)
522 device
->uevent_loaded
= true;
524 r
= sd_device_get_syspath(device
, &syspath
);
528 path
= strjoina(syspath
, "/uevent");
530 r
= read_full_file(path
, &uevent
, &uevent_len
);
532 /* empty uevent files may be write-only */
534 else if (r
== -ENOENT
)
535 /* some devices may not have uevent files, see set_syspath() */
538 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
542 for (i
= 0; i
< uevent_len
; i
++)
545 if (!strchr(NEWLINE
, uevent
[i
])) {
553 if (uevent
[i
] == '=') {
557 } else if (strchr(NEWLINE
, uevent
[i
])) {
559 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
569 _fallthrough_
; /* to handle empty property */
571 if (strchr(NEWLINE
, uevent
[i
])) {
574 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
576 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
583 assert_not_reached("invalid state when parsing uevent file");
587 r
= device_set_devnum(device
, major
, minor
);
589 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
595 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
598 assert_return(device
, -EINVAL
);
599 assert_return(ifindex
, -EINVAL
);
601 r
= device_read_uevent_file(device
);
605 *ifindex
= device
->ifindex
;
610 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
613 assert_return(ret
, -EINVAL
);
614 assert_return(id
, -EINVAL
);
623 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
627 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
631 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
632 _cleanup_close_
int sk
= -1;
633 struct ifreq ifr
= {};
636 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
640 sk
= socket_ioctl_fd();
644 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
648 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
652 r
= sd_device_get_ifindex(device
, &ifindex
);
656 /* this is racey, so we might end up with the wrong device */
657 if (ifr
.ifr_ifindex
!= ifindex
)
660 *ret
= TAKE_PTR(device
);
666 char subsys
[PATH_MAX
];
669 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
670 sysname
= strchr(subsys
, ':');
677 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
684 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
685 assert_return(device
, -EINVAL
);
686 assert_return(ret
, -EINVAL
);
688 assert(path_startswith(device
->syspath
, "/sys/"));
690 *ret
= device
->syspath
;
695 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
696 _cleanup_free_
char *path
= NULL
;
697 const char *subdir
, *syspath
;
703 r
= sd_device_get_syspath(child
, &syspath
);
707 path
= strdup(syspath
);
710 subdir
= path
+ STRLEN("/sys");
715 pos
= strrchr(subdir
, '/');
716 if (!pos
|| pos
< subdir
+ 2)
721 r
= sd_device_new_from_syspath(ret
, path
);
731 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
733 assert_return(ret
, -EINVAL
);
734 assert_return(child
, -EINVAL
);
736 if (!child
->parent_set
) {
737 child
->parent_set
= true;
739 (void)device_new_from_child(&child
->parent
, child
);
745 *ret
= child
->parent
;
750 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
751 _cleanup_free_
char *subsystem
= NULL
;
757 subsystem
= strdup(_subsystem
);
761 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
765 free_and_replace(device
->subsystem
, subsystem
);
767 device
->subsystem_set
= true;
772 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
773 _cleanup_free_
char *subsystem
= NULL
;
780 subsystem
= strdup(_subsystem
);
784 r
= device_set_subsystem(device
, "drivers");
788 free_and_replace(device
->driver_subsystem
, subsystem
);
793 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
794 const char *syspath
, *drivers
= NULL
;
797 assert_return(ret
, -EINVAL
);
798 assert_return(device
, -EINVAL
);
800 r
= sd_device_get_syspath(device
, &syspath
);
804 if (!device
->subsystem_set
) {
805 _cleanup_free_
char *subsystem
= NULL
;
808 /* read 'subsystem' link */
809 path
= strjoina(syspath
, "/subsystem");
810 r
= readlink_value(path
, &subsystem
);
812 r
= device_set_subsystem(device
, subsystem
);
813 /* use implicit names */
814 else if (path_startswith(device
->devpath
, "/module/"))
815 r
= device_set_subsystem(device
, "module");
816 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
817 (path_startswith(device
->devpath
, "/subsystem/") ||
818 path_startswith(device
->devpath
, "/class/") ||
819 path_startswith(device
->devpath
, "/bus/")))
820 r
= device_set_subsystem(device
, "subsystem");
821 if (r
< 0 && r
!= -ENOENT
)
822 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
824 device
->subsystem_set
= true;
825 } else if (!device
->driver_subsystem_set
)
826 drivers
= strstr(syspath
, "/drivers/");
828 if (!device
->driver_subsystem_set
) {
830 _cleanup_free_
char *subpath
= NULL
;
832 subpath
= strndup(syspath
, drivers
- syspath
);
838 subsys
= strrchr(subpath
, '/');
842 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
844 if (r
< 0 && r
!= -ENOENT
)
845 return log_debug_errno(r
, "sd-device: could not set subsystem for driver %s: %m", device
->devpath
);
848 device
->driver_subsystem_set
= true;
851 if (!device
->subsystem
)
854 *ret
= device
->subsystem
;
859 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
865 r
= device_read_uevent_file(device
);
869 *devtype
= device
->devtype
;
874 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
875 sd_device
*parent
= NULL
;
878 assert_return(child
, -EINVAL
);
879 assert_return(subsystem
, -EINVAL
);
881 r
= sd_device_get_parent(child
, &parent
);
883 const char *parent_subsystem
= NULL
;
884 const char *parent_devtype
= NULL
;
886 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
887 if (streq_ptr(parent_subsystem
, subsystem
)) {
891 (void)sd_device_get_devtype(parent
, &parent_devtype
);
892 if (streq_ptr(parent_devtype
, devtype
))
895 r
= sd_device_get_parent(parent
, &parent
);
906 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
909 assert_return(device
, -EINVAL
);
910 assert_return(devnum
, -EINVAL
);
912 r
= device_read_uevent_file(device
);
916 *devnum
= device
->devnum
;
921 int device_set_driver(sd_device
*device
, const char *_driver
) {
922 _cleanup_free_
char *driver
= NULL
;
928 driver
= strdup(_driver
);
932 r
= device_add_property_internal(device
, "DRIVER", driver
);
936 free_and_replace(device
->driver
, driver
);
938 device
->driver_set
= true;
943 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
944 assert_return(device
, -EINVAL
);
945 assert_return(ret
, -EINVAL
);
947 if (!device
->driver_set
) {
948 _cleanup_free_
char *driver
= NULL
;
953 r
= sd_device_get_syspath(device
, &syspath
);
957 path
= strjoina(syspath
, "/driver");
958 r
= readlink_value(path
, &driver
);
960 r
= device_set_driver(device
, driver
);
962 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
963 } else if (r
== -ENOENT
)
964 device
->driver_set
= true;
966 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
972 *ret
= device
->driver
;
977 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
978 assert_return(device
, -EINVAL
);
979 assert_return(devpath
, -EINVAL
);
981 assert(device
->devpath
);
982 assert(device
->devpath
[0] == '/');
984 *devpath
= device
->devpath
;
989 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
992 assert_return(device
, -EINVAL
);
993 assert_return(devname
, -EINVAL
);
995 r
= device_read_uevent_file(device
);
999 if (!device
->devname
)
1002 assert(path_startswith(device
->devname
, "/dev/"));
1004 *devname
= device
->devname
;
1009 static int device_set_sysname(sd_device
*device
) {
1010 _cleanup_free_
char *sysname
= NULL
;
1011 const char *sysnum
= NULL
;
1015 pos
= strrchr(device
->devpath
, '/');
1020 /* devpath is not a root directory */
1021 if (*pos
== '\0' || pos
<= device
->devpath
)
1024 sysname
= strdup(pos
);
1028 /* some devices have '!' in their name, change that to '/' */
1029 while (sysname
[len
] != '\0') {
1030 if (sysname
[len
] == '!')
1036 /* trailing number */
1037 while (len
> 0 && isdigit(sysname
[--len
]))
1038 sysnum
= &sysname
[len
];
1043 free_and_replace(device
->sysname
, sysname
);
1045 device
->sysnum
= sysnum
;
1047 device
->sysname_set
= true;
1052 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1055 assert_return(device
, -EINVAL
);
1056 assert_return(ret
, -EINVAL
);
1058 if (!device
->sysname_set
) {
1059 r
= device_set_sysname(device
);
1064 assert_return(device
->sysname
, -ENOENT
);
1066 *ret
= device
->sysname
;
1071 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1074 assert_return(device
, -EINVAL
);
1075 assert_return(ret
, -EINVAL
);
1077 if (!device
->sysname_set
) {
1078 r
= device_set_sysname(device
);
1083 *ret
= device
->sysnum
;
1088 static bool is_valid_tag(const char *tag
) {
1091 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1094 int device_add_tag(sd_device
*device
, const char *tag
) {
1100 if (!is_valid_tag(tag
))
1103 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1107 r
= set_put_strdup(device
->tags
, tag
);
1111 device
->tags_generation
++;
1112 device
->property_tags_outdated
= true;
1117 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1123 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1127 r
= set_put_strdup(device
->devlinks
, devlink
);
1131 device
->devlinks_generation
++;
1132 device
->property_devlinks_outdated
= true;
1137 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1138 _cleanup_free_
char *key
= NULL
;
1148 value
= strchr(key
, '=');
1154 if (isempty(++value
))
1157 return device_add_property_internal(device
, key
, value
);
1160 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1161 uint64_t usec_initialized
;
1165 assert(initialized
);
1167 r
= safe_atou64(initialized
, &usec_initialized
);
1171 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1175 device
->usec_initialized
= usec_initialized
;
1180 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1189 r
= device_add_tag(device
, value
);
1195 path
= strjoina("/dev/", value
);
1196 r
= device_add_devlink(device
, path
);
1202 r
= device_add_property_internal_from_string(device
, value
);
1208 r
= device_set_usec_initialized(device
, value
);
1214 r
= safe_atoi(value
, &device
->devlink_priority
);
1220 r
= safe_atoi(value
, &device
->watch_handle
);
1226 log_debug("device db: unknown key '%c'", key
);
1232 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1236 if (!device
->id_filename
) {
1237 _cleanup_free_
char *id
= NULL
;
1238 const char *subsystem
;
1242 r
= sd_device_get_subsystem(device
, &subsystem
);
1246 r
= sd_device_get_devnum(device
, &devnum
);
1250 r
= sd_device_get_ifindex(device
, &ifindex
);
1254 if (major(devnum
) > 0) {
1257 /* use dev_t — b259:131072, c254:0 */
1258 r
= asprintf(&id
, "%c%u:%u",
1259 streq(subsystem
, "block") ? 'b' : 'c',
1260 major(devnum
), minor(devnum
));
1263 } else if (ifindex
> 0) {
1264 /* use netdev ifindex — n3 */
1265 r
= asprintf(&id
, "n%u", ifindex
);
1269 /* use $subsys:$sysname — pci:0000:00:1f.2
1270 * sysname() has '!' translated, get it from devpath
1272 const char *sysname
;
1274 sysname
= basename(device
->devpath
);
1281 if (streq(subsystem
, "drivers")) {
1282 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1283 * encoded as well */
1284 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1288 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1294 device
->id_filename
= TAKE_PTR(id
);
1297 *ret
= device
->id_filename
;
1302 int device_read_db_aux(sd_device
*device
, bool force
) {
1303 _cleanup_free_
char *db
= NULL
;
1305 const char *id
, *value
;
1319 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1322 device
->db_loaded
= true;
1324 r
= device_get_id_filename(device
, &id
);
1328 path
= strjoina("/run/udev/data/", id
);
1330 r
= read_full_file(path
, &db
, &db_len
);
1335 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1338 /* devices with a database entry are initialized */
1339 device
->is_initialized
= true;
1341 for (i
= 0; i
< db_len
; i
++) {
1344 if (!strchr(NEWLINE
, db
[i
])) {
1353 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1355 state
= INVALID_LINE
;
1370 if (strchr(NEWLINE
, db
[i
]))
1375 if (strchr(NEWLINE
, db
[i
])) {
1377 r
= handle_db_line(device
, key
, value
);
1379 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1386 assert_not_reached("invalid state when parsing db");
1393 static int device_read_db(sd_device
*device
) {
1394 return device_read_db_aux(device
, false);
1397 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1400 assert_return(device
, -EINVAL
);
1401 assert_return(initialized
, -EINVAL
);
1403 r
= device_read_db(device
);
1407 *initialized
= device
->is_initialized
;
1412 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1416 assert_return(device
, -EINVAL
);
1417 assert_return(usec
, -EINVAL
);
1419 r
= device_read_db(device
);
1423 if (!device
->is_initialized
)
1426 if (!device
->usec_initialized
)
1429 now_ts
= now(clock_boottime_or_monotonic());
1431 if (now_ts
< device
->usec_initialized
)
1434 *usec
= now_ts
- device
->usec_initialized
;
1439 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1442 assert_return(device
, NULL
);
1444 (void) device_read_db(device
);
1446 device
->tags_iterator_generation
= device
->tags_generation
;
1447 device
->tags_iterator
= ITERATOR_FIRST
;
1449 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1453 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1456 assert_return(device
, NULL
);
1458 (void) device_read_db(device
);
1460 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1463 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1467 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1470 assert_return(device
, NULL
);
1472 (void) device_read_db(device
);
1474 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1475 device
->devlinks_iterator
= ITERATOR_FIRST
;
1477 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1481 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1484 assert_return(device
, NULL
);
1486 (void) device_read_db(device
);
1488 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1491 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1495 static int device_properties_prepare(sd_device
*device
) {
1500 r
= device_read_uevent_file(device
);
1504 r
= device_read_db(device
);
1508 if (device
->property_devlinks_outdated
) {
1509 _cleanup_free_
char *devlinks
= NULL
;
1510 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1511 const char *devlink
;
1513 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1516 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1518 if (devlinks_len
> 0)
1519 stpcpy(devlinks
+ devlinks_len
++, " ");
1520 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1521 devlinks_len
= e
- devlinks
;
1524 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1528 device
->property_devlinks_outdated
= false;
1531 if (device
->property_tags_outdated
) {
1532 _cleanup_free_
char *tags
= NULL
;
1533 size_t tags_allocated
= 0, tags_len
= 0;
1536 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1541 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1544 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1546 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1547 tags_len
= e
- tags
;
1550 r
= device_add_property_internal(device
, "TAGS", tags
);
1554 device
->property_tags_outdated
= false;
1560 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1565 assert_return(device
, NULL
);
1567 r
= device_properties_prepare(device
);
1571 device
->properties_iterator_generation
= device
->properties_generation
;
1572 device
->properties_iterator
= ITERATOR_FIRST
;
1574 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1582 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1587 assert_return(device
, NULL
);
1589 r
= device_properties_prepare(device
);
1593 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1596 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1604 static int device_sysattrs_read_all(sd_device
*device
) {
1605 _cleanup_closedir_
DIR *dir
= NULL
;
1606 const char *syspath
;
1607 struct dirent
*dent
;
1612 if (device
->sysattrs_read
)
1615 r
= sd_device_get_syspath(device
, &syspath
);
1619 dir
= opendir(syspath
);
1623 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1627 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1629 struct stat statbuf
;
1631 /* only handle symlinks and regular files */
1632 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
))
1635 path
= strjoina(syspath
, "/", dent
->d_name
);
1637 if (lstat(path
, &statbuf
) != 0)
1640 if (!(statbuf
.st_mode
& S_IRUSR
))
1643 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1648 device
->sysattrs_read
= true;
1653 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1657 assert_return(device
, NULL
);
1659 if (!device
->sysattrs_read
) {
1660 r
= device_sysattrs_read_all(device
);
1667 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1669 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1673 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1676 assert_return(device
, NULL
);
1678 if (!device
->sysattrs_read
)
1681 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1685 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1686 assert_return(device
, -EINVAL
);
1687 assert_return(tag
, -EINVAL
);
1689 (void) device_read_db(device
);
1691 return !!set_contains(device
->tags
, tag
);
1694 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1698 assert_return(device
, -EINVAL
);
1699 assert_return(key
, -EINVAL
);
1700 assert_return(_value
, -EINVAL
);
1702 r
= device_properties_prepare(device
);
1706 value
= ordered_hashmap_get(device
->properties
, key
);
1715 /* replaces the value if it already exists */
1716 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1717 _cleanup_free_
char *key
= NULL
;
1718 _cleanup_free_
char *value_old
= NULL
;
1724 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1728 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1735 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1744 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1745 const char *key
= NULL
, *value
;
1750 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1760 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1761 * with a NULL value in the cache, otherwise the returned string is stored */
1762 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1763 _cleanup_free_
char *value
= NULL
;
1764 const char *syspath
, *cached_value
= NULL
;
1766 struct stat statbuf
;
1769 assert_return(device
, -EINVAL
);
1770 assert_return(sysattr
, -EINVAL
);
1772 /* look for possibly already cached result */
1773 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1779 /* we looked up the sysattr before and it did not exist */
1783 *_value
= cached_value
;
1788 r
= sd_device_get_syspath(device
, &syspath
);
1792 path
= strjoina(syspath
, "/", sysattr
);
1793 r
= lstat(path
, &statbuf
);
1795 /* remember that we could not access the sysattr */
1796 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1801 } else if (S_ISLNK(statbuf
.st_mode
)) {
1802 /* Some core links return only the last element of the target path,
1803 * these are just values, the paths should not be exposed. */
1804 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1805 r
= readlink_value(path
, &value
);
1810 } else if (S_ISDIR(statbuf
.st_mode
)) {
1811 /* skip directories */
1813 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1814 /* skip non-readable files */
1819 /* read attribute value */
1820 r
= read_full_file(path
, &value
, &size
);
1824 /* drop trailing newlines */
1825 while (size
> 0 && value
[--size
] == '\n')
1829 r
= device_add_sysattr_value(device
, sysattr
, value
);
1833 *_value
= TAKE_PTR(value
);
1838 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1839 _cleanup_free_
char *key
= NULL
;
1840 _cleanup_free_
char *value
= NULL
;
1845 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1850 /* set the attribute and save it in the cache. If a NULL value is passed the
1851 * attribute is cleared from the cache */
1852 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1853 _cleanup_close_
int fd
= -1;
1854 _cleanup_free_
char *value
= NULL
;
1855 const char *syspath
;
1861 assert_return(device
, -EINVAL
);
1862 assert_return(sysattr
, -EINVAL
);
1865 device_remove_sysattr_value(device
, sysattr
);
1870 r
= sd_device_get_syspath(device
, &syspath
);
1874 path
= strjoina(syspath
, "/", sysattr
);
1876 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
1880 if (errno
== EISDIR
)
1887 r
= device_add_sysattr_value(device
, sysattr
, value
);
1895 len
= strlen(_value
);
1897 /* drop trailing newlines */
1898 while (len
> 0 && _value
[len
- 1] == '\n')
1901 /* value length is limited to 4k */
1905 value
= strndup(_value
, len
);
1909 size
= write(fd
, value
, len
);
1913 if ((size_t)size
!= len
)
1916 r
= device_add_sysattr_value(device
, sysattr
, value
);