2 This file is part of systemd.
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
25 #include "sd-device.h"
27 #include "device-internal.h"
28 #include "device-private.h"
29 #include "device-util.h"
35 #include "parse-util.h"
36 #include "path-util.h"
38 #include "stat-util.h"
39 #include "string-util.h"
44 int device_new_aux(sd_device
**ret
) {
45 _cleanup_device_unref_ sd_device
*device
= NULL
;
49 device
= new0(sd_device
, 1);
54 device
->watch_handle
= -1;
62 _public_ sd_device
*sd_device_ref(sd_device
*device
) {
64 assert_se(++ device
->n_ref
>= 2);
69 _public_ sd_device
*sd_device_unref(sd_device
*device
) {
70 if (device
&& -- device
->n_ref
== 0) {
71 sd_device_unref(device
->parent
);
72 free(device
->syspath
);
73 free(device
->sysname
);
74 free(device
->devtype
);
75 free(device
->devname
);
76 free(device
->subsystem
);
78 free(device
->id_filename
);
79 free(device
->properties_strv
);
80 free(device
->properties_nulstr
);
82 ordered_hashmap_free_free_free(device
->properties
);
83 ordered_hashmap_free_free_free(device
->properties_db
);
84 hashmap_free_free_free(device
->sysattr_values
);
85 set_free_free(device
->sysattrs
);
86 set_free_free(device
->tags
);
87 set_free_free(device
->devlinks
);
95 int device_add_property_aux(sd_device
*device
, const char *_key
, const char *_value
, bool db
) {
96 OrderedHashmap
**properties
;
102 properties
= &device
->properties_db
;
104 properties
= &device
->properties
;
107 _cleanup_free_
char *key
= NULL
, *value
= NULL
, *old_key
= NULL
, *old_value
= NULL
;
110 r
= ordered_hashmap_ensure_allocated(properties
, &string_hash_ops
);
118 value
= strdup(_value
);
122 old_value
= ordered_hashmap_get2(*properties
, key
, (void**) &old_key
);
124 r
= ordered_hashmap_replace(*properties
, key
, value
);
131 _cleanup_free_
char *key
= NULL
;
132 _cleanup_free_
char *value
= NULL
;
134 value
= ordered_hashmap_remove2(*properties
, _key
, (void**) &key
);
138 device
->properties_generation
++;
139 device
->properties_buf_outdated
= true;
145 int device_add_property_internal(sd_device
*device
, const char *key
, const char *value
) {
146 return device_add_property_aux(device
, key
, value
, false);
149 int device_set_syspath(sd_device
*device
, const char *_syspath
, bool verify
) {
150 _cleanup_free_
char *syspath
= NULL
;
157 /* must be a subdirectory of /sys */
158 if (!path_startswith(_syspath
, "/sys/")) {
159 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath
);
164 r
= readlink_and_canonicalize(_syspath
, &syspath
);
166 /* the device does not exist (any more?) */
168 else if (r
== -EINVAL
) {
170 syspath
= canonicalize_file_name(_syspath
);
173 /* the device does not exist (any more?) */
176 return log_debug_errno(errno
, "sd-device: could not canonicalize '%s': %m", _syspath
);
179 log_debug_errno(r
, "sd-device: could not get target of '%s': %m", _syspath
);
183 if (path_startswith(syspath
, "/sys/devices/")) {
186 /* all 'devices' require an 'uevent' file */
187 path
= strjoina(syspath
, "/uevent");
188 r
= access(path
, F_OK
);
191 /* this is not a valid device */
194 log_debug("sd-device: %s does not have an uevent file: %m", syspath
);
198 /* everything else just just needs to be a directory */
199 if (!is_dir(syspath
, false))
203 syspath
= strdup(_syspath
);
208 devpath
= syspath
+ strlen("/sys");
210 r
= device_add_property_internal(device
, "DEVPATH", devpath
);
214 free(device
->syspath
);
215 device
->syspath
= syspath
;
218 device
->devpath
= devpath
;
223 _public_
int sd_device_new_from_syspath(sd_device
**ret
, const char *syspath
) {
224 _cleanup_device_unref_ sd_device
*device
= NULL
;
227 assert_return(ret
, -EINVAL
);
228 assert_return(syspath
, -EINVAL
);
230 r
= device_new_aux(&device
);
234 r
= device_set_syspath(device
, syspath
, true);
244 _public_
int sd_device_new_from_devnum(sd_device
**ret
, char type
, dev_t devnum
) {
246 char id
[DECIMAL_STR_MAX(unsigned) * 2 + 1];
248 assert_return(ret
, -EINVAL
);
249 assert_return(type
== 'b' || type
== 'c', -EINVAL
);
251 /* use /sys/dev/{block,char}/<maj>:<min> link */
252 snprintf(id
, sizeof(id
), "%u:%u", major(devnum
), minor(devnum
));
254 syspath
= strjoina("/sys/dev/", (type
== 'b' ? "block" : "char"), "/", id
);
256 return sd_device_new_from_syspath(ret
, syspath
);
259 _public_
int sd_device_new_from_subsystem_sysname(sd_device
**ret
, const char *subsystem
, const char *sysname
) {
262 assert_return(ret
, -EINVAL
);
263 assert_return(subsystem
, -EINVAL
);
264 assert_return(sysname
, -EINVAL
);
266 if (streq(subsystem
, "subsystem")) {
267 syspath
= strjoina("/sys/subsystem/", sysname
);
268 if (access(syspath
, F_OK
) >= 0)
269 return sd_device_new_from_syspath(ret
, syspath
);
271 syspath
= strjoina("/sys/bus/", sysname
);
272 if (access(syspath
, F_OK
) >= 0)
273 return sd_device_new_from_syspath(ret
, syspath
);
275 syspath
= strjoina("/sys/class/", sysname
);
276 if (access(syspath
, F_OK
) >= 0)
277 return sd_device_new_from_syspath(ret
, syspath
);
278 } else if (streq(subsystem
, "module")) {
279 syspath
= strjoina("/sys/module/", sysname
);
280 if (access(syspath
, F_OK
) >= 0)
281 return sd_device_new_from_syspath(ret
, syspath
);
282 } else if (streq(subsystem
, "drivers")) {
283 char subsys
[PATH_MAX
];
286 strscpy(subsys
, sizeof(subsys
), sysname
);
287 driver
= strchr(subsys
, ':');
292 syspath
= strjoina("/sys/subsystem/", subsys
, "/drivers/", driver
);
293 if (access(syspath
, F_OK
) >= 0)
294 return sd_device_new_from_syspath(ret
, syspath
);
296 syspath
= strjoina("/sys/bus/", subsys
, "/drivers/", driver
);
297 if (access(syspath
, F_OK
) >= 0)
298 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
);
330 int device_set_devtype(sd_device
*device
, const char *_devtype
) {
331 _cleanup_free_
char *devtype
= NULL
;
337 devtype
= strdup(_devtype
);
341 r
= device_add_property_internal(device
, "DEVTYPE", devtype
);
345 free(device
->devtype
);
346 device
->devtype
= devtype
;
352 int device_set_ifindex(sd_device
*device
, const char *_ifindex
) {
358 r
= safe_atoi(_ifindex
, &ifindex
);
365 r
= device_add_property_internal(device
, "IFINDEX", _ifindex
);
369 device
->ifindex
= ifindex
;
374 int device_set_devname(sd_device
*device
, const char *_devname
) {
375 _cleanup_free_
char *devname
= NULL
;
381 if (_devname
[0] != '/') {
382 r
= asprintf(&devname
, "/dev/%s", _devname
);
386 devname
= strdup(_devname
);
391 r
= device_add_property_internal(device
, "DEVNAME", devname
);
395 free(device
->devname
);
396 device
->devname
= devname
;
402 int device_set_devmode(sd_device
*device
, const char *_devmode
) {
409 r
= safe_atou(_devmode
, &devmode
);
416 r
= device_add_property_internal(device
, "DEVMODE", _devmode
);
420 device
->devmode
= devmode
;
425 int device_set_devnum(sd_device
*device
, const char *major
, const char *minor
) {
426 unsigned maj
= 0, min
= 0;
432 r
= safe_atou(major
, &maj
);
439 r
= safe_atou(minor
, &min
);
444 r
= device_add_property_internal(device
, "MAJOR", major
);
449 r
= device_add_property_internal(device
, "MINOR", minor
);
454 device
->devnum
= makedev(maj
, min
);
459 static int handle_uevent_line(sd_device
*device
, const char *key
, const char *value
, const char **major
, const char **minor
) {
468 if (streq(key
, "DEVTYPE")) {
469 r
= device_set_devtype(device
, value
);
472 } else if (streq(key
, "IFINDEX")) {
473 r
= device_set_ifindex(device
, value
);
476 } else if (streq(key
, "DEVNAME")) {
477 r
= device_set_devname(device
, value
);
480 } else if (streq(key
, "DEVMODE")) {
481 r
= device_set_devmode(device
, value
);
484 } else if (streq(key
, "MAJOR"))
486 else if (streq(key
, "MINOR"))
489 r
= device_add_property_internal(device
, key
, value
);
497 int device_read_uevent_file(sd_device
*device
) {
498 _cleanup_free_
char *uevent
= NULL
;
499 const char *syspath
, *key
, *value
, *major
= NULL
, *minor
= NULL
;
515 if (device
->uevent_loaded
|| device
->sealed
)
518 device
->uevent_loaded
= true;
520 r
= sd_device_get_syspath(device
, &syspath
);
524 path
= strjoina(syspath
, "/uevent");
526 r
= read_full_file(path
, &uevent
, &uevent_len
);
528 /* empty uevent files may be write-only */
530 else if (r
== -ENOENT
)
531 /* some devices may not have uevent files, see set_syspath() */
534 log_debug_errno(r
, "sd-device: failed to read uevent file '%s': %m", path
);
538 for (i
= 0; i
< uevent_len
; i
++) {
541 if (!strchr(NEWLINE
, uevent
[i
])) {
549 if (uevent
[i
] == '=') {
553 } else if (strchr(NEWLINE
, uevent
[i
])) {
555 log_debug("sd-device: ignoring invalid uevent line '%s'", key
);
568 if (strchr(NEWLINE
, uevent
[i
])) {
571 r
= handle_uevent_line(device
, key
, value
, &major
, &minor
);
573 log_debug_errno(r
, "sd-device: failed to handle uevent entry '%s=%s': %m", key
, value
);
580 assert_not_reached("invalid state when parsing uevent file");
585 r
= device_set_devnum(device
, major
, minor
);
587 log_debug_errno(r
, "sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %m", major
, minor
, path
);
593 _public_
int sd_device_get_ifindex(sd_device
*device
, int *ifindex
) {
596 assert_return(device
, -EINVAL
);
597 assert_return(ifindex
, -EINVAL
);
599 r
= device_read_uevent_file(device
);
603 *ifindex
= device
->ifindex
;
608 _public_
int sd_device_new_from_device_id(sd_device
**ret
, const char *id
) {
611 assert_return(ret
, -EINVAL
);
612 assert_return(id
, -EINVAL
);
621 r
= sscanf(id
, "%c%i:%i", &type
, &maj
, &min
);
625 return sd_device_new_from_devnum(ret
, type
, makedev(maj
, min
));
629 _cleanup_device_unref_ sd_device
*device
= NULL
;
630 _cleanup_close_
int sk
= -1;
631 struct ifreq ifr
= {};
634 r
= safe_atoi(&id
[1], &ifr
.ifr_ifindex
);
637 else if (ifr
.ifr_ifindex
<= 0)
640 sk
= socket(PF_INET
, SOCK_DGRAM
, 0);
644 r
= ioctl(sk
, SIOCGIFNAME
, &ifr
);
648 r
= sd_device_new_from_subsystem_sysname(&device
, "net", ifr
.ifr_name
);
652 r
= sd_device_get_ifindex(device
, &ifindex
);
656 /* this is racey, so we might end up with the wrong device */
657 if (ifr
.ifr_ifindex
!= ifindex
)
667 char subsys
[PATH_MAX
];
670 (void)strscpy(subsys
, sizeof(subsys
), id
+ 1);
671 sysname
= strchr(subsys
, ':');
678 return sd_device_new_from_subsystem_sysname(ret
, subsys
, sysname
);
685 _public_
int sd_device_get_syspath(sd_device
*device
, const char **ret
) {
686 assert_return(device
, -EINVAL
);
687 assert_return(ret
, -EINVAL
);
689 assert(path_startswith(device
->syspath
, "/sys/"));
691 *ret
= device
->syspath
;
696 static int device_new_from_child(sd_device
**ret
, sd_device
*child
) {
697 _cleanup_free_
char *path
= NULL
;
698 const char *subdir
, *syspath
;
704 r
= sd_device_get_syspath(child
, &syspath
);
708 path
= strdup(syspath
);
711 subdir
= path
+ strlen("/sys");
716 pos
= strrchr(subdir
, '/');
717 if (!pos
|| pos
< subdir
+ 2)
722 r
= sd_device_new_from_syspath(ret
, path
);
732 _public_
int sd_device_get_parent(sd_device
*child
, sd_device
**ret
) {
734 assert_return(ret
, -EINVAL
);
735 assert_return(child
, -EINVAL
);
737 if (!child
->parent_set
) {
738 child
->parent_set
= true;
740 (void)device_new_from_child(&child
->parent
, child
);
746 *ret
= child
->parent
;
751 int device_set_subsystem(sd_device
*device
, const char *_subsystem
) {
752 _cleanup_free_
char *subsystem
= NULL
;
758 subsystem
= strdup(_subsystem
);
762 r
= device_add_property_internal(device
, "SUBSYSTEM", subsystem
);
766 free(device
->subsystem
);
767 device
->subsystem
= subsystem
;
770 device
->subsystem_set
= true;
775 _public_
int sd_device_get_subsystem(sd_device
*device
, const char **ret
) {
776 assert_return(ret
, -EINVAL
);
777 assert_return(device
, -EINVAL
);
779 if (!device
->subsystem_set
) {
780 _cleanup_free_
char *subsystem
= NULL
;
785 /* read 'subsystem' link */
786 r
= sd_device_get_syspath(device
, &syspath
);
790 path
= strjoina(syspath
, "/subsystem");
791 r
= readlink_value(path
, &subsystem
);
793 r
= device_set_subsystem(device
, subsystem
);
794 /* use implicit names */
795 else if (path_startswith(device
->devpath
, "/module/"))
796 r
= device_set_subsystem(device
, "module");
797 else if (strstr(device
->devpath
, "/drivers/"))
798 r
= device_set_subsystem(device
, "drivers");
799 else if (path_startswith(device
->devpath
, "/subsystem/") ||
800 path_startswith(device
->devpath
, "/class/") ||
801 path_startswith(device
->devpath
, "/bus/"))
802 r
= device_set_subsystem(device
, "subsystem");
803 if (r
< 0 && r
!= -ENOENT
)
804 return log_debug_errno(r
, "sd-device: could not set subsystem for %s: %m", device
->devpath
);
806 device
->subsystem_set
= true;
809 if (!device
->subsystem
)
812 *ret
= device
->subsystem
;
817 _public_
int sd_device_get_devtype(sd_device
*device
, const char **devtype
) {
823 r
= device_read_uevent_file(device
);
827 *devtype
= device
->devtype
;
832 _public_
int sd_device_get_parent_with_subsystem_devtype(sd_device
*child
, const char *subsystem
, const char *devtype
, sd_device
**ret
) {
833 sd_device
*parent
= NULL
;
836 assert_return(child
, -EINVAL
);
837 assert_return(subsystem
, -EINVAL
);
839 r
= sd_device_get_parent(child
, &parent
);
841 const char *parent_subsystem
= NULL
;
842 const char *parent_devtype
= NULL
;
844 (void)sd_device_get_subsystem(parent
, &parent_subsystem
);
845 if (streq_ptr(parent_subsystem
, subsystem
)) {
849 (void)sd_device_get_devtype(parent
, &parent_devtype
);
850 if (streq_ptr(parent_devtype
, devtype
))
853 r
= sd_device_get_parent(parent
, &parent
);
864 _public_
int sd_device_get_devnum(sd_device
*device
, dev_t
*devnum
) {
867 assert_return(device
, -EINVAL
);
868 assert_return(devnum
, -EINVAL
);
870 r
= device_read_uevent_file(device
);
874 *devnum
= device
->devnum
;
879 int device_set_driver(sd_device
*device
, const char *_driver
) {
880 _cleanup_free_
char *driver
= NULL
;
886 driver
= strdup(_driver
);
890 r
= device_add_property_internal(device
, "DRIVER", driver
);
894 free(device
->driver
);
895 device
->driver
= driver
;
898 device
->driver_set
= true;
903 _public_
int sd_device_get_driver(sd_device
*device
, const char **ret
) {
904 assert_return(device
, -EINVAL
);
905 assert_return(ret
, -EINVAL
);
907 if (!device
->driver_set
) {
908 _cleanup_free_
char *driver
= NULL
;
913 r
= sd_device_get_syspath(device
, &syspath
);
917 path
= strjoina(syspath
, "/driver");
918 r
= readlink_value(path
, &driver
);
920 r
= device_set_driver(device
, driver
);
922 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
923 } else if (r
== -ENOENT
)
924 device
->driver_set
= true;
926 return log_debug_errno(r
, "sd-device: could not set driver for %s: %m", device
->devpath
);
932 *ret
= device
->driver
;
937 _public_
int sd_device_get_devpath(sd_device
*device
, const char **devpath
) {
938 assert_return(device
, -EINVAL
);
939 assert_return(devpath
, -EINVAL
);
941 assert(device
->devpath
);
942 assert(device
->devpath
[0] == '/');
944 *devpath
= device
->devpath
;
949 _public_
int sd_device_get_devname(sd_device
*device
, const char **devname
) {
952 assert_return(device
, -EINVAL
);
953 assert_return(devname
, -EINVAL
);
955 r
= device_read_uevent_file(device
);
959 if (!device
->devname
)
962 assert(path_startswith(device
->devname
, "/dev/"));
964 *devname
= device
->devname
;
969 static int device_set_sysname(sd_device
*device
) {
970 _cleanup_free_
char *sysname
= NULL
;
971 const char *sysnum
= NULL
;
975 pos
= strrchr(device
->devpath
, '/');
980 /* devpath is not a root directory */
981 if (*pos
== '\0' || pos
<= device
->devpath
)
984 sysname
= strdup(pos
);
988 /* some devices have '!' in their name, change that to '/' */
989 while (sysname
[len
] != '\0') {
990 if (sysname
[len
] == '!')
996 /* trailing number */
997 while (len
> 0 && isdigit(sysname
[--len
]))
998 sysnum
= &sysname
[len
];
1003 free(device
->sysname
);
1004 device
->sysname
= sysname
;
1007 device
->sysnum
= sysnum
;
1009 device
->sysname_set
= true;
1014 _public_
int sd_device_get_sysname(sd_device
*device
, const char **ret
) {
1017 assert_return(device
, -EINVAL
);
1018 assert_return(ret
, -EINVAL
);
1020 if (!device
->sysname_set
) {
1021 r
= device_set_sysname(device
);
1026 assert_return(device
->sysname
, -ENOENT
);
1028 *ret
= device
->sysname
;
1033 _public_
int sd_device_get_sysnum(sd_device
*device
, const char **ret
) {
1036 assert_return(device
, -EINVAL
);
1037 assert_return(ret
, -EINVAL
);
1039 if (!device
->sysname_set
) {
1040 r
= device_set_sysname(device
);
1045 *ret
= device
->sysnum
;
1050 static bool is_valid_tag(const char *tag
) {
1053 return !strchr(tag
, ':') && !strchr(tag
, ' ');
1056 int device_add_tag(sd_device
*device
, const char *tag
) {
1062 if (!is_valid_tag(tag
))
1065 r
= set_ensure_allocated(&device
->tags
, &string_hash_ops
);
1069 r
= set_put_strdup(device
->tags
, tag
);
1073 device
->tags_generation
++;
1074 device
->property_tags_outdated
= true;
1079 int device_add_devlink(sd_device
*device
, const char *devlink
) {
1085 r
= set_ensure_allocated(&device
->devlinks
, &string_hash_ops
);
1089 r
= set_put_strdup(device
->devlinks
, devlink
);
1093 device
->devlinks_generation
++;
1094 device
->property_devlinks_outdated
= true;
1099 static int device_add_property_internal_from_string(sd_device
*device
, const char *str
) {
1100 _cleanup_free_
char *key
= NULL
;
1110 value
= strchr(key
, '=');
1116 if (isempty(++value
))
1119 return device_add_property_internal(device
, key
, value
);
1122 int device_set_usec_initialized(sd_device
*device
, const char *initialized
) {
1123 uint64_t usec_initialized
;
1127 assert(initialized
);
1129 r
= safe_atou64(initialized
, &usec_initialized
);
1133 r
= device_add_property_internal(device
, "USEC_INITIALIZED", initialized
);
1137 device
->usec_initialized
= usec_initialized
;
1142 static int handle_db_line(sd_device
*device
, char key
, const char *value
) {
1151 r
= device_add_tag(device
, value
);
1157 path
= strjoina("/dev/", value
);
1158 r
= device_add_devlink(device
, path
);
1164 r
= device_add_property_internal_from_string(device
, value
);
1170 r
= device_set_usec_initialized(device
, value
);
1176 r
= safe_atoi(value
, &device
->devlink_priority
);
1182 r
= safe_atoi(value
, &device
->watch_handle
);
1188 log_debug("device db: unknown key '%c'", key
);
1194 int device_get_id_filename(sd_device
*device
, const char **ret
) {
1198 if (!device
->id_filename
) {
1199 _cleanup_free_
char *id
= NULL
;
1200 const char *subsystem
;
1204 r
= sd_device_get_subsystem(device
, &subsystem
);
1208 r
= sd_device_get_devnum(device
, &devnum
);
1212 r
= sd_device_get_ifindex(device
, &ifindex
);
1216 if (major(devnum
) > 0) {
1219 /* use dev_t -- b259:131072, c254:0 */
1220 r
= asprintf(&id
, "%c%u:%u",
1221 streq(subsystem
, "block") ? 'b' : 'c',
1222 major(devnum
), minor(devnum
));
1225 } else if (ifindex
> 0) {
1226 /* use netdev ifindex -- n3 */
1227 r
= asprintf(&id
, "n%u", ifindex
);
1231 /* use $subsys:$sysname -- pci:0000:00:1f.2
1232 * sysname() has '!' translated, get it from devpath
1234 const char *sysname
;
1236 sysname
= basename(device
->devpath
);
1243 r
= asprintf(&id
, "+%s:%s", subsystem
, sysname
);
1248 device
->id_filename
= id
;
1252 *ret
= device
->id_filename
;
1257 int device_read_db_aux(sd_device
*device
, bool force
) {
1258 _cleanup_free_
char *db
= NULL
;
1260 const char *id
, *value
;
1274 if (device
->db_loaded
|| (!force
&& device
->sealed
))
1277 device
->db_loaded
= true;
1279 r
= device_get_id_filename(device
, &id
);
1283 path
= strjoina("/run/udev/data/", id
);
1285 r
= read_full_file(path
, &db
, &db_len
);
1290 return log_debug_errno(r
, "sd-device: failed to read db '%s': %m", path
);
1293 /* devices with a database entry are initialized */
1294 device
->is_initialized
= true;
1296 for (i
= 0; i
< db_len
; i
++) {
1299 if (!strchr(NEWLINE
, db
[i
])) {
1308 log_debug("sd-device: ignoring invalid db entry with key '%c'", key
);
1310 state
= INVALID_LINE
;
1325 if (strchr(NEWLINE
, db
[i
]))
1330 if (strchr(NEWLINE
, db
[i
])) {
1332 r
= handle_db_line(device
, key
, value
);
1334 log_debug_errno(r
, "sd-device: failed to handle db entry '%c:%s': %m", key
, value
);
1341 assert_not_reached("invalid state when parsing db");
1348 static int device_read_db(sd_device
*device
) {
1349 return device_read_db_aux(device
, false);
1352 _public_
int sd_device_get_is_initialized(sd_device
*device
, int *initialized
) {
1355 assert_return(device
, -EINVAL
);
1356 assert_return(initialized
, -EINVAL
);
1358 r
= device_read_db(device
);
1362 *initialized
= device
->is_initialized
;
1367 _public_
int sd_device_get_usec_since_initialized(sd_device
*device
, uint64_t *usec
) {
1371 assert_return(device
, -EINVAL
);
1372 assert_return(usec
, -EINVAL
);
1374 r
= device_read_db(device
);
1378 if (!device
->is_initialized
)
1381 if (!device
->usec_initialized
)
1384 now_ts
= now(clock_boottime_or_monotonic());
1386 if (now_ts
< device
->usec_initialized
)
1389 *usec
= now_ts
- device
->usec_initialized
;
1394 _public_
const char *sd_device_get_tag_first(sd_device
*device
) {
1397 assert_return(device
, NULL
);
1399 (void) device_read_db(device
);
1401 device
->tags_iterator_generation
= device
->tags_generation
;
1402 device
->tags_iterator
= ITERATOR_FIRST
;
1404 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1408 _public_
const char *sd_device_get_tag_next(sd_device
*device
) {
1411 assert_return(device
, NULL
);
1413 (void) device_read_db(device
);
1415 if (device
->tags_iterator_generation
!= device
->tags_generation
)
1418 set_iterate(device
->tags
, &device
->tags_iterator
, &v
);
1422 _public_
const char *sd_device_get_devlink_first(sd_device
*device
) {
1425 assert_return(device
, NULL
);
1427 (void) device_read_db(device
);
1429 device
->devlinks_iterator_generation
= device
->devlinks_generation
;
1430 device
->devlinks_iterator
= ITERATOR_FIRST
;
1432 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1436 _public_
const char *sd_device_get_devlink_next(sd_device
*device
) {
1439 assert_return(device
, NULL
);
1441 (void) device_read_db(device
);
1443 if (device
->devlinks_iterator_generation
!= device
->devlinks_generation
)
1446 set_iterate(device
->devlinks
, &device
->devlinks_iterator
, &v
);
1450 static int device_properties_prepare(sd_device
*device
) {
1455 r
= device_read_uevent_file(device
);
1459 r
= device_read_db(device
);
1463 if (device
->property_devlinks_outdated
) {
1464 char *devlinks
= NULL
;
1465 const char *devlink
;
1467 devlink
= sd_device_get_devlink_first(device
);
1469 devlinks
= strdupa(devlink
);
1471 while ((devlink
= sd_device_get_devlink_next(device
)))
1472 devlinks
= strjoina(devlinks
, " ", devlink
);
1474 r
= device_add_property_internal(device
, "DEVLINKS", devlinks
);
1478 device
->property_devlinks_outdated
= false;
1481 if (device
->property_tags_outdated
) {
1485 tag
= sd_device_get_tag_first(device
);
1487 tags
= strjoina(":", tag
);
1489 while ((tag
= sd_device_get_tag_next(device
)))
1490 tags
= strjoina(tags
, ":", tag
);
1492 tags
= strjoina(tags
, ":");
1494 r
= device_add_property_internal(device
, "TAGS", tags
);
1498 device
->property_tags_outdated
= false;
1504 _public_
const char *sd_device_get_property_first(sd_device
*device
, const char **_value
) {
1509 assert_return(device
, NULL
);
1511 r
= device_properties_prepare(device
);
1515 device
->properties_iterator_generation
= device
->properties_generation
;
1516 device
->properties_iterator
= ITERATOR_FIRST
;
1518 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1526 _public_
const char *sd_device_get_property_next(sd_device
*device
, const char **_value
) {
1531 assert_return(device
, NULL
);
1533 r
= device_properties_prepare(device
);
1537 if (device
->properties_iterator_generation
!= device
->properties_generation
)
1540 ordered_hashmap_iterate(device
->properties
, &device
->properties_iterator
, (void**)&value
, (const void**)&key
);
1548 static int device_sysattrs_read_all(sd_device
*device
) {
1549 _cleanup_closedir_
DIR *dir
= NULL
;
1550 const char *syspath
;
1551 struct dirent
*dent
;
1556 if (device
->sysattrs_read
)
1559 r
= sd_device_get_syspath(device
, &syspath
);
1563 dir
= opendir(syspath
);
1567 r
= set_ensure_allocated(&device
->sysattrs
, &string_hash_ops
);
1571 for (dent
= readdir(dir
); dent
!= NULL
; dent
= readdir(dir
)) {
1573 struct stat statbuf
;
1575 /* only handle symlinks and regular files */
1576 if (dent
->d_type
!= DT_LNK
&& dent
->d_type
!= DT_REG
)
1579 path
= strjoina(syspath
, "/", dent
->d_name
);
1581 if (lstat(path
, &statbuf
) != 0)
1584 if (!(statbuf
.st_mode
& S_IRUSR
))
1587 r
= set_put_strdup(device
->sysattrs
, dent
->d_name
);
1592 device
->sysattrs_read
= true;
1597 _public_
const char *sd_device_get_sysattr_first(sd_device
*device
) {
1601 assert_return(device
, NULL
);
1603 if (!device
->sysattrs_read
) {
1604 r
= device_sysattrs_read_all(device
);
1611 device
->sysattrs_iterator
= ITERATOR_FIRST
;
1613 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1617 _public_
const char *sd_device_get_sysattr_next(sd_device
*device
) {
1620 assert_return(device
, NULL
);
1622 if (!device
->sysattrs_read
)
1625 set_iterate(device
->sysattrs
, &device
->sysattrs_iterator
, &v
);
1629 _public_
int sd_device_has_tag(sd_device
*device
, const char *tag
) {
1630 assert_return(device
, -EINVAL
);
1631 assert_return(tag
, -EINVAL
);
1633 (void) device_read_db(device
);
1635 return !!set_contains(device
->tags
, tag
);
1638 _public_
int sd_device_get_property_value(sd_device
*device
, const char *key
, const char **_value
) {
1642 assert_return(device
, -EINVAL
);
1643 assert_return(key
, -EINVAL
);
1644 assert_return(_value
, -EINVAL
);
1646 r
= device_properties_prepare(device
);
1650 value
= ordered_hashmap_get(device
->properties
, key
);
1659 /* replaces the value if it already exists */
1660 static int device_add_sysattr_value(sd_device
*device
, const char *_key
, char *value
) {
1661 _cleanup_free_
char *key
= NULL
;
1662 _cleanup_free_
char *value_old
= NULL
;
1668 r
= hashmap_ensure_allocated(&device
->sysattr_values
, &string_hash_ops
);
1672 value_old
= hashmap_remove2(device
->sysattr_values
, _key
, (void **)&key
);
1679 r
= hashmap_put(device
->sysattr_values
, key
, value
);
1688 static int device_get_sysattr_value(sd_device
*device
, const char *_key
, const char **_value
) {
1689 const char *key
= NULL
, *value
;
1694 value
= hashmap_get2(device
->sysattr_values
, _key
, (void **) &key
);
1704 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1705 * with a NULL value in the cache, otherwise the returned string is stored */
1706 _public_
int sd_device_get_sysattr_value(sd_device
*device
, const char *sysattr
, const char **_value
) {
1707 _cleanup_free_
char *value
= NULL
;
1708 const char *syspath
, *cached_value
= NULL
;
1710 struct stat statbuf
;
1713 assert_return(device
, -EINVAL
);
1714 assert_return(sysattr
, -EINVAL
);
1716 /* look for possibly already cached result */
1717 r
= device_get_sysattr_value(device
, sysattr
, &cached_value
);
1723 /* we looked up the sysattr before and it did not exist */
1727 *_value
= cached_value
;
1732 r
= sd_device_get_syspath(device
, &syspath
);
1736 path
= strjoina(syspath
, "/", sysattr
);
1737 r
= lstat(path
, &statbuf
);
1739 /* remember that we could not access the sysattr */
1740 r
= device_add_sysattr_value(device
, sysattr
, NULL
);
1745 } else if (S_ISLNK(statbuf
.st_mode
)) {
1746 /* Some core links return only the last element of the target path,
1747 * these are just values, the paths should not be exposed. */
1748 if (STR_IN_SET(sysattr
, "driver", "subsystem", "module")) {
1749 r
= readlink_value(path
, &value
);
1754 } else if (S_ISDIR(statbuf
.st_mode
)) {
1755 /* skip directories */
1757 } else if (!(statbuf
.st_mode
& S_IRUSR
)) {
1758 /* skip non-readable files */
1763 /* read attribute value */
1764 r
= read_full_file(path
, &value
, &size
);
1768 /* drop trailing newlines */
1769 while (size
> 0 && value
[--size
] == '\n')
1773 r
= device_add_sysattr_value(device
, sysattr
, value
);
1783 static void device_remove_sysattr_value(sd_device
*device
, const char *_key
) {
1784 _cleanup_free_
char *key
= NULL
;
1785 _cleanup_free_
char *value
= NULL
;
1790 value
= hashmap_remove2(device
->sysattr_values
, _key
, (void **) &key
);
1795 /* set the attribute and save it in the cache. If a NULL value is passed the
1796 * attribute is cleared from the cache */
1797 _public_
int sd_device_set_sysattr_value(sd_device
*device
, const char *sysattr
, char *_value
) {
1798 _cleanup_close_
int fd
= -1;
1799 _cleanup_free_
char *value
= NULL
;
1800 const char *syspath
;
1802 struct stat statbuf
;
1803 size_t value_len
= 0;
1807 assert_return(device
, -EINVAL
);
1808 assert_return(sysattr
, -EINVAL
);
1811 device_remove_sysattr_value(device
, sysattr
);
1816 r
= sd_device_get_syspath(device
, &syspath
);
1820 path
= strjoina(syspath
, "/", sysattr
);
1821 r
= lstat(path
, &statbuf
);
1827 r
= device_add_sysattr_value(device
, sysattr
, value
);
1834 if (S_ISLNK(statbuf
.st_mode
))
1837 /* skip directories */
1838 if (S_ISDIR(statbuf
.st_mode
))
1841 /* skip non-readable files */
1842 if ((statbuf
.st_mode
& S_IRUSR
) == 0)
1845 value_len
= strlen(_value
);
1847 /* drop trailing newlines */
1848 while (value_len
> 0 && _value
[value_len
- 1] == '\n')
1849 _value
[--value_len
] = '\0';
1851 /* value length is limited to 4k */
1852 if (value_len
> 4096)
1855 fd
= open(path
, O_WRONLY
| O_CLOEXEC
);
1859 value
= strdup(_value
);
1863 size
= write(fd
, value
, value_len
);
1867 if ((size_t)size
!= value_len
)
1870 r
= device_add_sysattr_value(device
, sysattr
, value
);