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/>.
22 #include <sys/types.h>
27 #include "path-util.h"
34 #include "sd-device.h"
36 #include "device-util.h"
37 #include "device-private.h"
38 #include "device-internal.h"
40 int device_new_aux(sd_device
**ret
) {
41 _cleanup_device_unref_ sd_device
*device
= NULL
;
45 device
= new0(sd_device
, 1);
50 device
->watch_handle
= -1;
58 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
60 assert_se(++ device
->n_ref
>= 2);
65 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
66 if (device
&& -- device
->n_ref
== 0) {
67 sd_device_unref(device
->parent
);
68 free(device
->syspath
);
69 free(device
->sysname
);
70 free(device
->devtype
);
71 free(device
->devname
);
72 free(device
->subsystem
);
74 free(device
->id_filename
);
75 free(device
->properties_strv
);
76 free(device
->properties_nulstr
);
78 ordered_hashmap_free_free_free(device
->properties
);
79 ordered_hashmap_free_free_free(device
->properties_db
);
80 hashmap_free_free_free(device
->sysattr_values
);
81 set_free_free(device
->sysattrs
);
82 set_free_free(device
->tags
);
83 set_free_free(device
->devlinks
);
91 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
92 OrderedHashmap
**properties
;
98 properties
= &device
->properties_db
;
100 properties
= &device
->properties
;
103 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
106 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
114 value
= strdup(_value
);
118 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
120 r
= ordered_hashmap_replace(*properties
, key
, value
);
127 _cleanup_free_
char *key
= NULL
;
128 _cleanup_free_
char *value
= NULL
;
130 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
134 device
->properties_generation
++;
135 device
->properties_buf_outdated
= true;
141 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
142 return device_add_property_aux(device
, key
, value
, false);
145 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
146 _cleanup_free_
char *syspath
= NULL
;
153 /* must be a subdirectory of /sys */
154 if (!path_startswith(_syspath
, "/sys/")) {
155 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
160 r
= readlink_and_canonicalize(_syspath
, &syspath
);
162 /* the device does not exist (any more?) */
164 else if (r
== -EINVAL
) {
166 syspath
= canonicalize_file_name(_syspath
);
169 /* the device does not exist (any more?) */
172 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
175 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
179 if (path_startswith(syspath
, "/sys/devices/")) {
182 /* all 'devices' require an 'uevent' file */
183 path
= strjoina(syspath
, "/uevent");
184 r
= access(path
, F_OK
);
187 /* this is not a valid device */
190 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
194 /* everything else just just needs to be a directory */
195 if (!is_dir(syspath
, false))
199 syspath
= strdup(_syspath
);
204 devpath
= syspath
+ strlen("/sys");
206 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
210 free(device
->syspath
);
211 device
->syspath
= syspath
;
214 device
->devpath
= devpath
;
219 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
220 _cleanup_device_unref_ sd_device
*device
= NULL
;
223 assert_return(ret
, -EINVAL
);
224 assert_return(syspath
, -EINVAL
);
226 r
= device_new_aux(&device
);
230 r
= device_set_syspath(device
, syspath
, true);
240 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
242 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
244 assert_return(ret
, -EINVAL
);
245 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
247 /* use /sys/dev/{block,char}/<maj>:<min> link */
248 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
250 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
252 return sd_device_new_from_syspath(ret
, syspath
);
255 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
258 assert_return(ret
, -EINVAL
);
259 assert_return(subsystem
, -EINVAL
);
260 assert_return(sysname
, -EINVAL
);
262 if (streq(subsystem
, "subsystem")) {
263 syspath
= strjoina("/sys/subsystem/", sysname
);
264 if (access(syspath
, F_OK
) >= 0)
265 return sd_device_new_from_syspath(ret
, syspath
);
267 syspath
= strjoina("/sys/bus/", sysname
);
268 if (access(syspath
, F_OK
) >= 0)
269 return sd_device_new_from_syspath(ret
, syspath
);
271 syspath
= strjoina("/sys/class/", sysname
);
272 if (access(syspath
, F_OK
) >= 0)
273 return sd_device_new_from_syspath(ret
, syspath
);
274 } else if (streq(subsystem
, "module")) {
275 syspath
= strjoina("/sys/module/", sysname
);
276 if (access(syspath
, F_OK
) >= 0)
277 return sd_device_new_from_syspath(ret
, syspath
);
278 } else if (streq(subsystem
, "drivers")) {
279 char subsys
[PATH_MAX
];
282 strscpy(subsys
, sizeof(subsys
), sysname
);
283 driver
= strchr(subsys
, ':');
288 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
289 if (access(syspath
, F_OK
) >= 0)
290 return sd_device_new_from_syspath(ret
, syspath
);
292 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
293 if (access(syspath
, F_OK
) >= 0)
294 return sd_device_new_from_syspath(ret
, syspath
);
301 /* translate sysname back to sysfs filename */
302 name
= strdupa(sysname
);
303 while (name
[len
] != '\0') {
304 if (name
[len
] == '/')
310 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
311 if (access(syspath
, F_OK
) >= 0)
312 return sd_device_new_from_syspath(ret
, syspath
);
314 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
315 if (access(syspath
, F_OK
) >= 0)
316 return sd_device_new_from_syspath(ret
, syspath
);
318 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
319 if (access(syspath
, F_OK
) >= 0)
320 return sd_device_new_from_syspath(ret
, syspath
);
326 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
327 _cleanup_free_
char *devtype
= NULL
;
333 devtype
= strdup(_devtype
);
337 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
341 free(device
->devtype
);
342 device
->devtype
= devtype
;
348 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
354 r
= safe_atoi(_ifindex
, &ifindex
);
361 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
365 device
->ifindex
= ifindex
;
370 int device_set_devname(sd_device
*device
, const char *_devname
) {
371 _cleanup_free_
char *devname
= NULL
;
377 if (_devname
[0] != '/') {
378 r
= asprintf(&devname
, "/dev/%s", _devname
);
382 devname
= strdup(_devname
);
387 r
= device_add_property_internal(device
, "DEVNAME", devname
);
391 free(device
->devname
);
392 device
->devname
= devname
;
398 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
405 r
= safe_atou(_devmode
, &devmode
);
412 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
416 device
->devmode
= devmode
;
421 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
422 unsigned maj
= 0, min
= 0;
428 r
= safe_atou(major
, &maj
);
435 r
= safe_atou(minor
, &min
);
440 r
= device_add_property_internal(device
, "MAJOR", major
);
445 r
= device_add_property_internal(device
, "MINOR", minor
);
450 device
->devnum
= makedev(maj
, min
);
455 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
464 if (streq(key
, "DEVTYPE")) {
465 r
= device_set_devtype(device
, value
);
468 } else if (streq(key
, "IFINDEX")) {
469 r
= device_set_ifindex(device
, value
);
472 } else if (streq(key
, "DEVNAME")) {
473 r
= device_set_devname(device
, value
);
476 } else if (streq(key
, "DEVMODE")) {
477 r
= device_set_devmode(device
, value
);
480 } else if (streq(key
, "MAJOR"))
482 else if (streq(key
, "MINOR"))
485 r
= device_add_property_internal(device
, key
, value
);
493 int device_read_uevent_file(sd_device
*device
) {
494 _cleanup_free_
char *uevent
= NULL
;
495 const char *syspath
, *key
, *value
, *major
= NULL
, *minor
= NULL
;
511 if (device
->uevent_loaded
|| device
->sealed
)
514 device
->uevent_loaded
= true;
516 r
= sd_device_get_syspath(device
, &syspath
);
520 path
= strjoina(syspath
, "/uevent");
522 r
= read_full_file(path
, &uevent
, &uevent_len
);
524 /* empty uevent files may be write-only */
526 else if (r
== -ENOENT
)
527 /* some devices may not have uevent files, see set_syspath() */
530 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
534 for (i
= 0; i
< uevent_len
; i
++) {
537 if (!strchr(NEWLINE
, uevent
[i
])) {
545 if (uevent
[i
] == '=') {
549 } else if (strchr(NEWLINE
, uevent
[i
])) {
551 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
564 if (strchr(NEWLINE
, uevent
[i
])) {
567 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
569 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
576 assert_not_reached("invalid state when parsing uevent file");
581 r
= device_set_devnum(device
, major
, minor
);
583 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
589 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
592 assert_return(device
, -EINVAL
);
593 assert_return(ifindex
, -EINVAL
);
595 r
= device_read_uevent_file(device
);
599 *ifindex
= device
->ifindex
;
604 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
607 assert_return(ret
, -EINVAL
);
608 assert_return(id
, -EINVAL
);
617 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
621 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
625 _cleanup_device_unref_ sd_device
*device
= NULL
;
626 _cleanup_close_
int sk
= -1;
627 struct ifreq ifr
= {};
630 r
= safe_atoi(&id
[1], &ifr
.ifr_ifindex
);
633 else if (ifr
.ifr_ifindex
<= 0)
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
);