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 /* the device does not exist (any more?) */
174 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
178 if (!path_startswith(syspath
, "/sys")) {
179 _cleanup_free_
char *real_sys
= NULL
, *new_syspath
= NULL
;
182 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
183 r
= chase_symlinks("/sys", NULL
, 0, &real_sys
);
185 return log_debug_errno(r
, "sd-device: could not chase symlink /sys: %m");
187 p
= path_startswith(syspath
, real_sys
);
189 log_debug("sd-device: canonicalized path '%s' does not starts with sysfs mount point '%s'", syspath
, real_sys
);
193 new_syspath
= strjoin("/sys/", p
);
197 free_and_replace(syspath
, new_syspath
);
198 path_kill_slashes(syspath
);
201 if (path_startswith(syspath
, "/sys/devices/")) {
204 /* all 'devices' require an 'uevent' file */
205 path
= strjoina(syspath
, "/uevent");
206 r
= access(path
, F_OK
);
209 /* this is not a valid device */
212 return log_debug_errno(errno
, "sd-device: %s does not have an uevent file: %m", syspath
);
215 /* everything else just needs to be a directory */
216 if (!is_dir(syspath
, false))
220 syspath
= strdup(_syspath
);
225 devpath
= syspath
+ STRLEN("/sys");
227 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
231 free_and_replace(device
->syspath
, syspath
);
233 device
->devpath
= devpath
;
238 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
239 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
242 assert_return(ret
, -EINVAL
);
243 assert_return(syspath
, -EINVAL
);
245 r
= device_new_aux(&device
);
249 r
= device_set_syspath(device
, syspath
, true);
259 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
261 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
263 assert_return(ret
, -EINVAL
);
264 assert_return(IN_SET(type
, 'b', 'c'), -EINVAL
);
266 /* use /sys/dev/{block,char}/<maj>:<min> link */
267 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
269 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
271 return sd_device_new_from_syspath(ret
, syspath
);
274 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
275 char *name
, *syspath
;
278 assert_return(ret
, -EINVAL
);
279 assert_return(subsystem
, -EINVAL
);
280 assert_return(sysname
, -EINVAL
);
282 if (streq(subsystem
, "subsystem")) {
283 syspath
= strjoina("/sys/subsystem/", sysname
);
284 if (access(syspath
, F_OK
) >= 0)
285 return sd_device_new_from_syspath(ret
, syspath
);
287 syspath
= strjoina("/sys/bus/", sysname
);
288 if (access(syspath
, F_OK
) >= 0)
289 return sd_device_new_from_syspath(ret
, syspath
);
291 syspath
= strjoina("/sys/class/", sysname
);
292 if (access(syspath
, F_OK
) >= 0)
293 return sd_device_new_from_syspath(ret
, syspath
);
294 } else if (streq(subsystem
, "module")) {
295 syspath
= strjoina("/sys/module/", sysname
);
296 if (access(syspath
, F_OK
) >= 0)
297 return sd_device_new_from_syspath(ret
, syspath
);
298 } else if (streq(subsystem
, "drivers")) {
299 char subsys
[PATH_MAX
];
302 strscpy(subsys
, sizeof(subsys
), sysname
);
303 driver
= strchr(subsys
, ':');
308 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
309 if (access(syspath
, F_OK
) >= 0)
310 return sd_device_new_from_syspath(ret
, syspath
);
312 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
313 if (access(syspath
, F_OK
) >= 0)
314 return sd_device_new_from_syspath(ret
, syspath
);
318 /* translate sysname back to sysfs filename */
319 name
= strdupa(sysname
);
320 while (name
[len
] != '\0') {
321 if (name
[len
] == '/')
327 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
328 if (access(syspath
, F_OK
) >= 0)
329 return sd_device_new_from_syspath(ret
, syspath
);
331 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
332 if (access(syspath
, F_OK
) >= 0)
333 return sd_device_new_from_syspath(ret
, syspath
);
335 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
336 if (access(syspath
, F_OK
) >= 0)
337 return sd_device_new_from_syspath(ret
, syspath
);
339 syspath
= strjoina("/sys/firmware/", subsystem
, "/", sysname
);
340 if (access(syspath
, F_OK
) >= 0)
341 return sd_device_new_from_syspath(ret
, syspath
);
346 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
347 _cleanup_free_
char *devtype
= NULL
;
353 devtype
= strdup(_devtype
);
357 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
361 free_and_replace(device
->devtype
, devtype
);
366 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
372 r
= parse_ifindex(_ifindex
, &ifindex
);
376 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
380 device
->ifindex
= ifindex
;
385 int device_set_devname(sd_device
*device
, const char *_devname
) {
386 _cleanup_free_
char *devname
= NULL
;
392 if (_devname
[0] != '/') {
393 r
= asprintf(&devname
, "/dev/%s", _devname
);
397 devname
= strdup(_devname
);
402 r
= device_add_property_internal(device
, "DEVNAME", devname
);
406 free_and_replace(device
->devname
, devname
);
411 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
418 r
= safe_atou(_devmode
, &devmode
);
425 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
429 device
->devmode
= devmode
;
434 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
435 unsigned maj
= 0, min
= 0;
441 r
= safe_atou(major
, &maj
);
448 r
= safe_atou(minor
, &min
);
453 r
= device_add_property_internal(device
, "MAJOR", major
);
458 r
= device_add_property_internal(device
, "MINOR", minor
);
463 device
->devnum
= makedev(maj
, min
);
468 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
477 if (streq(key
, "DEVTYPE")) {
478 r
= device_set_devtype(device
, value
);
481 } else if (streq(key
, "IFINDEX")) {
482 r
= device_set_ifindex(device
, value
);
485 } else if (streq(key
, "DEVNAME")) {
486 r
= device_set_devname(device
, value
);
489 } else if (streq(key
, "DEVMODE")) {
490 r
= device_set_devmode(device
, value
);
493 } else if (streq(key
, "MAJOR"))
495 else if (streq(key
, "MINOR"))
498 r
= device_add_property_internal(device
, key
, value
);
506 int device_read_uevent_file(sd_device
*device
) {
507 _cleanup_free_
char *uevent
= NULL
;
508 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
524 if (device
->uevent_loaded
|| device
->sealed
)
527 device
->uevent_loaded
= true;
529 r
= sd_device_get_syspath(device
, &syspath
);
533 path
= strjoina(syspath
, "/uevent");
535 r
= read_full_file(path
, &uevent
, &uevent_len
);
537 /* empty uevent files may be write-only */
539 else if (r
== -ENOENT
)
540 /* some devices may not have uevent files, see set_syspath() */
543 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
547 for (i
= 0; i
< uevent_len
; i
++)
550 if (!strchr(NEWLINE
, uevent
[i
])) {
558 if (uevent
[i
] == '=') {
562 } else if (strchr(NEWLINE
, uevent
[i
])) {
564 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
574 _fallthrough_
; /* to handle empty property */
576 if (strchr(NEWLINE
, uevent
[i
])) {
579 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
581 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
588 assert_not_reached("invalid state when parsing uevent file");
592 r
= device_set_devnum(device
, major
, minor
);
594 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
600 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
603 assert_return(device
, -EINVAL
);
604 assert_return(ifindex
, -EINVAL
);
606 r
= device_read_uevent_file(device
);
610 *ifindex
= device
->ifindex
;
615 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
618 assert_return(ret
, -EINVAL
);
619 assert_return(id
, -EINVAL
);
628 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
632 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
636 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
637 _cleanup_close_
int sk
= -1;
638 struct ifreq ifr
= {};
641 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
645 sk
= socket_ioctl_fd();
649 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
653 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
657 r
= sd_device_get_ifindex(device
, &ifindex
);
661 /* this is racey, so we might end up with the wrong device */
662 if (ifr
.ifr_ifindex
!= ifindex
)
672 char subsys
[PATH_MAX
];
675 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
676 sysname
= strchr(subsys
, ':');
683 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
690 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
691 assert_return(device
, -EINVAL
);
692 assert_return(ret
, -EINVAL
);
694 assert(path_startswith(device
->syspath
, "/sys/"));
696 *ret
= device
->syspath
;
701 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
702 _cleanup_free_
char *path
= NULL
;
703 const char *subdir
, *syspath
;
709 r
= sd_device_get_syspath(child
, &syspath
);
713 path
= strdup(syspath
);
716 subdir
= path
+ STRLEN("/sys");
721 pos
= strrchr(subdir
, '/');
722 if (!pos
|| pos
< subdir
+ 2)
727 r
= sd_device_new_from_syspath(ret
, path
);
737 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
739 assert_return(ret
, -EINVAL
);
740 assert_return(child
, -EINVAL
);
742 if (!child
->parent_set
) {
743 child
->parent_set
= true;
745 (void)device_new_from_child(&child
->parent
, child
);
751 *ret
= child
->parent
;
756 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
757 _cleanup_free_
char *subsystem
= NULL
;
763 subsystem
= strdup(_subsystem
);
767 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
771 free_and_replace(device
->subsystem
, subsystem
);
773 device
->subsystem_set
= true;
778 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
779 _cleanup_free_
char *subsystem
= NULL
;
786 subsystem
= strdup(_subsystem
);
790 r
= device_set_subsystem(device
, "drivers");
794 free_and_replace(device
->driver_subsystem
, subsystem
);
799 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
800 const char *syspath
, *drivers
= NULL
;
803 assert_return(ret
, -EINVAL
);
804 assert_return(device
, -EINVAL
);
806 r
= sd_device_get_syspath(device
, &syspath
);
810 if (!device
->subsystem_set
) {
811 _cleanup_free_
char *subsystem
= NULL
;
814 /* read 'subsystem' link */
815 path
= strjoina(syspath
, "/subsystem");
816 r
= readlink_value(path
, &subsystem
);
818 r
= device_set_subsystem(device
, subsystem
);
819 /* use implicit names */
820 else if (path_startswith(device
->devpath
, "/module/"))
821 r
= device_set_subsystem(device
, "module");
822 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
823 (path_startswith(device
->devpath
, "/subsystem/") ||
824 path_startswith(device
->devpath
, "/class/") ||
825 path_startswith(device
->devpath
, "/bus/")))
826 r
= device_set_subsystem(device
, "subsystem");
827 if (r
< 0 && r
!= -ENOENT
)
828 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
830 device
->subsystem_set
= true;
831 } else if (!device
->driver_subsystem_set
)
832 drivers
= strstr(syspath
, "/drivers/");
834 if (!device
->driver_subsystem_set
) {
836 _cleanup_free_
char *subpath
= NULL
;
838 subpath
= strndup(syspath
, drivers
- syspath
);
844 subsys
= strrchr(subpath
, '/');
848 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
850 if (r
< 0 && r
!= -ENOENT
)
851 return log_debug_errno(r
, "sd-device: could not set subsystem for driver %s: %m", device
->devpath
);
854 device
->driver_subsystem_set
= true;
857 if (!device
->subsystem
)
860 *ret
= device
->subsystem
;
865 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
871 r
= device_read_uevent_file(device
);
875 *devtype
= device
->devtype
;
880 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
881 sd_device
*parent
= NULL
;
884 assert_return(child
, -EINVAL
);
885 assert_return(subsystem
, -EINVAL
);
887 r
= sd_device_get_parent(child
, &parent
);
889 const char *parent_subsystem
= NULL
;
890 const char *parent_devtype
= NULL
;
892 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
893 if (streq_ptr(parent_subsystem
, subsystem
)) {
897 (void)sd_device_get_devtype(parent
, &parent_devtype
);
898 if (streq_ptr(parent_devtype
, devtype
))
901 r
= sd_device_get_parent(parent
, &parent
);
912 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
915 assert_return(device
, -EINVAL
);
916 assert_return(devnum
, -EINVAL
);
918 r
= device_read_uevent_file(device
);
922 *devnum
= device
->devnum
;
927 int device_set_driver(sd_device
*device
, const char *_driver
) {
928 _cleanup_free_
char *driver
= NULL
;
934 driver
= strdup(_driver
);
938 r
= device_add_property_internal(device
, "DRIVER", driver
);
942 free_and_replace(device
->driver
, driver
);
944 device
->driver_set
= true;
949 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
950 assert_return(device
, -EINVAL
);
951 assert_return(ret
, -EINVAL
);
953 if (!device
->driver_set
) {
954 _cleanup_free_
char *driver
= NULL
;
959 r
= sd_device_get_syspath(device
, &syspath
);
963 path
= strjoina(syspath
, "/driver");
964 r
= readlink_value(path
, &driver
);
966 r
= device_set_driver(device
, driver
);
968 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
969 } else if (r
== -ENOENT
)
970 device
->driver_set
= true;
972 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
978 *ret
= device
->driver
;
983 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
984 assert_return(device
, -EINVAL
);
985 assert_return(devpath
, -EINVAL
);
987 assert(device
->devpath
);
988 assert(device
->devpath
[0] == '/');
990 *devpath
= device
->devpath
;
995 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
998 assert_return(device
, -EINVAL
);
999 assert_return(devname
, -EINVAL
);
1001 r
= device_read_uevent_file(device
);
1005 if (!device
->devname
)
1008 assert(path_startswith(device
->devname
, "/dev/"));
1010 *devname
= device
->devname
;
1015 static int device_set_sysname(sd_device
*device
) {
1016 _cleanup_free_
char *sysname
= NULL
;
1017 const char *sysnum
= NULL
;
1021 pos
= strrchr(device
->devpath
, '/');
1026 /* devpath is not a root directory */
1027 if (*pos
== '\0' || pos
<= device
->devpath
)
1030 sysname
= strdup(pos
);
1034 /* some devices have '!' in their name, change that to '/' */
1035 while (sysname
[len
] != '\0') {
1036 if (sysname
[len
] == '!')
1042 /* trailing number */
1043 while (len
> 0 && isdigit(sysname
[--len
]))
1044 sysnum
= &sysname
[len
];
1049 free_and_replace(device
->sysname
, sysname
);
1051 device
->sysnum
= sysnum
;
1053 device
->sysname_set
= true;
1058 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1061 assert_return(device
, -EINVAL
);
1062 assert_return(ret
, -EINVAL
);
1064 if (!device
->sysname_set
) {
1065 r
= device_set_sysname(device
);
1070 assert_return(device
->sysname
, -ENOENT
);
1072 *ret
= device
->sysname
;
1077 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1080 assert_return(device
, -EINVAL
);
1081 assert_return(ret
, -EINVAL
);
1083 if (!device
->sysname_set
) {
1084 r
= device_set_sysname(device
);
1089 *ret
= device
->sysnum
;
1094 static bool is_valid_tag(const char *tag
) {
1097 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1100 int device_add_tag(sd_device
*device
, const char *tag
) {
1106 if (!is_valid_tag(tag
))
1109 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1113 r
= set_put_strdup(device
->tags
, tag
);
1117 device
->tags_generation
++;
1118 device
->property_tags_outdated
= true;
1123 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1129 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1133 r
= set_put_strdup(device
->devlinks
, devlink
);
1137 device
->devlinks_generation
++;
1138 device
->property_devlinks_outdated
= true;
1143 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1144 _cleanup_free_
char *key
= NULL
;
1154 value
= strchr(key
, '=');
1160 if (isempty(++value
))
1163 return device_add_property_internal(device
, key
, value
);
1166 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1167 uint64_t usec_initialized
;
1171 assert(initialized
);
1173 r
= safe_atou64(initialized
, &usec_initialized
);
1177 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1181 device
->usec_initialized
= usec_initialized
;
1186 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1195 r
= device_add_tag(device
, value
);
1201 path
= strjoina("/dev/", value
);
1202 r
= device_add_devlink(device
, path
);
1208 r
= device_add_property_internal_from_string(device
, value
);
1214 r
= device_set_usec_initialized(device
, value
);
1220 r
= safe_atoi(value
, &device
->devlink_priority
);
1226 r
= safe_atoi(value
, &device
->watch_handle
);
1232 log_debug("device db: unknown key '%c'", key
);
1238 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1242 if (!device
->id_filename
) {
1243 _cleanup_free_
char *id
= NULL
;
1244 const char *subsystem
;
1248 r
= sd_device_get_subsystem(device
, &subsystem
);
1252 r
= sd_device_get_devnum(device
, &devnum
);
1256 r
= sd_device_get_ifindex(device
, &ifindex
);
1260 if (major(devnum
) > 0) {
1263 /* use dev_t — b259:131072, c254:0 */
1264 r
= asprintf(&id
, "%c%u:%u",
1265 streq(subsystem
, "block") ? 'b' : 'c',
1266 major(devnum
), minor(devnum
));
1269 } else if (ifindex
> 0) {
1270 /* use netdev ifindex — n3 */
1271 r
= asprintf(&id
, "n%u", ifindex
);
1275 /* use $subsys:$sysname — pci:0000:00:1f.2
1276 * sysname() has '!' translated, get it from devpath
1278 const char *sysname
;
1280 sysname
= basename(device
->devpath
);
1287 if (streq(subsystem
, "drivers")) {
1288 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1289 * encoded as well */
1290 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1294 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1300 device
->id_filename
= TAKE_PTR(id
);
1303 *ret
= device
->id_filename
;
1308 int device_read_db_aux(sd_device
*device
, bool force
) {
1309 _cleanup_free_
char *db
= NULL
;
1311 const char *id
, *value
;
1325 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1328 device
->db_loaded
= true;
1330 r
= device_get_id_filename(device
, &id
);
1334 path
= strjoina("/run/udev/data/", id
);
1336 r
= read_full_file(path
, &db
, &db_len
);
1341 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1344 /* devices with a database entry are initialized */
1345 device
->is_initialized
= true;
1347 for (i
= 0; i
< db_len
; i
++) {
1350 if (!strchr(NEWLINE
, db
[i
])) {
1359 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1361 state
= INVALID_LINE
;
1376 if (strchr(NEWLINE
, db
[i
]))
1381 if (strchr(NEWLINE
, db
[i
])) {
1383 r
= handle_db_line(device
, key
, value
);
1385 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1392 assert_not_reached("invalid state when parsing db");
1399 static int device_read_db(sd_device
*device
) {
1400 return device_read_db_aux(device
, false);
1403 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1406 assert_return(device
, -EINVAL
);
1407 assert_return(initialized
, -EINVAL
);
1409 r
= device_read_db(device
);
1413 *initialized
= device
->is_initialized
;
1418 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1422 assert_return(device
, -EINVAL
);
1423 assert_return(usec
, -EINVAL
);
1425 r
= device_read_db(device
);
1429 if (!device
->is_initialized
)
1432 if (!device
->usec_initialized
)
1435 now_ts
= now(clock_boottime_or_monotonic());
1437 if (now_ts
< device
->usec_initialized
)
1440 *usec
= now_ts
- device
->usec_initialized
;
1445 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1448 assert_return(device
, NULL
);
1450 (void) device_read_db(device
);
1452 device
->tags_iterator_generation
= device
->tags_generation
;
1453 device
->tags_iterator
= ITERATOR_FIRST
;
1455 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1459 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1462 assert_return(device
, NULL
);
1464 (void) device_read_db(device
);
1466 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1469 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1473 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1476 assert_return(device
, NULL
);
1478 (void) device_read_db(device
);
1480 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1481 device
->devlinks_iterator
= ITERATOR_FIRST
;
1483 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1487 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1490 assert_return(device
, NULL
);
1492 (void) device_read_db(device
);
1494 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1497 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1501 static int device_properties_prepare(sd_device
*device
) {
1506 r
= device_read_uevent_file(device
);
1510 r
= device_read_db(device
);
1514 if (device
->property_devlinks_outdated
) {
1515 _cleanup_free_
char *devlinks
= NULL
;
1516 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1517 const char *devlink
;
1519 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1522 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1524 if (devlinks_len
> 0)
1525 stpcpy(devlinks
+ devlinks_len
++, " ");
1526 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1527 devlinks_len
= e
- devlinks
;
1530 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1534 device
->property_devlinks_outdated
= false;
1537 if (device
->property_tags_outdated
) {
1538 _cleanup_free_
char *tags
= NULL
;
1539 size_t tags_allocated
= 0, tags_len
= 0;
1542 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1547 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1550 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1552 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1553 tags_len
= e
- tags
;
1556 r
= device_add_property_internal(device
, "TAGS", tags
);
1560 device
->property_tags_outdated
= false;
1566 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1571 assert_return(device
, NULL
);
1573 r
= device_properties_prepare(device
);
1577 device
->properties_iterator_generation
= device
->properties_generation
;
1578 device
->properties_iterator
= ITERATOR_FIRST
;
1580 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1588 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1593 assert_return(device
, NULL
);
1595 r
= device_properties_prepare(device
);
1599 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1602 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1610 static int device_sysattrs_read_all(sd_device
*device
) {
1611 _cleanup_closedir_
DIR *dir
= NULL
;
1612 const char *syspath
;
1613 struct dirent
*dent
;
1618 if (device
->sysattrs_read
)
1621 r
= sd_device_get_syspath(device
, &syspath
);
1625 dir
= opendir(syspath
);
1629 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1633 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1635 struct stat statbuf
;
1637 /* only handle symlinks and regular files */
1638 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
))
1641 path
= strjoina(syspath
, "/", dent
->d_name
);
1643 if (lstat(path
, &statbuf
) != 0)
1646 if (!(statbuf
.st_mode
& S_IRUSR
))
1649 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1654 device
->sysattrs_read
= true;
1659 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1663 assert_return(device
, NULL
);
1665 if (!device
->sysattrs_read
) {
1666 r
= device_sysattrs_read_all(device
);
1673 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1675 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1679 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1682 assert_return(device
, NULL
);
1684 if (!device
->sysattrs_read
)
1687 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1691 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1692 assert_return(device
, -EINVAL
);
1693 assert_return(tag
, -EINVAL
);
1695 (void) device_read_db(device
);
1697 return !!set_contains(device
->tags
, tag
);
1700 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1704 assert_return(device
, -EINVAL
);
1705 assert_return(key
, -EINVAL
);
1706 assert_return(_value
, -EINVAL
);
1708 r
= device_properties_prepare(device
);
1712 value
= ordered_hashmap_get(device
->properties
, key
);
1721 /* replaces the value if it already exists */
1722 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1723 _cleanup_free_
char *key
= NULL
;
1724 _cleanup_free_
char *value_old
= NULL
;
1730 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1734 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1741 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1750 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1751 const char *key
= NULL
, *value
;
1756 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1766 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1767 * with a NULL value in the cache, otherwise the returned string is stored */
1768 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1769 _cleanup_free_
char *value
= NULL
;
1770 const char *syspath
, *cached_value
= NULL
;
1772 struct stat statbuf
;
1775 assert_return(device
, -EINVAL
);
1776 assert_return(sysattr
, -EINVAL
);
1778 /* look for possibly already cached result */
1779 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1785 /* we looked up the sysattr before and it did not exist */
1789 *_value
= cached_value
;
1794 r
= sd_device_get_syspath(device
, &syspath
);
1798 path
= strjoina(syspath
, "/", sysattr
);
1799 r
= lstat(path
, &statbuf
);
1801 /* remember that we could not access the sysattr */
1802 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1807 } else if (S_ISLNK(statbuf
.st_mode
)) {
1808 /* Some core links return only the last element of the target path,
1809 * these are just values, the paths should not be exposed. */
1810 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1811 r
= readlink_value(path
, &value
);
1816 } else if (S_ISDIR(statbuf
.st_mode
)) {
1817 /* skip directories */
1819 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1820 /* skip non-readable files */
1825 /* read attribute value */
1826 r
= read_full_file(path
, &value
, &size
);
1830 /* drop trailing newlines */
1831 while (size
> 0 && value
[--size
] == '\n')
1835 r
= device_add_sysattr_value(device
, sysattr
, value
);
1845 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1846 _cleanup_free_
char *key
= NULL
;
1847 _cleanup_free_
char *value
= NULL
;
1852 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1857 /* set the attribute and save it in the cache. If a NULL value is passed the
1858 * attribute is cleared from the cache */
1859 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1860 _cleanup_close_
int fd
= -1;
1861 _cleanup_free_
char *value
= NULL
;
1862 const char *syspath
;
1868 assert_return(device
, -EINVAL
);
1869 assert_return(sysattr
, -EINVAL
);
1872 device_remove_sysattr_value(device
, sysattr
);
1877 r
= sd_device_get_syspath(device
, &syspath
);
1881 path
= strjoina(syspath
, "/", sysattr
);
1883 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
1887 if (errno
== EISDIR
)
1894 r
= device_add_sysattr_value(device
, sysattr
, value
);
1902 len
= strlen(_value
);
1904 /* drop trailing newlines */
1905 while (len
> 0 && _value
[len
- 1] == '\n')
1908 /* value length is limited to 4k */
1912 value
= strndup(_value
, len
);
1916 size
= write(fd
, value
, len
);
1920 if ((size_t)size
!= len
)
1923 r
= device_add_sysattr_value(device
, sysattr
, value
);