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
= chase_symlinks(_syspath
, NULL
, 0, &syspath
);
171 return -ENODEV
; /* the device does not exist (any more?) */
173 return log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
175 if (!path_startswith(syspath
, "/sys")) {
176 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
179 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
180 r
= chase_symlinks("/sys", NULL
, 0, &real_sys
);
182 return log_debug_errno(r
, "sd-device: could not chase symlink /sys: %m");
184 p
= path_startswith(syspath
, real_sys
);
186 log_debug("sd-device: canonicalized path '%s' does not starts with sysfs mount point '%s'", syspath
, real_sys
);
190 new_syspath
= strjoin("/sys/", p
);
194 free_and_replace(syspath
, new_syspath
);
195 path_kill_slashes(syspath
);
198 if (path_startswith(syspath
, "/sys/devices/")) {
201 /* all 'devices' require an 'uevent' file */
202 path
= strjoina(syspath
, "/uevent");
203 r
= access(path
, F_OK
);
206 /* this is not a valid device */
209 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
212 /* everything else just needs to be a directory */
213 if (!is_dir(syspath
, false))
217 syspath
= strdup(_syspath
);
222 devpath
= syspath
+ STRLEN("/sys");
224 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
228 free_and_replace(device
->syspath
, syspath
);
230 device
->devpath
= devpath
;
235 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
236 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
239 assert_return(ret
, -EINVAL
);
240 assert_return(syspath
, -EINVAL
);
242 r
= device_new_aux(&device
);
246 r
= device_set_syspath(device
, syspath
, true);
256 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
258 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
260 assert_return(ret
, -EINVAL
);
261 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
263 /* use /sys/dev/{block,char}/<maj>:<min> link */
264 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
266 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
268 return sd_device_new_from_syspath(ret
, syspath
);
271 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
272 char *name
, *syspath
;
275 assert_return(ret
, -EINVAL
);
276 assert_return(subsystem
, -EINVAL
);
277 assert_return(sysname
, -EINVAL
);
279 if (streq(subsystem
, "subsystem")) {
280 syspath
= strjoina("/sys/subsystem/", sysname
);
281 if (access(syspath
, F_OK
) >= 0)
282 return sd_device_new_from_syspath(ret
, syspath
);
284 syspath
= strjoina("/sys/bus/", sysname
);
285 if (access(syspath
, F_OK
) >= 0)
286 return sd_device_new_from_syspath(ret
, syspath
);
288 syspath
= strjoina("/sys/class/", sysname
);
289 if (access(syspath
, F_OK
) >= 0)
290 return sd_device_new_from_syspath(ret
, syspath
);
291 } else if (streq(subsystem
, "module")) {
292 syspath
= strjoina("/sys/module/", sysname
);
293 if (access(syspath
, F_OK
) >= 0)
294 return sd_device_new_from_syspath(ret
, syspath
);
295 } else if (streq(subsystem
, "drivers")) {
296 char subsys
[PATH_MAX
];
299 strscpy(subsys
, sizeof(subsys
), sysname
);
300 driver
= strchr(subsys
, ':');
305 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
306 if (access(syspath
, F_OK
) >= 0)
307 return sd_device_new_from_syspath(ret
, syspath
);
309 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
310 if (access(syspath
, F_OK
) >= 0)
311 return sd_device_new_from_syspath(ret
, syspath
);
315 /* translate sysname back to sysfs filename */
316 name
= strdupa(sysname
);
317 while (name
[len
] != '\0') {
318 if (name
[len
] == '/')
324 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
325 if (access(syspath
, F_OK
) >= 0)
326 return sd_device_new_from_syspath(ret
, syspath
);
328 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
329 if (access(syspath
, F_OK
) >= 0)
330 return sd_device_new_from_syspath(ret
, syspath
);
332 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
333 if (access(syspath
, F_OK
) >= 0)
334 return sd_device_new_from_syspath(ret
, syspath
);
336 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
337 if (access(syspath
, F_OK
) >= 0)
338 return sd_device_new_from_syspath(ret
, syspath
);
343 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
344 _cleanup_free_
char *devtype
= NULL
;
350 devtype
= strdup(_devtype
);
354 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
358 free_and_replace(device
->devtype
, devtype
);
363 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
369 r
= parse_ifindex(_ifindex
, &ifindex
);
373 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
377 device
->ifindex
= ifindex
;
382 int device_set_devname(sd_device
*device
, const char *_devname
) {
383 _cleanup_free_
char *devname
= NULL
;
389 if (_devname
[0] != '/') {
390 r
= asprintf(&devname
, "/dev/%s", _devname
);
394 devname
= strdup(_devname
);
399 r
= device_add_property_internal(device
, "DEVNAME", devname
);
403 free_and_replace(device
->devname
, devname
);
408 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
415 r
= safe_atou(_devmode
, &devmode
);
422 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
426 device
->devmode
= devmode
;
431 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
432 unsigned maj
= 0, min
= 0;
438 r
= safe_atou(major
, &maj
);
445 r
= safe_atou(minor
, &min
);
450 r
= device_add_property_internal(device
, "MAJOR", major
);
455 r
= device_add_property_internal(device
, "MINOR", minor
);
460 device
->devnum
= makedev(maj
, min
);
465 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
474 if (streq(key
, "DEVTYPE")) {
475 r
= device_set_devtype(device
, value
);
478 } else if (streq(key
, "IFINDEX")) {
479 r
= device_set_ifindex(device
, value
);
482 } else if (streq(key
, "DEVNAME")) {
483 r
= device_set_devname(device
, value
);
486 } else if (streq(key
, "DEVMODE")) {
487 r
= device_set_devmode(device
, value
);
490 } else if (streq(key
, "MAJOR"))
492 else if (streq(key
, "MINOR"))
495 r
= device_add_property_internal(device
, key
, value
);
503 int device_read_uevent_file(sd_device
*device
) {
504 _cleanup_free_
char *uevent
= NULL
;
505 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
521 if (device
->uevent_loaded
|| device
->sealed
)
524 device
->uevent_loaded
= true;
526 r
= sd_device_get_syspath(device
, &syspath
);
530 path
= strjoina(syspath
, "/uevent");
532 r
= read_full_file(path
, &uevent
, &uevent_len
);
534 /* empty uevent files may be write-only */
536 else if (r
== -ENOENT
)
537 /* some devices may not have uevent files, see set_syspath() */
540 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
544 for (i
= 0; i
< uevent_len
; i
++)
547 if (!strchr(NEWLINE
, uevent
[i
])) {
555 if (uevent
[i
] == '=') {
559 } else if (strchr(NEWLINE
, uevent
[i
])) {
561 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
571 _fallthrough_
; /* to handle empty property */
573 if (strchr(NEWLINE
, uevent
[i
])) {
576 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
578 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
585 assert_not_reached("invalid state when parsing uevent file");
589 r
= device_set_devnum(device
, major
, minor
);
591 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
597 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
600 assert_return(device
, -EINVAL
);
601 assert_return(ifindex
, -EINVAL
);
603 r
= device_read_uevent_file(device
);
607 *ifindex
= device
->ifindex
;
612 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
615 assert_return(ret
, -EINVAL
);
616 assert_return(id
, -EINVAL
);
625 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
629 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
633 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
634 _cleanup_close_
int sk
= -1;
635 struct ifreq ifr
= {};
638 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
642 sk
= socket_ioctl_fd();
646 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
650 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
654 r
= sd_device_get_ifindex(device
, &ifindex
);
658 /* this is racey, so we might end up with the wrong device */
659 if (ifr
.ifr_ifindex
!= ifindex
)
669 char subsys
[PATH_MAX
];
672 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
673 sysname
= strchr(subsys
, ':');
680 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
687 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
688 assert_return(device
, -EINVAL
);
689 assert_return(ret
, -EINVAL
);
691 assert(path_startswith(device
->syspath
, "/sys/"));
693 *ret
= device
->syspath
;
698 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
699 _cleanup_free_
char *path
= NULL
;
700 const char *subdir
, *syspath
;
706 r
= sd_device_get_syspath(child
, &syspath
);
710 path
= strdup(syspath
);
713 subdir
= path
+ STRLEN("/sys");
718 pos
= strrchr(subdir
, '/');
719 if (!pos
|| pos
< subdir
+ 2)
724 r
= sd_device_new_from_syspath(ret
, path
);
734 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
736 assert_return(ret
, -EINVAL
);
737 assert_return(child
, -EINVAL
);
739 if (!child
->parent_set
) {
740 child
->parent_set
= true;
742 (void)device_new_from_child(&child
->parent
, child
);
748 *ret
= child
->parent
;
753 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
754 _cleanup_free_
char *subsystem
= NULL
;
760 subsystem
= strdup(_subsystem
);
764 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
768 free_and_replace(device
->subsystem
, subsystem
);
770 device
->subsystem_set
= true;
775 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
776 _cleanup_free_
char *subsystem
= NULL
;
783 subsystem
= strdup(_subsystem
);
787 r
= device_set_subsystem(device
, "drivers");
791 free_and_replace(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_and_replace(device
->driver
, driver
);
941 device
->driver_set
= true;
946 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
947 assert_return(device
, -EINVAL
);
948 assert_return(ret
, -EINVAL
);
950 if (!device
->driver_set
) {
951 _cleanup_free_
char *driver
= NULL
;
956 r
= sd_device_get_syspath(device
, &syspath
);
960 path
= strjoina(syspath
, "/driver");
961 r
= readlink_value(path
, &driver
);
963 r
= device_set_driver(device
, driver
);
965 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
966 } else if (r
== -ENOENT
)
967 device
->driver_set
= true;
969 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
975 *ret
= device
->driver
;
980 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
981 assert_return(device
, -EINVAL
);
982 assert_return(devpath
, -EINVAL
);
984 assert(device
->devpath
);
985 assert(device
->devpath
[0] == '/');
987 *devpath
= device
->devpath
;
992 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
995 assert_return(device
, -EINVAL
);
996 assert_return(devname
, -EINVAL
);
998 r
= device_read_uevent_file(device
);
1002 if (!device
->devname
)
1005 assert(path_startswith(device
->devname
, "/dev/"));
1007 *devname
= device
->devname
;
1012 static int device_set_sysname(sd_device
*device
) {
1013 _cleanup_free_
char *sysname
= NULL
;
1014 const char *sysnum
= NULL
;
1018 pos
= strrchr(device
->devpath
, '/');
1023 /* devpath is not a root directory */
1024 if (*pos
== '\0' || pos
<= device
->devpath
)
1027 sysname
= strdup(pos
);
1031 /* some devices have '!' in their name, change that to '/' */
1032 while (sysname
[len
] != '\0') {
1033 if (sysname
[len
] == '!')
1039 /* trailing number */
1040 while (len
> 0 && isdigit(sysname
[--len
]))
1041 sysnum
= &sysname
[len
];
1046 free_and_replace(device
->sysname
, sysname
);
1048 device
->sysnum
= sysnum
;
1050 device
->sysname_set
= true;
1055 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1058 assert_return(device
, -EINVAL
);
1059 assert_return(ret
, -EINVAL
);
1061 if (!device
->sysname_set
) {
1062 r
= device_set_sysname(device
);
1067 assert_return(device
->sysname
, -ENOENT
);
1069 *ret
= device
->sysname
;
1074 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1077 assert_return(device
, -EINVAL
);
1078 assert_return(ret
, -EINVAL
);
1080 if (!device
->sysname_set
) {
1081 r
= device_set_sysname(device
);
1086 *ret
= device
->sysnum
;
1091 static bool is_valid_tag(const char *tag
) {
1094 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1097 int device_add_tag(sd_device
*device
, const char *tag
) {
1103 if (!is_valid_tag(tag
))
1106 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1110 r
= set_put_strdup(device
->tags
, tag
);
1114 device
->tags_generation
++;
1115 device
->property_tags_outdated
= true;
1120 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1126 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1130 r
= set_put_strdup(device
->devlinks
, devlink
);
1134 device
->devlinks_generation
++;
1135 device
->property_devlinks_outdated
= true;
1140 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1141 _cleanup_free_
char *key
= NULL
;
1151 value
= strchr(key
, '=');
1157 if (isempty(++value
))
1160 return device_add_property_internal(device
, key
, value
);
1163 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1164 uint64_t usec_initialized
;
1168 assert(initialized
);
1170 r
= safe_atou64(initialized
, &usec_initialized
);
1174 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1178 device
->usec_initialized
= usec_initialized
;
1183 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1192 r
= device_add_tag(device
, value
);
1198 path
= strjoina("/dev/", value
);
1199 r
= device_add_devlink(device
, path
);
1205 r
= device_add_property_internal_from_string(device
, value
);
1211 r
= device_set_usec_initialized(device
, value
);
1217 r
= safe_atoi(value
, &device
->devlink_priority
);
1223 r
= safe_atoi(value
, &device
->watch_handle
);
1229 log_debug("device db: unknown key '%c'", key
);
1235 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1239 if (!device
->id_filename
) {
1240 _cleanup_free_
char *id
= NULL
;
1241 const char *subsystem
;
1245 r
= sd_device_get_subsystem(device
, &subsystem
);
1249 r
= sd_device_get_devnum(device
, &devnum
);
1253 r
= sd_device_get_ifindex(device
, &ifindex
);
1257 if (major(devnum
) > 0) {
1260 /* use dev_t — b259:131072, c254:0 */
1261 r
= asprintf(&id
, "%c%u:%u",
1262 streq(subsystem
, "block") ? 'b' : 'c',
1263 major(devnum
), minor(devnum
));
1266 } else if (ifindex
> 0) {
1267 /* use netdev ifindex — n3 */
1268 r
= asprintf(&id
, "n%u", ifindex
);
1272 /* use $subsys:$sysname — pci:0000:00:1f.2
1273 * sysname() has '!' translated, get it from devpath
1275 const char *sysname
;
1277 sysname
= basename(device
->devpath
);
1284 if (streq(subsystem
, "drivers")) {
1285 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1286 * encoded as well */
1287 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1291 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1297 device
->id_filename
= TAKE_PTR(id
);
1300 *ret
= device
->id_filename
;
1305 int device_read_db_aux(sd_device
*device
, bool force
) {
1306 _cleanup_free_
char *db
= NULL
;
1308 const char *id
, *value
;
1322 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1325 device
->db_loaded
= true;
1327 r
= device_get_id_filename(device
, &id
);
1331 path
= strjoina("/run/udev/data/", id
);
1333 r
= read_full_file(path
, &db
, &db_len
);
1338 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1341 /* devices with a database entry are initialized */
1342 device
->is_initialized
= true;
1344 for (i
= 0; i
< db_len
; i
++) {
1347 if (!strchr(NEWLINE
, db
[i
])) {
1356 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1358 state
= INVALID_LINE
;
1373 if (strchr(NEWLINE
, db
[i
]))
1378 if (strchr(NEWLINE
, db
[i
])) {
1380 r
= handle_db_line(device
, key
, value
);
1382 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1389 assert_not_reached("invalid state when parsing db");
1396 static int device_read_db(sd_device
*device
) {
1397 return device_read_db_aux(device
, false);
1400 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1403 assert_return(device
, -EINVAL
);
1404 assert_return(initialized
, -EINVAL
);
1406 r
= device_read_db(device
);
1410 *initialized
= device
->is_initialized
;
1415 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1419 assert_return(device
, -EINVAL
);
1420 assert_return(usec
, -EINVAL
);
1422 r
= device_read_db(device
);
1426 if (!device
->is_initialized
)
1429 if (!device
->usec_initialized
)
1432 now_ts
= now(clock_boottime_or_monotonic());
1434 if (now_ts
< device
->usec_initialized
)
1437 *usec
= now_ts
- device
->usec_initialized
;
1442 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1445 assert_return(device
, NULL
);
1447 (void) device_read_db(device
);
1449 device
->tags_iterator_generation
= device
->tags_generation
;
1450 device
->tags_iterator
= ITERATOR_FIRST
;
1452 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1456 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1459 assert_return(device
, NULL
);
1461 (void) device_read_db(device
);
1463 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1466 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1470 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1473 assert_return(device
, NULL
);
1475 (void) device_read_db(device
);
1477 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1478 device
->devlinks_iterator
= ITERATOR_FIRST
;
1480 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1484 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1487 assert_return(device
, NULL
);
1489 (void) device_read_db(device
);
1491 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1494 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1498 static int device_properties_prepare(sd_device
*device
) {
1503 r
= device_read_uevent_file(device
);
1507 r
= device_read_db(device
);
1511 if (device
->property_devlinks_outdated
) {
1512 _cleanup_free_
char *devlinks
= NULL
;
1513 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1514 const char *devlink
;
1516 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1519 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1521 if (devlinks_len
> 0)
1522 stpcpy(devlinks
+ devlinks_len
++, " ");
1523 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1524 devlinks_len
= e
- devlinks
;
1527 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1531 device
->property_devlinks_outdated
= false;
1534 if (device
->property_tags_outdated
) {
1535 _cleanup_free_
char *tags
= NULL
;
1536 size_t tags_allocated
= 0, tags_len
= 0;
1539 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1544 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1547 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1549 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1550 tags_len
= e
- tags
;
1553 r
= device_add_property_internal(device
, "TAGS", tags
);
1557 device
->property_tags_outdated
= false;
1563 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1568 assert_return(device
, NULL
);
1570 r
= device_properties_prepare(device
);
1574 device
->properties_iterator_generation
= device
->properties_generation
;
1575 device
->properties_iterator
= ITERATOR_FIRST
;
1577 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1585 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1590 assert_return(device
, NULL
);
1592 r
= device_properties_prepare(device
);
1596 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1599 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1607 static int device_sysattrs_read_all(sd_device
*device
) {
1608 _cleanup_closedir_
DIR *dir
= NULL
;
1609 const char *syspath
;
1610 struct dirent
*dent
;
1615 if (device
->sysattrs_read
)
1618 r
= sd_device_get_syspath(device
, &syspath
);
1622 dir
= opendir(syspath
);
1626 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1630 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1632 struct stat statbuf
;
1634 /* only handle symlinks and regular files */
1635 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
))
1638 path
= strjoina(syspath
, "/", dent
->d_name
);
1640 if (lstat(path
, &statbuf
) != 0)
1643 if (!(statbuf
.st_mode
& S_IRUSR
))
1646 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1651 device
->sysattrs_read
= true;
1656 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1660 assert_return(device
, NULL
);
1662 if (!device
->sysattrs_read
) {
1663 r
= device_sysattrs_read_all(device
);
1670 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1672 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1676 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1679 assert_return(device
, NULL
);
1681 if (!device
->sysattrs_read
)
1684 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1688 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1689 assert_return(device
, -EINVAL
);
1690 assert_return(tag
, -EINVAL
);
1692 (void) device_read_db(device
);
1694 return !!set_contains(device
->tags
, tag
);
1697 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1701 assert_return(device
, -EINVAL
);
1702 assert_return(key
, -EINVAL
);
1703 assert_return(_value
, -EINVAL
);
1705 r
= device_properties_prepare(device
);
1709 value
= ordered_hashmap_get(device
->properties
, key
);
1718 /* replaces the value if it already exists */
1719 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1720 _cleanup_free_
char *key
= NULL
;
1721 _cleanup_free_
char *value_old
= NULL
;
1727 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1731 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1738 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1747 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1748 const char *key
= NULL
, *value
;
1753 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1763 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1764 * with a NULL value in the cache, otherwise the returned string is stored */
1765 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1766 _cleanup_free_
char *value
= NULL
;
1767 const char *syspath
, *cached_value
= NULL
;
1769 struct stat statbuf
;
1772 assert_return(device
, -EINVAL
);
1773 assert_return(sysattr
, -EINVAL
);
1775 /* look for possibly already cached result */
1776 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1782 /* we looked up the sysattr before and it did not exist */
1786 *_value
= cached_value
;
1791 r
= sd_device_get_syspath(device
, &syspath
);
1795 path
= strjoina(syspath
, "/", sysattr
);
1796 r
= lstat(path
, &statbuf
);
1798 /* remember that we could not access the sysattr */
1799 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1804 } else if (S_ISLNK(statbuf
.st_mode
)) {
1805 /* Some core links return only the last element of the target path,
1806 * these are just values, the paths should not be exposed. */
1807 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1808 r
= readlink_value(path
, &value
);
1813 } else if (S_ISDIR(statbuf
.st_mode
)) {
1814 /* skip directories */
1816 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1817 /* skip non-readable files */
1822 /* read attribute value */
1823 r
= read_full_file(path
, &value
, &size
);
1827 /* drop trailing newlines */
1828 while (size
> 0 && value
[--size
] == '\n')
1832 r
= device_add_sysattr_value(device
, sysattr
, value
);
1842 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1843 _cleanup_free_
char *key
= NULL
;
1844 _cleanup_free_
char *value
= NULL
;
1849 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1854 /* set the attribute and save it in the cache. If a NULL value is passed the
1855 * attribute is cleared from the cache */
1856 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1857 _cleanup_close_
int fd
= -1;
1858 _cleanup_free_
char *value
= NULL
;
1859 const char *syspath
;
1865 assert_return(device
, -EINVAL
);
1866 assert_return(sysattr
, -EINVAL
);
1869 device_remove_sysattr_value(device
, sysattr
);
1874 r
= sd_device_get_syspath(device
, &syspath
);
1878 path
= strjoina(syspath
, "/", sysattr
);
1880 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
1884 if (errno
== EISDIR
)
1891 r
= device_add_sysattr_value(device
, sysattr
, value
);
1899 len
= strlen(_value
);
1901 /* drop trailing newlines */
1902 while (len
> 0 && _value
[len
- 1] == '\n')
1905 /* value length is limited to 4k */
1909 value
= strndup(_value
, len
);
1913 size
= write(fd
, value
, len
);
1917 if ((size_t)size
!= len
)
1920 r
= device_add_sysattr_value(device
, sysattr
, value
);