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("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
);
298 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", sysname
);
299 if (access(syspath
, F_OK
) >= 0)
300 return sd_device_new_from_syspath(ret
, syspath
);
302 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", sysname
);
303 if (access(syspath
, F_OK
) >= 0)
304 return sd_device_new_from_syspath(ret
, syspath
);
306 syspath
= strjoina("/sys/class/", subsystem
, "/", sysname
);
307 if (access(syspath
, F_OK
) >= 0)
308 return sd_device_new_from_syspath(ret
, syspath
);
314 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
315 _cleanup_free_
char *devtype
= NULL
;
321 devtype
= strdup(_devtype
);
325 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
329 free(device
->devtype
);
330 device
->devtype
= devtype
;
336 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
342 r
= safe_atoi(_ifindex
, &ifindex
);
349 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
353 device
->ifindex
= ifindex
;
358 int device_set_devname(sd_device
*device
, const char *_devname
) {
359 _cleanup_free_
char *devname
= NULL
;
365 if (_devname
[0] != '/') {
366 r
= asprintf(&devname
, "/dev/%s", _devname
);
370 devname
= strdup(_devname
);
375 r
= device_add_property_internal(device
, "DEVNAME", devname
);
379 free(device
->devname
);
380 device
->devname
= devname
;
386 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
393 r
= safe_atou(_devmode
, &devmode
);
400 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
404 device
->devmode
= devmode
;
409 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
410 unsigned maj
= 0, min
= 0;
416 r
= safe_atou(major
, &maj
);
423 r
= safe_atou(minor
, &min
);
428 r
= device_add_property_internal(device
, "MAJOR", major
);
433 r
= device_add_property_internal(device
, "MINOR", minor
);
438 device
->devnum
= makedev(maj
, min
);
443 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
452 if (streq(key
, "DEVTYPE")) {
453 r
= device_set_devtype(device
, value
);
456 } else if (streq(key
, "IFINDEX")) {
457 r
= device_set_ifindex(device
, value
);
460 } else if (streq(key
, "DEVNAME")) {
461 r
= device_set_devname(device
, value
);
464 } else if (streq(key
, "DEVMODE")) {
465 r
= device_set_devmode(device
, value
);
468 } else if (streq(key
, "MAJOR"))
470 else if (streq(key
, "MINOR"))
473 r
= device_add_property_internal(device
, key
, value
);
481 int device_read_uevent_file(sd_device
*device
) {
482 _cleanup_free_
char *uevent
= NULL
;
483 const char *syspath
, *key
, *value
, *major
= NULL
, *minor
= NULL
;
499 if (device
->uevent_loaded
|| device
->sealed
)
502 device
->uevent_loaded
= true;
504 r
= sd_device_get_syspath(device
, &syspath
);
508 path
= strjoina(syspath
, "/uevent");
510 r
= read_full_file(path
, &uevent
, &uevent_len
);
512 /* empty uevent files may be write-only */
514 else if (r
== -ENOENT
)
515 /* some devices may not have uevent files, see set_syspath() */
518 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
522 for (i
= 0; i
< uevent_len
; i
++) {
525 if (!strchr(NEWLINE
, uevent
[i
])) {
533 if (uevent
[i
] == '=') {
537 } else if (strchr(NEWLINE
, uevent
[i
])) {
539 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
552 if (strchr(NEWLINE
, uevent
[i
])) {
555 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
557 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %s", key
, value
);
564 assert_not_reached("invalid state when parsing uevent file");
569 r
= device_set_devnum(device
, major
, minor
);
571 log_debug_errno("sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
577 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
580 assert_return(device
, -EINVAL
);
581 assert_return(ifindex
, -EINVAL
);
583 r
= device_read_uevent_file(device
);
587 *ifindex
= device
->ifindex
;
592 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
595 assert_return(ret
, -EINVAL
);
596 assert_return(id
, -EINVAL
);
605 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
609 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
613 _cleanup_device_unref_ sd_device
*device
= NULL
;
614 _cleanup_close_
int sk
= -1;
615 struct ifreq ifr
= {};
618 r
= safe_atoi(&id
[1], &ifr
.ifr_ifindex
);
621 else if (ifr
.ifr_ifindex
<= 0)
624 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
628 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
632 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
636 r
= sd_device_get_ifindex(device
, &ifindex
);
640 /* this is racey, so we might end up with the wrong device */
641 if (ifr
.ifr_ifindex
!= ifindex
)
651 char subsys
[PATH_MAX
];
654 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
655 sysname
= strchr(subsys
, ':');
662 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
669 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
670 assert_return(device
, -EINVAL
);
671 assert_return(ret
, -EINVAL
);
673 assert(path_startswith(device
->syspath
, "/sys/"));
675 *ret
= device
->syspath
;
680 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
681 _cleanup_free_
char *path
= NULL
;
682 const char *subdir
, *syspath
;
688 r
= sd_device_get_syspath(child
, &syspath
);
692 path
= strdup(syspath
);
695 subdir
= path
+ strlen("/sys");
700 pos
= strrchr(subdir
, '/');
701 if (!pos
|| pos
< subdir
+ 2)
706 r
= sd_device_new_from_syspath(ret
, path
);
716 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
718 assert_return(ret
, -EINVAL
);
719 assert_return(child
, -EINVAL
);
721 if (!child
->parent_set
) {
722 child
->parent_set
= true;
724 (void)device_new_from_child(&child
->parent
, child
);
730 *ret
= child
->parent
;
735 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
736 _cleanup_free_
char *subsystem
= NULL
;
742 subsystem
= strdup(_subsystem
);
746 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
750 free(device
->subsystem
);
751 device
->subsystem
= subsystem
;
754 device
->subsystem_set
= true;
759 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
760 assert_return(ret
, -EINVAL
);
761 assert_return(device
, -EINVAL
);
763 if (!device
->subsystem_set
) {
764 _cleanup_free_
char *subsystem
= NULL
;
769 /* read 'subsystem' link */
770 r
= sd_device_get_syspath(device
, &syspath
);
774 path
= strjoina(syspath
, "/subsystem");
775 r
= readlink_value(path
, &subsystem
);
777 r
= device_set_subsystem(device
, subsystem
);
778 /* use implicit names */
779 else if (path_startswith(device
->devpath
, "/module/"))
780 r
= device_set_subsystem(device
, "module");
781 else if (strstr(device
->devpath
, "/drivers/"))
782 r
= device_set_subsystem(device
, "drivers");
783 else if (path_startswith(device
->devpath
, "/subsystem/") ||
784 path_startswith(device
->devpath
, "/class/") ||
785 path_startswith(device
->devpath
, "/bus/"))
786 r
= device_set_subsystem(device
, "subsystem");
787 if (r
< 0 && r
!= -ENOENT
)
788 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
790 device
->subsystem_set
= true;
793 if (!device
->subsystem
)
796 *ret
= device
->subsystem
;
801 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
807 r
= device_read_uevent_file(device
);
811 *devtype
= device
->devtype
;
816 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
817 sd_device
*parent
= NULL
;
820 assert_return(child
, -EINVAL
);
821 assert_return(subsystem
, -EINVAL
);
823 r
= sd_device_get_parent(child
, &parent
);
825 const char *parent_subsystem
= NULL
;
826 const char *parent_devtype
= NULL
;
828 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
829 if (streq_ptr(parent_subsystem
, subsystem
)) {
833 (void)sd_device_get_devtype(parent
, &parent_devtype
);
834 if (streq_ptr(parent_devtype
, devtype
))
837 r
= sd_device_get_parent(parent
, &parent
);
848 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
851 assert_return(device
, -EINVAL
);
852 assert_return(devnum
, -EINVAL
);
854 r
= device_read_uevent_file(device
);
858 *devnum
= device
->devnum
;
863 int device_set_driver(sd_device
*device
, const char *_driver
) {
864 _cleanup_free_
char *driver
= NULL
;
870 driver
= strdup(_driver
);
874 r
= device_add_property_internal(device
, "DRIVER", driver
);
878 free(device
->driver
);
879 device
->driver
= driver
;
882 device
->driver_set
= true;
887 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
888 assert_return(device
, -EINVAL
);
889 assert_return(ret
, -EINVAL
);
891 if (!device
->driver_set
) {
892 _cleanup_free_
char *driver
= NULL
;
897 r
= sd_device_get_syspath(device
, &syspath
);
901 path
= strjoina(syspath
, "/driver");
902 r
= readlink_value(path
, &driver
);
904 r
= device_set_driver(device
, driver
);
906 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
907 } else if (r
== -ENOENT
)
908 device
->driver_set
= true;
910 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
916 *ret
= device
->driver
;
921 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
922 assert_return(device
, -EINVAL
);
923 assert_return(devpath
, -EINVAL
);
925 assert(device
->devpath
);
926 assert(device
->devpath
[0] == '/');
928 *devpath
= device
->devpath
;
933 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
936 assert_return(device
, -EINVAL
);
937 assert_return(devname
, -EINVAL
);
939 r
= device_read_uevent_file(device
);
943 if (!device
->devname
)
946 assert(path_startswith(device
->devname
, "/dev/"));
948 *devname
= device
->devname
;
953 static int device_set_sysname(sd_device
*device
) {
954 _cleanup_free_
char *sysname
= NULL
;
955 const char *sysnum
= NULL
;
959 pos
= strrchr(device
->devpath
, '/');
964 /* devpath is not a root directory */
965 if (*pos
== '\0' || pos
<= device
->devpath
)
968 sysname
= strdup(pos
);
972 /* some devices have '!' in their name, change that to '/' */
973 while (sysname
[len
] != '\0') {
974 if (sysname
[len
] == '!')
980 /* trailing number */
981 while (len
> 0 && isdigit(sysname
[--len
]))
982 sysnum
= &sysname
[len
];
987 free(device
->sysname
);
988 device
->sysname
= sysname
;
991 device
->sysnum
= sysnum
;
993 device
->sysname_set
= true;
998 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1001 assert_return(device
, -EINVAL
);
1002 assert_return(ret
, -EINVAL
);
1004 if (!device
->sysname_set
) {
1005 r
= device_set_sysname(device
);
1010 assert_return(device
->sysname
, -ENOENT
);
1012 *ret
= device
->sysname
;
1017 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1020 assert_return(device
, -EINVAL
);
1021 assert_return(ret
, -EINVAL
);
1023 if (!device
->sysname_set
) {
1024 r
= device_set_sysname(device
);
1029 *ret
= device
->sysnum
;
1034 static bool is_valid_tag(const char *tag
) {
1037 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1040 int device_add_tag(sd_device
*device
, const char *tag
) {
1046 if (!is_valid_tag(tag
))
1049 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1053 r
= set_put_strdup(device
->tags
, tag
);
1057 device
->tags_generation
++;
1058 device
->property_tags_outdated
= true;
1063 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1069 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1073 r
= set_put_strdup(device
->devlinks
, devlink
);
1077 device
->devlinks_generation
++;
1078 device
->property_devlinks_outdated
= true;
1083 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1084 _cleanup_free_
char *key
= NULL
;
1094 value
= strchr(key
, '=');
1100 if (isempty(++value
))
1103 return device_add_property_internal(device
, key
, value
);
1106 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1107 uint64_t usec_initialized
;
1111 assert(initialized
);
1113 r
= safe_atou64(initialized
, &usec_initialized
);
1117 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1121 device
->usec_initialized
= usec_initialized
;
1126 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1135 r
= device_add_tag(device
, value
);
1141 path
= strjoina("/dev/", value
);
1142 r
= device_add_devlink(device
, path
);
1148 r
= device_add_property_internal_from_string(device
, value
);
1154 r
= device_set_usec_initialized(device
, value
);
1160 r
= safe_atoi(value
, &device
->devlink_priority
);
1166 r
= safe_atoi(value
, &device
->watch_handle
);
1172 log_debug("device db: unknown key '%c'", key
);
1178 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1182 if (!device
->id_filename
) {
1183 _cleanup_free_
char *id
= NULL
;
1184 const char *subsystem
;
1188 r
= sd_device_get_subsystem(device
, &subsystem
);
1192 r
= sd_device_get_devnum(device
, &devnum
);
1196 r
= sd_device_get_ifindex(device
, &ifindex
);
1200 if (major(devnum
) > 0) {
1203 /* use dev_t -- b259:131072, c254:0 */
1204 r
= asprintf(&id
, "%c%u:%u",
1205 streq(subsystem
, "block") ? 'b' : 'c',
1206 major(devnum
), minor(devnum
));
1209 } else if (ifindex
> 0) {
1210 /* use netdev ifindex -- n3 */
1211 r
= asprintf(&id
, "n%u", ifindex
);
1215 /* use $subsys:$sysname -- pci:0000:00:1f.2
1216 * sysname() has '!' translated, get it from devpath
1218 const char *sysname
;
1220 sysname
= basename(device
->devpath
);
1227 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1232 device
->id_filename
= id
;
1236 *ret
= device
->id_filename
;
1241 int device_read_db_aux(sd_device
*device
, bool force
) {
1242 _cleanup_free_
char *db
= NULL
;
1244 const char *id
, *value
;
1258 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1261 device
->db_loaded
= true;
1263 r
= device_get_id_filename(device
, &id
);
1267 path
= strjoina("/run/udev/data/", id
);
1269 r
= read_full_file(path
, &db
, &db_len
);
1274 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1277 /* devices with a database entry are initialized */
1278 device
->is_initialized
= true;
1280 for (i
= 0; i
< db_len
; i
++) {
1283 if (!strchr(NEWLINE
, db
[i
])) {
1292 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1294 state
= INVALID_LINE
;
1309 if (strchr(NEWLINE
, db
[i
]))
1314 if (strchr(NEWLINE
, db
[i
])) {
1316 r
= handle_db_line(device
, key
, value
);
1318 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %s", key
, value
);
1325 assert_not_reached("invalid state when parsing db");
1332 static int device_read_db(sd_device
*device
) {
1333 return device_read_db_aux(device
, false);
1336 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1339 assert_return(device
, -EINVAL
);
1340 assert_return(initialized
, -EINVAL
);
1342 r
= device_read_db(device
);
1346 *initialized
= device
->is_initialized
;
1351 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1355 assert_return(device
, -EINVAL
);
1356 assert_return(usec
, -EINVAL
);
1358 r
= device_read_db(device
);
1362 if (!device
->is_initialized
)
1365 if (!device
->usec_initialized
)
1368 now_ts
= now(clock_boottime_or_monotonic());
1370 if (now_ts
< device
->usec_initialized
)
1373 *usec
= now_ts
- device
->usec_initialized
;
1378 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1381 assert_return(device
, NULL
);
1383 (void) device_read_db(device
);
1385 device
->tags_iterator_generation
= device
->tags_generation
;
1386 device
->tags_iterator
= ITERATOR_FIRST
;
1388 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1392 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1395 assert_return(device
, NULL
);
1397 (void) device_read_db(device
);
1399 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1402 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1406 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1409 assert_return(device
, NULL
);
1411 (void) device_read_db(device
);
1413 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1414 device
->devlinks_iterator
= ITERATOR_FIRST
;
1416 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1420 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1423 assert_return(device
, NULL
);
1425 (void) device_read_db(device
);
1427 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1430 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1434 static int device_properties_prepare(sd_device
*device
) {
1439 r
= device_read_uevent_file(device
);
1443 r
= device_read_db(device
);
1447 if (device
->property_devlinks_outdated
) {
1448 char *devlinks
= NULL
;
1449 const char *devlink
;
1451 devlink
= sd_device_get_devlink_first(device
);
1453 devlinks
= strdupa(devlink
);
1455 while ((devlink
= sd_device_get_devlink_next(device
)))
1456 devlinks
= strjoina(devlinks
, " ", devlink
);
1458 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1462 device
->property_devlinks_outdated
= false;
1465 if (device
->property_tags_outdated
) {
1469 tag
= sd_device_get_tag_first(device
);
1471 tags
= strjoina(":", tag
);
1473 while ((tag
= sd_device_get_tag_next(device
)))
1474 tags
= strjoina(tags
, ":", tag
);
1476 tags
= strjoina(tags
, ":");
1478 r
= device_add_property_internal(device
, "TAGS", tags
);
1482 device
->property_tags_outdated
= false;
1488 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1493 assert_return(device
, NULL
);
1495 r
= device_properties_prepare(device
);
1499 device
->properties_iterator_generation
= device
->properties_generation
;
1500 device
->properties_iterator
= ITERATOR_FIRST
;
1502 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1510 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1515 assert_return(device
, NULL
);
1517 r
= device_properties_prepare(device
);
1521 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1524 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1532 static int device_sysattrs_read_all(sd_device
*device
) {
1533 _cleanup_closedir_
DIR *dir
= NULL
;
1534 const char *syspath
;
1535 struct dirent
*dent
;
1540 if (device
->sysattrs_read
)
1543 r
= sd_device_get_syspath(device
, &syspath
);
1547 dir
= opendir(syspath
);
1551 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1555 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1557 struct stat statbuf
;
1559 /* only handle symlinks and regular files */
1560 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1563 path
= strjoina(syspath
, "/", dent
->d_name
);
1565 if (lstat(path
, &statbuf
) != 0)
1568 if (!(statbuf
.st_mode
& S_IRUSR
))
1571 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1576 device
->sysattrs_read
= true;
1581 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1585 assert_return(device
, NULL
);
1587 if (!device
->sysattrs_read
) {
1588 r
= device_sysattrs_read_all(device
);
1595 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1597 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1601 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1604 assert_return(device
, NULL
);
1606 if (!device
->sysattrs_read
)
1609 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1613 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1614 assert_return(device
, -EINVAL
);
1615 assert_return(tag
, -EINVAL
);
1617 (void) device_read_db(device
);
1619 return !!set_contains(device
->tags
, tag
);
1622 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1626 assert_return(device
, -EINVAL
);
1627 assert_return(key
, -EINVAL
);
1628 assert_return(_value
, -EINVAL
);
1630 r
= device_properties_prepare(device
);
1634 value
= ordered_hashmap_get(device
->properties
, key
);
1643 /* replaces the value if it already exists */
1644 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1645 _cleanup_free_
char *key
= NULL
;
1646 _cleanup_free_
char *value_old
= NULL
;
1652 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1656 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1663 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1672 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1673 const char *key
= NULL
, *value
;
1678 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1688 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1689 * with a NULL value in the cache, otherwise the returned string is stored */
1690 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1691 _cleanup_free_
char *value
= NULL
;
1692 const char *syspath
, *cached_value
= NULL
;
1694 struct stat statbuf
;
1697 assert_return(device
, -EINVAL
);
1698 assert_return(sysattr
, -EINVAL
);
1700 /* look for possibly already cached result */
1701 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1707 /* we looked up the sysattr before and it did not exist */
1711 *_value
= cached_value
;
1716 r
= sd_device_get_syspath(device
, &syspath
);
1720 path
= strjoina(syspath
, "/", sysattr
);
1721 r
= lstat(path
, &statbuf
);
1723 /* remember that we could not access the sysattr */
1724 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1729 } else if (S_ISLNK(statbuf
.st_mode
)) {
1730 /* Some core links return only the last element of the target path,
1731 * these are just values, the paths should not be exposed. */
1732 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1733 r
= readlink_value(path
, &value
);
1738 } else if (S_ISDIR(statbuf
.st_mode
)) {
1739 /* skip directories */
1741 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1742 /* skip non-readable files */
1747 /* read attribute value */
1748 r
= read_full_file(path
, &value
, &size
);
1752 /* drop trailing newlines */
1753 while (size
> 0 && value
[--size
] == '\n')
1757 r
= device_add_sysattr_value(device
, sysattr
, value
);
1767 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1768 _cleanup_free_
char *key
= NULL
;
1769 _cleanup_free_
char *value
= NULL
;
1774 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1779 /* set the attribute and save it in the cache. If a NULL value is passed the
1780 * attribute is cleared from the cache */
1781 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1782 _cleanup_close_
int fd
= -1;
1783 _cleanup_free_
char *value
= NULL
;
1784 const char *syspath
;
1786 struct stat statbuf
;
1787 size_t value_len
= 0;
1791 assert_return(device
, -EINVAL
);
1792 assert_return(sysattr
, -EINVAL
);
1795 device_remove_sysattr_value(device
, sysattr
);
1800 r
= sd_device_get_syspath(device
, &syspath
);
1804 path
= strjoina(syspath
, "/", sysattr
);
1805 r
= lstat(path
, &statbuf
);
1811 r
= device_add_sysattr_value(device
, sysattr
, value
);
1818 if (S_ISLNK(statbuf
.st_mode
))
1821 /* skip directories */
1822 if (S_ISDIR(statbuf
.st_mode
))
1825 /* skip non-readable files */
1826 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1829 value_len
= strlen(_value
);
1831 /* drop trailing newlines */
1832 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1833 _value
[--value_len
] = '\0';
1835 /* value length is limited to 4k */
1836 if (value_len
> 4096)
1839 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1843 value
= strdup(_value
);
1847 size
= write(fd
, value
, value_len
);
1851 if ((size_t)size
!= value_len
)
1854 r
= device_add_sysattr_value(device
, sysattr
, value
);