]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/sd-device.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / libsystemd / sd-device / sd-device.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <ctype.h>
4 #include <net/if.h>
5 #include <sys/ioctl.h>
6 #include <sys/types.h>
7
8 #include "sd-device.h"
9
10 #include "alloc-util.h"
11 #include "device-internal.h"
12 #include "device-private.h"
13 #include "device-util.h"
14 #include "dirent-util.h"
15 #include "fd-util.h"
16 #include "fileio.h"
17 #include "fs-util.h"
18 #include "hashmap.h"
19 #include "macro.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "set.h"
23 #include "socket-util.h"
24 #include "stat-util.h"
25 #include "stdio-util.h"
26 #include "string-util.h"
27 #include "strv.h"
28 #include "strxcpyx.h"
29 #include "util.h"
30
31 int device_new_aux(sd_device **ret) {
32 sd_device *device;
33
34 assert(ret);
35
36 device = new(sd_device, 1);
37 if (!device)
38 return -ENOMEM;
39
40 *device = (sd_device) {
41 .n_ref = 1,
42 .watch_handle = -1,
43 .devmode = (mode_t) -1,
44 .devuid = (uid_t) -1,
45 .devgid = (gid_t) -1,
46 .action = _DEVICE_ACTION_INVALID,
47 };
48
49 *ret = device;
50 return 0;
51 }
52
53 static sd_device *device_free(sd_device *device) {
54 assert(device);
55
56 sd_device_unref(device->parent);
57 free(device->syspath);
58 free(device->sysname);
59 free(device->devtype);
60 free(device->devname);
61 free(device->subsystem);
62 free(device->driver_subsystem);
63 free(device->driver);
64 free(device->id_filename);
65 free(device->properties_strv);
66 free(device->properties_nulstr);
67
68 ordered_hashmap_free_free_free(device->properties);
69 ordered_hashmap_free_free_free(device->properties_db);
70 hashmap_free_free_free(device->sysattr_values);
71 set_free(device->sysattrs);
72 set_free(device->all_tags);
73 set_free(device->current_tags);
74 set_free(device->devlinks);
75
76 return mfree(device);
77 }
78
79 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device, sd_device, device_free);
80
81 int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) {
82 OrderedHashmap **properties;
83
84 assert(device);
85 assert(_key);
86
87 if (db)
88 properties = &device->properties_db;
89 else
90 properties = &device->properties;
91
92 if (_value) {
93 _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL;
94 int r;
95
96 r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops);
97 if (r < 0)
98 return r;
99
100 key = strdup(_key);
101 if (!key)
102 return -ENOMEM;
103
104 value = strdup(_value);
105 if (!value)
106 return -ENOMEM;
107
108 old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key);
109
110 r = ordered_hashmap_replace(*properties, key, value);
111 if (r < 0)
112 return r;
113
114 key = NULL;
115 value = NULL;
116 } else {
117 _cleanup_free_ char *key = NULL;
118 _cleanup_free_ char *value = NULL;
119
120 value = ordered_hashmap_remove2(*properties, _key, (void**) &key);
121 }
122
123 if (!db) {
124 device->properties_generation++;
125 device->properties_buf_outdated = true;
126 }
127
128 return 0;
129 }
130
131 int device_add_property_internal(sd_device *device, const char *key, const char *value) {
132 return device_add_property_aux(device, key, value, false);
133 }
134
135 int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
136 _cleanup_free_ char *syspath = NULL;
137 const char *devpath;
138 int r;
139
140 assert(device);
141 assert(_syspath);
142
143 /* must be a subdirectory of /sys */
144 if (!path_startswith(_syspath, "/sys/"))
145 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
146 "sd-device: Syspath '%s' is not a subdirectory of /sys",
147 _syspath);
148
149 if (verify) {
150 r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL);
151 if (r == -ENOENT)
152 return -ENODEV; /* the device does not exist (any more?) */
153 if (r < 0)
154 return log_debug_errno(r, "sd-device: Failed to get target of '%s': %m", _syspath);
155
156 if (!path_startswith(syspath, "/sys")) {
157 _cleanup_free_ char *real_sys = NULL, *new_syspath = NULL;
158 char *p;
159
160 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
161 r = chase_symlinks("/sys", NULL, 0, &real_sys, NULL);
162 if (r < 0)
163 return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");
164
165 p = path_startswith(syspath, real_sys);
166 if (!p)
167 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
168 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
169 syspath, real_sys);
170
171 new_syspath = path_join("/sys", p);
172 if (!new_syspath)
173 return -ENOMEM;
174
175 free_and_replace(syspath, new_syspath);
176 path_simplify(syspath, false);
177 }
178
179 if (path_startswith(syspath, "/sys/devices/")) {
180 char *path;
181
182 /* all 'devices' require an 'uevent' file */
183 path = strjoina(syspath, "/uevent");
184 r = access(path, F_OK);
185 if (r < 0) {
186 if (errno == ENOENT)
187 /* this is not a valid device */
188 return -ENODEV;
189
190 return log_debug_errno(errno, "sd-device: %s does not have an uevent file: %m", syspath);
191 }
192 } else {
193 /* everything else just needs to be a directory */
194 if (!is_dir(syspath, false))
195 return -ENODEV;
196 }
197 } else {
198 syspath = strdup(_syspath);
199 if (!syspath)
200 return -ENOMEM;
201 }
202
203 devpath = syspath + STRLEN("/sys");
204
205 if (devpath[0] == '\0')
206 /* '/sys' alone is not a valid device path */
207 return -ENODEV;
208
209 r = device_add_property_internal(device, "DEVPATH", devpath);
210 if (r < 0)
211 return r;
212
213 free_and_replace(device->syspath, syspath);
214 device->devpath = devpath;
215 return 0;
216 }
217
218 _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
219 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
220 int r;
221
222 assert_return(ret, -EINVAL);
223 assert_return(syspath, -EINVAL);
224
225 r = device_new_aux(&device);
226 if (r < 0)
227 return r;
228
229 r = device_set_syspath(device, syspath, true);
230 if (r < 0)
231 return r;
232
233 *ret = TAKE_PTR(device);
234 return 0;
235 }
236
237 _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) {
238 char *syspath;
239 char id[DECIMAL_STR_MAX(unsigned) * 2 + 1];
240
241 assert_return(ret, -EINVAL);
242 assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
243
244 /* use /sys/dev/{block,char}/<maj>:<min> link */
245 xsprintf(id, "%u:%u", major(devnum), minor(devnum));
246
247 syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id);
248
249 return sd_device_new_from_syspath(ret, syspath);
250 }
251
252 _public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) {
253 char *name, *syspath;
254 size_t len = 0;
255
256 assert_return(ret, -EINVAL);
257 assert_return(subsystem, -EINVAL);
258 assert_return(sysname, -EINVAL);
259
260 if (streq(subsystem, "subsystem")) {
261 syspath = strjoina("/sys/subsystem/", sysname);
262 if (access(syspath, F_OK) >= 0)
263 return sd_device_new_from_syspath(ret, syspath);
264
265 syspath = strjoina("/sys/bus/", sysname);
266 if (access(syspath, F_OK) >= 0)
267 return sd_device_new_from_syspath(ret, syspath);
268
269 syspath = strjoina("/sys/class/", sysname);
270 if (access(syspath, F_OK) >= 0)
271 return sd_device_new_from_syspath(ret, syspath);
272 } else if (streq(subsystem, "module")) {
273 syspath = strjoina("/sys/module/", sysname);
274 if (access(syspath, F_OK) >= 0)
275 return sd_device_new_from_syspath(ret, syspath);
276 } else if (streq(subsystem, "drivers")) {
277 char subsys[PATH_MAX];
278 char *driver;
279
280 strscpy(subsys, sizeof(subsys), sysname);
281 driver = strchr(subsys, ':');
282 if (driver) {
283 driver[0] = '\0';
284 driver++;
285
286 syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver);
287 if (access(syspath, F_OK) >= 0)
288 return sd_device_new_from_syspath(ret, syspath);
289
290 syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver);
291 if (access(syspath, F_OK) >= 0)
292 return sd_device_new_from_syspath(ret, syspath);
293 }
294 }
295
296 /* translate sysname back to sysfs filename */
297 name = strdupa(sysname);
298 while (name[len] != '\0') {
299 if (name[len] == '/')
300 name[len] = '!';
301
302 len++;
303 }
304
305 syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name);
306 if (access(syspath, F_OK) >= 0)
307 return sd_device_new_from_syspath(ret, syspath);
308
309 syspath = strjoina("/sys/bus/", subsystem, "/devices/", name);
310 if (access(syspath, F_OK) >= 0)
311 return sd_device_new_from_syspath(ret, syspath);
312
313 syspath = strjoina("/sys/class/", subsystem, "/", name);
314 if (access(syspath, F_OK) >= 0)
315 return sd_device_new_from_syspath(ret, syspath);
316
317 syspath = strjoina("/sys/firmware/", subsystem, "/", sysname);
318 if (access(syspath, F_OK) >= 0)
319 return sd_device_new_from_syspath(ret, syspath);
320
321 return -ENODEV;
322 }
323
324 int device_set_devtype(sd_device *device, const char *devtype) {
325 _cleanup_free_ char *t = NULL;
326 int r;
327
328 assert(device);
329 assert(devtype);
330
331 t = strdup(devtype);
332 if (!t)
333 return -ENOMEM;
334
335 r = device_add_property_internal(device, "DEVTYPE", t);
336 if (r < 0)
337 return r;
338
339 return free_and_replace(device->devtype, t);
340 }
341
342 int device_set_ifindex(sd_device *device, const char *name) {
343 int r, ifindex;
344
345 assert(device);
346 assert(name);
347
348 ifindex = parse_ifindex(name);
349 if (ifindex < 0)
350 return ifindex;
351
352 r = device_add_property_internal(device, "IFINDEX", name);
353 if (r < 0)
354 return r;
355
356 device->ifindex = ifindex;
357
358 return 0;
359 }
360
361 int device_set_devname(sd_device *device, const char *devname) {
362 _cleanup_free_ char *t = NULL;
363 int r;
364
365 assert(device);
366 assert(devname);
367
368 if (devname[0] != '/')
369 t = strjoin("/dev/", devname);
370 else
371 t = strdup(devname);
372 if (!t)
373 return -ENOMEM;
374
375 r = device_add_property_internal(device, "DEVNAME", t);
376 if (r < 0)
377 return r;
378
379 return free_and_replace(device->devname, t);
380 }
381
382 int device_set_devmode(sd_device *device, const char *_devmode) {
383 unsigned devmode;
384 int r;
385
386 assert(device);
387 assert(_devmode);
388
389 r = safe_atou(_devmode, &devmode);
390 if (r < 0)
391 return r;
392
393 if (devmode > 07777)
394 return -EINVAL;
395
396 r = device_add_property_internal(device, "DEVMODE", _devmode);
397 if (r < 0)
398 return r;
399
400 device->devmode = devmode;
401
402 return 0;
403 }
404
405 int device_set_devnum(sd_device *device, const char *major, const char *minor) {
406 unsigned maj = 0, min = 0;
407 int r;
408
409 assert(device);
410 assert(major);
411
412 r = safe_atou(major, &maj);
413 if (r < 0)
414 return r;
415 if (!maj)
416 return 0;
417
418 if (minor) {
419 r = safe_atou(minor, &min);
420 if (r < 0)
421 return r;
422 }
423
424 r = device_add_property_internal(device, "MAJOR", major);
425 if (r < 0)
426 return r;
427
428 if (minor) {
429 r = device_add_property_internal(device, "MINOR", minor);
430 if (r < 0)
431 return r;
432 }
433
434 device->devnum = makedev(maj, min);
435
436 return 0;
437 }
438
439 static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) {
440 int r;
441
442 assert(device);
443 assert(key);
444 assert(value);
445 assert(major);
446 assert(minor);
447
448 if (streq(key, "DEVTYPE")) {
449 r = device_set_devtype(device, value);
450 if (r < 0)
451 return r;
452 } else if (streq(key, "IFINDEX")) {
453 r = device_set_ifindex(device, value);
454 if (r < 0)
455 return r;
456 } else if (streq(key, "DEVNAME")) {
457 r = device_set_devname(device, value);
458 if (r < 0)
459 return r;
460 } else if (streq(key, "DEVMODE")) {
461 r = device_set_devmode(device, value);
462 if (r < 0)
463 return r;
464 } else if (streq(key, "MAJOR"))
465 *major = value;
466 else if (streq(key, "MINOR"))
467 *minor = value;
468 else {
469 r = device_add_property_internal(device, key, value);
470 if (r < 0)
471 return r;
472 }
473
474 return 0;
475 }
476
477 int device_read_uevent_file(sd_device *device) {
478 _cleanup_free_ char *uevent = NULL;
479 const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
480 char *path;
481 size_t uevent_len;
482 unsigned i;
483 int r;
484
485 enum {
486 PRE_KEY,
487 KEY,
488 PRE_VALUE,
489 VALUE,
490 INVALID_LINE,
491 } state = PRE_KEY;
492
493 assert(device);
494
495 if (device->uevent_loaded || device->sealed)
496 return 0;
497
498 r = sd_device_get_syspath(device, &syspath);
499 if (r < 0)
500 return r;
501
502 path = strjoina(syspath, "/uevent");
503
504 r = read_full_file(path, &uevent, &uevent_len);
505 if (r == -EACCES) {
506 /* empty uevent files may be write-only */
507 device->uevent_loaded = true;
508 return 0;
509 }
510 if (r == -ENOENT)
511 /* some devices may not have uevent files, see set_syspath() */
512 return 0;
513 if (r < 0)
514 return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path);
515
516 device->uevent_loaded = true;
517
518 for (i = 0; i < uevent_len; i++)
519 switch (state) {
520 case PRE_KEY:
521 if (!strchr(NEWLINE, uevent[i])) {
522 key = &uevent[i];
523
524 state = KEY;
525 }
526
527 break;
528 case KEY:
529 if (uevent[i] == '=') {
530 uevent[i] = '\0';
531
532 state = PRE_VALUE;
533 } else if (strchr(NEWLINE, uevent[i])) {
534 uevent[i] = '\0';
535 log_device_debug(device, "sd-device: Invalid uevent line '%s', ignoring", key);
536
537 state = PRE_KEY;
538 }
539
540 break;
541 case PRE_VALUE:
542 value = &uevent[i];
543 state = VALUE;
544
545 _fallthrough_; /* to handle empty property */
546 case VALUE:
547 if (strchr(NEWLINE, uevent[i])) {
548 uevent[i] = '\0';
549
550 r = handle_uevent_line(device, key, value, &major, &minor);
551 if (r < 0)
552 log_device_debug_errno(device, r, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key, value);
553
554 state = PRE_KEY;
555 }
556
557 break;
558 default:
559 assert_not_reached("Invalid state when parsing uevent file");
560 }
561
562 if (major) {
563 r = device_set_devnum(device, major, minor);
564 if (r < 0)
565 log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, minor, path);
566 }
567
568 return 0;
569 }
570
571 _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
572 int r;
573
574 assert_return(device, -EINVAL);
575
576 r = device_read_uevent_file(device);
577 if (r < 0)
578 return r;
579
580 if (device->ifindex <= 0)
581 return -ENOENT;
582
583 if (ifindex)
584 *ifindex = device->ifindex;
585
586 return 0;
587 }
588
589 _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
590 int r;
591
592 assert_return(ret, -EINVAL);
593 assert_return(id, -EINVAL);
594
595 switch (id[0]) {
596 case 'b':
597 case 'c': {
598 dev_t devt;
599
600 if (isempty(id))
601 return -EINVAL;
602
603 r = parse_dev(id + 1, &devt);
604 if (r < 0)
605 return r;
606
607 return sd_device_new_from_devnum(ret, id[0], devt);
608 }
609
610 case 'n': {
611 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
612 _cleanup_close_ int sk = -1;
613 struct ifreq ifr = {};
614 int ifindex;
615
616 r = ifr.ifr_ifindex = parse_ifindex(&id[1]);
617 if (r < 0)
618 return r;
619
620 sk = socket_ioctl_fd();
621 if (sk < 0)
622 return sk;
623
624 r = ioctl(sk, SIOCGIFNAME, &ifr);
625 if (r < 0)
626 return -errno;
627
628 r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name);
629 if (r < 0)
630 return r;
631
632 r = sd_device_get_ifindex(device, &ifindex);
633 if (r < 0)
634 return r;
635
636 /* this is racey, so we might end up with the wrong device */
637 if (ifr.ifr_ifindex != ifindex)
638 return -ENODEV;
639
640 *ret = TAKE_PTR(device);
641 return 0;
642 }
643
644 case '+': {
645 char subsys[PATH_MAX];
646 char *sysname;
647
648 (void) strscpy(subsys, sizeof(subsys), id + 1);
649 sysname = strchr(subsys, ':');
650 if (!sysname)
651 return -EINVAL;
652
653 sysname[0] = '\0';
654 sysname++;
655
656 return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
657 }
658
659 default:
660 return -EINVAL;
661 }
662 }
663
664 _public_ int sd_device_get_syspath(sd_device *device, const char **ret) {
665 assert_return(device, -EINVAL);
666 assert_return(ret, -EINVAL);
667
668 assert(path_startswith(device->syspath, "/sys/"));
669
670 *ret = device->syspath;
671
672 return 0;
673 }
674
675 static int device_new_from_child(sd_device **ret, sd_device *child) {
676 _cleanup_free_ char *path = NULL;
677 const char *subdir, *syspath;
678 int r;
679
680 assert(ret);
681 assert(child);
682
683 r = sd_device_get_syspath(child, &syspath);
684 if (r < 0)
685 return r;
686
687 path = strdup(syspath);
688 if (!path)
689 return -ENOMEM;
690 subdir = path + STRLEN("/sys");
691
692 for (;;) {
693 char *pos;
694
695 pos = strrchr(subdir, '/');
696 if (!pos || pos < subdir + 2)
697 break;
698
699 *pos = '\0';
700
701 r = sd_device_new_from_syspath(ret, path);
702 if (r < 0)
703 continue;
704
705 return 0;
706 }
707
708 return -ENODEV;
709 }
710
711 _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
712
713 assert_return(ret, -EINVAL);
714 assert_return(child, -EINVAL);
715
716 if (!child->parent_set) {
717 child->parent_set = true;
718
719 (void) device_new_from_child(&child->parent, child);
720 }
721
722 if (!child->parent)
723 return -ENOENT;
724
725 *ret = child->parent;
726 return 0;
727 }
728
729 int device_set_subsystem(sd_device *device, const char *_subsystem) {
730 _cleanup_free_ char *subsystem = NULL;
731 int r;
732
733 assert(device);
734 assert(_subsystem);
735
736 subsystem = strdup(_subsystem);
737 if (!subsystem)
738 return -ENOMEM;
739
740 r = device_add_property_internal(device, "SUBSYSTEM", subsystem);
741 if (r < 0)
742 return r;
743
744 device->subsystem_set = true;
745 return free_and_replace(device->subsystem, subsystem);
746 }
747
748 static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
749 _cleanup_free_ char *subsystem = NULL;
750 int r;
751
752 assert(device);
753 assert(_subsystem);
754 assert(*_subsystem);
755
756 subsystem = strdup(_subsystem);
757 if (!subsystem)
758 return -ENOMEM;
759
760 r = device_set_subsystem(device, "drivers");
761 if (r < 0)
762 return r;
763
764 return free_and_replace(device->driver_subsystem, subsystem);
765 }
766
767 _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
768 const char *syspath, *drivers = NULL;
769 int r;
770
771 assert_return(ret, -EINVAL);
772 assert_return(device, -EINVAL);
773
774 r = sd_device_get_syspath(device, &syspath);
775 if (r < 0)
776 return r;
777
778 if (!device->subsystem_set) {
779 _cleanup_free_ char *subsystem = NULL;
780 char *path;
781
782 /* read 'subsystem' link */
783 path = strjoina(syspath, "/subsystem");
784 r = readlink_value(path, &subsystem);
785 if (r >= 0)
786 r = device_set_subsystem(device, subsystem);
787 /* use implicit names */
788 else if (path_startswith(device->devpath, "/module/"))
789 r = device_set_subsystem(device, "module");
790 else if (!(drivers = strstr(syspath, "/drivers/")) &&
791 PATH_STARTSWITH_SET(device->devpath, "/subsystem/",
792 "/class/",
793 "/bus/"))
794 r = device_set_subsystem(device, "subsystem");
795 if (r < 0 && r != -ENOENT)
796 return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for %s: %m", device->devpath);
797
798 device->subsystem_set = true;
799 } else if (!device->driver_subsystem_set)
800 drivers = strstr(syspath, "/drivers/");
801
802 if (!device->driver_subsystem_set) {
803 if (drivers) {
804 _cleanup_free_ char *subpath = NULL;
805
806 subpath = strndup(syspath, drivers - syspath);
807 if (!subpath)
808 r = -ENOMEM;
809 else {
810 const char *subsys;
811
812 subsys = strrchr(subpath, '/');
813 if (!subsys)
814 r = -EINVAL;
815 else
816 r = device_set_drivers_subsystem(device, subsys + 1);
817 }
818 if (r < 0 && r != -ENOENT)
819 return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for driver %s: %m", device->devpath);
820 }
821
822 device->driver_subsystem_set = true;
823 }
824
825 if (!device->subsystem)
826 return -ENOENT;
827
828 *ret = device->subsystem;
829 return 0;
830 }
831
832 _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) {
833 int r;
834
835 assert_return(device, -EINVAL);
836
837 r = device_read_uevent_file(device);
838 if (r < 0)
839 return r;
840
841 if (!device->devtype)
842 return -ENOENT;
843
844 if (devtype)
845 *devtype = device->devtype;
846
847 return !!device->devtype;
848 }
849
850 _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) {
851 sd_device *parent = NULL;
852 int r;
853
854 assert_return(child, -EINVAL);
855 assert_return(subsystem, -EINVAL);
856
857 r = sd_device_get_parent(child, &parent);
858 while (r >= 0) {
859 const char *parent_subsystem = NULL;
860 const char *parent_devtype = NULL;
861
862 (void) sd_device_get_subsystem(parent, &parent_subsystem);
863 if (streq_ptr(parent_subsystem, subsystem)) {
864 if (!devtype)
865 break;
866
867 (void) sd_device_get_devtype(parent, &parent_devtype);
868 if (streq_ptr(parent_devtype, devtype))
869 break;
870 }
871 r = sd_device_get_parent(parent, &parent);
872 }
873
874 if (r < 0)
875 return r;
876
877 *ret = parent;
878 return 0;
879 }
880
881 _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
882 int r;
883
884 assert_return(device, -EINVAL);
885
886 r = device_read_uevent_file(device);
887 if (r < 0)
888 return r;
889
890 if (major(device->devnum) <= 0)
891 return -ENOENT;
892
893 if (devnum)
894 *devnum = device->devnum;
895
896 return 0;
897 }
898
899 int device_set_driver(sd_device *device, const char *_driver) {
900 _cleanup_free_ char *driver = NULL;
901 int r;
902
903 assert(device);
904 assert(_driver);
905
906 driver = strdup(_driver);
907 if (!driver)
908 return -ENOMEM;
909
910 r = device_add_property_internal(device, "DRIVER", driver);
911 if (r < 0)
912 return r;
913
914 device->driver_set = true;
915 return free_and_replace(device->driver, driver);
916 }
917
918 _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
919 assert_return(device, -EINVAL);
920 assert_return(ret, -EINVAL);
921
922 if (!device->driver_set) {
923 _cleanup_free_ char *driver = NULL;
924 const char *syspath;
925 char *path;
926 int r;
927
928 r = sd_device_get_syspath(device, &syspath);
929 if (r < 0)
930 return r;
931
932 path = strjoina(syspath, "/driver");
933 r = readlink_value(path, &driver);
934 if (r >= 0) {
935 r = device_set_driver(device, driver);
936 if (r < 0)
937 return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath);
938 } else if (r == -ENOENT)
939 device->driver_set = true;
940 else
941 return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath);
942 }
943
944 if (!device->driver)
945 return -ENOENT;
946
947 *ret = device->driver;
948 return 0;
949 }
950
951 _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
952 assert_return(device, -EINVAL);
953 assert_return(devpath, -EINVAL);
954
955 assert(device->devpath);
956 assert(device->devpath[0] == '/');
957
958 *devpath = device->devpath;
959 return 0;
960 }
961
962 _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
963 int r;
964
965 assert_return(device, -EINVAL);
966 assert_return(devname, -EINVAL);
967
968 r = device_read_uevent_file(device);
969 if (r < 0)
970 return r;
971
972 if (!device->devname)
973 return -ENOENT;
974
975 assert(path_startswith(device->devname, "/dev/"));
976
977 *devname = device->devname;
978 return 0;
979 }
980
981 static int device_set_sysname(sd_device *device) {
982 _cleanup_free_ char *sysname = NULL;
983 const char *sysnum = NULL;
984 const char *pos;
985 size_t len = 0;
986
987 if (!device->devpath)
988 return -EINVAL;
989
990 pos = strrchr(device->devpath, '/');
991 if (!pos)
992 return -EINVAL;
993 pos++;
994
995 /* devpath is not a root directory */
996 if (*pos == '\0' || pos <= device->devpath)
997 return -EINVAL;
998
999 sysname = strdup(pos);
1000 if (!sysname)
1001 return -ENOMEM;
1002
1003 /* some devices have '!' in their name, change that to '/' */
1004 while (sysname[len] != '\0') {
1005 if (sysname[len] == '!')
1006 sysname[len] = '/';
1007
1008 len++;
1009 }
1010
1011 /* trailing number */
1012 while (len > 0 && isdigit(sysname[--len]))
1013 sysnum = &sysname[len];
1014
1015 if (len == 0)
1016 sysnum = NULL;
1017
1018 device->sysname_set = true;
1019 device->sysnum = sysnum;
1020 return free_and_replace(device->sysname, sysname);
1021 }
1022
1023 _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
1024 int r;
1025
1026 assert_return(device, -EINVAL);
1027 assert_return(ret, -EINVAL);
1028
1029 if (!device->sysname_set) {
1030 r = device_set_sysname(device);
1031 if (r < 0)
1032 return r;
1033 }
1034
1035 assert_return(device->sysname, -ENOENT);
1036
1037 *ret = device->sysname;
1038 return 0;
1039 }
1040
1041 _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
1042 int r;
1043
1044 assert_return(device, -EINVAL);
1045 assert_return(ret, -EINVAL);
1046
1047 if (!device->sysname_set) {
1048 r = device_set_sysname(device);
1049 if (r < 0)
1050 return r;
1051 }
1052
1053 if (!device->sysnum)
1054 return -ENOENT;
1055
1056 *ret = device->sysnum;
1057 return 0;
1058 }
1059
1060 static bool is_valid_tag(const char *tag) {
1061 assert(tag);
1062
1063 return !strchr(tag, ':') && !strchr(tag, ' ');
1064 }
1065
1066 int device_add_tag(sd_device *device, const char *tag, bool both) {
1067 int r, added;
1068
1069 assert(device);
1070 assert(tag);
1071
1072 if (!is_valid_tag(tag))
1073 return -EINVAL;
1074
1075 /* Definitely add to the "all" list of tags (i.e. the sticky list) */
1076 added = set_put_strdup(&device->all_tags, tag);
1077 if (added < 0)
1078 return added;
1079
1080 /* And optionally, also add it to the current list of tags */
1081 if (both) {
1082 r = set_put_strdup(&device->current_tags, tag);
1083 if (r < 0) {
1084 if (added > 0)
1085 (void) set_remove(device->all_tags, tag);
1086
1087 return r;
1088 }
1089 }
1090
1091 device->tags_generation++;
1092 device->property_tags_outdated = true;
1093
1094 return 0;
1095 }
1096
1097 int device_add_devlink(sd_device *device, const char *devlink) {
1098 int r;
1099
1100 assert(device);
1101 assert(devlink);
1102
1103 r = set_put_strdup(&device->devlinks, devlink);
1104 if (r < 0)
1105 return r;
1106
1107 device->devlinks_generation++;
1108 device->property_devlinks_outdated = true;
1109
1110 return 0;
1111 }
1112
1113 static int device_add_property_internal_from_string(sd_device *device, const char *str) {
1114 _cleanup_free_ char *key = NULL;
1115 char *value;
1116 int r;
1117
1118 assert(device);
1119 assert(str);
1120
1121 key = strdup(str);
1122 if (!key)
1123 return -ENOMEM;
1124
1125 value = strchr(key, '=');
1126 if (!value)
1127 return -EINVAL;
1128
1129 *value = '\0';
1130
1131 if (isempty(++value))
1132 value = NULL;
1133
1134 /* Add the property to both sd_device::properties and sd_device::properties_db,
1135 * as this is called by only handle_db_line(). */
1136 r = device_add_property_aux(device, key, value, false);
1137 if (r < 0)
1138 return r;
1139
1140 return device_add_property_aux(device, key, value, true);
1141 }
1142
1143 int device_set_usec_initialized(sd_device *device, usec_t when) {
1144 char s[DECIMAL_STR_MAX(usec_t)];
1145 int r;
1146
1147 assert(device);
1148
1149 xsprintf(s, USEC_FMT, when);
1150
1151 r = device_add_property_internal(device, "USEC_INITIALIZED", s);
1152 if (r < 0)
1153 return r;
1154
1155 device->usec_initialized = when;
1156 return 0;
1157 }
1158
1159 static int handle_db_line(sd_device *device, char key, const char *value) {
1160 char *path;
1161 int r;
1162
1163 assert(device);
1164 assert(value);
1165
1166 switch (key) {
1167 case 'G': /* Any tag */
1168 case 'Q': /* Current tag */
1169 r = device_add_tag(device, value, key == 'Q');
1170 if (r < 0)
1171 return r;
1172
1173 break;
1174 case 'S':
1175 path = strjoina("/dev/", value);
1176 r = device_add_devlink(device, path);
1177 if (r < 0)
1178 return r;
1179
1180 break;
1181 case 'E':
1182 r = device_add_property_internal_from_string(device, value);
1183 if (r < 0)
1184 return r;
1185
1186 break;
1187 case 'I': {
1188 usec_t t;
1189
1190 r = safe_atou64(value, &t);
1191 if (r < 0)
1192 return r;
1193
1194 r = device_set_usec_initialized(device, t);
1195 if (r < 0)
1196 return r;
1197
1198 break;
1199 }
1200 case 'L':
1201 r = safe_atoi(value, &device->devlink_priority);
1202 if (r < 0)
1203 return r;
1204
1205 break;
1206 case 'W':
1207 r = safe_atoi(value, &device->watch_handle);
1208 if (r < 0)
1209 return r;
1210
1211 break;
1212 default:
1213 log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key);
1214 }
1215
1216 return 0;
1217 }
1218
1219 int device_get_id_filename(sd_device *device, const char **ret) {
1220 assert(device);
1221 assert(ret);
1222
1223 if (!device->id_filename) {
1224 _cleanup_free_ char *id = NULL;
1225 const char *subsystem;
1226 dev_t devnum;
1227 int ifindex, r;
1228
1229 r = sd_device_get_subsystem(device, &subsystem);
1230 if (r < 0)
1231 return r;
1232
1233 if (sd_device_get_devnum(device, &devnum) >= 0) {
1234 assert(subsystem);
1235
1236 /* use dev_t — b259:131072, c254:0 */
1237 r = asprintf(&id, "%c%u:%u",
1238 streq(subsystem, "block") ? 'b' : 'c',
1239 major(devnum), minor(devnum));
1240 if (r < 0)
1241 return -ENOMEM;
1242 } else if (sd_device_get_ifindex(device, &ifindex) >= 0) {
1243 /* use netdev ifindex — n3 */
1244 r = asprintf(&id, "n%u", (unsigned) ifindex);
1245 if (r < 0)
1246 return -ENOMEM;
1247 } else {
1248 /* use $subsys:$sysname — pci:0000:00:1f.2
1249 * sysname() has '!' translated, get it from devpath
1250 */
1251 const char *sysname;
1252
1253 sysname = basename(device->devpath);
1254 if (!sysname)
1255 return -EINVAL;
1256
1257 if (!subsystem)
1258 return -EINVAL;
1259
1260
1261 if (streq(subsystem, "drivers"))
1262 /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem
1263 * encoded as well */
1264 id = strjoin("+drivers:", device->driver_subsystem, ":", sysname);
1265 else
1266 id = strjoin("+", subsystem, ":", sysname);
1267 if (!id)
1268 return -ENOMEM;
1269 }
1270
1271 device->id_filename = TAKE_PTR(id);
1272 }
1273
1274 *ret = device->id_filename;
1275 return 0;
1276 }
1277
1278 int device_read_db_internal_filename(sd_device *device, const char *filename) {
1279 _cleanup_free_ char *db = NULL;
1280 const char *value;
1281 size_t db_len, i;
1282 char key;
1283 int r;
1284
1285 enum {
1286 PRE_KEY,
1287 KEY,
1288 PRE_VALUE,
1289 VALUE,
1290 INVALID_LINE,
1291 } state = PRE_KEY;
1292
1293 assert(device);
1294 assert(filename);
1295
1296 r = read_full_file(filename, &db, &db_len);
1297 if (r < 0) {
1298 if (r == -ENOENT)
1299 return 0;
1300
1301 return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", filename);
1302 }
1303
1304 /* devices with a database entry are initialized */
1305 device->is_initialized = true;
1306
1307 device->db_loaded = true;
1308
1309 for (i = 0; i < db_len; i++) {
1310 switch (state) {
1311 case PRE_KEY:
1312 if (!strchr(NEWLINE, db[i])) {
1313 key = db[i];
1314
1315 state = KEY;
1316 }
1317
1318 break;
1319 case KEY:
1320 if (db[i] != ':') {
1321 log_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", key);
1322
1323 state = INVALID_LINE;
1324 } else {
1325 db[i] = '\0';
1326
1327 state = PRE_VALUE;
1328 }
1329
1330 break;
1331 case PRE_VALUE:
1332 value = &db[i];
1333
1334 state = VALUE;
1335
1336 break;
1337 case INVALID_LINE:
1338 if (strchr(NEWLINE, db[i]))
1339 state = PRE_KEY;
1340
1341 break;
1342 case VALUE:
1343 if (strchr(NEWLINE, db[i])) {
1344 db[i] = '\0';
1345 r = handle_db_line(device, key, value);
1346 if (r < 0)
1347 log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key, value);
1348
1349 state = PRE_KEY;
1350 }
1351
1352 break;
1353 default:
1354 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL), "sd-device: invalid db syntax.");
1355 }
1356 }
1357
1358 return 0;
1359 }
1360
1361 int device_read_db_internal(sd_device *device, bool force) {
1362 const char *id, *path;
1363 int r;
1364
1365 assert(device);
1366
1367 if (device->db_loaded || (!force && device->sealed))
1368 return 0;
1369
1370 r = device_get_id_filename(device, &id);
1371 if (r < 0)
1372 return r;
1373
1374 path = strjoina("/run/udev/data/", id);
1375
1376 return device_read_db_internal_filename(device, path);
1377 }
1378
1379 _public_ int sd_device_get_is_initialized(sd_device *device) {
1380 int r;
1381
1382 assert_return(device, -EINVAL);
1383
1384 r = device_read_db(device);
1385 if (r < 0)
1386 return r;
1387
1388 return device->is_initialized;
1389 }
1390
1391 _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) {
1392 usec_t now_ts;
1393 int r;
1394
1395 assert_return(device, -EINVAL);
1396 assert_return(usec, -EINVAL);
1397
1398 r = device_read_db(device);
1399 if (r < 0)
1400 return r;
1401
1402 if (!device->is_initialized)
1403 return -EBUSY;
1404
1405 if (!device->usec_initialized)
1406 return -ENODATA;
1407
1408 now_ts = now(clock_boottime_or_monotonic());
1409
1410 if (now_ts < device->usec_initialized)
1411 return -EIO;
1412
1413 *usec = now_ts - device->usec_initialized;
1414 return 0;
1415 }
1416
1417 _public_ const char *sd_device_get_tag_first(sd_device *device) {
1418 void *v;
1419
1420 assert_return(device, NULL);
1421
1422 (void) device_read_db(device);
1423
1424 device->all_tags_iterator_generation = device->tags_generation;
1425 device->all_tags_iterator = ITERATOR_FIRST;
1426
1427 (void) set_iterate(device->all_tags, &device->all_tags_iterator, &v);
1428 return v;
1429 }
1430
1431 _public_ const char *sd_device_get_tag_next(sd_device *device) {
1432 void *v;
1433
1434 assert_return(device, NULL);
1435
1436 (void) device_read_db(device);
1437
1438 if (device->all_tags_iterator_generation != device->tags_generation)
1439 return NULL;
1440
1441 (void) set_iterate(device->all_tags, &device->all_tags_iterator, &v);
1442 return v;
1443 }
1444
1445 _public_ const char *sd_device_get_current_tag_first(sd_device *device) {
1446 void *v;
1447
1448 assert_return(device, NULL);
1449
1450 (void) device_read_db(device);
1451
1452 device->current_tags_iterator_generation = device->tags_generation;
1453 device->current_tags_iterator = ITERATOR_FIRST;
1454
1455 (void) set_iterate(device->current_tags, &device->current_tags_iterator, &v);
1456 return v;
1457 }
1458
1459 _public_ const char *sd_device_get_current_tag_next(sd_device *device) {
1460 void *v;
1461
1462 assert_return(device, NULL);
1463
1464 (void) device_read_db(device);
1465
1466 if (device->current_tags_iterator_generation != device->tags_generation)
1467 return NULL;
1468
1469 (void) set_iterate(device->current_tags, &device->current_tags_iterator, &v);
1470 return v;
1471 }
1472
1473 _public_ const char *sd_device_get_devlink_first(sd_device *device) {
1474 void *v;
1475
1476 assert_return(device, NULL);
1477
1478 (void) device_read_db(device);
1479
1480 device->devlinks_iterator_generation = device->devlinks_generation;
1481 device->devlinks_iterator = ITERATOR_FIRST;
1482
1483 (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
1484 return v;
1485 }
1486
1487 _public_ const char *sd_device_get_devlink_next(sd_device *device) {
1488 void *v;
1489
1490 assert_return(device, NULL);
1491
1492 (void) device_read_db(device);
1493
1494 if (device->devlinks_iterator_generation != device->devlinks_generation)
1495 return NULL;
1496
1497 (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
1498 return v;
1499 }
1500
1501 static char *join_string_set(Set *s) {
1502 size_t ret_allocated = 0, ret_len;
1503 _cleanup_free_ char *ret = NULL;
1504 const char *tag;
1505
1506 if (!GREEDY_REALLOC(ret, ret_allocated, 2))
1507 return NULL;
1508
1509 strcpy(ret, ":");
1510 ret_len = 1;
1511
1512 SET_FOREACH(tag, s) {
1513 char *e;
1514
1515 if (!GREEDY_REALLOC(ret, ret_allocated, ret_len + strlen(tag) + 2))
1516 return NULL;
1517
1518 e = stpcpy(stpcpy(ret + ret_len, tag), ":");
1519 ret_len = e - ret;
1520 }
1521
1522 return TAKE_PTR(ret);
1523 }
1524
1525 int device_properties_prepare(sd_device *device) {
1526 int r;
1527
1528 assert(device);
1529
1530 r = device_read_uevent_file(device);
1531 if (r < 0)
1532 return r;
1533
1534 r = device_read_db(device);
1535 if (r < 0)
1536 return r;
1537
1538 if (device->property_devlinks_outdated) {
1539 _cleanup_free_ char *devlinks = NULL;
1540 size_t devlinks_allocated = 0, devlinks_len = 0;
1541 const char *devlink;
1542
1543 for (devlink = sd_device_get_devlink_first(device); devlink; devlink = sd_device_get_devlink_next(device)) {
1544 char *e;
1545
1546 if (!GREEDY_REALLOC(devlinks, devlinks_allocated, devlinks_len + strlen(devlink) + 2))
1547 return -ENOMEM;
1548 if (devlinks_len > 0)
1549 stpcpy(devlinks + devlinks_len++, " ");
1550 e = stpcpy(devlinks + devlinks_len, devlink);
1551 devlinks_len = e - devlinks;
1552 }
1553
1554 r = device_add_property_internal(device, "DEVLINKS", devlinks);
1555 if (r < 0)
1556 return r;
1557
1558 device->property_devlinks_outdated = false;
1559 }
1560
1561 if (device->property_tags_outdated) {
1562 _cleanup_free_ char *tags = NULL;
1563
1564 tags = join_string_set(device->all_tags);
1565 if (!tags)
1566 return -ENOMEM;
1567
1568 if (!streq(tags, ":")) {
1569 r = device_add_property_internal(device, "TAGS", tags);
1570 if (r < 0)
1571 return r;
1572 }
1573
1574 free(tags);
1575 tags = join_string_set(device->current_tags);
1576 if (!tags)
1577 return -ENOMEM;
1578
1579 if (!streq(tags, ":")) {
1580 r = device_add_property_internal(device, "CURRENT_TAGS", tags);
1581 if (r < 0)
1582 return r;
1583 }
1584
1585 device->property_tags_outdated = false;
1586 }
1587
1588 return 0;
1589 }
1590
1591 _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
1592 const char *key;
1593 int r;
1594
1595 assert_return(device, NULL);
1596
1597 r = device_properties_prepare(device);
1598 if (r < 0)
1599 return NULL;
1600
1601 device->properties_iterator_generation = device->properties_generation;
1602 device->properties_iterator = ITERATOR_FIRST;
1603
1604 (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
1605 return key;
1606 }
1607
1608 _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
1609 const char *key;
1610 int r;
1611
1612 assert_return(device, NULL);
1613
1614 r = device_properties_prepare(device);
1615 if (r < 0)
1616 return NULL;
1617
1618 if (device->properties_iterator_generation != device->properties_generation)
1619 return NULL;
1620
1621 (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
1622 return key;
1623 }
1624
1625 static int device_sysattrs_read_all_internal(sd_device *device, const char *subdir) {
1626 _cleanup_free_ char *path_dir = NULL;
1627 _cleanup_closedir_ DIR *dir = NULL;
1628 struct dirent *dent;
1629 const char *syspath;
1630 int r;
1631
1632 r = sd_device_get_syspath(device, &syspath);
1633 if (r < 0)
1634 return r;
1635
1636 if (subdir) {
1637 _cleanup_free_ char *p = NULL;
1638
1639 p = path_join(syspath, subdir, "uevent");
1640 if (!p)
1641 return -ENOMEM;
1642
1643 if (access(p, F_OK) >= 0)
1644 /* this is a child device, skipping */
1645 return 0;
1646 if (errno != ENOENT) {
1647 log_device_debug_errno(device, errno, "sd-device: Failed to stat %s, ignoring subdir: %m", p);
1648 return 0;
1649 }
1650
1651 path_dir = path_join(syspath, subdir);
1652 if (!path_dir)
1653 return -ENOMEM;
1654 }
1655
1656 dir = opendir(path_dir ?: syspath);
1657 if (!dir)
1658 return -errno;
1659
1660 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
1661 _cleanup_free_ char *path = NULL, *p = NULL;
1662 struct stat statbuf;
1663
1664 if (dot_or_dot_dot(dent->d_name))
1665 continue;
1666
1667 /* only handle symlinks, regular files, and directories */
1668 if (!IN_SET(dent->d_type, DT_LNK, DT_REG, DT_DIR))
1669 continue;
1670
1671 if (subdir) {
1672 p = path_join(subdir, dent->d_name);
1673 if (!p)
1674 return -ENOMEM;
1675 }
1676
1677 if (dent->d_type == DT_DIR) {
1678 /* read subdirectory */
1679 r = device_sysattrs_read_all_internal(device, p ?: dent->d_name);
1680 if (r < 0)
1681 return r;
1682
1683 continue;
1684 }
1685
1686 path = path_join(syspath, p ?: dent->d_name);
1687 if (!path)
1688 return -ENOMEM;
1689
1690 if (lstat(path, &statbuf) != 0)
1691 continue;
1692
1693 if (!(statbuf.st_mode & S_IRUSR))
1694 continue;
1695
1696 r = set_put_strdup(&device->sysattrs, p ?: dent->d_name);
1697 if (r < 0)
1698 return r;
1699 }
1700
1701 return 0;
1702 }
1703
1704 static int device_sysattrs_read_all(sd_device *device) {
1705 int r;
1706
1707 assert(device);
1708
1709 if (device->sysattrs_read)
1710 return 0;
1711
1712 r = device_sysattrs_read_all_internal(device, NULL);
1713 if (r < 0)
1714 return r;
1715
1716 device->sysattrs_read = true;
1717
1718 return 0;
1719 }
1720
1721 _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
1722 void *v;
1723 int r;
1724
1725 assert_return(device, NULL);
1726
1727 if (!device->sysattrs_read) {
1728 r = device_sysattrs_read_all(device);
1729 if (r < 0) {
1730 errno = -r;
1731 return NULL;
1732 }
1733 }
1734
1735 device->sysattrs_iterator = ITERATOR_FIRST;
1736
1737 (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
1738 return v;
1739 }
1740
1741 _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
1742 void *v;
1743
1744 assert_return(device, NULL);
1745
1746 if (!device->sysattrs_read)
1747 return NULL;
1748
1749 (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
1750 return v;
1751 }
1752
1753 _public_ int sd_device_has_tag(sd_device *device, const char *tag) {
1754 assert_return(device, -EINVAL);
1755 assert_return(tag, -EINVAL);
1756
1757 (void) device_read_db(device);
1758
1759 return set_contains(device->all_tags, tag);
1760 }
1761
1762 _public_ int sd_device_has_current_tag(sd_device *device, const char *tag) {
1763 assert_return(device, -EINVAL);
1764 assert_return(tag, -EINVAL);
1765
1766 (void) device_read_db(device);
1767
1768 return set_contains(device->current_tags, tag);
1769 }
1770
1771 _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) {
1772 char *value;
1773 int r;
1774
1775 assert_return(device, -EINVAL);
1776 assert_return(key, -EINVAL);
1777
1778 r = device_properties_prepare(device);
1779 if (r < 0)
1780 return r;
1781
1782 value = ordered_hashmap_get(device->properties, key);
1783 if (!value)
1784 return -ENOENT;
1785
1786 if (_value)
1787 *_value = value;
1788 return 0;
1789 }
1790
1791 /* replaces the value if it already exists */
1792 static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) {
1793 _cleanup_free_ char *key = NULL;
1794 _cleanup_free_ char *value_old = NULL;
1795 int r;
1796
1797 assert(device);
1798 assert(_key);
1799
1800 r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops);
1801 if (r < 0)
1802 return r;
1803
1804 value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key);
1805 if (!key) {
1806 key = strdup(_key);
1807 if (!key)
1808 return -ENOMEM;
1809 }
1810
1811 r = hashmap_put(device->sysattr_values, key, value);
1812 if (r < 0)
1813 return r;
1814 TAKE_PTR(key);
1815
1816 return 0;
1817 }
1818
1819 static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) {
1820 const char *key = NULL, *value;
1821
1822 assert(device);
1823 assert(_key);
1824
1825 value = hashmap_get2(device->sysattr_values, _key, (void **) &key);
1826 if (!key)
1827 return -ENOENT;
1828
1829 if (_value)
1830 *_value = value;
1831 return 0;
1832 }
1833
1834 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
1835 * with a NULL value in the cache, otherwise the returned string is stored */
1836 _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) {
1837 _cleanup_free_ char *value = NULL;
1838 const char *path, *syspath, *cached_value = NULL;
1839 struct stat statbuf;
1840 int r;
1841
1842 assert_return(device, -EINVAL);
1843 assert_return(sysattr, -EINVAL);
1844
1845 /* look for possibly already cached result */
1846 r = device_get_sysattr_value(device, sysattr, &cached_value);
1847 if (r != -ENOENT) {
1848 if (r < 0)
1849 return r;
1850
1851 if (!cached_value)
1852 /* we looked up the sysattr before and it did not exist */
1853 return -ENOENT;
1854
1855 if (_value)
1856 *_value = cached_value;
1857
1858 return 0;
1859 }
1860
1861 r = sd_device_get_syspath(device, &syspath);
1862 if (r < 0)
1863 return r;
1864
1865 path = prefix_roota(syspath, sysattr);
1866 r = lstat(path, &statbuf);
1867 if (r < 0) {
1868 /* remember that we could not access the sysattr */
1869 r = device_add_sysattr_value(device, sysattr, NULL);
1870 if (r < 0)
1871 return r;
1872
1873 return -ENOENT;
1874 } else if (S_ISLNK(statbuf.st_mode)) {
1875 /* Some core links return only the last element of the target path,
1876 * these are just values, the paths should not be exposed. */
1877 if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) {
1878 r = readlink_value(path, &value);
1879 if (r < 0)
1880 return r;
1881 } else
1882 return -EINVAL;
1883 } else if (S_ISDIR(statbuf.st_mode)) {
1884 /* skip directories */
1885 return -EINVAL;
1886 } else if (!(statbuf.st_mode & S_IRUSR)) {
1887 /* skip non-readable files */
1888 return -EPERM;
1889 } else {
1890 size_t size;
1891
1892 /* read attribute value */
1893 r = read_full_virtual_file(path, &value, &size);
1894 if (r < 0)
1895 return r;
1896
1897 /* drop trailing newlines */
1898 while (size > 0 && value[--size] == '\n')
1899 value[size] = '\0';
1900 }
1901
1902 r = device_add_sysattr_value(device, sysattr, value);
1903 if (r < 0)
1904 return r;
1905
1906 *_value = TAKE_PTR(value);
1907
1908 return 0;
1909 }
1910
1911 static void device_remove_sysattr_value(sd_device *device, const char *_key) {
1912 _cleanup_free_ char *key = NULL;
1913
1914 assert(device);
1915 assert(_key);
1916
1917 free(hashmap_remove2(device->sysattr_values, _key, (void **) &key));
1918 }
1919
1920 /* set the attribute and save it in the cache. If a NULL value is passed the
1921 * attribute is cleared from the cache */
1922 _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *_value) {
1923 _cleanup_free_ char *value = NULL;
1924 const char *syspath, *path;
1925 size_t len;
1926 int r;
1927
1928 assert_return(device, -EINVAL);
1929 assert_return(sysattr, -EINVAL);
1930
1931 if (!_value) {
1932 device_remove_sysattr_value(device, sysattr);
1933 return 0;
1934 }
1935
1936 r = sd_device_get_syspath(device, &syspath);
1937 if (r < 0)
1938 return r;
1939
1940 path = prefix_roota(syspath, sysattr);
1941
1942 len = strlen(_value);
1943
1944 /* drop trailing newlines */
1945 while (len > 0 && _value[len - 1] == '\n')
1946 len --;
1947
1948 /* value length is limited to 4k */
1949 if (len > 4096)
1950 return -EINVAL;
1951
1952 value = strndup(_value, len);
1953 if (!value)
1954 return -ENOMEM;
1955
1956 r = write_string_file(path, value, WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_NOFOLLOW);
1957 if (r < 0) {
1958 if (r == -ELOOP)
1959 return -EINVAL;
1960 if (r == -EISDIR)
1961 return r;
1962
1963 r = free_and_strdup(&value, "");
1964 if (r < 0)
1965 return r;
1966
1967 r = device_add_sysattr_value(device, sysattr, value);
1968 if (r < 0)
1969 return r;
1970 TAKE_PTR(value);
1971
1972 return -ENXIO;
1973 }
1974
1975 r = device_add_sysattr_value(device, sysattr, value);
1976 if (r < 0)
1977 return r;
1978 TAKE_PTR(value);
1979
1980 return 0;
1981 }
1982
1983 _public_ int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) {
1984 _cleanup_free_ char *value = NULL;
1985 va_list ap;
1986 int r;
1987
1988 assert_return(device, -EINVAL);
1989 assert_return(sysattr, -EINVAL);
1990
1991 if (!format) {
1992 device_remove_sysattr_value(device, sysattr);
1993 return 0;
1994 }
1995
1996 va_start(ap, format);
1997 r = vasprintf(&value, format, ap);
1998 va_end(ap);
1999
2000 if (r < 0)
2001 return -ENOMEM;
2002
2003 return sd_device_set_sysattr_value(device, sysattr, value);
2004 }