2 This file is part of systemd.
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
25 #include "sd-device.h"
27 #include "alloc-util.h"
28 #include "device-internal.h"
29 #include "device-private.h"
30 #include "device-util.h"
36 #include "parse-util.h"
37 #include "path-util.h"
39 #include "stat-util.h"
40 #include "string-util.h"
45 int device_new_aux(sd_device
**ret
) {
46 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
50 device
= new0(sd_device
, 1);
55 device
->watch_handle
= -1;
63 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
65 assert_se(++ device
->n_ref
>= 2);
70 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
71 if (device
&& -- device
->n_ref
== 0) {
72 sd_device_unref(device
->parent
);
73 free(device
->syspath
);
74 free(device
->sysname
);
75 free(device
->devtype
);
76 free(device
->devname
);
77 free(device
->subsystem
);
79 free(device
->id_filename
);
80 free(device
->properties_strv
);
81 free(device
->properties_nulstr
);
83 ordered_hashmap_free_free_free(device
->properties
);
84 ordered_hashmap_free_free_free(device
->properties_db
);
85 hashmap_free_free_free(device
->sysattr_values
);
86 set_free_free(device
->sysattrs
);
87 set_free_free(device
->tags
);
88 set_free_free(device
->devlinks
);
96 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
97 OrderedHashmap
**properties
;
103 properties
= &device
->properties_db
;
105 properties
= &device
->properties
;
108 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
111 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
119 value
= strdup(_value
);
123 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
125 r
= ordered_hashmap_replace(*properties
, key
, value
);
132 _cleanup_free_
char *key
= NULL
;
133 _cleanup_free_
char *value
= NULL
;
135 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
139 device
->properties_generation
++;
140 device
->properties_buf_outdated
= true;
146 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
147 return device_add_property_aux(device
, key
, value
, false);
150 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
151 _cleanup_free_
char *syspath
= NULL
;
158 /* must be a subdirectory of /sys */
159 if (!path_startswith(_syspath
, "/sys/")) {
160 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
165 r
= readlink_and_canonicalize(_syspath
, &syspath
);
167 /* the device does not exist (any more?) */
169 else if (r
== -EINVAL
) {
171 syspath
= canonicalize_file_name(_syspath
);
174 /* the device does not exist (any more?) */
177 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
180 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
184 if (path_startswith(syspath
, "/sys/devices/")) {
187 /* all 'devices' require an 'uevent' file */
188 path
= strjoina(syspath
, "/uevent");
189 r
= access(path
, F_OK
);
192 /* this is not a valid device */
195 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
199 /* everything else just just needs to be a directory */
200 if (!is_dir(syspath
, false))
204 syspath
= strdup(_syspath
);
209 devpath
= syspath
+ strlen("/sys");
211 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
215 free(device
->syspath
);
216 device
->syspath
= syspath
;
219 device
->devpath
= devpath
;
224 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
225 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
228 assert_return(ret
, -EINVAL
);
229 assert_return(syspath
, -EINVAL
);
231 r
= device_new_aux(&device
);
235 r
= device_set_syspath(device
, syspath
, true);
245 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
247 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
249 assert_return(ret
, -EINVAL
);
250 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
252 /* use /sys/dev/{block,char}/<maj>:<min> link */
253 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
255 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
257 return sd_device_new_from_syspath(ret
, syspath
);
260 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
263 assert_return(ret
, -EINVAL
);
264 assert_return(subsystem
, -EINVAL
);
265 assert_return(sysname
, -EINVAL
);
267 if (streq(subsystem
, "subsystem")) {
268 syspath
= strjoina("/sys/subsystem/", sysname
);
269 if (access(syspath
, F_OK
) >= 0)
270 return sd_device_new_from_syspath(ret
, syspath
);
272 syspath
= strjoina("/sys/bus/", sysname
);
273 if (access(syspath
, F_OK
) >= 0)
274 return sd_device_new_from_syspath(ret
, syspath
);
276 syspath
= strjoina("/sys/class/", sysname
);
277 if (access(syspath
, F_OK
) >= 0)
278 return sd_device_new_from_syspath(ret
, syspath
);
279 } else if (streq(subsystem
, "module")) {
280 syspath
= strjoina("/sys/module/", sysname
);
281 if (access(syspath
, F_OK
) >= 0)
282 return sd_device_new_from_syspath(ret
, syspath
);
283 } else if (streq(subsystem
, "drivers")) {
284 char subsys
[PATH_MAX
];
287 strscpy(subsys
, sizeof(subsys
), sysname
);
288 driver
= strchr(subsys
, ':');
293 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
294 if (access(syspath
, F_OK
) >= 0)
295 return sd_device_new_from_syspath(ret
, syspath
);
297 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
298 if (access(syspath
, F_OK
) >= 0)
299 return sd_device_new_from_syspath(ret
, syspath
);
306 /* translate sysname back to sysfs filename */
307 name
= strdupa(sysname
);
308 while (name
[len
] != '\0') {
309 if (name
[len
] == '/')
315 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
316 if (access(syspath
, F_OK
) >= 0)
317 return sd_device_new_from_syspath(ret
, syspath
);
319 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
320 if (access(syspath
, F_OK
) >= 0)
321 return sd_device_new_from_syspath(ret
, syspath
);
323 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
324 if (access(syspath
, F_OK
) >= 0)
325 return sd_device_new_from_syspath(ret
, syspath
);
331 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
332 _cleanup_free_
char *devtype
= NULL
;
338 devtype
= strdup(_devtype
);
342 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
346 free(device
->devtype
);
347 device
->devtype
= devtype
;
353 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
359 r
= parse_ifindex(_ifindex
, &ifindex
);
363 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
367 device
->ifindex
= ifindex
;
372 int device_set_devname(sd_device
*device
, const char *_devname
) {
373 _cleanup_free_
char *devname
= NULL
;
379 if (_devname
[0] != '/') {
380 r
= asprintf(&devname
, "/dev/%s", _devname
);
384 devname
= strdup(_devname
);
389 r
= device_add_property_internal(device
, "DEVNAME", devname
);
393 free(device
->devname
);
394 device
->devname
= devname
;
400 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
407 r
= safe_atou(_devmode
, &devmode
);
414 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
418 device
->devmode
= devmode
;
423 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
424 unsigned maj
= 0, min
= 0;
430 r
= safe_atou(major
, &maj
);
437 r
= safe_atou(minor
, &min
);
442 r
= device_add_property_internal(device
, "MAJOR", major
);
447 r
= device_add_property_internal(device
, "MINOR", minor
);
452 device
->devnum
= makedev(maj
, min
);
457 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
466 if (streq(key
, "DEVTYPE")) {
467 r
= device_set_devtype(device
, value
);
470 } else if (streq(key
, "IFINDEX")) {
471 r
= device_set_ifindex(device
, value
);
474 } else if (streq(key
, "DEVNAME")) {
475 r
= device_set_devname(device
, value
);
478 } else if (streq(key
, "DEVMODE")) {
479 r
= device_set_devmode(device
, value
);
482 } else if (streq(key
, "MAJOR"))
484 else if (streq(key
, "MINOR"))
487 r
= device_add_property_internal(device
, key
, value
);
495 int device_read_uevent_file(sd_device
*device
) {
496 _cleanup_free_
char *uevent
= NULL
;
497 const char *syspath
, *key
= NULL
, *value
= NULL
, *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
);
563 /* fall through to handle empty property */
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");
581 r
= device_set_devnum(device
, major
, minor
);
583 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
589 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
592 assert_return(device
, -EINVAL
);
593 assert_return(ifindex
, -EINVAL
);
595 r
= device_read_uevent_file(device
);
599 *ifindex
= device
->ifindex
;
604 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
607 assert_return(ret
, -EINVAL
);
608 assert_return(id
, -EINVAL
);
617 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
621 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
625 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
626 _cleanup_close_
int sk
= -1;
627 struct ifreq ifr
= {};
630 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
634 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
638 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
642 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
646 r
= sd_device_get_ifindex(device
, &ifindex
);
650 /* this is racey, so we might end up with the wrong device */
651 if (ifr
.ifr_ifindex
!= ifindex
)
661 char subsys
[PATH_MAX
];
664 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
665 sysname
= strchr(subsys
, ':');
672 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
679 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
680 assert_return(device
, -EINVAL
);
681 assert_return(ret
, -EINVAL
);
683 assert(path_startswith(device
->syspath
, "/sys/"));
685 *ret
= device
->syspath
;
690 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
691 _cleanup_free_
char *path
= NULL
;
692 const char *subdir
, *syspath
;
698 r
= sd_device_get_syspath(child
, &syspath
);
702 path
= strdup(syspath
);
705 subdir
= path
+ strlen("/sys");
710 pos
= strrchr(subdir
, '/');
711 if (!pos
|| pos
< subdir
+ 2)
716 r
= sd_device_new_from_syspath(ret
, path
);
726 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
728 assert_return(ret
, -EINVAL
);
729 assert_return(child
, -EINVAL
);
731 if (!child
->parent_set
) {
732 child
->parent_set
= true;
734 (void)device_new_from_child(&child
->parent
, child
);
740 *ret
= child
->parent
;
745 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
746 _cleanup_free_
char *subsystem
= NULL
;
752 subsystem
= strdup(_subsystem
);
756 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
760 free(device
->subsystem
);
761 device
->subsystem
= subsystem
;
764 device
->subsystem_set
= true;
769 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
770 assert_return(ret
, -EINVAL
);
771 assert_return(device
, -EINVAL
);
773 if (!device
->subsystem_set
) {
774 _cleanup_free_
char *subsystem
= NULL
;
779 /* read 'subsystem' link */
780 r
= sd_device_get_syspath(device
, &syspath
);
784 path
= strjoina(syspath
, "/subsystem");
785 r
= readlink_value(path
, &subsystem
);
787 r
= device_set_subsystem(device
, subsystem
);
788 /* use implicit names */
789 else if (path_startswith(device
->devpath
, "/module/"))
790 r
= device_set_subsystem(device
, "module");
791 else if (strstr(device
->devpath
, "/drivers/"))
792 r
= device_set_subsystem(device
, "drivers");
793 else if (path_startswith(device
->devpath
, "/subsystem/") ||
794 path_startswith(device
->devpath
, "/class/") ||
795 path_startswith(device
->devpath
, "/bus/"))
796 r
= device_set_subsystem(device
, "subsystem");
797 if (r
< 0 && r
!= -ENOENT
)
798 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
800 device
->subsystem_set
= true;
803 if (!device
->subsystem
)
806 *ret
= device
->subsystem
;
811 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
817 r
= device_read_uevent_file(device
);
821 *devtype
= device
->devtype
;
826 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
827 sd_device
*parent
= NULL
;
830 assert_return(child
, -EINVAL
);
831 assert_return(subsystem
, -EINVAL
);
833 r
= sd_device_get_parent(child
, &parent
);
835 const char *parent_subsystem
= NULL
;
836 const char *parent_devtype
= NULL
;
838 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
839 if (streq_ptr(parent_subsystem
, subsystem
)) {
843 (void)sd_device_get_devtype(parent
, &parent_devtype
);
844 if (streq_ptr(parent_devtype
, devtype
))
847 r
= sd_device_get_parent(parent
, &parent
);
858 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
861 assert_return(device
, -EINVAL
);
862 assert_return(devnum
, -EINVAL
);
864 r
= device_read_uevent_file(device
);
868 *devnum
= device
->devnum
;
873 int device_set_driver(sd_device
*device
, const char *_driver
) {
874 _cleanup_free_
char *driver
= NULL
;
880 driver
= strdup(_driver
);
884 r
= device_add_property_internal(device
, "DRIVER", driver
);
888 free(device
->driver
);
889 device
->driver
= driver
;
892 device
->driver_set
= true;
897 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
898 assert_return(device
, -EINVAL
);
899 assert_return(ret
, -EINVAL
);
901 if (!device
->driver_set
) {
902 _cleanup_free_
char *driver
= NULL
;
907 r
= sd_device_get_syspath(device
, &syspath
);
911 path
= strjoina(syspath
, "/driver");
912 r
= readlink_value(path
, &driver
);
914 r
= device_set_driver(device
, driver
);
916 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
917 } else if (r
== -ENOENT
)
918 device
->driver_set
= true;
920 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
926 *ret
= device
->driver
;
931 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
932 assert_return(device
, -EINVAL
);
933 assert_return(devpath
, -EINVAL
);
935 assert(device
->devpath
);
936 assert(device
->devpath
[0] == '/');
938 *devpath
= device
->devpath
;
943 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
946 assert_return(device
, -EINVAL
);
947 assert_return(devname
, -EINVAL
);
949 r
= device_read_uevent_file(device
);
953 if (!device
->devname
)
956 assert(path_startswith(device
->devname
, "/dev/"));
958 *devname
= device
->devname
;
963 static int device_set_sysname(sd_device
*device
) {
964 _cleanup_free_
char *sysname
= NULL
;
965 const char *sysnum
= NULL
;
969 pos
= strrchr(device
->devpath
, '/');
974 /* devpath is not a root directory */
975 if (*pos
== '\0' || pos
<= device
->devpath
)
978 sysname
= strdup(pos
);
982 /* some devices have '!' in their name, change that to '/' */
983 while (sysname
[len
] != '\0') {
984 if (sysname
[len
] == '!')
990 /* trailing number */
991 while (len
> 0 && isdigit(sysname
[--len
]))
992 sysnum
= &sysname
[len
];
997 free(device
->sysname
);
998 device
->sysname
= sysname
;
1001 device
->sysnum
= sysnum
;
1003 device
->sysname_set
= true;
1008 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1011 assert_return(device
, -EINVAL
);
1012 assert_return(ret
, -EINVAL
);
1014 if (!device
->sysname_set
) {
1015 r
= device_set_sysname(device
);
1020 assert_return(device
->sysname
, -ENOENT
);
1022 *ret
= device
->sysname
;
1027 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1030 assert_return(device
, -EINVAL
);
1031 assert_return(ret
, -EINVAL
);
1033 if (!device
->sysname_set
) {
1034 r
= device_set_sysname(device
);
1039 *ret
= device
->sysnum
;
1044 static bool is_valid_tag(const char *tag
) {
1047 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1050 int device_add_tag(sd_device
*device
, const char *tag
) {
1056 if (!is_valid_tag(tag
))
1059 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1063 r
= set_put_strdup(device
->tags
, tag
);
1067 device
->tags_generation
++;
1068 device
->property_tags_outdated
= true;
1073 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1079 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1083 r
= set_put_strdup(device
->devlinks
, devlink
);
1087 device
->devlinks_generation
++;
1088 device
->property_devlinks_outdated
= true;
1093 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1094 _cleanup_free_
char *key
= NULL
;
1104 value
= strchr(key
, '=');
1110 if (isempty(++value
))
1113 return device_add_property_internal(device
, key
, value
);
1116 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1117 uint64_t usec_initialized
;
1121 assert(initialized
);
1123 r
= safe_atou64(initialized
, &usec_initialized
);
1127 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1131 device
->usec_initialized
= usec_initialized
;
1136 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1145 r
= device_add_tag(device
, value
);
1151 path
= strjoina("/dev/", value
);
1152 r
= device_add_devlink(device
, path
);
1158 r
= device_add_property_internal_from_string(device
, value
);
1164 r
= device_set_usec_initialized(device
, value
);
1170 r
= safe_atoi(value
, &device
->devlink_priority
);
1176 r
= safe_atoi(value
, &device
->watch_handle
);
1182 log_debug("device db: unknown key '%c'", key
);
1188 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1192 if (!device
->id_filename
) {
1193 _cleanup_free_
char *id
= NULL
;
1194 const char *subsystem
;
1198 r
= sd_device_get_subsystem(device
, &subsystem
);
1202 r
= sd_device_get_devnum(device
, &devnum
);
1206 r
= sd_device_get_ifindex(device
, &ifindex
);
1210 if (major(devnum
) > 0) {
1213 /* use dev_t — b259:131072, c254:0 */
1214 r
= asprintf(&id
, "%c%u:%u",
1215 streq(subsystem
, "block") ? 'b' : 'c',
1216 major(devnum
), minor(devnum
));
1219 } else if (ifindex
> 0) {
1220 /* use netdev ifindex — n3 */
1221 r
= asprintf(&id
, "n%u", ifindex
);
1225 /* use $subsys:$sysname — pci:0000:00:1f.2
1226 * sysname() has '!' translated, get it from devpath
1228 const char *sysname
;
1230 sysname
= basename(device
->devpath
);
1237 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1242 device
->id_filename
= id
;
1246 *ret
= device
->id_filename
;
1251 int device_read_db_aux(sd_device
*device
, bool force
) {
1252 _cleanup_free_
char *db
= NULL
;
1254 const char *id
, *value
;
1268 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1271 device
->db_loaded
= true;
1273 r
= device_get_id_filename(device
, &id
);
1277 path
= strjoina("/run/udev/data/", id
);
1279 r
= read_full_file(path
, &db
, &db_len
);
1284 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1287 /* devices with a database entry are initialized */
1288 device
->is_initialized
= true;
1290 for (i
= 0; i
< db_len
; i
++) {
1293 if (!strchr(NEWLINE
, db
[i
])) {
1302 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1304 state
= INVALID_LINE
;
1319 if (strchr(NEWLINE
, db
[i
]))
1324 if (strchr(NEWLINE
, db
[i
])) {
1326 r
= handle_db_line(device
, key
, value
);
1328 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1335 assert_not_reached("invalid state when parsing db");
1342 static int device_read_db(sd_device
*device
) {
1343 return device_read_db_aux(device
, false);
1346 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1349 assert_return(device
, -EINVAL
);
1350 assert_return(initialized
, -EINVAL
);
1352 r
= device_read_db(device
);
1356 *initialized
= device
->is_initialized
;
1361 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1365 assert_return(device
, -EINVAL
);
1366 assert_return(usec
, -EINVAL
);
1368 r
= device_read_db(device
);
1372 if (!device
->is_initialized
)
1375 if (!device
->usec_initialized
)
1378 now_ts
= now(clock_boottime_or_monotonic());
1380 if (now_ts
< device
->usec_initialized
)
1383 *usec
= now_ts
- device
->usec_initialized
;
1388 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1391 assert_return(device
, NULL
);
1393 (void) device_read_db(device
);
1395 device
->tags_iterator_generation
= device
->tags_generation
;
1396 device
->tags_iterator
= ITERATOR_FIRST
;
1398 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1402 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1405 assert_return(device
, NULL
);
1407 (void) device_read_db(device
);
1409 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1412 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1416 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1419 assert_return(device
, NULL
);
1421 (void) device_read_db(device
);
1423 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1424 device
->devlinks_iterator
= ITERATOR_FIRST
;
1426 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1430 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1433 assert_return(device
, NULL
);
1435 (void) device_read_db(device
);
1437 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1440 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1444 static int device_properties_prepare(sd_device
*device
) {
1449 r
= device_read_uevent_file(device
);
1453 r
= device_read_db(device
);
1457 if (device
->property_devlinks_outdated
) {
1458 _cleanup_free_
char *devlinks
= NULL
;
1459 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1460 const char *devlink
;
1462 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1465 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1467 if (devlinks_len
> 0)
1468 stpcpy(devlinks
+ devlinks_len
++, " ");
1469 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1470 devlinks_len
= e
- devlinks
;
1473 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1477 device
->property_devlinks_outdated
= false;
1480 if (device
->property_tags_outdated
) {
1481 _cleanup_free_
char *tags
= NULL
;
1482 size_t tags_allocated
= 0, tags_len
= 0;
1485 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1490 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1493 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1495 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1496 tags_len
= e
- tags
;
1499 r
= device_add_property_internal(device
, "TAGS", tags
);
1503 device
->property_tags_outdated
= false;
1509 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1514 assert_return(device
, NULL
);
1516 r
= device_properties_prepare(device
);
1520 device
->properties_iterator_generation
= device
->properties_generation
;
1521 device
->properties_iterator
= ITERATOR_FIRST
;
1523 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1531 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1536 assert_return(device
, NULL
);
1538 r
= device_properties_prepare(device
);
1542 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1545 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1553 static int device_sysattrs_read_all(sd_device
*device
) {
1554 _cleanup_closedir_
DIR *dir
= NULL
;
1555 const char *syspath
;
1556 struct dirent
*dent
;
1561 if (device
->sysattrs_read
)
1564 r
= sd_device_get_syspath(device
, &syspath
);
1568 dir
= opendir(syspath
);
1572 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1576 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1578 struct stat statbuf
;
1580 /* only handle symlinks and regular files */
1581 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1584 path
= strjoina(syspath
, "/", dent
->d_name
);
1586 if (lstat(path
, &statbuf
) != 0)
1589 if (!(statbuf
.st_mode
& S_IRUSR
))
1592 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1597 device
->sysattrs_read
= true;
1602 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1606 assert_return(device
, NULL
);
1608 if (!device
->sysattrs_read
) {
1609 r
= device_sysattrs_read_all(device
);
1616 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1618 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1622 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1625 assert_return(device
, NULL
);
1627 if (!device
->sysattrs_read
)
1630 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1634 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1635 assert_return(device
, -EINVAL
);
1636 assert_return(tag
, -EINVAL
);
1638 (void) device_read_db(device
);
1640 return !!set_contains(device
->tags
, tag
);
1643 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1647 assert_return(device
, -EINVAL
);
1648 assert_return(key
, -EINVAL
);
1649 assert_return(_value
, -EINVAL
);
1651 r
= device_properties_prepare(device
);
1655 value
= ordered_hashmap_get(device
->properties
, key
);
1664 /* replaces the value if it already exists */
1665 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1666 _cleanup_free_
char *key
= NULL
;
1667 _cleanup_free_
char *value_old
= NULL
;
1673 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1677 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1684 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1693 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1694 const char *key
= NULL
, *value
;
1699 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1709 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1710 * with a NULL value in the cache, otherwise the returned string is stored */
1711 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1712 _cleanup_free_
char *value
= NULL
;
1713 const char *syspath
, *cached_value
= NULL
;
1715 struct stat statbuf
;
1718 assert_return(device
, -EINVAL
);
1719 assert_return(sysattr
, -EINVAL
);
1721 /* look for possibly already cached result */
1722 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1728 /* we looked up the sysattr before and it did not exist */
1732 *_value
= cached_value
;
1737 r
= sd_device_get_syspath(device
, &syspath
);
1741 path
= strjoina(syspath
, "/", sysattr
);
1742 r
= lstat(path
, &statbuf
);
1744 /* remember that we could not access the sysattr */
1745 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1750 } else if (S_ISLNK(statbuf
.st_mode
)) {
1751 /* Some core links return only the last element of the target path,
1752 * these are just values, the paths should not be exposed. */
1753 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1754 r
= readlink_value(path
, &value
);
1759 } else if (S_ISDIR(statbuf
.st_mode
)) {
1760 /* skip directories */
1762 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1763 /* skip non-readable files */
1768 /* read attribute value */
1769 r
= read_full_file(path
, &value
, &size
);
1773 /* drop trailing newlines */
1774 while (size
> 0 && value
[--size
] == '\n')
1778 r
= device_add_sysattr_value(device
, sysattr
, value
);
1788 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1789 _cleanup_free_
char *key
= NULL
;
1790 _cleanup_free_
char *value
= NULL
;
1795 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1800 /* set the attribute and save it in the cache. If a NULL value is passed the
1801 * attribute is cleared from the cache */
1802 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1803 _cleanup_close_
int fd
= -1;
1804 _cleanup_free_
char *value
= NULL
;
1805 const char *syspath
;
1807 struct stat statbuf
;
1808 size_t value_len
= 0;
1812 assert_return(device
, -EINVAL
);
1813 assert_return(sysattr
, -EINVAL
);
1816 device_remove_sysattr_value(device
, sysattr
);
1821 r
= sd_device_get_syspath(device
, &syspath
);
1825 path
= strjoina(syspath
, "/", sysattr
);
1826 r
= lstat(path
, &statbuf
);
1832 r
= device_add_sysattr_value(device
, sysattr
, value
);
1839 if (S_ISLNK(statbuf
.st_mode
))
1842 /* skip directories */
1843 if (S_ISDIR(statbuf
.st_mode
))
1846 /* skip non-readable files */
1847 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1850 value_len
= strlen(_value
);
1852 /* drop trailing newlines */
1853 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1854 _value
[--value_len
] = '\0';
1856 /* value length is limited to 4k */
1857 if (value_len
> 4096)
1860 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1864 value
= strdup(_value
);
1868 size
= write(fd
, value
, value_len
);
1872 if ((size_t)size
!= value_len
)
1875 r
= device_add_sysattr_value(device
, sysattr
, value
);