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 "device-internal.h"
28 #include "device-private.h"
29 #include "device-util.h"
34 #include "path-util.h"
36 #include "string-util.h"
41 int device_new_aux(sd_device
**ret
) {
42 _cleanup_device_unref_ sd_device
*device
= NULL
;
46 device
= new0(sd_device
, 1);
51 device
->watch_handle
= -1;
59 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
61 assert_se(++ device
->n_ref
>= 2);
66 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
67 if (device
&& -- device
->n_ref
== 0) {
68 sd_device_unref(device
->parent
);
69 free(device
->syspath
);
70 free(device
->sysname
);
71 free(device
->devtype
);
72 free(device
->devname
);
73 free(device
->subsystem
);
75 free(device
->id_filename
);
76 free(device
->properties_strv
);
77 free(device
->properties_nulstr
);
79 ordered_hashmap_free_free_free(device
->properties
);
80 ordered_hashmap_free_free_free(device
->properties_db
);
81 hashmap_free_free_free(device
->sysattr_values
);
82 set_free_free(device
->sysattrs
);
83 set_free_free(device
->tags
);
84 set_free_free(device
->devlinks
);
92 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
93 OrderedHashmap
**properties
;
99 properties
= &device
->properties_db
;
101 properties
= &device
->properties
;
104 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
107 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
115 value
= strdup(_value
);
119 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
121 r
= ordered_hashmap_replace(*properties
, key
, value
);
128 _cleanup_free_
char *key
= NULL
;
129 _cleanup_free_
char *value
= NULL
;
131 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
135 device
->properties_generation
++;
136 device
->properties_buf_outdated
= true;
142 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
143 return device_add_property_aux(device
, key
, value
, false);
146 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
147 _cleanup_free_
char *syspath
= NULL
;
154 /* must be a subdirectory of /sys */
155 if (!path_startswith(_syspath
, "/sys/")) {
156 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
161 r
= readlink_and_canonicalize(_syspath
, &syspath
);
163 /* the device does not exist (any more?) */
165 else if (r
== -EINVAL
) {
167 syspath
= canonicalize_file_name(_syspath
);
170 /* the device does not exist (any more?) */
173 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
176 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
180 if (path_startswith(syspath
, "/sys/devices/")) {
183 /* all 'devices' require an 'uevent' file */
184 path
= strjoina(syspath
, "/uevent");
185 r
= access(path
, F_OK
);
188 /* this is not a valid device */
191 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
195 /* everything else just just needs to be a directory */
196 if (!is_dir(syspath
, false))
200 syspath
= strdup(_syspath
);
205 devpath
= syspath
+ strlen("/sys");
207 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
211 free(device
->syspath
);
212 device
->syspath
= syspath
;
215 device
->devpath
= devpath
;
220 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
221 _cleanup_device_unref_ sd_device
*device
= NULL
;
224 assert_return(ret
, -EINVAL
);
225 assert_return(syspath
, -EINVAL
);
227 r
= device_new_aux(&device
);
231 r
= device_set_syspath(device
, syspath
, true);
241 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
243 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
245 assert_return(ret
, -EINVAL
);
246 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
248 /* use /sys/dev/{block,char}/<maj>:<min> link */
249 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
251 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
253 return sd_device_new_from_syspath(ret
, syspath
);
256 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
259 assert_return(ret
, -EINVAL
);
260 assert_return(subsystem
, -EINVAL
);
261 assert_return(sysname
, -EINVAL
);
263 if (streq(subsystem
, "subsystem")) {
264 syspath
= strjoina("/sys/subsystem/", sysname
);
265 if (access(syspath
, F_OK
) >= 0)
266 return sd_device_new_from_syspath(ret
, syspath
);
268 syspath
= strjoina("/sys/bus/", sysname
);
269 if (access(syspath
, F_OK
) >= 0)
270 return sd_device_new_from_syspath(ret
, syspath
);
272 syspath
= strjoina("/sys/class/", sysname
);
273 if (access(syspath
, F_OK
) >= 0)
274 return sd_device_new_from_syspath(ret
, syspath
);
275 } else if (streq(subsystem
, "module")) {
276 syspath
= strjoina("/sys/module/", sysname
);
277 if (access(syspath
, F_OK
) >= 0)
278 return sd_device_new_from_syspath(ret
, syspath
);
279 } else if (streq(subsystem
, "drivers")) {
280 char subsys
[PATH_MAX
];
283 strscpy(subsys
, sizeof(subsys
), sysname
);
284 driver
= strchr(subsys
, ':');
289 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
290 if (access(syspath
, F_OK
) >= 0)
291 return sd_device_new_from_syspath(ret
, syspath
);
293 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
294 if (access(syspath
, F_OK
) >= 0)
295 return sd_device_new_from_syspath(ret
, syspath
);
302 /* translate sysname back to sysfs filename */
303 name
= strdupa(sysname
);
304 while (name
[len
] != '\0') {
305 if (name
[len
] == '/')
311 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
312 if (access(syspath
, F_OK
) >= 0)
313 return sd_device_new_from_syspath(ret
, syspath
);
315 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
316 if (access(syspath
, F_OK
) >= 0)
317 return sd_device_new_from_syspath(ret
, syspath
);
319 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
320 if (access(syspath
, F_OK
) >= 0)
321 return sd_device_new_from_syspath(ret
, syspath
);
327 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
328 _cleanup_free_
char *devtype
= NULL
;
334 devtype
= strdup(_devtype
);
338 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
342 free(device
->devtype
);
343 device
->devtype
= devtype
;
349 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
355 r
= safe_atoi(_ifindex
, &ifindex
);
362 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
366 device
->ifindex
= ifindex
;
371 int device_set_devname(sd_device
*device
, const char *_devname
) {
372 _cleanup_free_
char *devname
= NULL
;
378 if (_devname
[0] != '/') {
379 r
= asprintf(&devname
, "/dev/%s", _devname
);
383 devname
= strdup(_devname
);
388 r
= device_add_property_internal(device
, "DEVNAME", devname
);
392 free(device
->devname
);
393 device
->devname
= devname
;
399 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
406 r
= safe_atou(_devmode
, &devmode
);
413 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
417 device
->devmode
= devmode
;
422 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
423 unsigned maj
= 0, min
= 0;
429 r
= safe_atou(major
, &maj
);
436 r
= safe_atou(minor
, &min
);
441 r
= device_add_property_internal(device
, "MAJOR", major
);
446 r
= device_add_property_internal(device
, "MINOR", minor
);
451 device
->devnum
= makedev(maj
, min
);
456 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
465 if (streq(key
, "DEVTYPE")) {
466 r
= device_set_devtype(device
, value
);
469 } else if (streq(key
, "IFINDEX")) {
470 r
= device_set_ifindex(device
, value
);
473 } else if (streq(key
, "DEVNAME")) {
474 r
= device_set_devname(device
, value
);
477 } else if (streq(key
, "DEVMODE")) {
478 r
= device_set_devmode(device
, value
);
481 } else if (streq(key
, "MAJOR"))
483 else if (streq(key
, "MINOR"))
486 r
= device_add_property_internal(device
, key
, value
);
494 int device_read_uevent_file(sd_device
*device
) {
495 _cleanup_free_
char *uevent
= NULL
;
496 const char *syspath
, *key
, *value
, *major
= NULL
, *minor
= NULL
;
512 if (device
->uevent_loaded
|| device
->sealed
)
515 device
->uevent_loaded
= true;
517 r
= sd_device_get_syspath(device
, &syspath
);
521 path
= strjoina(syspath
, "/uevent");
523 r
= read_full_file(path
, &uevent
, &uevent_len
);
525 /* empty uevent files may be write-only */
527 else if (r
== -ENOENT
)
528 /* some devices may not have uevent files, see set_syspath() */
531 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
535 for (i
= 0; i
< uevent_len
; i
++) {
538 if (!strchr(NEWLINE
, uevent
[i
])) {
546 if (uevent
[i
] == '=') {
550 } else if (strchr(NEWLINE
, uevent
[i
])) {
552 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
565 if (strchr(NEWLINE
, uevent
[i
])) {
568 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
570 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
577 assert_not_reached("invalid state when parsing uevent file");
582 r
= device_set_devnum(device
, major
, minor
);
584 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
590 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
593 assert_return(device
, -EINVAL
);
594 assert_return(ifindex
, -EINVAL
);
596 r
= device_read_uevent_file(device
);
600 *ifindex
= device
->ifindex
;
605 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
608 assert_return(ret
, -EINVAL
);
609 assert_return(id
, -EINVAL
);
618 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
622 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
626 _cleanup_device_unref_ sd_device
*device
= NULL
;
627 _cleanup_close_
int sk
= -1;
628 struct ifreq ifr
= {};
631 r
= safe_atoi(&id
[1], &ifr
.ifr_ifindex
);
634 else if (ifr
.ifr_ifindex
<= 0)
637 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
641 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
645 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
649 r
= sd_device_get_ifindex(device
, &ifindex
);
653 /* this is racey, so we might end up with the wrong device */
654 if (ifr
.ifr_ifindex
!= ifindex
)
664 char subsys
[PATH_MAX
];
667 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
668 sysname
= strchr(subsys
, ':');
675 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
682 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
683 assert_return(device
, -EINVAL
);
684 assert_return(ret
, -EINVAL
);
686 assert(path_startswith(device
->syspath
, "/sys/"));
688 *ret
= device
->syspath
;
693 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
694 _cleanup_free_
char *path
= NULL
;
695 const char *subdir
, *syspath
;
701 r
= sd_device_get_syspath(child
, &syspath
);
705 path
= strdup(syspath
);
708 subdir
= path
+ strlen("/sys");
713 pos
= strrchr(subdir
, '/');
714 if (!pos
|| pos
< subdir
+ 2)
719 r
= sd_device_new_from_syspath(ret
, path
);
729 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
731 assert_return(ret
, -EINVAL
);
732 assert_return(child
, -EINVAL
);
734 if (!child
->parent_set
) {
735 child
->parent_set
= true;
737 (void)device_new_from_child(&child
->parent
, child
);
743 *ret
= child
->parent
;
748 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
749 _cleanup_free_
char *subsystem
= NULL
;
755 subsystem
= strdup(_subsystem
);
759 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
763 free(device
->subsystem
);
764 device
->subsystem
= subsystem
;
767 device
->subsystem_set
= true;
772 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
773 assert_return(ret
, -EINVAL
);
774 assert_return(device
, -EINVAL
);
776 if (!device
->subsystem_set
) {
777 _cleanup_free_
char *subsystem
= NULL
;
782 /* read 'subsystem' link */
783 r
= sd_device_get_syspath(device
, &syspath
);
787 path
= strjoina(syspath
, "/subsystem");
788 r
= readlink_value(path
, &subsystem
);
790 r
= device_set_subsystem(device
, subsystem
);
791 /* use implicit names */
792 else if (path_startswith(device
->devpath
, "/module/"))
793 r
= device_set_subsystem(device
, "module");
794 else if (strstr(device
->devpath
, "/drivers/"))
795 r
= device_set_subsystem(device
, "drivers");
796 else if (path_startswith(device
->devpath
, "/subsystem/") ||
797 path_startswith(device
->devpath
, "/class/") ||
798 path_startswith(device
->devpath
, "/bus/"))
799 r
= device_set_subsystem(device
, "subsystem");
800 if (r
< 0 && r
!= -ENOENT
)
801 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
803 device
->subsystem_set
= true;
806 if (!device
->subsystem
)
809 *ret
= device
->subsystem
;
814 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
820 r
= device_read_uevent_file(device
);
824 *devtype
= device
->devtype
;
829 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
830 sd_device
*parent
= NULL
;
833 assert_return(child
, -EINVAL
);
834 assert_return(subsystem
, -EINVAL
);
836 r
= sd_device_get_parent(child
, &parent
);
838 const char *parent_subsystem
= NULL
;
839 const char *parent_devtype
= NULL
;
841 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
842 if (streq_ptr(parent_subsystem
, subsystem
)) {
846 (void)sd_device_get_devtype(parent
, &parent_devtype
);
847 if (streq_ptr(parent_devtype
, devtype
))
850 r
= sd_device_get_parent(parent
, &parent
);
861 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
864 assert_return(device
, -EINVAL
);
865 assert_return(devnum
, -EINVAL
);
867 r
= device_read_uevent_file(device
);
871 *devnum
= device
->devnum
;
876 int device_set_driver(sd_device
*device
, const char *_driver
) {
877 _cleanup_free_
char *driver
= NULL
;
883 driver
= strdup(_driver
);
887 r
= device_add_property_internal(device
, "DRIVER", driver
);
891 free(device
->driver
);
892 device
->driver
= driver
;
895 device
->driver_set
= true;
900 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
901 assert_return(device
, -EINVAL
);
902 assert_return(ret
, -EINVAL
);
904 if (!device
->driver_set
) {
905 _cleanup_free_
char *driver
= NULL
;
910 r
= sd_device_get_syspath(device
, &syspath
);
914 path
= strjoina(syspath
, "/driver");
915 r
= readlink_value(path
, &driver
);
917 r
= device_set_driver(device
, driver
);
919 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
920 } else if (r
== -ENOENT
)
921 device
->driver_set
= true;
923 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
929 *ret
= device
->driver
;
934 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
935 assert_return(device
, -EINVAL
);
936 assert_return(devpath
, -EINVAL
);
938 assert(device
->devpath
);
939 assert(device
->devpath
[0] == '/');
941 *devpath
= device
->devpath
;
946 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
949 assert_return(device
, -EINVAL
);
950 assert_return(devname
, -EINVAL
);
952 r
= device_read_uevent_file(device
);
956 if (!device
->devname
)
959 assert(path_startswith(device
->devname
, "/dev/"));
961 *devname
= device
->devname
;
966 static int device_set_sysname(sd_device
*device
) {
967 _cleanup_free_
char *sysname
= NULL
;
968 const char *sysnum
= NULL
;
972 pos
= strrchr(device
->devpath
, '/');
977 /* devpath is not a root directory */
978 if (*pos
== '\0' || pos
<= device
->devpath
)
981 sysname
= strdup(pos
);
985 /* some devices have '!' in their name, change that to '/' */
986 while (sysname
[len
] != '\0') {
987 if (sysname
[len
] == '!')
993 /* trailing number */
994 while (len
> 0 && isdigit(sysname
[--len
]))
995 sysnum
= &sysname
[len
];
1000 free(device
->sysname
);
1001 device
->sysname
= sysname
;
1004 device
->sysnum
= sysnum
;
1006 device
->sysname_set
= true;
1011 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1014 assert_return(device
, -EINVAL
);
1015 assert_return(ret
, -EINVAL
);
1017 if (!device
->sysname_set
) {
1018 r
= device_set_sysname(device
);
1023 assert_return(device
->sysname
, -ENOENT
);
1025 *ret
= device
->sysname
;
1030 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1033 assert_return(device
, -EINVAL
);
1034 assert_return(ret
, -EINVAL
);
1036 if (!device
->sysname_set
) {
1037 r
= device_set_sysname(device
);
1042 *ret
= device
->sysnum
;
1047 static bool is_valid_tag(const char *tag
) {
1050 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1053 int device_add_tag(sd_device
*device
, const char *tag
) {
1059 if (!is_valid_tag(tag
))
1062 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1066 r
= set_put_strdup(device
->tags
, tag
);
1070 device
->tags_generation
++;
1071 device
->property_tags_outdated
= true;
1076 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1082 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1086 r
= set_put_strdup(device
->devlinks
, devlink
);
1090 device
->devlinks_generation
++;
1091 device
->property_devlinks_outdated
= true;
1096 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1097 _cleanup_free_
char *key
= NULL
;
1107 value
= strchr(key
, '=');
1113 if (isempty(++value
))
1116 return device_add_property_internal(device
, key
, value
);
1119 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1120 uint64_t usec_initialized
;
1124 assert(initialized
);
1126 r
= safe_atou64(initialized
, &usec_initialized
);
1130 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1134 device
->usec_initialized
= usec_initialized
;
1139 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1148 r
= device_add_tag(device
, value
);
1154 path
= strjoina("/dev/", value
);
1155 r
= device_add_devlink(device
, path
);
1161 r
= device_add_property_internal_from_string(device
, value
);
1167 r
= device_set_usec_initialized(device
, value
);
1173 r
= safe_atoi(value
, &device
->devlink_priority
);
1179 r
= safe_atoi(value
, &device
->watch_handle
);
1185 log_debug("device db: unknown key '%c'", key
);
1191 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1195 if (!device
->id_filename
) {
1196 _cleanup_free_
char *id
= NULL
;
1197 const char *subsystem
;
1201 r
= sd_device_get_subsystem(device
, &subsystem
);
1205 r
= sd_device_get_devnum(device
, &devnum
);
1209 r
= sd_device_get_ifindex(device
, &ifindex
);
1213 if (major(devnum
) > 0) {
1216 /* use dev_t -- b259:131072, c254:0 */
1217 r
= asprintf(&id
, "%c%u:%u",
1218 streq(subsystem
, "block") ? 'b' : 'c',
1219 major(devnum
), minor(devnum
));
1222 } else if (ifindex
> 0) {
1223 /* use netdev ifindex -- n3 */
1224 r
= asprintf(&id
, "n%u", ifindex
);
1228 /* use $subsys:$sysname -- pci:0000:00:1f.2
1229 * sysname() has '!' translated, get it from devpath
1231 const char *sysname
;
1233 sysname
= basename(device
->devpath
);
1240 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1245 device
->id_filename
= id
;
1249 *ret
= device
->id_filename
;
1254 int device_read_db_aux(sd_device
*device
, bool force
) {
1255 _cleanup_free_
char *db
= NULL
;
1257 const char *id
, *value
;
1271 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1274 device
->db_loaded
= true;
1276 r
= device_get_id_filename(device
, &id
);
1280 path
= strjoina("/run/udev/data/", id
);
1282 r
= read_full_file(path
, &db
, &db_len
);
1287 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1290 /* devices with a database entry are initialized */
1291 device
->is_initialized
= true;
1293 for (i
= 0; i
< db_len
; i
++) {
1296 if (!strchr(NEWLINE
, db
[i
])) {
1305 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1307 state
= INVALID_LINE
;
1322 if (strchr(NEWLINE
, db
[i
]))
1327 if (strchr(NEWLINE
, db
[i
])) {
1329 r
= handle_db_line(device
, key
, value
);
1331 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1338 assert_not_reached("invalid state when parsing db");
1345 static int device_read_db(sd_device
*device
) {
1346 return device_read_db_aux(device
, false);
1349 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1352 assert_return(device
, -EINVAL
);
1353 assert_return(initialized
, -EINVAL
);
1355 r
= device_read_db(device
);
1359 *initialized
= device
->is_initialized
;
1364 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1368 assert_return(device
, -EINVAL
);
1369 assert_return(usec
, -EINVAL
);
1371 r
= device_read_db(device
);
1375 if (!device
->is_initialized
)
1378 if (!device
->usec_initialized
)
1381 now_ts
= now(clock_boottime_or_monotonic());
1383 if (now_ts
< device
->usec_initialized
)
1386 *usec
= now_ts
- device
->usec_initialized
;
1391 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1394 assert_return(device
, NULL
);
1396 (void) device_read_db(device
);
1398 device
->tags_iterator_generation
= device
->tags_generation
;
1399 device
->tags_iterator
= ITERATOR_FIRST
;
1401 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1405 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1408 assert_return(device
, NULL
);
1410 (void) device_read_db(device
);
1412 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1415 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1419 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1422 assert_return(device
, NULL
);
1424 (void) device_read_db(device
);
1426 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1427 device
->devlinks_iterator
= ITERATOR_FIRST
;
1429 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1433 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1436 assert_return(device
, NULL
);
1438 (void) device_read_db(device
);
1440 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1443 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1447 static int device_properties_prepare(sd_device
*device
) {
1452 r
= device_read_uevent_file(device
);
1456 r
= device_read_db(device
);
1460 if (device
->property_devlinks_outdated
) {
1461 char *devlinks
= NULL
;
1462 const char *devlink
;
1464 devlink
= sd_device_get_devlink_first(device
);
1466 devlinks
= strdupa(devlink
);
1468 while ((devlink
= sd_device_get_devlink_next(device
)))
1469 devlinks
= strjoina(devlinks
, " ", devlink
);
1471 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1475 device
->property_devlinks_outdated
= false;
1478 if (device
->property_tags_outdated
) {
1482 tag
= sd_device_get_tag_first(device
);
1484 tags
= strjoina(":", tag
);
1486 while ((tag
= sd_device_get_tag_next(device
)))
1487 tags
= strjoina(tags
, ":", tag
);
1489 tags
= strjoina(tags
, ":");
1491 r
= device_add_property_internal(device
, "TAGS", tags
);
1495 device
->property_tags_outdated
= false;
1501 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1506 assert_return(device
, NULL
);
1508 r
= device_properties_prepare(device
);
1512 device
->properties_iterator_generation
= device
->properties_generation
;
1513 device
->properties_iterator
= ITERATOR_FIRST
;
1515 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1523 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1528 assert_return(device
, NULL
);
1530 r
= device_properties_prepare(device
);
1534 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1537 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1545 static int device_sysattrs_read_all(sd_device
*device
) {
1546 _cleanup_closedir_
DIR *dir
= NULL
;
1547 const char *syspath
;
1548 struct dirent
*dent
;
1553 if (device
->sysattrs_read
)
1556 r
= sd_device_get_syspath(device
, &syspath
);
1560 dir
= opendir(syspath
);
1564 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1568 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1570 struct stat statbuf
;
1572 /* only handle symlinks and regular files */
1573 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1576 path
= strjoina(syspath
, "/", dent
->d_name
);
1578 if (lstat(path
, &statbuf
) != 0)
1581 if (!(statbuf
.st_mode
& S_IRUSR
))
1584 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1589 device
->sysattrs_read
= true;
1594 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1598 assert_return(device
, NULL
);
1600 if (!device
->sysattrs_read
) {
1601 r
= device_sysattrs_read_all(device
);
1608 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1610 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1614 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1617 assert_return(device
, NULL
);
1619 if (!device
->sysattrs_read
)
1622 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1626 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1627 assert_return(device
, -EINVAL
);
1628 assert_return(tag
, -EINVAL
);
1630 (void) device_read_db(device
);
1632 return !!set_contains(device
->tags
, tag
);
1635 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1639 assert_return(device
, -EINVAL
);
1640 assert_return(key
, -EINVAL
);
1641 assert_return(_value
, -EINVAL
);
1643 r
= device_properties_prepare(device
);
1647 value
= ordered_hashmap_get(device
->properties
, key
);
1656 /* replaces the value if it already exists */
1657 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1658 _cleanup_free_
char *key
= NULL
;
1659 _cleanup_free_
char *value_old
= NULL
;
1665 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1669 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1676 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1685 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1686 const char *key
= NULL
, *value
;
1691 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1701 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1702 * with a NULL value in the cache, otherwise the returned string is stored */
1703 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1704 _cleanup_free_
char *value
= NULL
;
1705 const char *syspath
, *cached_value
= NULL
;
1707 struct stat statbuf
;
1710 assert_return(device
, -EINVAL
);
1711 assert_return(sysattr
, -EINVAL
);
1713 /* look for possibly already cached result */
1714 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1720 /* we looked up the sysattr before and it did not exist */
1724 *_value
= cached_value
;
1729 r
= sd_device_get_syspath(device
, &syspath
);
1733 path
= strjoina(syspath
, "/", sysattr
);
1734 r
= lstat(path
, &statbuf
);
1736 /* remember that we could not access the sysattr */
1737 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1742 } else if (S_ISLNK(statbuf
.st_mode
)) {
1743 /* Some core links return only the last element of the target path,
1744 * these are just values, the paths should not be exposed. */
1745 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1746 r
= readlink_value(path
, &value
);
1751 } else if (S_ISDIR(statbuf
.st_mode
)) {
1752 /* skip directories */
1754 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1755 /* skip non-readable files */
1760 /* read attribute value */
1761 r
= read_full_file(path
, &value
, &size
);
1765 /* drop trailing newlines */
1766 while (size
> 0 && value
[--size
] == '\n')
1770 r
= device_add_sysattr_value(device
, sysattr
, value
);
1780 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1781 _cleanup_free_
char *key
= NULL
;
1782 _cleanup_free_
char *value
= NULL
;
1787 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1792 /* set the attribute and save it in the cache. If a NULL value is passed the
1793 * attribute is cleared from the cache */
1794 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1795 _cleanup_close_
int fd
= -1;
1796 _cleanup_free_
char *value
= NULL
;
1797 const char *syspath
;
1799 struct stat statbuf
;
1800 size_t value_len
= 0;
1804 assert_return(device
, -EINVAL
);
1805 assert_return(sysattr
, -EINVAL
);
1808 device_remove_sysattr_value(device
, sysattr
);
1813 r
= sd_device_get_syspath(device
, &syspath
);
1817 path
= strjoina(syspath
, "/", sysattr
);
1818 r
= lstat(path
, &statbuf
);
1824 r
= device_add_sysattr_value(device
, sysattr
, value
);
1831 if (S_ISLNK(statbuf
.st_mode
))
1834 /* skip directories */
1835 if (S_ISDIR(statbuf
.st_mode
))
1838 /* skip non-readable files */
1839 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1842 value_len
= strlen(_value
);
1844 /* drop trailing newlines */
1845 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1846 _value
[--value_len
] = '\0';
1848 /* value length is limited to 4k */
1849 if (value_len
> 4096)
1852 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1856 value
= strdup(_value
);
1860 size
= write(fd
, value
, value_len
);
1864 if ((size_t)size
!= value_len
)
1867 r
= device_add_sysattr_value(device
, sysattr
, value
);