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
);
78 free(device
->driver_subsystem
);
80 free(device
->id_filename
);
81 free(device
->properties_strv
);
82 free(device
->properties_nulstr
);
84 ordered_hashmap_free_free_free(device
->properties
);
85 ordered_hashmap_free_free_free(device
->properties_db
);
86 hashmap_free_free_free(device
->sysattr_values
);
87 set_free_free(device
->sysattrs
);
88 set_free_free(device
->tags
);
89 set_free_free(device
->devlinks
);
97 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
98 OrderedHashmap
**properties
;
104 properties
= &device
->properties_db
;
106 properties
= &device
->properties
;
109 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
112 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
120 value
= strdup(_value
);
124 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
126 r
= ordered_hashmap_replace(*properties
, key
, value
);
133 _cleanup_free_
char *key
= NULL
;
134 _cleanup_free_
char *value
= NULL
;
136 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
140 device
->properties_generation
++;
141 device
->properties_buf_outdated
= true;
147 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
148 return device_add_property_aux(device
, key
, value
, false);
151 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
152 _cleanup_free_
char *syspath
= NULL
;
159 /* must be a subdirectory of /sys */
160 if (!path_startswith(_syspath
, "/sys/")) {
161 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
166 r
= readlink_and_canonicalize(_syspath
, &syspath
);
168 /* the device does not exist (any more?) */
170 else if (r
== -EINVAL
) {
172 syspath
= canonicalize_file_name(_syspath
);
175 /* the device does not exist (any more?) */
178 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
181 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
185 if (path_startswith(syspath
, "/sys/devices/")) {
188 /* all 'devices' require an 'uevent' file */
189 path
= strjoina(syspath
, "/uevent");
190 r
= access(path
, F_OK
);
193 /* this is not a valid device */
196 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
200 /* everything else just needs to be a directory */
201 if (!is_dir(syspath
, false))
205 syspath
= strdup(_syspath
);
210 devpath
= syspath
+ strlen("/sys");
212 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
216 free(device
->syspath
);
217 device
->syspath
= syspath
;
220 device
->devpath
= devpath
;
225 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
226 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
229 assert_return(ret
, -EINVAL
);
230 assert_return(syspath
, -EINVAL
);
232 r
= device_new_aux(&device
);
236 r
= device_set_syspath(device
, syspath
, true);
246 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
248 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
250 assert_return(ret
, -EINVAL
);
251 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
253 /* use /sys/dev/{block,char}/<maj>:<min> link */
254 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
256 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
258 return sd_device_new_from_syspath(ret
, syspath
);
261 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
262 char *name
, *syspath
;
265 assert_return(ret
, -EINVAL
);
266 assert_return(subsystem
, -EINVAL
);
267 assert_return(sysname
, -EINVAL
);
269 if (streq(subsystem
, "subsystem")) {
270 syspath
= strjoina("/sys/subsystem/", sysname
);
271 if (access(syspath
, F_OK
) >= 0)
272 return sd_device_new_from_syspath(ret
, syspath
);
274 syspath
= strjoina("/sys/bus/", sysname
);
275 if (access(syspath
, F_OK
) >= 0)
276 return sd_device_new_from_syspath(ret
, syspath
);
278 syspath
= strjoina("/sys/class/", sysname
);
279 if (access(syspath
, F_OK
) >= 0)
280 return sd_device_new_from_syspath(ret
, syspath
);
281 } else if (streq(subsystem
, "module")) {
282 syspath
= strjoina("/sys/module/", sysname
);
283 if (access(syspath
, F_OK
) >= 0)
284 return sd_device_new_from_syspath(ret
, syspath
);
285 } else if (streq(subsystem
, "drivers")) {
286 char subsys
[PATH_MAX
];
289 strscpy(subsys
, sizeof(subsys
), sysname
);
290 driver
= strchr(subsys
, ':');
295 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
296 if (access(syspath
, F_OK
) >= 0)
297 return sd_device_new_from_syspath(ret
, syspath
);
299 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
300 if (access(syspath
, F_OK
) >= 0)
301 return sd_device_new_from_syspath(ret
, syspath
);
305 /* translate sysname back to sysfs filename */
306 name
= strdupa(sysname
);
307 while (name
[len
] != '\0') {
308 if (name
[len
] == '/')
314 syspath
= strjoina("/sys/subsystem/", subsystem
, "/devices/", name
);
315 if (access(syspath
, F_OK
) >= 0)
316 return sd_device_new_from_syspath(ret
, syspath
);
318 syspath
= strjoina("/sys/bus/", subsystem
, "/devices/", name
);
319 if (access(syspath
, F_OK
) >= 0)
320 return sd_device_new_from_syspath(ret
, syspath
);
322 syspath
= strjoina("/sys/class/", subsystem
, "/", name
);
323 if (access(syspath
, F_OK
) >= 0)
324 return sd_device_new_from_syspath(ret
, syspath
);
329 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
330 _cleanup_free_
char *devtype
= NULL
;
336 devtype
= strdup(_devtype
);
340 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
344 free(device
->devtype
);
345 device
->devtype
= devtype
;
351 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
357 r
= parse_ifindex(_ifindex
, &ifindex
);
361 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
365 device
->ifindex
= ifindex
;
370 int device_set_devname(sd_device
*device
, const char *_devname
) {
371 _cleanup_free_
char *devname
= NULL
;
377 if (_devname
[0] != '/') {
378 r
= asprintf(&devname
, "/dev/%s", _devname
);
382 devname
= strdup(_devname
);
387 r
= device_add_property_internal(device
, "DEVNAME", devname
);
391 free(device
->devname
);
392 device
->devname
= devname
;
398 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
405 r
= safe_atou(_devmode
, &devmode
);
412 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
416 device
->devmode
= devmode
;
421 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
422 unsigned maj
= 0, min
= 0;
428 r
= safe_atou(major
, &maj
);
435 r
= safe_atou(minor
, &min
);
440 r
= device_add_property_internal(device
, "MAJOR", major
);
445 r
= device_add_property_internal(device
, "MINOR", minor
);
450 device
->devnum
= makedev(maj
, min
);
455 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
464 if (streq(key
, "DEVTYPE")) {
465 r
= device_set_devtype(device
, value
);
468 } else if (streq(key
, "IFINDEX")) {
469 r
= device_set_ifindex(device
, value
);
472 } else if (streq(key
, "DEVNAME")) {
473 r
= device_set_devname(device
, value
);
476 } else if (streq(key
, "DEVMODE")) {
477 r
= device_set_devmode(device
, value
);
480 } else if (streq(key
, "MAJOR"))
482 else if (streq(key
, "MINOR"))
485 r
= device_add_property_internal(device
, key
, value
);
493 int device_read_uevent_file(sd_device
*device
) {
494 _cleanup_free_
char *uevent
= NULL
;
495 const char *syspath
, *key
= NULL
, *value
= NULL
, *major
= NULL
, *minor
= NULL
;
511 if (device
->uevent_loaded
|| device
->sealed
)
514 device
->uevent_loaded
= true;
516 r
= sd_device_get_syspath(device
, &syspath
);
520 path
= strjoina(syspath
, "/uevent");
522 r
= read_full_file(path
, &uevent
, &uevent_len
);
524 /* empty uevent files may be write-only */
526 else if (r
== -ENOENT
)
527 /* some devices may not have uevent files, see set_syspath() */
530 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
534 for (i
= 0; i
< uevent_len
; i
++)
537 if (!strchr(NEWLINE
, uevent
[i
])) {
545 if (uevent
[i
] == '=') {
549 } else if (strchr(NEWLINE
, uevent
[i
])) {
551 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
561 /* fall through to handle empty property */
563 if (strchr(NEWLINE
, uevent
[i
])) {
566 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
568 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
575 assert_not_reached("invalid state when parsing uevent file");
579 r
= device_set_devnum(device
, major
, minor
);
581 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
587 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
590 assert_return(device
, -EINVAL
);
591 assert_return(ifindex
, -EINVAL
);
593 r
= device_read_uevent_file(device
);
597 *ifindex
= device
->ifindex
;
602 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
605 assert_return(ret
, -EINVAL
);
606 assert_return(id
, -EINVAL
);
615 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
619 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
623 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
624 _cleanup_close_
int sk
= -1;
625 struct ifreq ifr
= {};
628 r
= parse_ifindex(&id
[1], &ifr
.ifr_ifindex
);
632 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
636 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
640 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
644 r
= sd_device_get_ifindex(device
, &ifindex
);
648 /* this is racey, so we might end up with the wrong device */
649 if (ifr
.ifr_ifindex
!= ifindex
)
659 char subsys
[PATH_MAX
];
662 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
663 sysname
= strchr(subsys
, ':');
670 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
677 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
678 assert_return(device
, -EINVAL
);
679 assert_return(ret
, -EINVAL
);
681 assert(path_startswith(device
->syspath
, "/sys/"));
683 *ret
= device
->syspath
;
688 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
689 _cleanup_free_
char *path
= NULL
;
690 const char *subdir
, *syspath
;
696 r
= sd_device_get_syspath(child
, &syspath
);
700 path
= strdup(syspath
);
703 subdir
= path
+ strlen("/sys");
708 pos
= strrchr(subdir
, '/');
709 if (!pos
|| pos
< subdir
+ 2)
714 r
= sd_device_new_from_syspath(ret
, path
);
724 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
726 assert_return(ret
, -EINVAL
);
727 assert_return(child
, -EINVAL
);
729 if (!child
->parent_set
) {
730 child
->parent_set
= true;
732 (void)device_new_from_child(&child
->parent
, child
);
738 *ret
= child
->parent
;
743 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
744 _cleanup_free_
char *subsystem
= NULL
;
750 subsystem
= strdup(_subsystem
);
754 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
758 free(device
->subsystem
);
759 device
->subsystem
= subsystem
;
762 device
->subsystem_set
= true;
767 static int device_set_drivers_subsystem(sd_device
*device
, const char *_subsystem
) {
768 _cleanup_free_
char *subsystem
= NULL
;
775 subsystem
= strdup(_subsystem
);
779 r
= device_set_subsystem(device
, "drivers");
783 free(device
->driver_subsystem
);
784 device
->driver_subsystem
= subsystem
;
790 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
791 const char *syspath
, *drivers
= NULL
;
794 assert_return(ret
, -EINVAL
);
795 assert_return(device
, -EINVAL
);
797 r
= sd_device_get_syspath(device
, &syspath
);
801 if (!device
->subsystem_set
) {
802 _cleanup_free_
char *subsystem
= NULL
;
805 /* read 'subsystem' link */
806 path
= strjoina(syspath
, "/subsystem");
807 r
= readlink_value(path
, &subsystem
);
809 r
= device_set_subsystem(device
, subsystem
);
810 /* use implicit names */
811 else if (path_startswith(device
->devpath
, "/module/"))
812 r
= device_set_subsystem(device
, "module");
813 else if (!(drivers
= strstr(syspath
, "/drivers/")) &&
814 (path_startswith(device
->devpath
, "/subsystem/") ||
815 path_startswith(device
->devpath
, "/class/") ||
816 path_startswith(device
->devpath
, "/bus/")))
817 r
= device_set_subsystem(device
, "subsystem");
818 if (r
< 0 && r
!= -ENOENT
)
819 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
821 device
->subsystem_set
= true;
822 } else if (!device
->driver_subsystem_set
)
823 drivers
= strstr(syspath
, "/drivers/");
825 if (!device
->driver_subsystem_set
) {
827 _cleanup_free_
char *subpath
= NULL
;
829 subpath
= strndup(syspath
, drivers
- syspath
);
835 subsys
= strrchr(subpath
, '/');
839 r
= device_set_drivers_subsystem(device
, subsys
+ 1);
841 if (r
< 0 && r
!= -ENOENT
)
842 return log_debug_errno(r
, "sd-device: could not set subsystem for driver %s: %m", device
->devpath
);
845 device
->driver_subsystem_set
= true;
848 if (!device
->subsystem
)
851 *ret
= device
->subsystem
;
856 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
862 r
= device_read_uevent_file(device
);
866 *devtype
= device
->devtype
;
871 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
872 sd_device
*parent
= NULL
;
875 assert_return(child
, -EINVAL
);
876 assert_return(subsystem
, -EINVAL
);
878 r
= sd_device_get_parent(child
, &parent
);
880 const char *parent_subsystem
= NULL
;
881 const char *parent_devtype
= NULL
;
883 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
884 if (streq_ptr(parent_subsystem
, subsystem
)) {
888 (void)sd_device_get_devtype(parent
, &parent_devtype
);
889 if (streq_ptr(parent_devtype
, devtype
))
892 r
= sd_device_get_parent(parent
, &parent
);
903 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
906 assert_return(device
, -EINVAL
);
907 assert_return(devnum
, -EINVAL
);
909 r
= device_read_uevent_file(device
);
913 *devnum
= device
->devnum
;
918 int device_set_driver(sd_device
*device
, const char *_driver
) {
919 _cleanup_free_
char *driver
= NULL
;
925 driver
= strdup(_driver
);
929 r
= device_add_property_internal(device
, "DRIVER", driver
);
933 free(device
->driver
);
934 device
->driver
= driver
;
937 device
->driver_set
= true;
942 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
943 assert_return(device
, -EINVAL
);
944 assert_return(ret
, -EINVAL
);
946 if (!device
->driver_set
) {
947 _cleanup_free_
char *driver
= NULL
;
952 r
= sd_device_get_syspath(device
, &syspath
);
956 path
= strjoina(syspath
, "/driver");
957 r
= readlink_value(path
, &driver
);
959 r
= device_set_driver(device
, driver
);
961 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
962 } else if (r
== -ENOENT
)
963 device
->driver_set
= true;
965 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
971 *ret
= device
->driver
;
976 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
977 assert_return(device
, -EINVAL
);
978 assert_return(devpath
, -EINVAL
);
980 assert(device
->devpath
);
981 assert(device
->devpath
[0] == '/');
983 *devpath
= device
->devpath
;
988 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
991 assert_return(device
, -EINVAL
);
992 assert_return(devname
, -EINVAL
);
994 r
= device_read_uevent_file(device
);
998 if (!device
->devname
)
1001 assert(path_startswith(device
->devname
, "/dev/"));
1003 *devname
= device
->devname
;
1008 static int device_set_sysname(sd_device
*device
) {
1009 _cleanup_free_
char *sysname
= NULL
;
1010 const char *sysnum
= NULL
;
1014 pos
= strrchr(device
->devpath
, '/');
1019 /* devpath is not a root directory */
1020 if (*pos
== '\0' || pos
<= device
->devpath
)
1023 sysname
= strdup(pos
);
1027 /* some devices have '!' in their name, change that to '/' */
1028 while (sysname
[len
] != '\0') {
1029 if (sysname
[len
] == '!')
1035 /* trailing number */
1036 while (len
> 0 && isdigit(sysname
[--len
]))
1037 sysnum
= &sysname
[len
];
1042 free(device
->sysname
);
1043 device
->sysname
= sysname
;
1046 device
->sysnum
= sysnum
;
1048 device
->sysname_set
= true;
1053 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1056 assert_return(device
, -EINVAL
);
1057 assert_return(ret
, -EINVAL
);
1059 if (!device
->sysname_set
) {
1060 r
= device_set_sysname(device
);
1065 assert_return(device
->sysname
, -ENOENT
);
1067 *ret
= device
->sysname
;
1072 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1075 assert_return(device
, -EINVAL
);
1076 assert_return(ret
, -EINVAL
);
1078 if (!device
->sysname_set
) {
1079 r
= device_set_sysname(device
);
1084 *ret
= device
->sysnum
;
1089 static bool is_valid_tag(const char *tag
) {
1092 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1095 int device_add_tag(sd_device
*device
, const char *tag
) {
1101 if (!is_valid_tag(tag
))
1104 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1108 r
= set_put_strdup(device
->tags
, tag
);
1112 device
->tags_generation
++;
1113 device
->property_tags_outdated
= true;
1118 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1124 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1128 r
= set_put_strdup(device
->devlinks
, devlink
);
1132 device
->devlinks_generation
++;
1133 device
->property_devlinks_outdated
= true;
1138 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1139 _cleanup_free_
char *key
= NULL
;
1149 value
= strchr(key
, '=');
1155 if (isempty(++value
))
1158 return device_add_property_internal(device
, key
, value
);
1161 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1162 uint64_t usec_initialized
;
1166 assert(initialized
);
1168 r
= safe_atou64(initialized
, &usec_initialized
);
1172 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1176 device
->usec_initialized
= usec_initialized
;
1181 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1190 r
= device_add_tag(device
, value
);
1196 path
= strjoina("/dev/", value
);
1197 r
= device_add_devlink(device
, path
);
1203 r
= device_add_property_internal_from_string(device
, value
);
1209 r
= device_set_usec_initialized(device
, value
);
1215 r
= safe_atoi(value
, &device
->devlink_priority
);
1221 r
= safe_atoi(value
, &device
->watch_handle
);
1227 log_debug("device db: unknown key '%c'", key
);
1233 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1237 if (!device
->id_filename
) {
1238 _cleanup_free_
char *id
= NULL
;
1239 const char *subsystem
;
1243 r
= sd_device_get_subsystem(device
, &subsystem
);
1247 r
= sd_device_get_devnum(device
, &devnum
);
1251 r
= sd_device_get_ifindex(device
, &ifindex
);
1255 if (major(devnum
) > 0) {
1258 /* use dev_t — b259:131072, c254:0 */
1259 r
= asprintf(&id
, "%c%u:%u",
1260 streq(subsystem
, "block") ? 'b' : 'c',
1261 major(devnum
), minor(devnum
));
1264 } else if (ifindex
> 0) {
1265 /* use netdev ifindex — n3 */
1266 r
= asprintf(&id
, "n%u", ifindex
);
1270 /* use $subsys:$sysname — pci:0000:00:1f.2
1271 * sysname() has '!' translated, get it from devpath
1273 const char *sysname
;
1275 sysname
= basename(device
->devpath
);
1282 if (streq(subsystem
, "drivers")) {
1283 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1284 * encoded as well */
1285 r
= asprintf(&id
, "+drivers:%s:%s", device
->driver_subsystem
, sysname
);
1289 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1295 device
->id_filename
= id
;
1299 *ret
= device
->id_filename
;
1304 int device_read_db_aux(sd_device
*device
, bool force
) {
1305 _cleanup_free_
char *db
= NULL
;
1307 const char *id
, *value
;
1321 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1324 device
->db_loaded
= true;
1326 r
= device_get_id_filename(device
, &id
);
1330 path
= strjoina("/run/udev/data/", id
);
1332 r
= read_full_file(path
, &db
, &db_len
);
1337 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1340 /* devices with a database entry are initialized */
1341 device
->is_initialized
= true;
1343 for (i
= 0; i
< db_len
; i
++) {
1346 if (!strchr(NEWLINE
, db
[i
])) {
1355 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1357 state
= INVALID_LINE
;
1372 if (strchr(NEWLINE
, db
[i
]))
1377 if (strchr(NEWLINE
, db
[i
])) {
1379 r
= handle_db_line(device
, key
, value
);
1381 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1388 assert_not_reached("invalid state when parsing db");
1395 static int device_read_db(sd_device
*device
) {
1396 return device_read_db_aux(device
, false);
1399 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1402 assert_return(device
, -EINVAL
);
1403 assert_return(initialized
, -EINVAL
);
1405 r
= device_read_db(device
);
1409 *initialized
= device
->is_initialized
;
1414 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1418 assert_return(device
, -EINVAL
);
1419 assert_return(usec
, -EINVAL
);
1421 r
= device_read_db(device
);
1425 if (!device
->is_initialized
)
1428 if (!device
->usec_initialized
)
1431 now_ts
= now(clock_boottime_or_monotonic());
1433 if (now_ts
< device
->usec_initialized
)
1436 *usec
= now_ts
- device
->usec_initialized
;
1441 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1444 assert_return(device
, NULL
);
1446 (void) device_read_db(device
);
1448 device
->tags_iterator_generation
= device
->tags_generation
;
1449 device
->tags_iterator
= ITERATOR_FIRST
;
1451 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1455 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1458 assert_return(device
, NULL
);
1460 (void) device_read_db(device
);
1462 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1465 (void) set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1469 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1472 assert_return(device
, NULL
);
1474 (void) device_read_db(device
);
1476 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1477 device
->devlinks_iterator
= ITERATOR_FIRST
;
1479 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1483 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1486 assert_return(device
, NULL
);
1488 (void) device_read_db(device
);
1490 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1493 (void) set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1497 static int device_properties_prepare(sd_device
*device
) {
1502 r
= device_read_uevent_file(device
);
1506 r
= device_read_db(device
);
1510 if (device
->property_devlinks_outdated
) {
1511 _cleanup_free_
char *devlinks
= NULL
;
1512 size_t devlinks_allocated
= 0, devlinks_len
= 0;
1513 const char *devlink
;
1515 for (devlink
= sd_device_get_devlink_first(device
); devlink
; devlink
= sd_device_get_devlink_next(device
)) {
1518 if (!GREEDY_REALLOC(devlinks
, devlinks_allocated
, devlinks_len
+ strlen(devlink
) + 2))
1520 if (devlinks_len
> 0)
1521 stpcpy(devlinks
+ devlinks_len
++, " ");
1522 e
= stpcpy(devlinks
+ devlinks_len
, devlink
);
1523 devlinks_len
= e
- devlinks
;
1526 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1530 device
->property_devlinks_outdated
= false;
1533 if (device
->property_tags_outdated
) {
1534 _cleanup_free_
char *tags
= NULL
;
1535 size_t tags_allocated
= 0, tags_len
= 0;
1538 if (!GREEDY_REALLOC(tags
, tags_allocated
, 2))
1543 for (tag
= sd_device_get_tag_first(device
); tag
; tag
= sd_device_get_tag_next(device
)) {
1546 if (!GREEDY_REALLOC(tags
, tags_allocated
, tags_len
+ strlen(tag
) + 2))
1548 e
= stpcpy(stpcpy(tags
+ tags_len
, tag
), ":");
1549 tags_len
= e
- tags
;
1552 r
= device_add_property_internal(device
, "TAGS", tags
);
1556 device
->property_tags_outdated
= false;
1562 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1567 assert_return(device
, NULL
);
1569 r
= device_properties_prepare(device
);
1573 device
->properties_iterator_generation
= device
->properties_generation
;
1574 device
->properties_iterator
= ITERATOR_FIRST
;
1576 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1584 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1589 assert_return(device
, NULL
);
1591 r
= device_properties_prepare(device
);
1595 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1598 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1606 static int device_sysattrs_read_all(sd_device
*device
) {
1607 _cleanup_closedir_
DIR *dir
= NULL
;
1608 const char *syspath
;
1609 struct dirent
*dent
;
1614 if (device
->sysattrs_read
)
1617 r
= sd_device_get_syspath(device
, &syspath
);
1621 dir
= opendir(syspath
);
1625 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1629 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1631 struct stat statbuf
;
1633 /* only handle symlinks and regular files */
1634 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1637 path
= strjoina(syspath
, "/", dent
->d_name
);
1639 if (lstat(path
, &statbuf
) != 0)
1642 if (!(statbuf
.st_mode
& S_IRUSR
))
1645 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1650 device
->sysattrs_read
= true;
1655 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1659 assert_return(device
, NULL
);
1661 if (!device
->sysattrs_read
) {
1662 r
= device_sysattrs_read_all(device
);
1669 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1671 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1675 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1678 assert_return(device
, NULL
);
1680 if (!device
->sysattrs_read
)
1683 (void) set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1687 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1688 assert_return(device
, -EINVAL
);
1689 assert_return(tag
, -EINVAL
);
1691 (void) device_read_db(device
);
1693 return !!set_contains(device
->tags
, tag
);
1696 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1700 assert_return(device
, -EINVAL
);
1701 assert_return(key
, -EINVAL
);
1702 assert_return(_value
, -EINVAL
);
1704 r
= device_properties_prepare(device
);
1708 value
= ordered_hashmap_get(device
->properties
, key
);
1717 /* replaces the value if it already exists */
1718 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1719 _cleanup_free_
char *key
= NULL
;
1720 _cleanup_free_
char *value_old
= NULL
;
1726 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1730 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1737 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1746 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1747 const char *key
= NULL
, *value
;
1752 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1762 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1763 * with a NULL value in the cache, otherwise the returned string is stored */
1764 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1765 _cleanup_free_
char *value
= NULL
;
1766 const char *syspath
, *cached_value
= NULL
;
1768 struct stat statbuf
;
1771 assert_return(device
, -EINVAL
);
1772 assert_return(sysattr
, -EINVAL
);
1774 /* look for possibly already cached result */
1775 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1781 /* we looked up the sysattr before and it did not exist */
1785 *_value
= cached_value
;
1790 r
= sd_device_get_syspath(device
, &syspath
);
1794 path
= strjoina(syspath
, "/", sysattr
);
1795 r
= lstat(path
, &statbuf
);
1797 /* remember that we could not access the sysattr */
1798 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1803 } else if (S_ISLNK(statbuf
.st_mode
)) {
1804 /* Some core links return only the last element of the target path,
1805 * these are just values, the paths should not be exposed. */
1806 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1807 r
= readlink_value(path
, &value
);
1812 } else if (S_ISDIR(statbuf
.st_mode
)) {
1813 /* skip directories */
1815 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1816 /* skip non-readable files */
1821 /* read attribute value */
1822 r
= read_full_file(path
, &value
, &size
);
1826 /* drop trailing newlines */
1827 while (size
> 0 && value
[--size
] == '\n')
1831 r
= device_add_sysattr_value(device
, sysattr
, value
);
1841 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1842 _cleanup_free_
char *key
= NULL
;
1843 _cleanup_free_
char *value
= NULL
;
1848 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1853 /* set the attribute and save it in the cache. If a NULL value is passed the
1854 * attribute is cleared from the cache */
1855 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1856 _cleanup_close_
int fd
= -1;
1857 _cleanup_free_
char *value
= NULL
;
1858 const char *syspath
;
1860 struct stat statbuf
;
1861 size_t value_len
= 0;
1865 assert_return(device
, -EINVAL
);
1866 assert_return(sysattr
, -EINVAL
);
1869 device_remove_sysattr_value(device
, sysattr
);
1874 r
= sd_device_get_syspath(device
, &syspath
);
1878 path
= strjoina(syspath
, "/", sysattr
);
1879 r
= lstat(path
, &statbuf
);
1885 r
= device_add_sysattr_value(device
, sysattr
, value
);
1892 if (S_ISLNK(statbuf
.st_mode
))
1895 /* skip directories */
1896 if (S_ISDIR(statbuf
.st_mode
))
1899 /* skip non-readable files */
1900 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1903 value_len
= strlen(_value
);
1905 /* drop trailing newlines */
1906 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1907 _value
[--value_len
] = '\0';
1909 /* value length is limited to 4k */
1910 if (value_len
> 4096)
1913 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1917 value
= strdup(_value
);
1921 size
= write(fd
, value
, value_len
);
1925 if ((size_t)size
!= value_len
)
1928 r
= device_add_sysattr_value(device
, sysattr
, value
);