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 "parse-util.h"
35 #include "path-util.h"
37 #include "string-util.h"
42 int device_new_aux(sd_device
**ret
) {
43 _cleanup_device_unref_ sd_device
*device
= NULL
;
47 device
= new0(sd_device
, 1);
52 device
->watch_handle
= -1;
60 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
62 assert_se(++ device
->n_ref
>= 2);
67 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
68 if (device
&& -- device
->n_ref
== 0) {
69 sd_device_unref(device
->parent
);
70 free(device
->syspath
);
71 free(device
->sysname
);
72 free(device
->devtype
);
73 free(device
->devname
);
74 free(device
->subsystem
);
76 free(device
->id_filename
);
77 free(device
->properties_strv
);
78 free(device
->properties_nulstr
);
80 ordered_hashmap_free_free_free(device
->properties
);
81 ordered_hashmap_free_free_free(device
->properties_db
);
82 hashmap_free_free_free(device
->sysattr_values
);
83 set_free_free(device
->sysattrs
);
84 set_free_free(device
->tags
);
85 set_free_free(device
->devlinks
);
93 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
94 OrderedHashmap
**properties
;
100 properties
= &device
->properties_db
;
102 properties
= &device
->properties
;
105 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
108 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
116 value
= strdup(_value
);
120 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
122 r
= ordered_hashmap_replace(*properties
, key
, value
);
129 _cleanup_free_
char *key
= NULL
;
130 _cleanup_free_
char *value
= NULL
;
132 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
136 device
->properties_generation
++;
137 device
->properties_buf_outdated
= true;
143 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
144 return device_add_property_aux(device
, key
, value
, false);
147 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
148 _cleanup_free_
char *syspath
= NULL
;
155 /* must be a subdirectory of /sys */
156 if (!path_startswith(_syspath
, "/sys/")) {
157 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
162 r
= readlink_and_canonicalize(_syspath
, &syspath
);
164 /* the device does not exist (any more?) */
166 else if (r
== -EINVAL
) {
168 syspath
= canonicalize_file_name(_syspath
);
171 /* the device does not exist (any more?) */
174 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
177 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
181 if (path_startswith(syspath
, "/sys/devices/")) {
184 /* all 'devices' require an 'uevent' file */
185 path
= strjoina(syspath
, "/uevent");
186 r
= access(path
, F_OK
);
189 /* this is not a valid device */
192 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
196 /* everything else just just needs to be a directory */
197 if (!is_dir(syspath
, false))
201 syspath
= strdup(_syspath
);
206 devpath
= syspath
+ strlen("/sys");
208 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
212 free(device
->syspath
);
213 device
->syspath
= syspath
;
216 device
->devpath
= devpath
;
221 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
222 _cleanup_device_unref_ sd_device
*device
= NULL
;
225 assert_return(ret
, -EINVAL
);
226 assert_return(syspath
, -EINVAL
);
228 r
= device_new_aux(&device
);
232 r
= device_set_syspath(device
, syspath
, true);
242 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
244 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
246 assert_return(ret
, -EINVAL
);
247 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
249 /* use /sys/dev/{block,char}/<maj>:<min> link */
250 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
252 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
254 return sd_device_new_from_syspath(ret
, syspath
);
257 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
260 assert_return(ret
, -EINVAL
);
261 assert_return(subsystem
, -EINVAL
);
262 assert_return(sysname
, -EINVAL
);
264 if (streq(subsystem
, "subsystem")) {
265 syspath
= strjoina("/sys/subsystem/", sysname
);
266 if (access(syspath
, F_OK
) >= 0)
267 return sd_device_new_from_syspath(ret
, syspath
);
269 syspath
= strjoina("/sys/bus/", sysname
);
270 if (access(syspath
, F_OK
) >= 0)
271 return sd_device_new_from_syspath(ret
, syspath
);
273 syspath
= strjoina("/sys/class/", sysname
);
274 if (access(syspath
, F_OK
) >= 0)
275 return sd_device_new_from_syspath(ret
, syspath
);
276 } else if (streq(subsystem
, "module")) {
277 syspath
= strjoina("/sys/module/", sysname
);
278 if (access(syspath
, F_OK
) >= 0)
279 return sd_device_new_from_syspath(ret
, syspath
);
280 } else if (streq(subsystem
, "drivers")) {
281 char subsys
[PATH_MAX
];
284 strscpy(subsys
, sizeof(subsys
), sysname
);
285 driver
= strchr(subsys
, ':');
290 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
291 if (access(syspath
, F_OK
) >= 0)
292 return sd_device_new_from_syspath(ret
, syspath
);
294 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
295 if (access(syspath
, F_OK
) >= 0)
296 return sd_device_new_from_syspath(ret
, syspath
);
303 /* translate sysname back to sysfs filename */
304 name
= strdupa(sysname
);
305 while (name
[len
] != '\0') {
306 if (name
[len
] == '/')
312 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
313 if (access(syspath
, F_OK
) >= 0)
314 return sd_device_new_from_syspath(ret
, syspath
);
316 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
317 if (access(syspath
, F_OK
) >= 0)
318 return sd_device_new_from_syspath(ret
, syspath
);
320 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
321 if (access(syspath
, F_OK
) >= 0)
322 return sd_device_new_from_syspath(ret
, syspath
);
328 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
329 _cleanup_free_
char *devtype
= NULL
;
335 devtype
= strdup(_devtype
);
339 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
343 free(device
->devtype
);
344 device
->devtype
= devtype
;
350 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
356 r
= safe_atoi(_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
= safe_atoi(&id
[1], &ifr
.ifr_ifindex
);
635 else if (ifr
.ifr_ifindex
<= 0)
638 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
642 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
646 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
650 r
= sd_device_get_ifindex(device
, &ifindex
);
654 /* this is racey, so we might end up with the wrong device */
655 if (ifr
.ifr_ifindex
!= ifindex
)
665 char subsys
[PATH_MAX
];
668 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
669 sysname
= strchr(subsys
, ':');
676 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
683 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
684 assert_return(device
, -EINVAL
);
685 assert_return(ret
, -EINVAL
);
687 assert(path_startswith(device
->syspath
, "/sys/"));
689 *ret
= device
->syspath
;
694 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
695 _cleanup_free_
char *path
= NULL
;
696 const char *subdir
, *syspath
;
702 r
= sd_device_get_syspath(child
, &syspath
);
706 path
= strdup(syspath
);
709 subdir
= path
+ strlen("/sys");
714 pos
= strrchr(subdir
, '/');
715 if (!pos
|| pos
< subdir
+ 2)
720 r
= sd_device_new_from_syspath(ret
, path
);
730 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
732 assert_return(ret
, -EINVAL
);
733 assert_return(child
, -EINVAL
);
735 if (!child
->parent_set
) {
736 child
->parent_set
= true;
738 (void)device_new_from_child(&child
->parent
, child
);
744 *ret
= child
->parent
;
749 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
750 _cleanup_free_
char *subsystem
= NULL
;
756 subsystem
= strdup(_subsystem
);
760 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
764 free(device
->subsystem
);
765 device
->subsystem
= subsystem
;
768 device
->subsystem_set
= true;
773 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
774 assert_return(ret
, -EINVAL
);
775 assert_return(device
, -EINVAL
);
777 if (!device
->subsystem_set
) {
778 _cleanup_free_
char *subsystem
= NULL
;
783 /* read 'subsystem' link */
784 r
= sd_device_get_syspath(device
, &syspath
);
788 path
= strjoina(syspath
, "/subsystem");
789 r
= readlink_value(path
, &subsystem
);
791 r
= device_set_subsystem(device
, subsystem
);
792 /* use implicit names */
793 else if (path_startswith(device
->devpath
, "/module/"))
794 r
= device_set_subsystem(device
, "module");
795 else if (strstr(device
->devpath
, "/drivers/"))
796 r
= device_set_subsystem(device
, "drivers");
797 else if (path_startswith(device
->devpath
, "/subsystem/") ||
798 path_startswith(device
->devpath
, "/class/") ||
799 path_startswith(device
->devpath
, "/bus/"))
800 r
= device_set_subsystem(device
, "subsystem");
801 if (r
< 0 && r
!= -ENOENT
)
802 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
804 device
->subsystem_set
= true;
807 if (!device
->subsystem
)
810 *ret
= device
->subsystem
;
815 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
821 r
= device_read_uevent_file(device
);
825 *devtype
= device
->devtype
;
830 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
831 sd_device
*parent
= NULL
;
834 assert_return(child
, -EINVAL
);
835 assert_return(subsystem
, -EINVAL
);
837 r
= sd_device_get_parent(child
, &parent
);
839 const char *parent_subsystem
= NULL
;
840 const char *parent_devtype
= NULL
;
842 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
843 if (streq_ptr(parent_subsystem
, subsystem
)) {
847 (void)sd_device_get_devtype(parent
, &parent_devtype
);
848 if (streq_ptr(parent_devtype
, devtype
))
851 r
= sd_device_get_parent(parent
, &parent
);
862 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
865 assert_return(device
, -EINVAL
);
866 assert_return(devnum
, -EINVAL
);
868 r
= device_read_uevent_file(device
);
872 *devnum
= device
->devnum
;
877 int device_set_driver(sd_device
*device
, const char *_driver
) {
878 _cleanup_free_
char *driver
= NULL
;
884 driver
= strdup(_driver
);
888 r
= device_add_property_internal(device
, "DRIVER", driver
);
892 free(device
->driver
);
893 device
->driver
= driver
;
896 device
->driver_set
= true;
901 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
902 assert_return(device
, -EINVAL
);
903 assert_return(ret
, -EINVAL
);
905 if (!device
->driver_set
) {
906 _cleanup_free_
char *driver
= NULL
;
911 r
= sd_device_get_syspath(device
, &syspath
);
915 path
= strjoina(syspath
, "/driver");
916 r
= readlink_value(path
, &driver
);
918 r
= device_set_driver(device
, driver
);
920 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
921 } else if (r
== -ENOENT
)
922 device
->driver_set
= true;
924 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
930 *ret
= device
->driver
;
935 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
936 assert_return(device
, -EINVAL
);
937 assert_return(devpath
, -EINVAL
);
939 assert(device
->devpath
);
940 assert(device
->devpath
[0] == '/');
942 *devpath
= device
->devpath
;
947 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
950 assert_return(device
, -EINVAL
);
951 assert_return(devname
, -EINVAL
);
953 r
= device_read_uevent_file(device
);
957 if (!device
->devname
)
960 assert(path_startswith(device
->devname
, "/dev/"));
962 *devname
= device
->devname
;
967 static int device_set_sysname(sd_device
*device
) {
968 _cleanup_free_
char *sysname
= NULL
;
969 const char *sysnum
= NULL
;
973 pos
= strrchr(device
->devpath
, '/');
978 /* devpath is not a root directory */
979 if (*pos
== '\0' || pos
<= device
->devpath
)
982 sysname
= strdup(pos
);
986 /* some devices have '!' in their name, change that to '/' */
987 while (sysname
[len
] != '\0') {
988 if (sysname
[len
] == '!')
994 /* trailing number */
995 while (len
> 0 && isdigit(sysname
[--len
]))
996 sysnum
= &sysname
[len
];
1001 free(device
->sysname
);
1002 device
->sysname
= sysname
;
1005 device
->sysnum
= sysnum
;
1007 device
->sysname_set
= true;
1012 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1015 assert_return(device
, -EINVAL
);
1016 assert_return(ret
, -EINVAL
);
1018 if (!device
->sysname_set
) {
1019 r
= device_set_sysname(device
);
1024 assert_return(device
->sysname
, -ENOENT
);
1026 *ret
= device
->sysname
;
1031 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1034 assert_return(device
, -EINVAL
);
1035 assert_return(ret
, -EINVAL
);
1037 if (!device
->sysname_set
) {
1038 r
= device_set_sysname(device
);
1043 *ret
= device
->sysnum
;
1048 static bool is_valid_tag(const char *tag
) {
1051 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1054 int device_add_tag(sd_device
*device
, const char *tag
) {
1060 if (!is_valid_tag(tag
))
1063 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1067 r
= set_put_strdup(device
->tags
, tag
);
1071 device
->tags_generation
++;
1072 device
->property_tags_outdated
= true;
1077 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1083 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1087 r
= set_put_strdup(device
->devlinks
, devlink
);
1091 device
->devlinks_generation
++;
1092 device
->property_devlinks_outdated
= true;
1097 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1098 _cleanup_free_
char *key
= NULL
;
1108 value
= strchr(key
, '=');
1114 if (isempty(++value
))
1117 return device_add_property_internal(device
, key
, value
);
1120 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1121 uint64_t usec_initialized
;
1125 assert(initialized
);
1127 r
= safe_atou64(initialized
, &usec_initialized
);
1131 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1135 device
->usec_initialized
= usec_initialized
;
1140 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1149 r
= device_add_tag(device
, value
);
1155 path
= strjoina("/dev/", value
);
1156 r
= device_add_devlink(device
, path
);
1162 r
= device_add_property_internal_from_string(device
, value
);
1168 r
= device_set_usec_initialized(device
, value
);
1174 r
= safe_atoi(value
, &device
->devlink_priority
);
1180 r
= safe_atoi(value
, &device
->watch_handle
);
1186 log_debug("device db: unknown key '%c'", key
);
1192 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1196 if (!device
->id_filename
) {
1197 _cleanup_free_
char *id
= NULL
;
1198 const char *subsystem
;
1202 r
= sd_device_get_subsystem(device
, &subsystem
);
1206 r
= sd_device_get_devnum(device
, &devnum
);
1210 r
= sd_device_get_ifindex(device
, &ifindex
);
1214 if (major(devnum
) > 0) {
1217 /* use dev_t -- b259:131072, c254:0 */
1218 r
= asprintf(&id
, "%c%u:%u",
1219 streq(subsystem
, "block") ? 'b' : 'c',
1220 major(devnum
), minor(devnum
));
1223 } else if (ifindex
> 0) {
1224 /* use netdev ifindex -- n3 */
1225 r
= asprintf(&id
, "n%u", ifindex
);
1229 /* use $subsys:$sysname -- pci:0000:00:1f.2
1230 * sysname() has '!' translated, get it from devpath
1232 const char *sysname
;
1234 sysname
= basename(device
->devpath
);
1241 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1246 device
->id_filename
= id
;
1250 *ret
= device
->id_filename
;
1255 int device_read_db_aux(sd_device
*device
, bool force
) {
1256 _cleanup_free_
char *db
= NULL
;
1258 const char *id
, *value
;
1272 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1275 device
->db_loaded
= true;
1277 r
= device_get_id_filename(device
, &id
);
1281 path
= strjoina("/run/udev/data/", id
);
1283 r
= read_full_file(path
, &db
, &db_len
);
1288 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1291 /* devices with a database entry are initialized */
1292 device
->is_initialized
= true;
1294 for (i
= 0; i
< db_len
; i
++) {
1297 if (!strchr(NEWLINE
, db
[i
])) {
1306 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1308 state
= INVALID_LINE
;
1323 if (strchr(NEWLINE
, db
[i
]))
1328 if (strchr(NEWLINE
, db
[i
])) {
1330 r
= handle_db_line(device
, key
, value
);
1332 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1339 assert_not_reached("invalid state when parsing db");
1346 static int device_read_db(sd_device
*device
) {
1347 return device_read_db_aux(device
, false);
1350 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1353 assert_return(device
, -EINVAL
);
1354 assert_return(initialized
, -EINVAL
);
1356 r
= device_read_db(device
);
1360 *initialized
= device
->is_initialized
;
1365 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1369 assert_return(device
, -EINVAL
);
1370 assert_return(usec
, -EINVAL
);
1372 r
= device_read_db(device
);
1376 if (!device
->is_initialized
)
1379 if (!device
->usec_initialized
)
1382 now_ts
= now(clock_boottime_or_monotonic());
1384 if (now_ts
< device
->usec_initialized
)
1387 *usec
= now_ts
- device
->usec_initialized
;
1392 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1395 assert_return(device
, NULL
);
1397 (void) device_read_db(device
);
1399 device
->tags_iterator_generation
= device
->tags_generation
;
1400 device
->tags_iterator
= ITERATOR_FIRST
;
1402 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1406 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1409 assert_return(device
, NULL
);
1411 (void) device_read_db(device
);
1413 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1416 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1420 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1423 assert_return(device
, NULL
);
1425 (void) device_read_db(device
);
1427 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1428 device
->devlinks_iterator
= ITERATOR_FIRST
;
1430 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1434 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1437 assert_return(device
, NULL
);
1439 (void) device_read_db(device
);
1441 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1444 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1448 static int device_properties_prepare(sd_device
*device
) {
1453 r
= device_read_uevent_file(device
);
1457 r
= device_read_db(device
);
1461 if (device
->property_devlinks_outdated
) {
1462 char *devlinks
= NULL
;
1463 const char *devlink
;
1465 devlink
= sd_device_get_devlink_first(device
);
1467 devlinks
= strdupa(devlink
);
1469 while ((devlink
= sd_device_get_devlink_next(device
)))
1470 devlinks
= strjoina(devlinks
, " ", devlink
);
1472 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1476 device
->property_devlinks_outdated
= false;
1479 if (device
->property_tags_outdated
) {
1483 tag
= sd_device_get_tag_first(device
);
1485 tags
= strjoina(":", tag
);
1487 while ((tag
= sd_device_get_tag_next(device
)))
1488 tags
= strjoina(tags
, ":", tag
);
1490 tags
= strjoina(tags
, ":");
1492 r
= device_add_property_internal(device
, "TAGS", tags
);
1496 device
->property_tags_outdated
= false;
1502 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1507 assert_return(device
, NULL
);
1509 r
= device_properties_prepare(device
);
1513 device
->properties_iterator_generation
= device
->properties_generation
;
1514 device
->properties_iterator
= ITERATOR_FIRST
;
1516 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1524 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1529 assert_return(device
, NULL
);
1531 r
= device_properties_prepare(device
);
1535 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1538 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1546 static int device_sysattrs_read_all(sd_device
*device
) {
1547 _cleanup_closedir_
DIR *dir
= NULL
;
1548 const char *syspath
;
1549 struct dirent
*dent
;
1554 if (device
->sysattrs_read
)
1557 r
= sd_device_get_syspath(device
, &syspath
);
1561 dir
= opendir(syspath
);
1565 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1569 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1571 struct stat statbuf
;
1573 /* only handle symlinks and regular files */
1574 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1577 path
= strjoina(syspath
, "/", dent
->d_name
);
1579 if (lstat(path
, &statbuf
) != 0)
1582 if (!(statbuf
.st_mode
& S_IRUSR
))
1585 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1590 device
->sysattrs_read
= true;
1595 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1599 assert_return(device
, NULL
);
1601 if (!device
->sysattrs_read
) {
1602 r
= device_sysattrs_read_all(device
);
1609 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1611 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1615 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1618 assert_return(device
, NULL
);
1620 if (!device
->sysattrs_read
)
1623 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1627 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1628 assert_return(device
, -EINVAL
);
1629 assert_return(tag
, -EINVAL
);
1631 (void) device_read_db(device
);
1633 return !!set_contains(device
->tags
, tag
);
1636 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1640 assert_return(device
, -EINVAL
);
1641 assert_return(key
, -EINVAL
);
1642 assert_return(_value
, -EINVAL
);
1644 r
= device_properties_prepare(device
);
1648 value
= ordered_hashmap_get(device
->properties
, key
);
1657 /* replaces the value if it already exists */
1658 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1659 _cleanup_free_
char *key
= NULL
;
1660 _cleanup_free_
char *value_old
= NULL
;
1666 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1670 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1677 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1686 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1687 const char *key
= NULL
, *value
;
1692 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1702 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1703 * with a NULL value in the cache, otherwise the returned string is stored */
1704 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1705 _cleanup_free_
char *value
= NULL
;
1706 const char *syspath
, *cached_value
= NULL
;
1708 struct stat statbuf
;
1711 assert_return(device
, -EINVAL
);
1712 assert_return(sysattr
, -EINVAL
);
1714 /* look for possibly already cached result */
1715 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1721 /* we looked up the sysattr before and it did not exist */
1725 *_value
= cached_value
;
1730 r
= sd_device_get_syspath(device
, &syspath
);
1734 path
= strjoina(syspath
, "/", sysattr
);
1735 r
= lstat(path
, &statbuf
);
1737 /* remember that we could not access the sysattr */
1738 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1743 } else if (S_ISLNK(statbuf
.st_mode
)) {
1744 /* Some core links return only the last element of the target path,
1745 * these are just values, the paths should not be exposed. */
1746 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1747 r
= readlink_value(path
, &value
);
1752 } else if (S_ISDIR(statbuf
.st_mode
)) {
1753 /* skip directories */
1755 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1756 /* skip non-readable files */
1761 /* read attribute value */
1762 r
= read_full_file(path
, &value
, &size
);
1766 /* drop trailing newlines */
1767 while (size
> 0 && value
[--size
] == '\n')
1771 r
= device_add_sysattr_value(device
, sysattr
, value
);
1781 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1782 _cleanup_free_
char *key
= NULL
;
1783 _cleanup_free_
char *value
= NULL
;
1788 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1793 /* set the attribute and save it in the cache. If a NULL value is passed the
1794 * attribute is cleared from the cache */
1795 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1796 _cleanup_close_
int fd
= -1;
1797 _cleanup_free_
char *value
= NULL
;
1798 const char *syspath
;
1800 struct stat statbuf
;
1801 size_t value_len
= 0;
1805 assert_return(device
, -EINVAL
);
1806 assert_return(sysattr
, -EINVAL
);
1809 device_remove_sysattr_value(device
, sysattr
);
1814 r
= sd_device_get_syspath(device
, &syspath
);
1818 path
= strjoina(syspath
, "/", sysattr
);
1819 r
= lstat(path
, &statbuf
);
1825 r
= device_add_sysattr_value(device
, sysattr
, value
);
1832 if (S_ISLNK(statbuf
.st_mode
))
1835 /* skip directories */
1836 if (S_ISDIR(statbuf
.st_mode
))
1839 /* skip non-readable files */
1840 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1843 value_len
= strlen(_value
);
1845 /* drop trailing newlines */
1846 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1847 _value
[--value_len
] = '\0';
1849 /* value length is limited to 4k */
1850 if (value_len
> 4096)
1853 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1857 value
= strdup(_value
);
1861 size
= write(fd
, value
, value_len
);
1865 if ((size_t)size
!= value_len
)
1868 r
= device_add_sysattr_value(device
, sysattr
, value
);