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
= id
;
1304 *ret
= device
->id_filename
;
1309 int device_read_db_aux(sd_device
*device
, bool force
) {
1310 _cleanup_free_
char *db
= NULL
;
1312 const char *id
, *value
;
1326 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1329 device
->db_loaded
= true;
1331 r
= device_get_id_filename(device
, &id
);
1335 path
= strjoina("/run/udev/data/", id
);
1337 r
= read_full_file(path
, &db
, &db_len
);
1342 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1345 /* devices with a database entry are initialized */
1346 device
->is_initialized
= true;
1348 for (i
= 0; i
< db_len
; i
++) {
1351 if (!strchr(NEWLINE
, db
[i
])) {
1360 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1362 state
= INVALID_LINE
;
1377 if (strchr(NEWLINE
, db
[i
]))
1382 if (strchr(NEWLINE
, db
[i
])) {
1384 r
= handle_db_line(device
, key
, value
);
1386 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1393 assert_not_reached("invalid state when parsing db");
1400 static int device_read_db(sd_device
*device
) {
1401 return device_read_db_aux(device
, false);
1404 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1407 assert_return(device
, -EINVAL
);
1408 assert_return(initialized
, -EINVAL
);
1410 r
= device_read_db(device
);
1414 *initialized
= device
->is_initialized
;
1419 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1423 assert_return(device
, -EINVAL
);
1424 assert_return(usec
, -EINVAL
);
1426 r
= device_read_db(device
);
1430 if (!device
->is_initialized
)
1433 if (!device
->usec_initialized
)
1436 now_ts
= now(clock_boottime_or_monotonic());
1438 if (now_ts
< device
->usec_initialized
)
1441 *usec
= now_ts
- device
->usec_initialized
;
1446 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1449 assert_return(device
, NULL
);
1451 (void) device_read_db(device
);
1453 device
->tags_iterator_generation
= device
->tags_generation
;
1454 device
->tags_iterator
= ITERATOR_FIRST
;
1456 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1460 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1463 assert_return(device
, NULL
);
1465 (void) device_read_db(device
);
1467 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1470 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1474 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1477 assert_return(device
, NULL
);
1479 (void) device_read_db(device
);
1481 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1482 device
->devlinks_iterator
= ITERATOR_FIRST
;
1484 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1488 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1491 assert_return(device
, NULL
);
1493 (void) device_read_db(device
);
1495 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1498 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1502 static int device_properties_prepare(sd_device
*device
) {
1507 r
= device_read_uevent_file(device
);
1511 r
= device_read_db(device
);
1515 if (device
->property_devlinks_outdated
) {
1516 _cleanup_free_
char *devlinks
= NULL
;
1517 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1518 const char *devlink
;
1520 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1523 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1525 if (devlinks_len
> 0)
1526 stpcpy(devlinks
+ devlinks_len
++, " ");
1527 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1528 devlinks_len
= e
- devlinks
;
1531 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1535 device
->property_devlinks_outdated
= false;
1538 if (device
->property_tags_outdated
) {
1539 _cleanup_free_
char *tags
= NULL
;
1540 size_t tags_allocated
= 0, tags_len
= 0;
1543 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1548 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1551 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1553 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1554 tags_len
= e
- tags
;
1557 r
= device_add_property_internal(device
, "TAGS", tags
);
1561 device
->property_tags_outdated
= false;
1567 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1572 assert_return(device
, NULL
);
1574 r
= device_properties_prepare(device
);
1578 device
->properties_iterator_generation
= device
->properties_generation
;
1579 device
->properties_iterator
= ITERATOR_FIRST
;
1581 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1589 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1594 assert_return(device
, NULL
);
1596 r
= device_properties_prepare(device
);
1600 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1603 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1611 static int device_sysattrs_read_all(sd_device
*device
) {
1612 _cleanup_closedir_
DIR *dir
= NULL
;
1613 const char *syspath
;
1614 struct dirent
*dent
;
1619 if (device
->sysattrs_read
)
1622 r
= sd_device_get_syspath(device
, &syspath
);
1626 dir
= opendir(syspath
);
1630 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1634 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
1636 struct stat statbuf
;
1638 /* only handle symlinks and regular files */
1639 if (!IN_SET(dent
->d_type
, DT_LNK
, DT_REG
))
1642 path
= strjoina(syspath
, "/", dent
->d_name
);
1644 if (lstat(path
, &statbuf
) != 0)
1647 if (!(statbuf
.st_mode
& S_IRUSR
))
1650 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1655 device
->sysattrs_read
= true;
1660 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1664 assert_return(device
, NULL
);
1666 if (!device
->sysattrs_read
) {
1667 r
= device_sysattrs_read_all(device
);
1674 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1676 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1680 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1683 assert_return(device
, NULL
);
1685 if (!device
->sysattrs_read
)
1688 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1692 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1693 assert_return(device
, -EINVAL
);
1694 assert_return(tag
, -EINVAL
);
1696 (void) device_read_db(device
);
1698 return !!set_contains(device
->tags
, tag
);
1701 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1705 assert_return(device
, -EINVAL
);
1706 assert_return(key
, -EINVAL
);
1707 assert_return(_value
, -EINVAL
);
1709 r
= device_properties_prepare(device
);
1713 value
= ordered_hashmap_get(device
->properties
, key
);
1722 /* replaces the value if it already exists */
1723 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1724 _cleanup_free_
char *key
= NULL
;
1725 _cleanup_free_
char *value_old
= NULL
;
1731 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1735 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1742 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1751 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1752 const char *key
= NULL
, *value
;
1757 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1767 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1768 * with a NULL value in the cache, otherwise the returned string is stored */
1769 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1770 _cleanup_free_
char *value
= NULL
;
1771 const char *syspath
, *cached_value
= NULL
;
1773 struct stat statbuf
;
1776 assert_return(device
, -EINVAL
);
1777 assert_return(sysattr
, -EINVAL
);
1779 /* look for possibly already cached result */
1780 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1786 /* we looked up the sysattr before and it did not exist */
1790 *_value
= cached_value
;
1795 r
= sd_device_get_syspath(device
, &syspath
);
1799 path
= strjoina(syspath
, "/", sysattr
);
1800 r
= lstat(path
, &statbuf
);
1802 /* remember that we could not access the sysattr */
1803 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1808 } else if (S_ISLNK(statbuf
.st_mode
)) {
1809 /* Some core links return only the last element of the target path,
1810 * these are just values, the paths should not be exposed. */
1811 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1812 r
= readlink_value(path
, &value
);
1817 } else if (S_ISDIR(statbuf
.st_mode
)) {
1818 /* skip directories */
1820 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1821 /* skip non-readable files */
1826 /* read attribute value */
1827 r
= read_full_file(path
, &value
, &size
);
1831 /* drop trailing newlines */
1832 while (size
> 0 && value
[--size
] == '\n')
1836 r
= device_add_sysattr_value(device
, sysattr
, value
);
1846 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1847 _cleanup_free_
char *key
= NULL
;
1848 _cleanup_free_
char *value
= NULL
;
1853 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1858 /* set the attribute and save it in the cache. If a NULL value is passed the
1859 * attribute is cleared from the cache */
1860 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1861 _cleanup_close_
int fd
= -1;
1862 _cleanup_free_
char *value
= NULL
;
1863 const char *syspath
;
1869 assert_return(device
, -EINVAL
);
1870 assert_return(sysattr
, -EINVAL
);
1873 device_remove_sysattr_value(device
, sysattr
);
1878 r
= sd_device_get_syspath(device
, &syspath
);
1882 path
= strjoina(syspath
, "/", sysattr
);
1884 fd
= open(path
, O_WRONLY
| O_CLOEXEC
| O_NOFOLLOW
);
1888 if (errno
== EISDIR
)
1895 r
= device_add_sysattr_value(device
, sysattr
, value
);
1903 len
= strlen(_value
);
1905 /* drop trailing newlines */
1906 while (len
> 0 && _value
[len
- 1] == '\n')
1909 /* value length is limited to 4k */
1913 value
= strndup(_value
, len
);
1917 size
= write(fd
, value
, len
);
1921 if ((size_t)size
!= len
)
1924 r
= device_add_sysattr_value(device
, sysattr
, value
);