2 This file is part of systemd.
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/types.h>
27 #include "path-util.h"
34 #include "sd-device.h"
36 #include "device-util.h"
37 #include "device-private.h"
38 #include "device-internal.h"
40 int device_new_aux(sd_device **ret) {
41 _cleanup_device_unref_ sd_device *device = NULL;
45 device = new0(sd_device, 1);
50 device->watch_handle = -1;
58 _public_ sd_device *sd_device_ref(sd_device *device) {
60 assert_se(++ device->n_ref >= 2);
65 _public_ sd_device *sd_device_unref(sd_device *device) {
66 if (device && -- device->n_ref == 0) {
67 sd_device_unref(device->parent);
68 free(device->syspath);
69 free(device->sysname);
70 free(device->devtype);
71 free(device->devname);
72 free(device->subsystem);
74 free(device->id_filename);
75 free(device->properties_strv);
76 free(device->properties_nulstr);
78 ordered_hashmap_free_free_free(device->properties);
79 ordered_hashmap_free_free_free(device->properties_db);
80 hashmap_free_free_free(device->sysattr_values);
81 set_free_free(device->sysattrs);
82 set_free_free(device->tags);
83 set_free_free(device->devlinks);
91 int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) {
92 OrderedHashmap **properties;
98 properties = &device->properties_db;
100 properties = &device->properties;
103 _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL;
106 r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops);
114 value = strdup(_value);
118 old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key);
120 r = ordered_hashmap_replace(*properties, key, value);
127 _cleanup_free_ char *key = NULL;
128 _cleanup_free_ char *value = NULL;
130 value = ordered_hashmap_remove2(*properties, _key, (void**) &key);
134 device->properties_generation ++;
135 device->properties_buf_outdated = true;
141 int device_add_property_internal(sd_device *device, const char *key, const char *value) {
142 return device_add_property_aux(device, key, value, false);
145 int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
146 _cleanup_free_ char *syspath = NULL;
153 /* must be a subdirectory of /sys */
154 if (!path_startswith(_syspath, "/sys/")) {
155 log_debug("sd-device: syspath '%s' is not a subdirectory of /sys", _syspath);
160 r = readlink_and_canonicalize(_syspath, &syspath);
162 /* the device does not exist (any more?) */
164 else if (r == -EINVAL) {
166 syspath = canonicalize_file_name(_syspath);
169 /* the device does not exist (any more?) */
172 log_debug("sd-device: could not canonicalize '%s': %m", _syspath);
176 log_debug("sd-device: could not get target of '%s': %s", _syspath, strerror(-r));
180 if (path_startswith(syspath, "/sys/devices/")) {
183 /* all 'devices' require an 'uevent' file */
184 path = strjoina(syspath, "/uevent");
185 r = access(path, F_OK);
188 /* this is not a valid device */
191 log_debug("sd-device: %s does not have an uevent file: %m", syspath);
195 /* everything else just just needs to be a directory */
196 if (!is_dir(syspath, false))
200 syspath = strdup(_syspath);
205 devpath = syspath + strlen("/sys");
207 r = device_add_property_internal(device, "DEVPATH", devpath);
211 free(device->syspath);
212 device->syspath = syspath;
215 device->devpath = devpath;
220 _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
221 _cleanup_device_unref_ sd_device *device = NULL;
224 assert_return(ret, -EINVAL);
225 assert_return(syspath, -EINVAL);
227 r = device_new_aux(&device);
231 r = device_set_syspath(device, syspath, true);
241 _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) {
243 char id[DECIMAL_STR_MAX(unsigned) * 2 + 1];
245 assert_return(ret, -EINVAL);
246 assert_return(type == 'b' || type == 'c', -EINVAL);
248 /* use /sys/dev/{block,char}/<maj>:<min> link */
249 snprintf(id, sizeof(id), "%u:%u", major(devnum), minor(devnum));
251 syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id);
253 return sd_device_new_from_syspath(ret, syspath);
256 _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) {
259 assert_return(ret, -EINVAL);
260 assert_return(subsystem, -EINVAL);
261 assert_return(sysname, -EINVAL);
263 if (streq(subsystem, "subsystem")) {
264 syspath = strjoina("/sys/subsystem/", sysname);
265 if (access(syspath, F_OK) >= 0)
266 return sd_device_new_from_syspath(ret, syspath);
268 syspath = strjoina("/sys/bus/", sysname);
269 if (access(syspath, F_OK) >= 0)
270 return sd_device_new_from_syspath(ret, syspath);
272 syspath = strjoina("/sys/class/", sysname);
273 if (access(syspath, F_OK) >= 0)
274 return sd_device_new_from_syspath(ret, syspath);
275 } else if (streq(subsystem, "module")) {
276 syspath = strjoina("/sys/module/", sysname);
277 if (access(syspath, F_OK) >= 0)
278 return sd_device_new_from_syspath(ret, syspath);
279 } else if (streq(subsystem, "drivers")) {
280 char subsys[PATH_MAX];
283 strscpy(subsys, sizeof(subsys), sysname);
284 driver = strchr(subsys, ':');
289 syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver);
290 if (access(syspath, F_OK) >= 0)
291 return sd_device_new_from_syspath(ret, syspath);
293 syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver);
294 if (access(syspath, F_OK) >= 0)
295 return sd_device_new_from_syspath(ret, syspath);
299 syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", sysname);
300 if (access(syspath, F_OK) >= 0)
301 return sd_device_new_from_syspath(ret, syspath);
303 syspath = strjoina("/sys/bus/", subsystem, "/devices/", sysname);
304 if (access(syspath, F_OK) >= 0)
305 return sd_device_new_from_syspath(ret, syspath);
307 syspath = strjoina("/sys/class/", subsystem, "/", sysname);
308 if (access(syspath, F_OK) >= 0)
309 return sd_device_new_from_syspath(ret, syspath);
315 int device_set_devtype(sd_device *device, const char *_devtype) {
316 _cleanup_free_ char *devtype = NULL;
322 devtype = strdup(_devtype);
326 r = device_add_property_internal(device, "DEVTYPE", devtype);
330 free(device->devtype);
331 device->devtype = devtype;
337 int device_set_ifindex(sd_device *device, const char *_ifindex) {
343 r = safe_atoi(_ifindex, &ifindex);
350 r = device_add_property_internal(device, "IFINDEX", _ifindex);
354 device->ifindex = ifindex;
359 int device_set_devname(sd_device *device, const char *_devname) {
360 _cleanup_free_ char *devname = NULL;
366 if (_devname[0] != '/') {
367 r = asprintf(&devname, "/dev/%s", _devname);
371 devname = strdup(_devname);
376 r = device_add_property_internal(device, "DEVNAME", devname);
380 free(device->devname);
381 device->devname = devname;
387 int device_set_devmode(sd_device *device, const char *_devmode) {
394 r = safe_atou(_devmode, &devmode);
401 r = device_add_property_internal(device, "DEVMODE", _devmode);
405 device->devmode = devmode;
410 int device_set_devnum(sd_device *device, const char *major, const char *minor) {
411 unsigned maj = 0, min = 0;
417 r = safe_atou(major, &maj);
424 r = safe_atou(minor, &min);
429 r = device_add_property_internal(device, "MAJOR", major);
434 r = device_add_property_internal(device, "MINOR", minor);
439 device->devnum = makedev(maj, min);
444 static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) {
453 if (streq(key, "DEVTYPE")) {
454 r = device_set_devtype(device, value);
457 } else if (streq(key, "IFINDEX")) {
458 r = device_set_ifindex(device, value);
461 } else if (streq(key, "DEVNAME")) {
462 r = device_set_devname(device, value);
465 } else if (streq(key, "DEVMODE")) {
466 r = device_set_devmode(device, value);
469 } else if (streq(key, "MAJOR"))
471 else if (streq(key, "MINOR"))
474 r = device_add_property_internal(device, key, value);
482 int device_read_uevent_file(sd_device *device) {
483 _cleanup_free_ char *uevent = NULL;
484 const char *syspath, *key, *value, *major = NULL, *minor = NULL;
500 if (device->uevent_loaded || device->sealed)
503 device->uevent_loaded = true;
505 r = sd_device_get_syspath(device, &syspath);
509 path = strjoina(syspath, "/uevent");
511 r = read_full_file(path, &uevent, &uevent_len);
513 /* empty uevent files may be write-only */
515 else if (r == -ENOENT)
516 /* some devices may not have uevent files, see set_syspath() */
519 log_debug("sd-device: failed to read uevent file '%s': %s", path, strerror(-r));
523 for (i = 0; i < uevent_len; i++) {
526 if (!strchr(NEWLINE, uevent[i])) {
534 if (uevent[i] == '=') {
538 } else if (strchr(NEWLINE, uevent[i])) {
540 log_debug("sd-device: ignoring invalid uevent line '%s'", key);
553 if (strchr(NEWLINE, uevent[i])) {
556 r = handle_uevent_line(device, key, value, &major, &minor);
558 log_debug("sd-device: failed to handle uevent entry '%s=%s': %s", key, value, strerror(-r));
565 assert_not_reached("invalid state when parsing uevent file");
570 r = device_set_devnum(device, major, minor);
572 log_debug("sd-device: could not set 'MAJOR=%s' or 'MINOR=%s' from '%s': %s", major, minor, path, strerror(-r));
578 _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
581 assert_return(device, -EINVAL);
582 assert_return(ifindex, -EINVAL);
584 r = device_read_uevent_file(device);
588 *ifindex = device->ifindex;
593 _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
596 assert_return(ret, -EINVAL);
597 assert_return(id, -EINVAL);
606 r = sscanf(id, "%c%i:%i", &type, &maj, &min);
610 return sd_device_new_from_devnum(ret, type, makedev(maj, min));
614 _cleanup_device_unref_ sd_device *device = NULL;
615 _cleanup_close_ int sk = -1;
616 struct ifreq ifr = {};
619 r = safe_atoi(&id[1], &ifr.ifr_ifindex);
622 else if (ifr.ifr_ifindex <= 0)
625 sk = socket(PF_INET, SOCK_DGRAM, 0);
629 r = ioctl(sk, SIOCGIFNAME, &ifr);
633 r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name);
637 r = sd_device_get_ifindex(device, &ifindex);
641 /* this is racey, so we might end up with the wrong device */
642 if (ifr.ifr_ifindex != ifindex)
652 char subsys[PATH_MAX];
655 (void)strscpy(subsys, sizeof(subsys), id + 1);
656 sysname = strchr(subsys, ':');
663 return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
670 _public_ int sd_device_get_syspath(sd_device *device, const char **ret) {
671 assert_return(device, -EINVAL);
672 assert_return(ret, -EINVAL);
674 assert(path_startswith(device->syspath, "/sys/"));
676 *ret = device->syspath;
681 static int device_new_from_child(sd_device **ret, sd_device *child) {
682 _cleanup_free_ char *path = NULL;
683 const char *subdir, *syspath;
689 r = sd_device_get_syspath(child, &syspath);
693 path = strdup(syspath);
696 subdir = path + strlen("/sys");
701 pos = strrchr(subdir, '/');
702 if (!pos || pos < subdir + 2)
707 r = sd_device_new_from_syspath(ret, path);
717 _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
719 assert_return(ret, -EINVAL);
720 assert_return(child, -EINVAL);
722 if (!child->parent_set) {
723 child->parent_set = true;
725 (void)device_new_from_child(&child->parent, child);
731 *ret = child->parent;
736 int device_set_subsystem(sd_device *device, const char *_subsystem) {
737 _cleanup_free_ char *subsystem = NULL;
743 subsystem = strdup(_subsystem);
747 r = device_add_property_internal(device, "SUBSYSTEM", subsystem);
751 free(device->subsystem);
752 device->subsystem = subsystem;
755 device->subsystem_set = true;
760 _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
761 assert_return(ret, -EINVAL);
762 assert_return(device, -EINVAL);
764 if (!device->subsystem_set) {
765 _cleanup_free_ char *subsystem = NULL;
770 /* read 'subsystem' link */
771 r = sd_device_get_syspath(device, &syspath);
775 path = strjoina(syspath, "/subsystem");
776 r = readlink_value(path, &subsystem);
778 r = device_set_subsystem(device, subsystem);
779 /* use implicit names */
780 else if (path_startswith(device->devpath, "/module/"))
781 r = device_set_subsystem(device, "module");
782 else if (strstr(device->devpath, "/drivers/"))
783 r = device_set_subsystem(device, "drivers");
784 else if (path_startswith(device->devpath, "/subsystem/") ||
785 path_startswith(device->devpath, "/class/") ||
786 path_startswith(device->devpath, "/bus/"))
787 r = device_set_subsystem(device, "subsystem");
788 if (r < 0 && r != -ENOENT)
789 return log_debug_errno(r, "sd-device: could not set subsystem for %s: %m", device->devpath);
791 device->subsystem_set = true;
794 *ret = device->subsystem;
799 _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) {
805 r = device_read_uevent_file(device);
809 *devtype = device->devtype;
814 _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) {
815 sd_device *parent = NULL;
818 assert_return(child, -EINVAL);
819 assert_return(subsystem, -EINVAL);
821 r = sd_device_get_parent(child, &parent);
823 const char *parent_subsystem = NULL;
824 const char *parent_devtype = NULL;
826 (void)sd_device_get_subsystem(parent, &parent_subsystem);
827 if (streq_ptr(parent_subsystem, subsystem)) {
831 (void)sd_device_get_devtype(parent, &parent_devtype);
832 if (streq_ptr(parent_devtype, devtype))
835 r = sd_device_get_parent(parent, &parent);
846 _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
849 assert_return(device, -EINVAL);
850 assert_return(devnum, -EINVAL);
852 r = device_read_uevent_file(device);
856 *devnum = device->devnum;
861 int device_set_driver(sd_device *device, const char *_driver) {
862 _cleanup_free_ char *driver = NULL;
868 driver = strdup(_driver);
872 r = device_add_property_internal(device, "DRIVER", driver);
876 free(device->driver);
877 device->driver = driver;
880 device->driver_set = true;
885 _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
886 assert_return(device, -EINVAL);
887 assert_return(ret, -EINVAL);
889 if (!device->driver_set) {
890 _cleanup_free_ char *driver = NULL;
895 r = sd_device_get_syspath(device, &syspath);
899 path = strjoina(syspath, "/driver");
900 r = readlink_value(path, &driver);
902 r = device_set_driver(device, driver);
908 *ret = device->driver;
913 _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
914 assert_return(device, -EINVAL);
915 assert_return(devpath, -EINVAL);
917 assert(device->devpath);
918 assert(device->devpath[0] == '/');
920 *devpath = device->devpath;
925 _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
928 assert_return(device, -EINVAL);
929 assert_return(devname, -EINVAL);
931 r = device_read_uevent_file(device);
935 if (!device->devname)
938 assert(path_startswith(device->devname, "/dev/"));
940 *devname = device->devname;
945 static int device_set_sysname(sd_device *device) {
946 _cleanup_free_ char *sysname = NULL;
947 const char *sysnum = NULL;
951 pos = strrchr(device->devpath, '/');
956 /* devpath is not a root directory */
957 if (*pos == '\0' || pos <= device->devpath)
960 sysname = strdup(pos);
964 /* some devices have '!' in their name, change that to '/' */
965 while (sysname[len] != '\0') {
966 if (sysname[len] == '!')
972 /* trailing number */
973 while (len > 0 && isdigit(sysname[--len]))
974 sysnum = &sysname[len];
979 free(device->sysname);
980 device->sysname = sysname;
983 device->sysnum = sysnum;
985 device->sysname_set = true;
990 _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
993 assert_return(device, -EINVAL);
994 assert_return(ret, -EINVAL);
996 if (!device->sysname_set) {
997 r = device_set_sysname(device);
1002 *ret = device->sysname;
1007 _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
1010 assert_return(device, -EINVAL);
1011 assert_return(ret, -EINVAL);
1013 if (!device->sysname_set) {
1014 r = device_set_sysname(device);
1019 *ret = device->sysnum;
1024 static bool is_valid_tag(const char *tag) {
1027 return !strchr(tag, ':') && !strchr(tag, ' ');
1030 int device_add_tag(sd_device *device, const char *tag) {
1036 if (!is_valid_tag(tag))
1039 r = set_ensure_allocated(&device->tags, &string_hash_ops);
1043 r = set_put_strdup(device->tags, tag);
1047 device->tags_generation ++;
1048 device->property_tags_outdated = true;
1053 int device_add_devlink(sd_device *device, const char *devlink) {
1059 r = set_ensure_allocated(&device->devlinks, &string_hash_ops);
1063 r = set_put_strdup(device->devlinks, devlink);
1067 device->devlinks_generation ++;
1068 device->property_devlinks_outdated = true;
1073 static int device_add_property_internal_from_string(sd_device *device, const char *str) {
1074 _cleanup_free_ char *key = NULL;
1084 value = strchr(key, '=');
1090 if (isempty(++value))
1093 return device_add_property_internal(device, key, value);
1096 int device_set_usec_initialized(sd_device *device, const char *initialized) {
1097 uint64_t usec_initialized;
1101 assert(initialized);
1103 r = safe_atou64(initialized, &usec_initialized);
1107 r = device_add_property_internal(device, "USEC_INITIALIZED", initialized);
1111 device->usec_initialized = usec_initialized;
1116 static int handle_db_line(sd_device *device, char key, const char *value) {
1125 r = device_add_tag(device, value);
1131 path = strjoina("/dev/", value);
1132 r = device_add_devlink(device, path);
1138 r = device_add_property_internal_from_string(device, value);
1144 r = device_set_usec_initialized(device, value);
1150 r = safe_atoi(value, &device->devlink_priority);
1156 r = safe_atoi(value, &device->watch_handle);
1162 log_debug("device db: unknown key '%c'", key);
1168 int device_get_id_filename(sd_device *device, const char **ret) {
1172 if (!device->id_filename) {
1173 _cleanup_free_ char *id = NULL;
1174 const char *subsystem;
1178 r = sd_device_get_subsystem(device, &subsystem);
1182 r = sd_device_get_devnum(device, &devnum);
1186 r = sd_device_get_ifindex(device, &ifindex);
1190 if (major(devnum) > 0) {
1193 /* use dev_t -- b259:131072, c254:0 */
1194 r = asprintf(&id, "%c%u:%u",
1195 streq(subsystem, "block") ? 'b' : 'c',
1196 major(devnum), minor(devnum));
1199 } else if (ifindex > 0) {
1200 /* use netdev ifindex -- n3 */
1201 r = asprintf(&id, "n%u", ifindex);
1205 /* use $subsys:$sysname -- pci:0000:00:1f.2
1206 * sysname() has '!' translated, get it from devpath
1208 const char *sysname;
1210 sysname = basename(device->devpath);
1217 r = asprintf(&id, "+%s:%s", subsystem, sysname);
1222 device->id_filename = id;
1226 *ret = device->id_filename;
1231 int device_read_db_aux(sd_device *device, bool force) {
1232 _cleanup_free_ char *db = NULL;
1234 const char *id, *value;
1248 if (device->db_loaded || (!force && device->sealed))
1251 device->db_loaded = true;
1253 r = device_get_id_filename(device, &id);
1257 path = strjoina("/run/udev/data/", id);
1259 r = read_full_file(path, &db, &db_len);
1264 log_debug("sd-device: failed to read db '%s': %s", path, strerror(-r));
1269 /* devices with a database entry are initialized */
1270 device->is_initialized = true;;
1272 for (i = 0; i < db_len; i++) {
1275 if (!strchr(NEWLINE, db[i])) {
1284 log_debug("sd-device: ignoring invalid db entry with key '%c'", key);
1286 state = INVALID_LINE;
1301 if (strchr(NEWLINE, db[i]))
1306 if (strchr(NEWLINE, db[i])) {
1308 r = handle_db_line(device, key, value);
1310 log_debug("sd-device: failed to handle db entry '%c:%s': %s", key, value, strerror(-r));
1317 assert_not_reached("invalid state when parsing db");
1324 static int device_read_db(sd_device *device) {
1325 return device_read_db_aux(device, false);
1328 _public_ int sd_device_get_is_initialized(sd_device *device, int *initialized) {
1331 assert_return(device, -EINVAL);
1332 assert_return(initialized, -EINVAL);
1334 r = device_read_db(device);
1338 *initialized = device->is_initialized;
1343 _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
1347 assert_return(device, -EINVAL);
1348 assert_return(usec, -EINVAL);
1350 r = device_read_db(device);
1354 if (!device->is_initialized)
1357 if (!device->usec_initialized)
1360 now_ts = now(clock_boottime_or_monotonic());
1362 if (now_ts < device->usec_initialized)
1365 *usec = now_ts - device->usec_initialized;
1370 _public_ const char *sd_device_get_tag_first(sd_device *device) {
1371 assert_return(device, NULL);
1373 (void) device_read_db(device);
1375 device->tags_iterator_generation = device->tags_generation;
1376 device->tags_iterator = ITERATOR_FIRST;
1378 return set_iterate(device->tags, &device->tags_iterator);
1381 _public_ const char *sd_device_get_tag_next(sd_device *device) {
1382 assert_return(device, NULL);
1384 (void) device_read_db(device);
1386 if (device->tags_iterator_generation != device->tags_generation)
1389 return set_iterate(device->tags, &device->tags_iterator);
1392 _public_ const char *sd_device_get_devlink_first(sd_device *device) {
1393 assert_return(device, NULL);
1395 (void) device_read_db(device);
1397 device->devlinks_iterator_generation = device->devlinks_generation;
1398 device->devlinks_iterator = ITERATOR_FIRST;
1400 return set_iterate(device->devlinks, &device->devlinks_iterator);
1403 _public_ const char *sd_device_get_devlink_next(sd_device *device) {
1404 assert_return(device, NULL);
1406 (void) device_read_db(device);
1408 if (device->devlinks_iterator_generation != device->devlinks_generation)
1411 return set_iterate(device->devlinks, &device->devlinks_iterator);
1414 static int device_properties_prepare(sd_device *device) {
1419 r = device_read_uevent_file(device);
1423 r = device_read_db(device);
1427 if (device->property_devlinks_outdated) {
1428 char *devlinks = NULL;
1429 const char *devlink;
1431 devlink = sd_device_get_devlink_first(device);
1433 devlinks = strdupa(devlink);
1435 while ((devlink = sd_device_get_devlink_next(device)))
1436 devlinks = strjoina(devlinks, " ", devlink);
1438 r = device_add_property_internal(device, "DEVLINKS", devlinks);
1442 device->property_devlinks_outdated = false;
1445 if (device->property_tags_outdated) {
1449 tag = sd_device_get_tag_first(device);
1451 tags = strjoina(":", tag);
1453 while ((tag = sd_device_get_tag_next(device)))
1454 tags = strjoina(tags, ":", tag);
1456 tags = strjoina(tags, ":");
1458 r = device_add_property_internal(device, "TAGS", tags);
1462 device->property_tags_outdated = false;
1468 _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
1473 assert_return(device, NULL);
1475 r = device_properties_prepare(device);
1479 device->properties_iterator_generation = device->properties_generation;
1480 device->properties_iterator = ITERATOR_FIRST;
1482 value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key);
1490 _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
1495 assert_return(device, NULL);
1497 r = device_properties_prepare(device);
1501 if (device->properties_iterator_generation != device->properties_generation)
1504 value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key);
1512 static int device_sysattrs_read_all(sd_device *device) {
1513 _cleanup_closedir_ DIR *dir = NULL;
1514 const char *syspath;
1515 struct dirent *dent;
1520 if (device->sysattrs_read)
1523 r = sd_device_get_syspath(device, &syspath);
1527 dir = opendir(syspath);
1531 r = set_ensure_allocated(&device->sysattrs, &string_hash_ops);
1535 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
1537 struct stat statbuf;
1539 /* only handle symlinks and regular files */
1540 if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
1543 path = strjoina(syspath, "/", dent->d_name);
1545 if (lstat(path, &statbuf) != 0)
1548 if (!(statbuf.st_mode & S_IRUSR))
1551 r = set_put_strdup(device->sysattrs, dent->d_name);
1556 device->sysattrs_read = true;
1561 _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
1564 assert_return(device, NULL);
1566 if (!device->sysattrs_read) {
1567 r = device_sysattrs_read_all(device);
1574 device->sysattrs_iterator = ITERATOR_FIRST;
1576 return set_iterate(device->sysattrs, &device->sysattrs_iterator);
1579 _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
1580 assert_return(device, NULL);
1582 if (!device->sysattrs_read)
1585 return set_iterate(device->sysattrs, &device->sysattrs_iterator);
1588 _public_ int sd_device_has_tag(sd_device *device, const char *tag) {
1589 assert_return(device, -EINVAL);
1590 assert_return(tag, -EINVAL);
1592 (void) device_read_db(device);
1594 return !!set_contains(device->tags, tag);
1597 _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) {
1601 assert_return(device, -EINVAL);
1602 assert_return(key, -EINVAL);
1603 assert_return(_value, -EINVAL);
1605 r = device_properties_prepare(device);
1609 value = ordered_hashmap_get(device->properties, key);
1618 /* replaces the value if it already exists */
1619 static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) {
1620 _cleanup_free_ char *key = NULL;
1621 _cleanup_free_ char *value_old = NULL;
1627 r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops);
1631 value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key);
1638 r = hashmap_put(device->sysattr_values, key, value);
1647 static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) {
1648 const char *key = NULL, *value;
1653 value = hashmap_get2(device->sysattr_values, _key, (void **) &key);
1663 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1664 * with a NULL value in the cache, otherwise the returned string is stored */
1665 _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) {
1666 _cleanup_free_ char *value = NULL;
1667 const char *syspath, *cached_value = NULL;
1669 struct stat statbuf;
1672 assert_return(device, -EINVAL);
1673 assert_return(sysattr, -EINVAL);
1675 /* look for possibly already cached result */
1676 r = device_get_sysattr_value(device, sysattr, &cached_value);
1682 /* we looked up the sysattr before and it did not exist */
1686 *_value = cached_value;
1691 r = sd_device_get_syspath(device, &syspath);
1695 path = strjoina(syspath, "/", sysattr);
1696 r = lstat(path, &statbuf);
1698 /* remember that we could not access the sysattr */
1699 r = device_add_sysattr_value(device, sysattr, NULL);
1704 } else if (S_ISLNK(statbuf.st_mode)) {
1705 /* Some core links return only the last element of the target path,
1706 * these are just values, the paths should not be exposed. */
1707 if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) {
1708 r = readlink_value(path, &value);
1713 } else if (S_ISDIR(statbuf.st_mode)) {
1714 /* skip directories */
1716 } else if (!(statbuf.st_mode & S_IRUSR)) {
1717 /* skip non-readable files */
1722 /* read attribute value */
1723 r = read_full_file(path, &value, &size);
1727 /* drop trailing newlines */
1728 while (size > 0 && value[--size] == '\n')
1732 r = device_add_sysattr_value(device, sysattr, value);
1742 static void device_remove_sysattr_value(sd_device *device, const char *_key) {
1743 _cleanup_free_ char *key = NULL;
1744 _cleanup_free_ char *value = NULL;
1749 value = hashmap_remove2(device->sysattr_values, _key, (void **) &key);
1754 /* set the attribute and save it in the cache. If a NULL value is passed the
1755 * attribute is cleared from the cache */
1756 _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, char *_value) {
1757 _cleanup_close_ int fd = -1;
1758 _cleanup_free_ char *value = NULL;
1759 const char *syspath;
1761 struct stat statbuf;
1762 size_t value_len = 0;
1766 assert_return(device, -EINVAL);
1767 assert_return(sysattr, -EINVAL);
1770 device_remove_sysattr_value(device, sysattr);
1775 r = sd_device_get_syspath(device, &syspath);
1779 path = strjoina(syspath, "/", sysattr);
1780 r = lstat(path, &statbuf);
1786 r = device_add_sysattr_value(device, sysattr, value);
1793 if (S_ISLNK(statbuf.st_mode))
1796 /* skip directories */
1797 if (S_ISDIR(statbuf.st_mode))
1800 /* skip non-readable files */
1801 if ((statbuf.st_mode & S_IRUSR) == 0)
1804 value_len = strlen(_value);
1806 /* drop trailing newlines */
1807 while (value_len > 0 && _value[value_len - 1] == '\n')
1808 _value[--value_len] = '\0';
1810 /* value length is limited to 4k */
1811 if (value_len > 4096)
1814 fd = open(path, O_WRONLY | O_CLOEXEC);
1818 value = strdup(_value);
1822 size = write(fd, value, value_len);
1826 if ((size_t)size != value_len)
1829 r = device_add_sysattr_value(device, sysattr, value);