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);
904 return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
905 } else if (r == -ENOENT)
906 device->driver_set = true;
908 return log_debug_errno(r, "sd-device: could not set driver for %s: %m", device->devpath);
911 *ret = device->driver;
916 _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
917 assert_return(device, -EINVAL);
918 assert_return(devpath, -EINVAL);
920 assert(device->devpath);
921 assert(device->devpath[0] == '/');
923 *devpath = device->devpath;
928 _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
931 assert_return(device, -EINVAL);
932 assert_return(devname, -EINVAL);
934 r = device_read_uevent_file(device);
938 if (!device->devname)
941 assert(path_startswith(device->devname, "/dev/"));
943 *devname = device->devname;
948 static int device_set_sysname(sd_device *device) {
949 _cleanup_free_ char *sysname = NULL;
950 const char *sysnum = NULL;
954 pos = strrchr(device->devpath, '/');
959 /* devpath is not a root directory */
960 if (*pos == '\0' || pos <= device->devpath)
963 sysname = strdup(pos);
967 /* some devices have '!' in their name, change that to '/' */
968 while (sysname[len] != '\0') {
969 if (sysname[len] == '!')
975 /* trailing number */
976 while (len > 0 && isdigit(sysname[--len]))
977 sysnum = &sysname[len];
982 free(device->sysname);
983 device->sysname = sysname;
986 device->sysnum = sysnum;
988 device->sysname_set = true;
993 _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
996 assert_return(device, -EINVAL);
997 assert_return(ret, -EINVAL);
999 if (!device->sysname_set) {
1000 r = device_set_sysname(device);
1005 *ret = device->sysname;
1010 _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
1013 assert_return(device, -EINVAL);
1014 assert_return(ret, -EINVAL);
1016 if (!device->sysname_set) {
1017 r = device_set_sysname(device);
1022 *ret = device->sysnum;
1027 static bool is_valid_tag(const char *tag) {
1030 return !strchr(tag, ':') && !strchr(tag, ' ');
1033 int device_add_tag(sd_device *device, const char *tag) {
1039 if (!is_valid_tag(tag))
1042 r = set_ensure_allocated(&device->tags, &string_hash_ops);
1046 r = set_put_strdup(device->tags, tag);
1050 device->tags_generation ++;
1051 device->property_tags_outdated = true;
1056 int device_add_devlink(sd_device *device, const char *devlink) {
1062 r = set_ensure_allocated(&device->devlinks, &string_hash_ops);
1066 r = set_put_strdup(device->devlinks, devlink);
1070 device->devlinks_generation ++;
1071 device->property_devlinks_outdated = true;
1076 static int device_add_property_internal_from_string(sd_device *device, const char *str) {
1077 _cleanup_free_ char *key = NULL;
1087 value = strchr(key, '=');
1093 if (isempty(++value))
1096 return device_add_property_internal(device, key, value);
1099 int device_set_usec_initialized(sd_device *device, const char *initialized) {
1100 uint64_t usec_initialized;
1104 assert(initialized);
1106 r = safe_atou64(initialized, &usec_initialized);
1110 r = device_add_property_internal(device, "USEC_INITIALIZED", initialized);
1114 device->usec_initialized = usec_initialized;
1119 static int handle_db_line(sd_device *device, char key, const char *value) {
1128 r = device_add_tag(device, value);
1134 path = strjoina("/dev/", value);
1135 r = device_add_devlink(device, path);
1141 r = device_add_property_internal_from_string(device, value);
1147 r = device_set_usec_initialized(device, value);
1153 r = safe_atoi(value, &device->devlink_priority);
1159 r = safe_atoi(value, &device->watch_handle);
1165 log_debug("device db: unknown key '%c'", key);
1171 int device_get_id_filename(sd_device *device, const char **ret) {
1175 if (!device->id_filename) {
1176 _cleanup_free_ char *id = NULL;
1177 const char *subsystem;
1181 r = sd_device_get_subsystem(device, &subsystem);
1185 r = sd_device_get_devnum(device, &devnum);
1189 r = sd_device_get_ifindex(device, &ifindex);
1193 if (major(devnum) > 0) {
1196 /* use dev_t -- b259:131072, c254:0 */
1197 r = asprintf(&id, "%c%u:%u",
1198 streq(subsystem, "block") ? 'b' : 'c',
1199 major(devnum), minor(devnum));
1202 } else if (ifindex > 0) {
1203 /* use netdev ifindex -- n3 */
1204 r = asprintf(&id, "n%u", ifindex);
1208 /* use $subsys:$sysname -- pci:0000:00:1f.2
1209 * sysname() has '!' translated, get it from devpath
1211 const char *sysname;
1213 sysname = basename(device->devpath);
1220 r = asprintf(&id, "+%s:%s", subsystem, sysname);
1225 device->id_filename = id;
1229 *ret = device->id_filename;
1234 int device_read_db_aux(sd_device *device, bool force) {
1235 _cleanup_free_ char *db = NULL;
1237 const char *id, *value;
1251 if (device->db_loaded || (!force && device->sealed))
1254 device->db_loaded = true;
1256 r = device_get_id_filename(device, &id);
1260 path = strjoina("/run/udev/data/", id);
1262 r = read_full_file(path, &db, &db_len);
1267 log_debug("sd-device: failed to read db '%s': %s", path, strerror(-r));
1272 /* devices with a database entry are initialized */
1273 device->is_initialized = true;
1275 for (i = 0; i < db_len; i++) {
1278 if (!strchr(NEWLINE, db[i])) {
1287 log_debug("sd-device: ignoring invalid db entry with key '%c'", key);
1289 state = INVALID_LINE;
1304 if (strchr(NEWLINE, db[i]))
1309 if (strchr(NEWLINE, db[i])) {
1311 r = handle_db_line(device, key, value);
1313 log_debug("sd-device: failed to handle db entry '%c:%s': %s", key, value, strerror(-r));
1320 assert_not_reached("invalid state when parsing db");
1327 static int device_read_db(sd_device *device) {
1328 return device_read_db_aux(device, false);
1331 _public_ int sd_device_get_is_initialized(sd_device *device, int *initialized) {
1334 assert_return(device, -EINVAL);
1335 assert_return(initialized, -EINVAL);
1337 r = device_read_db(device);
1341 *initialized = device->is_initialized;
1346 _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
1350 assert_return(device, -EINVAL);
1351 assert_return(usec, -EINVAL);
1353 r = device_read_db(device);
1357 if (!device->is_initialized)
1360 if (!device->usec_initialized)
1363 now_ts = now(clock_boottime_or_monotonic());
1365 if (now_ts < device->usec_initialized)
1368 *usec = now_ts - device->usec_initialized;
1373 _public_ const char *sd_device_get_tag_first(sd_device *device) {
1376 assert_return(device, NULL);
1378 (void) device_read_db(device);
1380 device->tags_iterator_generation = device->tags_generation;
1381 device->tags_iterator = ITERATOR_FIRST;
1383 set_iterate(device->tags, &device->tags_iterator, &v);
1387 _public_ const char *sd_device_get_tag_next(sd_device *device) {
1390 assert_return(device, NULL);
1392 (void) device_read_db(device);
1394 if (device->tags_iterator_generation != device->tags_generation)
1397 set_iterate(device->tags, &device->tags_iterator, &v);
1401 _public_ const char *sd_device_get_devlink_first(sd_device *device) {
1404 assert_return(device, NULL);
1406 (void) device_read_db(device);
1408 device->devlinks_iterator_generation = device->devlinks_generation;
1409 device->devlinks_iterator = ITERATOR_FIRST;
1411 set_iterate(device->devlinks, &device->devlinks_iterator, &v);
1415 _public_ const char *sd_device_get_devlink_next(sd_device *device) {
1418 assert_return(device, NULL);
1420 (void) device_read_db(device);
1422 if (device->devlinks_iterator_generation != device->devlinks_generation)
1425 set_iterate(device->devlinks, &device->devlinks_iterator, &v);
1429 static int device_properties_prepare(sd_device *device) {
1434 r = device_read_uevent_file(device);
1438 r = device_read_db(device);
1442 if (device->property_devlinks_outdated) {
1443 char *devlinks = NULL;
1444 const char *devlink;
1446 devlink = sd_device_get_devlink_first(device);
1448 devlinks = strdupa(devlink);
1450 while ((devlink = sd_device_get_devlink_next(device)))
1451 devlinks = strjoina(devlinks, " ", devlink);
1453 r = device_add_property_internal(device, "DEVLINKS", devlinks);
1457 device->property_devlinks_outdated = false;
1460 if (device->property_tags_outdated) {
1464 tag = sd_device_get_tag_first(device);
1466 tags = strjoina(":", tag);
1468 while ((tag = sd_device_get_tag_next(device)))
1469 tags = strjoina(tags, ":", tag);
1471 tags = strjoina(tags, ":");
1473 r = device_add_property_internal(device, "TAGS", tags);
1477 device->property_tags_outdated = false;
1483 _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
1488 assert_return(device, NULL);
1490 r = device_properties_prepare(device);
1494 device->properties_iterator_generation = device->properties_generation;
1495 device->properties_iterator = ITERATOR_FIRST;
1497 ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
1505 _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
1510 assert_return(device, NULL);
1512 r = device_properties_prepare(device);
1516 if (device->properties_iterator_generation != device->properties_generation)
1519 ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
1527 static int device_sysattrs_read_all(sd_device *device) {
1528 _cleanup_closedir_ DIR *dir = NULL;
1529 const char *syspath;
1530 struct dirent *dent;
1535 if (device->sysattrs_read)
1538 r = sd_device_get_syspath(device, &syspath);
1542 dir = opendir(syspath);
1546 r = set_ensure_allocated(&device->sysattrs, &string_hash_ops);
1550 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
1552 struct stat statbuf;
1554 /* only handle symlinks and regular files */
1555 if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
1558 path = strjoina(syspath, "/", dent->d_name);
1560 if (lstat(path, &statbuf) != 0)
1563 if (!(statbuf.st_mode & S_IRUSR))
1566 r = set_put_strdup(device->sysattrs, dent->d_name);
1571 device->sysattrs_read = true;
1576 _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
1580 assert_return(device, NULL);
1582 if (!device->sysattrs_read) {
1583 r = device_sysattrs_read_all(device);
1590 device->sysattrs_iterator = ITERATOR_FIRST;
1592 set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
1596 _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
1599 assert_return(device, NULL);
1601 if (!device->sysattrs_read)
1604 set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
1608 _public_ int sd_device_has_tag(sd_device *device, const char *tag) {
1609 assert_return(device, -EINVAL);
1610 assert_return(tag, -EINVAL);
1612 (void) device_read_db(device);
1614 return !!set_contains(device->tags, tag);
1617 _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) {
1621 assert_return(device, -EINVAL);
1622 assert_return(key, -EINVAL);
1623 assert_return(_value, -EINVAL);
1625 r = device_properties_prepare(device);
1629 value = ordered_hashmap_get(device->properties, key);
1638 /* replaces the value if it already exists */
1639 static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) {
1640 _cleanup_free_ char *key = NULL;
1641 _cleanup_free_ char *value_old = NULL;
1647 r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops);
1651 value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key);
1658 r = hashmap_put(device->sysattr_values, key, value);
1667 static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) {
1668 const char *key = NULL, *value;
1673 value = hashmap_get2(device->sysattr_values, _key, (void **) &key);
1683 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1684 * with a NULL value in the cache, otherwise the returned string is stored */
1685 _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) {
1686 _cleanup_free_ char *value = NULL;
1687 const char *syspath, *cached_value = NULL;
1689 struct stat statbuf;
1692 assert_return(device, -EINVAL);
1693 assert_return(sysattr, -EINVAL);
1695 /* look for possibly already cached result */
1696 r = device_get_sysattr_value(device, sysattr, &cached_value);
1702 /* we looked up the sysattr before and it did not exist */
1706 *_value = cached_value;
1711 r = sd_device_get_syspath(device, &syspath);
1715 path = strjoina(syspath, "/", sysattr);
1716 r = lstat(path, &statbuf);
1718 /* remember that we could not access the sysattr */
1719 r = device_add_sysattr_value(device, sysattr, NULL);
1724 } else if (S_ISLNK(statbuf.st_mode)) {
1725 /* Some core links return only the last element of the target path,
1726 * these are just values, the paths should not be exposed. */
1727 if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) {
1728 r = readlink_value(path, &value);
1733 } else if (S_ISDIR(statbuf.st_mode)) {
1734 /* skip directories */
1736 } else if (!(statbuf.st_mode & S_IRUSR)) {
1737 /* skip non-readable files */
1742 /* read attribute value */
1743 r = read_full_file(path, &value, &size);
1747 /* drop trailing newlines */
1748 while (size > 0 && value[--size] == '\n')
1752 r = device_add_sysattr_value(device, sysattr, value);
1762 static void device_remove_sysattr_value(sd_device *device, const char *_key) {
1763 _cleanup_free_ char *key = NULL;
1764 _cleanup_free_ char *value = NULL;
1769 value = hashmap_remove2(device->sysattr_values, _key, (void **) &key);
1774 /* set the attribute and save it in the cache. If a NULL value is passed the
1775 * attribute is cleared from the cache */
1776 _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, char *_value) {
1777 _cleanup_close_ int fd = -1;
1778 _cleanup_free_ char *value = NULL;
1779 const char *syspath;
1781 struct stat statbuf;
1782 size_t value_len = 0;
1786 assert_return(device, -EINVAL);
1787 assert_return(sysattr, -EINVAL);
1790 device_remove_sysattr_value(device, sysattr);
1795 r = sd_device_get_syspath(device, &syspath);
1799 path = strjoina(syspath, "/", sysattr);
1800 r = lstat(path, &statbuf);
1806 r = device_add_sysattr_value(device, sysattr, value);
1813 if (S_ISLNK(statbuf.st_mode))
1816 /* skip directories */
1817 if (S_ISDIR(statbuf.st_mode))
1820 /* skip non-readable files */
1821 if ((statbuf.st_mode & S_IRUSR) == 0)
1824 value_len = strlen(_value);
1826 /* drop trailing newlines */
1827 while (value_len > 0 && _value[value_len - 1] == '\n')
1828 _value[--value_len] = '\0';
1830 /* value length is limited to 4k */
1831 if (value_len > 4096)
1834 fd = open(path, O_WRONLY | O_CLOEXEC);
1838 value = strdup(_value);
1842 size = write(fd, value, value_len);
1846 if ((size_t)size != value_len)
1849 r = device_add_sysattr_value(device, sysattr, value);