2 This file is part of systemd.
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
25 #include "sd-device.h"
27 #include "alloc-util.h"
28 #include "device-internal.h"
29 #include "device-private.h"
30 #include "device-util.h"
36 #include "parse-util.h"
37 #include "path-util.h"
39 #include "stat-util.h"
40 #include "string-util.h"
45 int device_new_aux(sd_device
**ret
) {
46 _cleanup_device_unref_ sd_device
*device
= NULL
;
50 device
= new0(sd_device
, 1);
55 device
->watch_handle
= -1;
63 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
65 assert_se(++ device
->n_ref
>= 2);
70 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
71 if (device
&& -- device
->n_ref
== 0) {
72 sd_device_unref(device
->parent
);
73 free(device
->syspath
);
74 free(device
->sysname
);
75 free(device
->devtype
);
76 free(device
->devname
);
77 free(device
->subsystem
);
79 free(device
->id_filename
);
80 free(device
->properties_strv
);
81 free(device
->properties_nulstr
);
83 ordered_hashmap_free_free_free(device
->properties
);
84 ordered_hashmap_free_free_free(device
->properties_db
);
85 hashmap_free_free_free(device
->sysattr_values
);
86 set_free_free(device
->sysattrs
);
87 set_free_free(device
->tags
);
88 set_free_free(device
->devlinks
);
96 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
97 OrderedHashmap
**properties
;
103 properties
= &device
->properties_db
;
105 properties
= &device
->properties
;
108 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
111 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
119 value
= strdup(_value
);
123 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
125 r
= ordered_hashmap_replace(*properties
, key
, value
);
132 _cleanup_free_
char *key
= NULL
;
133 _cleanup_free_
char *value
= NULL
;
135 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
139 device
->properties_generation
++;
140 device
->properties_buf_outdated
= true;
146 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
147 return device_add_property_aux(device
, key
, value
, false);
150 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
151 _cleanup_free_
char *syspath
= NULL
;
158 /* must be a subdirectory of /sys */
159 if (!path_startswith(_syspath
, "/sys/")) {
160 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
165 r
= readlink_and_canonicalize(_syspath
, &syspath
);
167 /* the device does not exist (any more?) */
169 else if (r
== -EINVAL
) {
171 syspath
= canonicalize_file_name(_syspath
);
174 /* the device does not exist (any more?) */
177 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
180 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
184 if (path_startswith(syspath
, "/sys/devices/")) {
187 /* all 'devices' require an 'uevent' file */
188 path
= strjoina(syspath
, "/uevent");
189 r
= access(path
, F_OK
);
192 /* this is not a valid device */
195 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
199 /* everything else just just needs to be a directory */
200 if (!is_dir(syspath
, false))
204 syspath
= strdup(_syspath
);
209 devpath
= syspath
+ strlen("/sys");
211 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
215 free(device
->syspath
);
216 device
->syspath
= syspath
;
219 device
->devpath
= devpath
;
224 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
225 _cleanup_device_unref_ sd_device
*device
= NULL
;
228 assert_return(ret
, -EINVAL
);
229 assert_return(syspath
, -EINVAL
);
231 r
= device_new_aux(&device
);
235 r
= device_set_syspath(device
, syspath
, true);
245 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
247 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
249 assert_return(ret
, -EINVAL
);
250 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
252 /* use /sys/dev/{block,char}/<maj>:<min> link */
253 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
255 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
257 return sd_device_new_from_syspath(ret
, syspath
);
260 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
263 assert_return(ret
, -EINVAL
);
264 assert_return(subsystem
, -EINVAL
);
265 assert_return(sysname
, -EINVAL
);
267 if (streq(subsystem
, "subsystem")) {
268 syspath
= strjoina("/sys/subsystem/", sysname
);
269 if (access(syspath
, F_OK
) >= 0)
270 return sd_device_new_from_syspath(ret
, syspath
);
272 syspath
= strjoina("/sys/bus/", sysname
);
273 if (access(syspath
, F_OK
) >= 0)
274 return sd_device_new_from_syspath(ret
, syspath
);
276 syspath
= strjoina("/sys/class/", sysname
);
277 if (access(syspath
, F_OK
) >= 0)
278 return sd_device_new_from_syspath(ret
, syspath
);
279 } else if (streq(subsystem
, "module")) {
280 syspath
= strjoina("/sys/module/", sysname
);
281 if (access(syspath
, F_OK
) >= 0)
282 return sd_device_new_from_syspath(ret
, syspath
);
283 } else if (streq(subsystem
, "drivers")) {
284 char subsys
[PATH_MAX
];
287 strscpy(subsys
, sizeof(subsys
), sysname
);
288 driver
= strchr(subsys
, ':');
293 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
294 if (access(syspath
, F_OK
) >= 0)
295 return sd_device_new_from_syspath(ret
, syspath
);
297 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
298 if (access(syspath
, F_OK
) >= 0)
299 return sd_device_new_from_syspath(ret
, syspath
);
306 /* translate sysname back to sysfs filename */
307 name
= strdupa(sysname
);
308 while (name
[len
] != '\0') {
309 if (name
[len
] == '/')
315 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
316 if (access(syspath
, F_OK
) >= 0)
317 return sd_device_new_from_syspath(ret
, syspath
);
319 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
320 if (access(syspath
, F_OK
) >= 0)
321 return sd_device_new_from_syspath(ret
, syspath
);
323 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
324 if (access(syspath
, F_OK
) >= 0)
325 return sd_device_new_from_syspath(ret
, syspath
);
331 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
332 _cleanup_free_
char *devtype
= NULL
;
338 devtype
= strdup(_devtype
);
342 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
346 free(device
->devtype
);
347 device
->devtype
= devtype
;
353 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
359 r
= parse_ifindex(_ifindex
, &ifindex
);
363 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
367 device
->ifindex
= ifindex
;
372 int device_set_devname(sd_device
*device
, const char *_devname
) {
373 _cleanup_free_
char *devname
= NULL
;
379 if (_devname
[0] != '/') {
380 r
= asprintf(&devname
, "/dev/%s", _devname
);
384 devname
= strdup(_devname
);
389 r
= device_add_property_internal(device
, "DEVNAME", devname
);
393 free(device
->devname
);
394 device
->devname
= devname
;
400 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
407 r
= safe_atou(_devmode
, &devmode
);
414 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
418 device
->devmode
= devmode
;
423 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
424 unsigned maj
= 0, min
= 0;
430 r
= safe_atou(major
, &maj
);
437 r
= safe_atou(minor
, &min
);
442 r
= device_add_property_internal(device
, "MAJOR", major
);
447 r
= device_add_property_internal(device
, "MINOR", minor
);
452 device
->devnum
= makedev(maj
, min
);
457 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
466 if (streq(key
, "DEVTYPE")) {
467 r
= device_set_devtype(device
, value
);
470 } else if (streq(key
, "IFINDEX")) {
471 r
= device_set_ifindex(device
, value
);
474 } else if (streq(key
, "DEVNAME")) {
475 r
= device_set_devname(device
, value
);
478 } else if (streq(key
, "DEVMODE")) {
479 r
= device_set_devmode(device
, value
);
482 } else if (streq(key
, "MAJOR"))
484 else if (streq(key
, "MINOR"))
487 r
= device_add_property_internal(device
, key
, value
);
495 int device_read_uevent_file(sd_device
*device
) {
496 _cleanup_free_
char *uevent
= NULL
;
497 const char *syspath
, *key
, *value
, *major
= NULL
, *minor
= NULL
;
513 if (device
->uevent_loaded
|| device
->sealed
)
516 device
->uevent_loaded
= true;
518 r
= sd_device_get_syspath(device
, &syspath
);
522 path
= strjoina(syspath
, "/uevent");
524 r
= read_full_file(path
, &uevent
, &uevent_len
);
526 /* empty uevent files may be write-only */
528 else if (r
== -ENOENT
)
529 /* some devices may not have uevent files, see set_syspath() */
532 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
536 for (i
= 0; i
< uevent_len
; i
++) {
539 if (!strchr(NEWLINE
, uevent
[i
])) {
547 if (uevent
[i
] == '=') {
551 } else if (strchr(NEWLINE
, uevent
[i
])) {
553 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
566 if (strchr(NEWLINE
, uevent
[i
])) {
569 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
571 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
578 assert_not_reached("invalid state when parsing uevent file");
583 r
= device_set_devnum(device
, major
, minor
);
585 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
591 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
594 assert_return(device
, -EINVAL
);
595 assert_return(ifindex
, -EINVAL
);
597 r
= device_read_uevent_file(device
);
601 *ifindex
= device
->ifindex
;
606 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
609 assert_return(ret
, -EINVAL
);
610 assert_return(id
, -EINVAL
);
619 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
623 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
627 _cleanup_device_unref_ sd_device
*device
= NULL
;
628 _cleanup_close_
int sk
= -1;
629 struct ifreq ifr
= {};
632 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
636 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
640 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
644 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
648 r
= sd_device_get_ifindex(device
, &ifindex
);
652 /* this is racey, so we might end up with the wrong device */
653 if (ifr
.ifr_ifindex
!= ifindex
)
663 char subsys
[PATH_MAX
];
666 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
667 sysname
= strchr(subsys
, ':');
674 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
681 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
682 assert_return(device
, -EINVAL
);
683 assert_return(ret
, -EINVAL
);
685 assert(path_startswith(device
->syspath
, "/sys/"));
687 *ret
= device
->syspath
;
692 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
693 _cleanup_free_
char *path
= NULL
;
694 const char *subdir
, *syspath
;
700 r
= sd_device_get_syspath(child
, &syspath
);
704 path
= strdup(syspath
);
707 subdir
= path
+ strlen("/sys");
712 pos
= strrchr(subdir
, '/');
713 if (!pos
|| pos
< subdir
+ 2)
718 r
= sd_device_new_from_syspath(ret
, path
);
728 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
730 assert_return(ret
, -EINVAL
);
731 assert_return(child
, -EINVAL
);
733 if (!child
->parent_set
) {
734 child
->parent_set
= true;
736 (void)device_new_from_child(&child
->parent
, child
);
742 *ret
= child
->parent
;
747 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
748 _cleanup_free_
char *subsystem
= NULL
;
754 subsystem
= strdup(_subsystem
);
758 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
762 free(device
->subsystem
);
763 device
->subsystem
= subsystem
;
766 device
->subsystem_set
= true;
771 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
772 assert_return(ret
, -EINVAL
);
773 assert_return(device
, -EINVAL
);
775 if (!device
->subsystem_set
) {
776 _cleanup_free_
char *subsystem
= NULL
;
781 /* read 'subsystem' link */
782 r
= sd_device_get_syspath(device
, &syspath
);
786 path
= strjoina(syspath
, "/subsystem");
787 r
= readlink_value(path
, &subsystem
);
789 r
= device_set_subsystem(device
, subsystem
);
790 /* use implicit names */
791 else if (path_startswith(device
->devpath
, "/module/"))
792 r
= device_set_subsystem(device
, "module");
793 else if (strstr(device
->devpath
, "/drivers/"))
794 r
= device_set_subsystem(device
, "drivers");
795 else if (path_startswith(device
->devpath
, "/subsystem/") ||
796 path_startswith(device
->devpath
, "/class/") ||
797 path_startswith(device
->devpath
, "/bus/"))
798 r
= device_set_subsystem(device
, "subsystem");
799 if (r
< 0 && r
!= -ENOENT
)
800 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
802 device
->subsystem_set
= true;
805 if (!device
->subsystem
)
808 *ret
= device
->subsystem
;
813 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
819 r
= device_read_uevent_file(device
);
823 *devtype
= device
->devtype
;
828 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
829 sd_device
*parent
= NULL
;
832 assert_return(child
, -EINVAL
);
833 assert_return(subsystem
, -EINVAL
);
835 r
= sd_device_get_parent(child
, &parent
);
837 const char *parent_subsystem
= NULL
;
838 const char *parent_devtype
= NULL
;
840 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
841 if (streq_ptr(parent_subsystem
, subsystem
)) {
845 (void)sd_device_get_devtype(parent
, &parent_devtype
);
846 if (streq_ptr(parent_devtype
, devtype
))
849 r
= sd_device_get_parent(parent
, &parent
);
860 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
863 assert_return(device
, -EINVAL
);
864 assert_return(devnum
, -EINVAL
);
866 r
= device_read_uevent_file(device
);
870 *devnum
= device
->devnum
;
875 int device_set_driver(sd_device
*device
, const char *_driver
) {
876 _cleanup_free_
char *driver
= NULL
;
882 driver
= strdup(_driver
);
886 r
= device_add_property_internal(device
, "DRIVER", driver
);
890 free(device
->driver
);
891 device
->driver
= driver
;
894 device
->driver_set
= true;
899 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
900 assert_return(device
, -EINVAL
);
901 assert_return(ret
, -EINVAL
);
903 if (!device
->driver_set
) {
904 _cleanup_free_
char *driver
= NULL
;
909 r
= sd_device_get_syspath(device
, &syspath
);
913 path
= strjoina(syspath
, "/driver");
914 r
= readlink_value(path
, &driver
);
916 r
= device_set_driver(device
, driver
);
918 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
919 } else if (r
== -ENOENT
)
920 device
->driver_set
= true;
922 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
928 *ret
= device
->driver
;
933 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
934 assert_return(device
, -EINVAL
);
935 assert_return(devpath
, -EINVAL
);
937 assert(device
->devpath
);
938 assert(device
->devpath
[0] == '/');
940 *devpath
= device
->devpath
;
945 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
948 assert_return(device
, -EINVAL
);
949 assert_return(devname
, -EINVAL
);
951 r
= device_read_uevent_file(device
);
955 if (!device
->devname
)
958 assert(path_startswith(device
->devname
, "/dev/"));
960 *devname
= device
->devname
;
965 static int device_set_sysname(sd_device
*device
) {
966 _cleanup_free_
char *sysname
= NULL
;
967 const char *sysnum
= NULL
;
971 pos
= strrchr(device
->devpath
, '/');
976 /* devpath is not a root directory */
977 if (*pos
== '\0' || pos
<= device
->devpath
)
980 sysname
= strdup(pos
);
984 /* some devices have '!' in their name, change that to '/' */
985 while (sysname
[len
] != '\0') {
986 if (sysname
[len
] == '!')
992 /* trailing number */
993 while (len
> 0 && isdigit(sysname
[--len
]))
994 sysnum
= &sysname
[len
];
999 free(device
->sysname
);
1000 device
->sysname
= sysname
;
1003 device
->sysnum
= sysnum
;
1005 device
->sysname_set
= true;
1010 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1013 assert_return(device
, -EINVAL
);
1014 assert_return(ret
, -EINVAL
);
1016 if (!device
->sysname_set
) {
1017 r
= device_set_sysname(device
);
1022 assert_return(device
->sysname
, -ENOENT
);
1024 *ret
= device
->sysname
;
1029 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1032 assert_return(device
, -EINVAL
);
1033 assert_return(ret
, -EINVAL
);
1035 if (!device
->sysname_set
) {
1036 r
= device_set_sysname(device
);
1041 *ret
= device
->sysnum
;
1046 static bool is_valid_tag(const char *tag
) {
1049 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1052 int device_add_tag(sd_device
*device
, const char *tag
) {
1058 if (!is_valid_tag(tag
))
1061 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1065 r
= set_put_strdup(device
->tags
, tag
);
1069 device
->tags_generation
++;
1070 device
->property_tags_outdated
= true;
1075 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1081 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1085 r
= set_put_strdup(device
->devlinks
, devlink
);
1089 device
->devlinks_generation
++;
1090 device
->property_devlinks_outdated
= true;
1095 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1096 _cleanup_free_
char *key
= NULL
;
1106 value
= strchr(key
, '=');
1112 if (isempty(++value
))
1115 return device_add_property_internal(device
, key
, value
);
1118 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1119 uint64_t usec_initialized
;
1123 assert(initialized
);
1125 r
= safe_atou64(initialized
, &usec_initialized
);
1129 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1133 device
->usec_initialized
= usec_initialized
;
1138 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1147 r
= device_add_tag(device
, value
);
1153 path
= strjoina("/dev/", value
);
1154 r
= device_add_devlink(device
, path
);
1160 r
= device_add_property_internal_from_string(device
, value
);
1166 r
= device_set_usec_initialized(device
, value
);
1172 r
= safe_atoi(value
, &device
->devlink_priority
);
1178 r
= safe_atoi(value
, &device
->watch_handle
);
1184 log_debug("device db: unknown key '%c'", key
);
1190 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1194 if (!device
->id_filename
) {
1195 _cleanup_free_
char *id
= NULL
;
1196 const char *subsystem
;
1200 r
= sd_device_get_subsystem(device
, &subsystem
);
1204 r
= sd_device_get_devnum(device
, &devnum
);
1208 r
= sd_device_get_ifindex(device
, &ifindex
);
1212 if (major(devnum
) > 0) {
1215 /* use dev_t -- b259:131072, c254:0 */
1216 r
= asprintf(&id
, "%c%u:%u",
1217 streq(subsystem
, "block") ? 'b' : 'c',
1218 major(devnum
), minor(devnum
));
1221 } else if (ifindex
> 0) {
1222 /* use netdev ifindex -- n3 */
1223 r
= asprintf(&id
, "n%u", ifindex
);
1227 /* use $subsys:$sysname -- pci:0000:00:1f.2
1228 * sysname() has '!' translated, get it from devpath
1230 const char *sysname
;
1232 sysname
= basename(device
->devpath
);
1239 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1244 device
->id_filename
= id
;
1248 *ret
= device
->id_filename
;
1253 int device_read_db_aux(sd_device
*device
, bool force
) {
1254 _cleanup_free_
char *db
= NULL
;
1256 const char *id
, *value
;
1270 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1273 device
->db_loaded
= true;
1275 r
= device_get_id_filename(device
, &id
);
1279 path
= strjoina("/run/udev/data/", id
);
1281 r
= read_full_file(path
, &db
, &db_len
);
1286 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1289 /* devices with a database entry are initialized */
1290 device
->is_initialized
= true;
1292 for (i
= 0; i
< db_len
; i
++) {
1295 if (!strchr(NEWLINE
, db
[i
])) {
1304 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1306 state
= INVALID_LINE
;
1321 if (strchr(NEWLINE
, db
[i
]))
1326 if (strchr(NEWLINE
, db
[i
])) {
1328 r
= handle_db_line(device
, key
, value
);
1330 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1337 assert_not_reached("invalid state when parsing db");
1344 static int device_read_db(sd_device
*device
) {
1345 return device_read_db_aux(device
, false);
1348 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1351 assert_return(device
, -EINVAL
);
1352 assert_return(initialized
, -EINVAL
);
1354 r
= device_read_db(device
);
1358 *initialized
= device
->is_initialized
;
1363 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1367 assert_return(device
, -EINVAL
);
1368 assert_return(usec
, -EINVAL
);
1370 r
= device_read_db(device
);
1374 if (!device
->is_initialized
)
1377 if (!device
->usec_initialized
)
1380 now_ts
= now(clock_boottime_or_monotonic());
1382 if (now_ts
< device
->usec_initialized
)
1385 *usec
= now_ts
- device
->usec_initialized
;
1390 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1393 assert_return(device
, NULL
);
1395 (void) device_read_db(device
);
1397 device
->tags_iterator_generation
= device
->tags_generation
;
1398 device
->tags_iterator
= ITERATOR_FIRST
;
1400 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1404 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1407 assert_return(device
, NULL
);
1409 (void) device_read_db(device
);
1411 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1414 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1418 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1421 assert_return(device
, NULL
);
1423 (void) device_read_db(device
);
1425 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1426 device
->devlinks_iterator
= ITERATOR_FIRST
;
1428 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1432 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1435 assert_return(device
, NULL
);
1437 (void) device_read_db(device
);
1439 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1442 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1446 static int device_properties_prepare(sd_device
*device
) {
1451 r
= device_read_uevent_file(device
);
1455 r
= device_read_db(device
);
1459 if (device
->property_devlinks_outdated
) {
1460 char *devlinks
= NULL
;
1461 const char *devlink
;
1463 devlink
= sd_device_get_devlink_first(device
);
1465 devlinks
= strdupa(devlink
);
1467 while ((devlink
= sd_device_get_devlink_next(device
)))
1468 devlinks
= strjoina(devlinks
, " ", devlink
);
1470 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1474 device
->property_devlinks_outdated
= false;
1477 if (device
->property_tags_outdated
) {
1481 tag
= sd_device_get_tag_first(device
);
1483 tags
= strjoina(":", tag
);
1485 while ((tag
= sd_device_get_tag_next(device
)))
1486 tags
= strjoina(tags
, ":", tag
);
1488 tags
= strjoina(tags
, ":");
1490 r
= device_add_property_internal(device
, "TAGS", tags
);
1494 device
->property_tags_outdated
= false;
1500 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1505 assert_return(device
, NULL
);
1507 r
= device_properties_prepare(device
);
1511 device
->properties_iterator_generation
= device
->properties_generation
;
1512 device
->properties_iterator
= ITERATOR_FIRST
;
1514 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1522 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1527 assert_return(device
, NULL
);
1529 r
= device_properties_prepare(device
);
1533 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1536 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1544 static int device_sysattrs_read_all(sd_device
*device
) {
1545 _cleanup_closedir_
DIR *dir
= NULL
;
1546 const char *syspath
;
1547 struct dirent
*dent
;
1552 if (device
->sysattrs_read
)
1555 r
= sd_device_get_syspath(device
, &syspath
);
1559 dir
= opendir(syspath
);
1563 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1567 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1569 struct stat statbuf
;
1571 /* only handle symlinks and regular files */
1572 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1575 path
= strjoina(syspath
, "/", dent
->d_name
);
1577 if (lstat(path
, &statbuf
) != 0)
1580 if (!(statbuf
.st_mode
& S_IRUSR
))
1583 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1588 device
->sysattrs_read
= true;
1593 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1597 assert_return(device
, NULL
);
1599 if (!device
->sysattrs_read
) {
1600 r
= device_sysattrs_read_all(device
);
1607 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1609 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1613 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1616 assert_return(device
, NULL
);
1618 if (!device
->sysattrs_read
)
1621 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1625 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1626 assert_return(device
, -EINVAL
);
1627 assert_return(tag
, -EINVAL
);
1629 (void) device_read_db(device
);
1631 return !!set_contains(device
->tags
, tag
);
1634 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1638 assert_return(device
, -EINVAL
);
1639 assert_return(key
, -EINVAL
);
1640 assert_return(_value
, -EINVAL
);
1642 r
= device_properties_prepare(device
);
1646 value
= ordered_hashmap_get(device
->properties
, key
);
1655 /* replaces the value if it already exists */
1656 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1657 _cleanup_free_
char *key
= NULL
;
1658 _cleanup_free_
char *value_old
= NULL
;
1664 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1668 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1675 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1684 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1685 const char *key
= NULL
, *value
;
1690 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1700 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1701 * with a NULL value in the cache, otherwise the returned string is stored */
1702 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1703 _cleanup_free_
char *value
= NULL
;
1704 const char *syspath
, *cached_value
= NULL
;
1706 struct stat statbuf
;
1709 assert_return(device
, -EINVAL
);
1710 assert_return(sysattr
, -EINVAL
);
1712 /* look for possibly already cached result */
1713 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1719 /* we looked up the sysattr before and it did not exist */
1723 *_value
= cached_value
;
1728 r
= sd_device_get_syspath(device
, &syspath
);
1732 path
= strjoina(syspath
, "/", sysattr
);
1733 r
= lstat(path
, &statbuf
);
1735 /* remember that we could not access the sysattr */
1736 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1741 } else if (S_ISLNK(statbuf
.st_mode
)) {
1742 /* Some core links return only the last element of the target path,
1743 * these are just values, the paths should not be exposed. */
1744 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1745 r
= readlink_value(path
, &value
);
1750 } else if (S_ISDIR(statbuf
.st_mode
)) {
1751 /* skip directories */
1753 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1754 /* skip non-readable files */
1759 /* read attribute value */
1760 r
= read_full_file(path
, &value
, &size
);
1764 /* drop trailing newlines */
1765 while (size
> 0 && value
[--size
] == '\n')
1769 r
= device_add_sysattr_value(device
, sysattr
, value
);
1779 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1780 _cleanup_free_
char *key
= NULL
;
1781 _cleanup_free_
char *value
= NULL
;
1786 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1791 /* set the attribute and save it in the cache. If a NULL value is passed the
1792 * attribute is cleared from the cache */
1793 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1794 _cleanup_close_
int fd
= -1;
1795 _cleanup_free_
char *value
= NULL
;
1796 const char *syspath
;
1798 struct stat statbuf
;
1799 size_t value_len
= 0;
1803 assert_return(device
, -EINVAL
);
1804 assert_return(sysattr
, -EINVAL
);
1807 device_remove_sysattr_value(device
, sysattr
);
1812 r
= sd_device_get_syspath(device
, &syspath
);
1816 path
= strjoina(syspath
, "/", sysattr
);
1817 r
= lstat(path
, &statbuf
);
1823 r
= device_add_sysattr_value(device
, sysattr
, value
);
1830 if (S_ISLNK(statbuf
.st_mode
))
1833 /* skip directories */
1834 if (S_ISDIR(statbuf
.st_mode
))
1837 /* skip non-readable files */
1838 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1841 value_len
= strlen(_value
);
1843 /* drop trailing newlines */
1844 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1845 _value
[--value_len
] = '\0';
1847 /* value length is limited to 4k */
1848 if (value_len
> 4096)
1851 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1855 value
= strdup(_value
);
1859 size
= write(fd
, value
, value_len
);
1863 if ((size_t)size
!= value_len
)
1866 r
= device_add_sysattr_value(device
, sysattr
, value
);