]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/sd-device.c
Merge pull request #29193 from keszybz/path-util-adjustment
[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 "chase.h"
12 #include "device-internal.h"
13 #include "device-private.h"
14 #include "device-util.h"
15 #include "devnum-util.h"
16 #include "dirent-util.h"
17 #include "env-util.h"
18 #include "fd-util.h"
19 #include "fileio.h"
20 #include "format-util.h"
21 #include "fs-util.h"
22 #include "hashmap.h"
23 #include "id128-util.h"
24 #include "macro.h"
25 #include "missing_magic.h"
26 #include "netlink-util.h"
27 #include "parse-util.h"
28 #include "path-util.h"
29 #include "set.h"
30 #include "socket-util.h"
31 #include "stdio-util.h"
32 #include "string-util.h"
33 #include "strv.h"
34 #include "strxcpyx.h"
35 #include "user-util.h"
36
37 int device_new_aux(sd_device **ret) {
38 sd_device *device;
39
40 assert(ret);
41
42 device = new(sd_device, 1);
43 if (!device)
44 return -ENOMEM;
45
46 *device = (sd_device) {
47 .n_ref = 1,
48 .devmode = MODE_INVALID,
49 .devuid = UID_INVALID,
50 .devgid = GID_INVALID,
51 .action = _SD_DEVICE_ACTION_INVALID,
52 };
53
54 *ret = device;
55 return 0;
56 }
57
58 static sd_device *device_free(sd_device *device) {
59 assert(device);
60
61 sd_device_unref(device->parent);
62 free(device->syspath);
63 free(device->sysname);
64 free(device->devtype);
65 free(device->devname);
66 free(device->subsystem);
67 free(device->driver_subsystem);
68 free(device->driver);
69 free(device->device_id);
70 free(device->properties_strv);
71 free(device->properties_nulstr);
72
73 ordered_hashmap_free(device->properties);
74 ordered_hashmap_free(device->properties_db);
75 hashmap_free(device->sysattr_values);
76 set_free(device->sysattrs);
77 set_free(device->all_tags);
78 set_free(device->current_tags);
79 set_free(device->devlinks);
80 hashmap_free(device->children);
81
82 return mfree(device);
83 }
84
85 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device, sd_device, device_free);
86
87 int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db) {
88 OrderedHashmap **properties;
89
90 assert(device);
91 assert(key);
92
93 if (db)
94 properties = &device->properties_db;
95 else
96 properties = &device->properties;
97
98 if (value) {
99 _unused_ _cleanup_free_ char *old_value = NULL;
100 _cleanup_free_ char *new_key = NULL, *new_value = NULL, *old_key = NULL;
101 int r;
102
103 r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops_free_free);
104 if (r < 0)
105 return r;
106
107 new_key = strdup(key);
108 if (!new_key)
109 return -ENOMEM;
110
111 new_value = strdup(value);
112 if (!new_value)
113 return -ENOMEM;
114
115 old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key);
116
117 /* ordered_hashmap_replace() does not fail when the hashmap already has the entry. */
118 r = ordered_hashmap_replace(*properties, new_key, new_value);
119 if (r < 0)
120 return r;
121
122 TAKE_PTR(new_key);
123 TAKE_PTR(new_value);
124 } else {
125 _unused_ _cleanup_free_ char *old_value = NULL;
126 _cleanup_free_ char *old_key = NULL;
127
128 old_value = ordered_hashmap_remove2(*properties, key, (void**) &old_key);
129 }
130
131 if (!db) {
132 device->properties_generation++;
133 device->properties_buf_outdated = true;
134 }
135
136 return 0;
137 }
138
139 int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
140 _cleanup_free_ char *syspath = NULL;
141 const char *devpath;
142 int r;
143
144 assert(device);
145 assert(_syspath);
146
147 if (verify) {
148 _cleanup_close_ int fd = -EBADF;
149
150 /* The input path maybe a symlink located outside of /sys. Let's try to chase the symlink at first.
151 * The primary use case is that e.g. /proc/device-tree is a symlink to /sys/firmware/devicetree/base.
152 * By chasing symlinks in the path at first, we can call sd_device_new_from_path() with such path. */
153 r = chase(_syspath, NULL, 0, &syspath, &fd);
154 if (r == -ENOENT)
155 /* the device does not exist (any more?) */
156 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
157 "sd-device: Failed to chase symlinks in \"%s\".", _syspath);
158 if (r < 0)
159 return log_debug_errno(r, "sd-device: Failed to get target of '%s': %m", _syspath);
160
161 if (!path_startswith(syspath, "/sys")) {
162 _cleanup_free_ char *real_sys = NULL, *new_syspath = NULL;
163 char *p;
164
165 /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
166 r = chase("/sys", NULL, 0, &real_sys, NULL);
167 if (r < 0)
168 return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");
169
170 p = path_startswith(syspath, real_sys);
171 if (!p)
172 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
173 "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
174 syspath, real_sys);
175
176 new_syspath = path_join("/sys", p);
177 if (!new_syspath)
178 return log_oom_debug();
179
180 free_and_replace(syspath, new_syspath);
181 path_simplify(syspath);
182 }
183
184 if (path_startswith(syspath, "/sys/devices/")) {
185 /* For proper devices, stricter rules apply: they must have a 'uevent' file,
186 * otherwise we won't allow them */
187
188 if (faccessat(fd, "uevent", F_OK, 0) < 0) {
189 if (errno == ENOENT)
190 /* This is not a valid device. Note, this condition is quite often
191 * satisfied when enumerating devices or finding a parent device.
192 * Hence, use log_trace_errno() here. */
193 return log_trace_errno(SYNTHETIC_ERRNO(ENODEV),
194 "sd-device: the uevent file \"%s/uevent\" does not exist.", syspath);
195 if (errno == ENOTDIR)
196 /* Not actually a directory. */
197 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
198 "sd-device: the syspath \"%s\" is not a directory.", syspath);
199
200 return log_debug_errno(errno, "sd-device: cannot find uevent file for %s: %m", syspath);
201 }
202 } else {
203 struct stat st;
204
205 /* For everything else lax rules apply: they just need to be a directory */
206
207 if (fstat(fd, &st) < 0)
208 return log_debug_errno(errno, "sd-device: failed to check if syspath \"%s\" is a directory: %m", syspath);
209 if (!S_ISDIR(st.st_mode))
210 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
211 "sd-device: the syspath \"%s\" is not a directory.", syspath);
212 }
213
214 /* Only operate on sysfs, i.e. refuse going down into /sys/fs/cgroup/ or similar places where
215 * things are not arranged as kobjects in kernel, and hence don't necessarily have
216 * kobject/attribute structure. */
217 r = getenv_bool_secure("SYSTEMD_DEVICE_VERIFY_SYSFS");
218 if (r < 0 && r != -ENXIO)
219 log_debug_errno(r, "Failed to parse $SYSTEMD_DEVICE_VERIFY_SYSFS value: %m");
220 if (r != 0) {
221 r = fd_is_fs_type(fd, SYSFS_MAGIC);
222 if (r < 0)
223 return log_debug_errno(r, "sd-device: failed to check if syspath \"%s\" is backed by sysfs.", syspath);
224 if (r == 0)
225 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
226 "sd-device: the syspath \"%s\" is outside of sysfs, refusing.", syspath);
227 }
228 } else {
229 /* must be a subdirectory of /sys */
230 if (!path_startswith(_syspath, "/sys/"))
231 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
232 "sd-device: Syspath '%s' is not a subdirectory of /sys",
233 _syspath);
234
235 r = path_simplify_alloc(_syspath, &syspath);
236 if (r < 0)
237 return r;
238 }
239
240 assert_se(devpath = startswith(syspath, "/sys"));
241 if (devpath[0] != '/')
242 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "sd-device: \"/sys\" alone is not a valid device path.");
243
244 r = device_add_property_internal(device, "DEVPATH", devpath);
245 if (r < 0)
246 return log_debug_errno(r, "sd-device: Failed to add \"DEVPATH\" property for device \"%s\": %m", syspath);
247
248 free_and_replace(device->syspath, syspath);
249 device->devpath = devpath;
250
251 /* Unset sysname and sysnum, they will be assigned when requested. */
252 device->sysnum = NULL;
253 device->sysname = mfree(device->sysname);
254 return 0;
255 }
256
257 static int device_new_from_syspath(sd_device **ret, const char *syspath, bool strict) {
258 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
259 int r;
260
261 assert_return(ret, -EINVAL);
262 assert_return(syspath, -EINVAL);
263
264 if (strict && !path_startswith(syspath, "/sys/"))
265 return -EINVAL;
266
267 r = device_new_aux(&device);
268 if (r < 0)
269 return r;
270
271 r = device_set_syspath(device, syspath, /* verify= */ true);
272 if (r < 0)
273 return r;
274
275 *ret = TAKE_PTR(device);
276 return 0;
277 }
278
279 _public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) {
280 return device_new_from_syspath(ret, syspath, /* strict = */ true);
281 }
282
283 int device_new_from_mode_and_devnum(sd_device **ret, mode_t mode, dev_t devnum) {
284 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
285 _cleanup_free_ char *syspath = NULL;
286 const char *t, *subsystem = NULL;
287 dev_t n;
288 int r;
289
290 assert(ret);
291
292 if (S_ISCHR(mode))
293 t = "char";
294 else if (S_ISBLK(mode))
295 t = "block";
296 else
297 return -ENOTTY;
298
299 if (major(devnum) == 0)
300 return -ENODEV;
301
302 if (asprintf(&syspath, "/sys/dev/%s/" DEVNUM_FORMAT_STR, t, DEVNUM_FORMAT_VAL(devnum)) < 0)
303 return -ENOMEM;
304
305 r = sd_device_new_from_syspath(&dev, syspath);
306 if (r < 0)
307 return r;
308
309 r = sd_device_get_devnum(dev, &n);
310 if (r == -ENOENT)
311 return -ENXIO;
312 if (r < 0)
313 return r;
314 if (n != devnum)
315 return -ENXIO;
316
317 r = sd_device_get_subsystem(dev, &subsystem);
318 if (r < 0 && r != -ENOENT)
319 return r;
320 if (streq_ptr(subsystem, "block") != !!S_ISBLK(mode))
321 return -ENXIO;
322
323 *ret = TAKE_PTR(dev);
324 return 0;
325 }
326
327 _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) {
328 assert_return(ret, -EINVAL);
329 assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
330
331 return device_new_from_mode_and_devnum(ret, type == 'b' ? S_IFBLK : S_IFCHR, devnum);
332 }
333
334 static int device_new_from_main_ifname(sd_device **ret, const char *ifname) {
335 const char *syspath;
336
337 assert(ret);
338 assert(ifname);
339
340 syspath = strjoina("/sys/class/net/", ifname);
341 return sd_device_new_from_syspath(ret, syspath);
342 }
343
344 _public_ int sd_device_new_from_ifname(sd_device **ret, const char *ifname) {
345 _cleanup_free_ char *main_name = NULL;
346 int r;
347
348 assert_return(ret, -EINVAL);
349 assert_return(ifname, -EINVAL);
350
351 r = parse_ifindex(ifname);
352 if (r > 0)
353 return sd_device_new_from_ifindex(ret, r);
354
355 if (ifname_valid(ifname)) {
356 r = device_new_from_main_ifname(ret, ifname);
357 if (r >= 0)
358 return r;
359 }
360
361 r = rtnl_resolve_link_alternative_name(NULL, ifname, &main_name);
362 if (r < 0)
363 return r;
364
365 return device_new_from_main_ifname(ret, main_name);
366 }
367
368 _public_ int sd_device_new_from_ifindex(sd_device **ret, int ifindex) {
369 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
370 char ifname[IF_NAMESIZE];
371 int r, i;
372
373 assert_return(ret, -EINVAL);
374 assert_return(ifindex > 0, -EINVAL);
375
376 if (format_ifname(ifindex, ifname) < 0)
377 return -ENODEV;
378
379 r = device_new_from_main_ifname(&dev, ifname);
380 if (r < 0)
381 return r;
382
383 r = sd_device_get_ifindex(dev, &i);
384 if (r == -ENOENT)
385 return -ENXIO;
386 if (r < 0)
387 return r;
388 if (i != ifindex)
389 return -ENXIO;
390
391 *ret = TAKE_PTR(dev);
392 return 0;
393 }
394
395 static int device_strjoin_new(
396 const char *a,
397 const char *b,
398 const char *c,
399 const char *d,
400 sd_device **ret) {
401
402 const char *p;
403 int r;
404
405 p = strjoina(a, b, c, d);
406 if (access(p, F_OK) < 0)
407 return IN_SET(errno, ENOENT, ENAMETOOLONG) ? 0 : -errno; /* If this sysfs is too long then it doesn't exist either */
408
409 r = sd_device_new_from_syspath(ret, p);
410 if (r < 0)
411 return r;
412
413 return 1;
414 }
415
416 _public_ int sd_device_new_from_subsystem_sysname(
417 sd_device **ret,
418 const char *subsystem,
419 const char *sysname) {
420
421 char *name;
422 int r;
423
424 assert_return(ret, -EINVAL);
425 assert_return(path_is_normalized(subsystem), -EINVAL);
426 assert_return(path_is_normalized(sysname), -EINVAL);
427
428 /* translate sysname back to sysfs filename */
429 name = strdupa_safe(sysname);
430 string_replace_char(name, '/', '!');
431
432 if (streq(subsystem, "subsystem")) {
433 FOREACH_STRING(s, "/sys/bus/", "/sys/class/") {
434 r = device_strjoin_new(s, name, NULL, NULL, ret);
435 if (r < 0)
436 return r;
437 if (r > 0)
438 return 0;
439 }
440
441 } else if (streq(subsystem, "module")) {
442 r = device_strjoin_new("/sys/module/", name, NULL, NULL, ret);
443 if (r < 0)
444 return r;
445 if (r > 0)
446 return 0;
447
448 } else if (streq(subsystem, "drivers")) {
449 const char *sep;
450
451 sep = strchr(name, ':');
452 if (sep && sep[1] != '\0') { /* Require ":" and something non-empty after that. */
453
454 const char *subsys = memdupa_suffix0(name, sep - name);
455 sep++;
456
457 if (streq(sep, "drivers")) /* If the sysname is "drivers", then it's the drivers directory itself that is meant. */
458 r = device_strjoin_new("/sys/bus/", subsys, "/drivers", NULL, ret);
459 else
460 r = device_strjoin_new("/sys/bus/", subsys, "/drivers/", sep, ret);
461 if (r < 0)
462 return r;
463 if (r > 0)
464 return 0;
465 }
466 }
467
468 r = device_strjoin_new("/sys/bus/", subsystem, "/devices/", name, ret);
469 if (r < 0)
470 return r;
471 if (r > 0)
472 return 0;
473
474 r = device_strjoin_new("/sys/class/", subsystem, "/", name, ret);
475 if (r < 0)
476 return r;
477 if (r > 0)
478 return 0;
479
480 r = device_strjoin_new("/sys/firmware/", subsystem, "/", name, ret);
481 if (r < 0)
482 return r;
483 if (r > 0)
484 return 0;
485
486 return -ENODEV;
487 }
488
489 _public_ int sd_device_new_from_stat_rdev(sd_device **ret, const struct stat *st) {
490 assert_return(ret, -EINVAL);
491 assert_return(st, -EINVAL);
492
493 return device_new_from_mode_and_devnum(ret, st->st_mode, st->st_rdev);
494 }
495
496 _public_ int sd_device_new_from_devname(sd_device **ret, const char *devname) {
497 struct stat st;
498 dev_t devnum;
499 mode_t mode;
500
501 assert_return(ret, -EINVAL);
502 assert_return(devname, -EINVAL);
503
504 /* This function actually accepts both devlinks and devnames, i.e. both symlinks and device
505 * nodes below /dev/. */
506
507 /* Also ignore when the specified path is "/dev". */
508 if (isempty(path_startswith(devname, "/dev")))
509 return -EINVAL;
510
511 if (device_path_parse_major_minor(devname, &mode, &devnum) >= 0)
512 /* Let's shortcut when "/dev/block/maj:min" or "/dev/char/maj:min" is specified.
513 * In that case, we can directly convert the path to syspath, hence it is not necessary
514 * that the specified path exists. So, this works fine without udevd being running. */
515 return device_new_from_mode_and_devnum(ret, mode, devnum);
516
517 if (stat(devname, &st) < 0)
518 return ERRNO_IS_DEVICE_ABSENT(errno) ? -ENODEV : -errno;
519
520 return sd_device_new_from_stat_rdev(ret, &st);
521 }
522
523 _public_ int sd_device_new_from_path(sd_device **ret, const char *path) {
524 assert_return(ret, -EINVAL);
525 assert_return(path, -EINVAL);
526
527 if (path_startswith(path, "/dev"))
528 return sd_device_new_from_devname(ret, path);
529
530 return device_new_from_syspath(ret, path, /* strict = */ false);
531 }
532
533 int device_set_devtype(sd_device *device, const char *devtype) {
534 _cleanup_free_ char *t = NULL;
535 int r;
536
537 assert(device);
538 assert(devtype);
539
540 t = strdup(devtype);
541 if (!t)
542 return -ENOMEM;
543
544 r = device_add_property_internal(device, "DEVTYPE", t);
545 if (r < 0)
546 return r;
547
548 return free_and_replace(device->devtype, t);
549 }
550
551 int device_set_ifindex(sd_device *device, const char *name) {
552 int r, ifindex;
553
554 assert(device);
555 assert(name);
556
557 ifindex = parse_ifindex(name);
558 if (ifindex < 0)
559 return ifindex;
560
561 r = device_add_property_internal(device, "IFINDEX", name);
562 if (r < 0)
563 return r;
564
565 device->ifindex = ifindex;
566
567 return 0;
568 }
569
570 static int mangle_devname(const char *p, char **ret) {
571 char *q;
572
573 assert(p);
574 assert(ret);
575
576 if (!path_is_safe(p))
577 return -EINVAL;
578
579 /* When the path is absolute, it must start with "/dev/", but ignore "/dev/" itself. */
580 if (path_is_absolute(p)) {
581 if (isempty(path_startswith(p, "/dev/")))
582 return -EINVAL;
583
584 q = strdup(p);
585 } else
586 q = path_join("/dev/", p);
587 if (!q)
588 return -ENOMEM;
589
590 path_simplify(q);
591
592 *ret = q;
593 return 0;
594 }
595
596 int device_set_devname(sd_device *device, const char *devname) {
597 _cleanup_free_ char *t = NULL;
598 int r;
599
600 assert(device);
601 assert(devname);
602
603 r = mangle_devname(devname, &t);
604 if (r < 0)
605 return r;
606
607 r = device_add_property_internal(device, "DEVNAME", t);
608 if (r < 0)
609 return r;
610
611 return free_and_replace(device->devname, t);
612 }
613
614 int device_set_devmode(sd_device *device, const char *_devmode) {
615 unsigned devmode;
616 int r;
617
618 assert(device);
619 assert(_devmode);
620
621 r = safe_atou(_devmode, &devmode);
622 if (r < 0)
623 return r;
624
625 if (devmode > 07777)
626 return -EINVAL;
627
628 r = device_add_property_internal(device, "DEVMODE", _devmode);
629 if (r < 0)
630 return r;
631
632 device->devmode = devmode;
633
634 return 0;
635 }
636
637 int device_set_devnum(sd_device *device, const char *major, const char *minor) {
638 unsigned maj, min = 0;
639 int r;
640
641 assert(device);
642 assert(major);
643
644 r = safe_atou(major, &maj);
645 if (r < 0)
646 return r;
647 if (maj == 0)
648 return 0;
649 if (!DEVICE_MAJOR_VALID(maj))
650 return -EINVAL;
651
652 if (minor) {
653 r = safe_atou(minor, &min);
654 if (r < 0)
655 return r;
656 if (!DEVICE_MINOR_VALID(min))
657 return -EINVAL;
658 }
659
660 r = device_add_property_internal(device, "MAJOR", major);
661 if (r < 0)
662 return r;
663
664 if (minor) {
665 r = device_add_property_internal(device, "MINOR", minor);
666 if (r < 0)
667 return r;
668 }
669
670 device->devnum = makedev(maj, min);
671
672 return 0;
673 }
674
675 int device_set_diskseq(sd_device *device, const char *str) {
676 uint64_t diskseq;
677 int r;
678
679 assert(device);
680 assert(str);
681
682 r = safe_atou64(str, &diskseq);
683 if (r < 0)
684 return r;
685 if (diskseq == 0)
686 return -EINVAL;
687
688 r = device_add_property_internal(device, "DISKSEQ", str);
689 if (r < 0)
690 return r;
691
692 device->diskseq = diskseq;
693
694 return 0;
695 }
696
697 static int handle_uevent_line(
698 sd_device *device,
699 const char *key,
700 const char *value,
701 const char **major,
702 const char **minor) {
703
704 assert(device);
705 assert(key);
706 assert(value);
707 assert(major);
708 assert(minor);
709
710 if (streq(key, "DEVTYPE"))
711 return device_set_devtype(device, value);
712 if (streq(key, "IFINDEX"))
713 return device_set_ifindex(device, value);
714 if (streq(key, "DEVNAME"))
715 return device_set_devname(device, value);
716 if (streq(key, "DEVMODE"))
717 return device_set_devmode(device, value);
718 if (streq(key, "DISKSEQ"))
719 return device_set_diskseq(device, value);
720 if (streq(key, "MAJOR"))
721 *major = value;
722 else if (streq(key, "MINOR"))
723 *minor = value;
724 else
725 return device_add_property_internal(device, key, value);
726
727 return 0;
728 }
729
730 int device_read_uevent_file(sd_device *device) {
731 _cleanup_free_ char *uevent = NULL;
732 const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
733 char *path;
734 size_t uevent_len;
735 int r;
736
737 enum {
738 PRE_KEY,
739 KEY,
740 PRE_VALUE,
741 VALUE,
742 INVALID_LINE,
743 } state = PRE_KEY;
744
745 assert(device);
746
747 if (device->uevent_loaded || device->sealed)
748 return 0;
749
750 r = sd_device_get_syspath(device, &syspath);
751 if (r < 0)
752 return r;
753
754 device->uevent_loaded = true;
755
756 path = strjoina(syspath, "/uevent");
757
758 r = read_full_virtual_file(path, &uevent, &uevent_len);
759 if (r == -EACCES || ERRNO_IS_NEG_DEVICE_ABSENT(r))
760 /* The uevent files may be write-only, the device may be already removed, or the device
761 * may not have the uevent file. */
762 return 0;
763 if (r < 0)
764 return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path);
765
766 for (size_t i = 0; i < uevent_len; i++)
767 switch (state) {
768 case PRE_KEY:
769 if (!strchr(NEWLINE, uevent[i])) {
770 key = &uevent[i];
771
772 state = KEY;
773 }
774
775 break;
776 case KEY:
777 if (uevent[i] == '=') {
778 uevent[i] = '\0';
779
780 state = PRE_VALUE;
781 } else if (strchr(NEWLINE, uevent[i])) {
782 uevent[i] = '\0';
783 log_device_debug(device, "sd-device: Invalid uevent line '%s', ignoring", key);
784
785 state = PRE_KEY;
786 }
787
788 break;
789 case PRE_VALUE:
790 value = &uevent[i];
791 state = VALUE;
792
793 _fallthrough_; /* to handle empty property */
794 case VALUE:
795 if (strchr(NEWLINE, uevent[i])) {
796 uevent[i] = '\0';
797
798 r = handle_uevent_line(device, key, value, &major, &minor);
799 if (r < 0)
800 log_device_debug_errno(device, r, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key, value);
801
802 state = PRE_KEY;
803 }
804
805 break;
806 default:
807 assert_not_reached();
808 }
809
810 if (major) {
811 r = device_set_devnum(device, major, minor);
812 if (r < 0)
813 log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, strna(minor), path);
814 }
815
816 return 0;
817 }
818
819 _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
820 int r;
821
822 assert_return(device, -EINVAL);
823
824 r = device_read_uevent_file(device);
825 if (r < 0)
826 return r;
827
828 if (device->ifindex <= 0)
829 return -ENOENT;
830
831 if (ifindex)
832 *ifindex = device->ifindex;
833
834 return 0;
835 }
836
837 _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
838 int r;
839
840 assert_return(ret, -EINVAL);
841 assert_return(id, -EINVAL);
842
843 switch (id[0]) {
844 case 'b':
845 case 'c': {
846 dev_t devt;
847
848 if (isempty(id))
849 return -EINVAL;
850
851 r = parse_devnum(id + 1, &devt);
852 if (r < 0)
853 return r;
854
855 return sd_device_new_from_devnum(ret, id[0], devt);
856 }
857
858 case 'n': {
859 int ifindex;
860
861 ifindex = parse_ifindex(id + 1);
862 if (ifindex < 0)
863 return ifindex;
864
865 return sd_device_new_from_ifindex(ret, ifindex);
866 }
867
868 case '+': {
869 const char *subsys, *sep;
870
871 sep = strchr(id + 1, ':');
872 if (!sep || sep - id - 1 > NAME_MAX)
873 return -EINVAL;
874
875 subsys = memdupa_suffix0(id + 1, sep - id - 1);
876
877 return sd_device_new_from_subsystem_sysname(ret, subsys, sep + 1);
878 }
879
880 default:
881 return -EINVAL;
882 }
883 }
884
885 _public_ int sd_device_get_syspath(sd_device *device, const char **ret) {
886 assert_return(device, -EINVAL);
887
888 assert(path_startswith(device->syspath, "/sys/"));
889
890 if (ret)
891 *ret = device->syspath;
892
893 return 0;
894 }
895
896 DEFINE_PRIVATE_HASH_OPS_FULL(
897 device_by_path_hash_ops,
898 char, path_hash_func, path_compare, free,
899 sd_device, sd_device_unref);
900
901 static int device_enumerate_children_internal(sd_device *device, const char *subdir, Set **stack, Hashmap **children) {
902 _cleanup_closedir_ DIR *dir = NULL;
903 int r;
904
905 assert(device);
906 assert(stack);
907 assert(children);
908
909 r = device_opendir(device, subdir, &dir);
910 if (r < 0)
911 return r;
912
913 FOREACH_DIRENT_ALL(de, dir, return -errno) {
914 _cleanup_(sd_device_unrefp) sd_device *child = NULL;
915 _cleanup_free_ char *p = NULL;
916
917 if (dot_or_dot_dot(de->d_name))
918 continue;
919
920 if (!IN_SET(de->d_type, DT_LNK, DT_DIR))
921 continue;
922
923 if (subdir)
924 p = path_join(subdir, de->d_name);
925 else
926 p = strdup(de->d_name);
927 if (!p)
928 return -ENOMEM;
929
930 /* Try to create child device. */
931 r = sd_device_new_child(&child, device, p);
932 if (r >= 0) {
933 /* OK, this is a child device, saving it. */
934 r = hashmap_ensure_put(children, &device_by_path_hash_ops, p, child);
935 if (r < 0)
936 return r;
937
938 TAKE_PTR(p);
939 TAKE_PTR(child);
940 } else if (r == -ENODEV) {
941 /* This is not a child device. Push the sub-directory into stack, and read it later. */
942
943 if (de->d_type == DT_LNK)
944 /* Do not follow symlinks, otherwise, we will enter an infinite loop, e.g.,
945 * /sys/class/block/nvme0n1/subsystem/nvme0n1/subsystem/nvme0n1/subsystem/… */
946 continue;
947
948 r = set_ensure_consume(stack, &path_hash_ops_free, TAKE_PTR(p));
949 if (r < 0)
950 return r;
951 } else
952 return r;
953 }
954
955 return 0;
956 }
957
958 static int device_enumerate_children(sd_device *device) {
959 _cleanup_hashmap_free_ Hashmap *children = NULL;
960 _cleanup_set_free_ Set *stack = NULL;
961 int r;
962
963 assert(device);
964
965 if (device->children_enumerated)
966 return 0; /* Already enumerated. */
967
968 r = device_enumerate_children_internal(device, NULL, &stack, &children);
969 if (r < 0)
970 return r;
971
972 for (;;) {
973 _cleanup_free_ char *subdir = NULL;
974
975 subdir = set_steal_first(stack);
976 if (!subdir)
977 break;
978
979 r = device_enumerate_children_internal(device, subdir, &stack, &children);
980 if (r < 0)
981 return r;
982 }
983
984 device->children_enumerated = true;
985 device->children = TAKE_PTR(children);
986 return 1; /* Enumerated. */
987 }
988
989 _public_ sd_device *sd_device_get_child_first(sd_device *device, const char **ret_suffix) {
990 int r;
991
992 assert(device);
993
994 r = device_enumerate_children(device);
995 if (r < 0) {
996 log_device_debug_errno(device, r, "sd-device: failed to enumerate child devices: %m");
997 if (ret_suffix)
998 *ret_suffix = NULL;
999 return NULL;
1000 }
1001
1002 device->children_iterator = ITERATOR_FIRST;
1003
1004 return sd_device_get_child_next(device, ret_suffix);
1005 }
1006
1007 _public_ sd_device *sd_device_get_child_next(sd_device *device, const char **ret_suffix) {
1008 sd_device *child;
1009
1010 assert(device);
1011
1012 (void) hashmap_iterate(device->children, &device->children_iterator, (void**) &child, (const void**) ret_suffix);
1013 return child;
1014 }
1015
1016 _public_ int sd_device_new_child(sd_device **ret, sd_device *device, const char *suffix) {
1017 _cleanup_free_ char *path = NULL;
1018 sd_device *child;
1019 const char *s;
1020 int r;
1021
1022 assert_return(ret, -EINVAL);
1023 assert_return(device, -EINVAL);
1024 assert_return(suffix, -EINVAL);
1025
1026 if (!path_is_safe(suffix))
1027 return -EINVAL;
1028
1029 /* If we have already enumerated children, try to find the child from the cache. */
1030 child = hashmap_get(device->children, suffix);
1031 if (child) {
1032 *ret = sd_device_ref(child);
1033 return 0;
1034 }
1035
1036 r = sd_device_get_syspath(device, &s);
1037 if (r < 0)
1038 return r;
1039
1040 path = path_join(s, suffix);
1041 if (!path)
1042 return -ENOMEM;
1043
1044 return sd_device_new_from_syspath(ret, path);
1045 }
1046
1047 static int device_new_from_child(sd_device **ret, sd_device *child) {
1048 _cleanup_free_ char *path = NULL;
1049 const char *syspath;
1050 int r;
1051
1052 assert(ret);
1053 assert(child);
1054
1055 r = sd_device_get_syspath(child, &syspath);
1056 if (r < 0)
1057 return r;
1058
1059 for (;;) {
1060 _cleanup_free_ char *p = NULL;
1061
1062 r = path_extract_directory(path ?: syspath, &p);
1063 if (r < 0)
1064 return r;
1065
1066 if (path_equal(p, "/sys"))
1067 return -ENODEV;
1068
1069 r = sd_device_new_from_syspath(ret, p);
1070 if (r != -ENODEV)
1071 return r;
1072
1073 free_and_replace(path, p);
1074 }
1075 }
1076
1077 _public_ int sd_device_get_parent(sd_device *child, sd_device **ret) {
1078 int r;
1079
1080 assert_return(child, -EINVAL);
1081
1082 if (!child->parent_set) {
1083 r = device_new_from_child(&child->parent, child);
1084 if (r < 0 && r != -ENODEV)
1085 return r;
1086
1087 child->parent_set = true;
1088 }
1089
1090 if (!child->parent)
1091 return -ENOENT;
1092
1093 if (ret)
1094 *ret = child->parent;
1095 return 0;
1096 }
1097
1098 int device_set_subsystem(sd_device *device, const char *subsystem) {
1099 _cleanup_free_ char *s = NULL;
1100 int r;
1101
1102 assert(device);
1103
1104 if (subsystem) {
1105 s = strdup(subsystem);
1106 if (!s)
1107 return -ENOMEM;
1108 }
1109
1110 r = device_add_property_internal(device, "SUBSYSTEM", s);
1111 if (r < 0)
1112 return r;
1113
1114 device->subsystem_set = true;
1115 return free_and_replace(device->subsystem, s);
1116 }
1117
1118 int device_set_drivers_subsystem(sd_device *device) {
1119 _cleanup_free_ char *subsystem = NULL;
1120 const char *devpath, *drivers, *p;
1121 int r;
1122
1123 assert(device);
1124
1125 r = sd_device_get_devpath(device, &devpath);
1126 if (r < 0)
1127 return r;
1128
1129 drivers = strstr(devpath, "/drivers/");
1130 if (!drivers)
1131 drivers = endswith(devpath, "/drivers");
1132 if (!drivers)
1133 return -EINVAL;
1134
1135 /* Find the path component immediately before the "/drivers/" string */
1136 r = path_find_last_component(devpath, /* accept_dot_dot= */ false, &drivers, &p);
1137 if (r < 0)
1138 return r;
1139 if (r == 0)
1140 return -EINVAL;
1141
1142 subsystem = strndup(p, r);
1143 if (!subsystem)
1144 return -ENOMEM;
1145
1146 r = device_set_subsystem(device, "drivers");
1147 if (r < 0)
1148 return r;
1149
1150 return free_and_replace(device->driver_subsystem, subsystem);
1151 }
1152
1153 _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
1154 int r;
1155
1156 assert_return(device, -EINVAL);
1157
1158 if (!device->subsystem_set) {
1159 _cleanup_free_ char *subsystem = NULL;
1160 const char *syspath;
1161 char *path;
1162
1163 r = sd_device_get_syspath(device, &syspath);
1164 if (r < 0)
1165 return r;
1166
1167 /* read 'subsystem' link */
1168 path = strjoina(syspath, "/subsystem");
1169 r = readlink_value(path, &subsystem);
1170 if (r < 0 && r != -ENOENT)
1171 return log_device_debug_errno(device, r,
1172 "sd-device: Failed to read subsystem for %s: %m",
1173 device->devpath);
1174
1175 if (subsystem)
1176 r = device_set_subsystem(device, subsystem);
1177 /* use implicit names */
1178 else if (!isempty(path_startswith(device->devpath, "/module/")))
1179 r = device_set_subsystem(device, "module");
1180 else if (strstr(syspath, "/drivers/") || endswith(syspath, "/drivers"))
1181 r = device_set_drivers_subsystem(device);
1182 else if (!isempty(PATH_STARTSWITH_SET(device->devpath, "/class/", "/bus/")))
1183 r = device_set_subsystem(device, "subsystem");
1184 else {
1185 device->subsystem_set = true;
1186 r = 0;
1187 }
1188 if (r < 0)
1189 return log_device_debug_errno(device, r,
1190 "sd-device: Failed to set subsystem for %s: %m",
1191 device->devpath);
1192 }
1193
1194 if (!device->subsystem)
1195 return -ENOENT;
1196
1197 if (ret)
1198 *ret = device->subsystem;
1199 return 0;
1200 }
1201
1202 _public_ int sd_device_get_devtype(sd_device *device, const char **devtype) {
1203 int r;
1204
1205 assert_return(device, -EINVAL);
1206
1207 r = device_read_uevent_file(device);
1208 if (r < 0)
1209 return r;
1210
1211 if (!device->devtype)
1212 return -ENOENT;
1213
1214 if (devtype)
1215 *devtype = device->devtype;
1216
1217 return !!device->devtype;
1218 }
1219
1220 _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) {
1221 sd_device *parent = NULL;
1222 int r;
1223
1224 assert_return(child, -EINVAL);
1225 assert_return(subsystem, -EINVAL);
1226
1227 r = sd_device_get_parent(child, &parent);
1228 while (r >= 0) {
1229 const char *parent_subsystem = NULL;
1230
1231 (void) sd_device_get_subsystem(parent, &parent_subsystem);
1232 if (streq_ptr(parent_subsystem, subsystem)) {
1233 const char *parent_devtype = NULL;
1234
1235 if (!devtype)
1236 break;
1237
1238 (void) sd_device_get_devtype(parent, &parent_devtype);
1239 if (streq_ptr(parent_devtype, devtype))
1240 break;
1241 }
1242 r = sd_device_get_parent(parent, &parent);
1243 }
1244
1245 if (r < 0)
1246 return r;
1247
1248 if (ret)
1249 *ret = parent;
1250 return 0;
1251 }
1252
1253 _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
1254 int r;
1255
1256 assert_return(device, -EINVAL);
1257
1258 r = device_read_uevent_file(device);
1259 if (r < 0)
1260 return r;
1261
1262 if (major(device->devnum) <= 0)
1263 return -ENOENT;
1264
1265 if (devnum)
1266 *devnum = device->devnum;
1267
1268 return 0;
1269 }
1270
1271 int device_set_driver(sd_device *device, const char *driver) {
1272 _cleanup_free_ char *d = NULL;
1273 int r;
1274
1275 assert(device);
1276
1277 if (driver) {
1278 d = strdup(driver);
1279 if (!d)
1280 return -ENOMEM;
1281 }
1282
1283 r = device_add_property_internal(device, "DRIVER", d);
1284 if (r < 0)
1285 return r;
1286
1287 device->driver_set = true;
1288 return free_and_replace(device->driver, d);
1289 }
1290
1291 _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
1292 assert_return(device, -EINVAL);
1293
1294 if (!device->driver_set) {
1295 _cleanup_free_ char *driver = NULL;
1296 const char *syspath;
1297 char *path;
1298 int r;
1299
1300 r = sd_device_get_syspath(device, &syspath);
1301 if (r < 0)
1302 return r;
1303
1304 path = strjoina(syspath, "/driver");
1305 r = readlink_value(path, &driver);
1306 if (r < 0 && r != -ENOENT)
1307 return log_device_debug_errno(device, r,
1308 "sd-device: readlink(\"%s\") failed: %m", path);
1309
1310 r = device_set_driver(device, driver);
1311 if (r < 0)
1312 return log_device_debug_errno(device, r,
1313 "sd-device: Failed to set driver \"%s\": %m", driver);
1314 }
1315
1316 if (!device->driver)
1317 return -ENOENT;
1318
1319 if (ret)
1320 *ret = device->driver;
1321 return 0;
1322 }
1323
1324 _public_ int sd_device_get_devpath(sd_device *device, const char **ret) {
1325 assert_return(device, -EINVAL);
1326
1327 assert(device->devpath);
1328 assert(device->devpath[0] == '/');
1329
1330 if (ret)
1331 *ret = device->devpath;
1332
1333 return 0;
1334 }
1335
1336 _public_ int sd_device_get_devname(sd_device *device, const char **devname) {
1337 int r;
1338
1339 assert_return(device, -EINVAL);
1340
1341 r = device_read_uevent_file(device);
1342 if (r < 0)
1343 return r;
1344
1345 if (!device->devname)
1346 return -ENOENT;
1347
1348 assert(!isempty(path_startswith(device->devname, "/dev/")));
1349
1350 if (devname)
1351 *devname = device->devname;
1352 return 0;
1353 }
1354
1355 static int device_set_sysname_and_sysnum(sd_device *device) {
1356 _cleanup_free_ char *sysname = NULL;
1357 size_t len, n;
1358 int r;
1359
1360 assert(device);
1361
1362 r = path_extract_filename(device->devpath, &sysname);
1363 if (r < 0)
1364 return r;
1365 if (r == O_DIRECTORY)
1366 return -EINVAL;
1367
1368 /* some devices have '!' in their name, change that to '/' */
1369 string_replace_char(sysname, '!', '/');
1370
1371 n = strspn_from_end(sysname, DIGITS);
1372 len = strlen(sysname);
1373 assert(n <= len);
1374 if (n == len)
1375 n = 0; /* Do not set sysnum for number only sysname. */
1376
1377 device->sysnum = n > 0 ? sysname + len - n : NULL;
1378 return free_and_replace(device->sysname, sysname);
1379 }
1380
1381 _public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
1382 int r;
1383
1384 assert_return(device, -EINVAL);
1385
1386 if (!device->sysname) {
1387 r = device_set_sysname_and_sysnum(device);
1388 if (r < 0)
1389 return r;
1390 }
1391
1392 if (ret)
1393 *ret = device->sysname;
1394 return 0;
1395 }
1396
1397 _public_ int sd_device_get_sysnum(sd_device *device, const char **ret) {
1398 int r;
1399
1400 assert_return(device, -EINVAL);
1401
1402 if (!device->sysname) {
1403 r = device_set_sysname_and_sysnum(device);
1404 if (r < 0)
1405 return r;
1406 }
1407
1408 if (!device->sysnum)
1409 return -ENOENT;
1410
1411 if (ret)
1412 *ret = device->sysnum;
1413 return 0;
1414 }
1415
1416 _public_ int sd_device_get_action(sd_device *device, sd_device_action_t *ret) {
1417 assert_return(device, -EINVAL);
1418
1419 if (device->action < 0)
1420 return -ENOENT;
1421
1422 if (ret)
1423 *ret = device->action;
1424
1425 return 0;
1426 }
1427
1428 _public_ int sd_device_get_seqnum(sd_device *device, uint64_t *ret) {
1429 assert_return(device, -EINVAL);
1430
1431 if (device->seqnum == 0)
1432 return -ENOENT;
1433
1434 if (ret)
1435 *ret = device->seqnum;
1436
1437 return 0;
1438 }
1439
1440 _public_ int sd_device_get_diskseq(sd_device *device, uint64_t *ret) {
1441 int r;
1442
1443 assert_return(device, -EINVAL);
1444
1445 r = device_read_uevent_file(device);
1446 if (r < 0)
1447 return r;
1448
1449 if (device->diskseq == 0)
1450 return -ENOENT;
1451
1452 if (ret)
1453 *ret = device->diskseq;
1454
1455 return 0;
1456 }
1457
1458 static bool is_valid_tag(const char *tag) {
1459 assert(tag);
1460
1461 return in_charset(tag, ALPHANUMERICAL "-_") && filename_is_valid(tag);
1462 }
1463
1464 int device_add_tag(sd_device *device, const char *tag, bool both) {
1465 int r, added;
1466
1467 assert(device);
1468 assert(tag);
1469
1470 if (!is_valid_tag(tag))
1471 return -EINVAL;
1472
1473 /* Definitely add to the "all" list of tags (i.e. the sticky list) */
1474 added = set_put_strdup(&device->all_tags, tag);
1475 if (added < 0)
1476 return added;
1477
1478 /* And optionally, also add it to the current list of tags */
1479 if (both) {
1480 r = set_put_strdup(&device->current_tags, tag);
1481 if (r < 0) {
1482 if (added > 0)
1483 (void) set_remove(device->all_tags, tag);
1484
1485 return r;
1486 }
1487 }
1488
1489 device->tags_generation++;
1490 device->property_tags_outdated = true;
1491
1492 return 0;
1493 }
1494
1495 int device_add_devlink(sd_device *device, const char *devlink) {
1496 char *p;
1497 int r;
1498
1499 assert(device);
1500 assert(devlink);
1501
1502 r = mangle_devname(devlink, &p);
1503 if (r < 0)
1504 return r;
1505
1506 r = set_ensure_consume(&device->devlinks, &path_hash_ops_free, p);
1507 if (r < 0)
1508 return r;
1509
1510 device->devlinks_generation++;
1511 device->property_devlinks_outdated = true;
1512
1513 return r; /* return 1 when newly added, 0 when already exists */
1514 }
1515
1516 int device_remove_devlink(sd_device *device, const char *devlink) {
1517 _cleanup_free_ char *p = NULL, *s = NULL;
1518 int r;
1519
1520 assert(device);
1521 assert(devlink);
1522
1523 r = mangle_devname(devlink, &p);
1524 if (r < 0)
1525 return r;
1526
1527 s = set_remove(device->devlinks, p);
1528 if (!s)
1529 return 0; /* does not exist */
1530
1531 device->devlinks_generation++;
1532 device->property_devlinks_outdated = true;
1533 return 1; /* removed */
1534 }
1535
1536 bool device_has_devlink(sd_device *device, const char *devlink) {
1537 assert(device);
1538 assert(devlink);
1539
1540 return set_contains(device->devlinks, devlink);
1541 }
1542
1543 static int device_add_property_internal_from_string(sd_device *device, const char *str) {
1544 _cleanup_free_ char *key = NULL;
1545 char *value;
1546 int r;
1547
1548 assert(device);
1549 assert(str);
1550
1551 key = strdup(str);
1552 if (!key)
1553 return -ENOMEM;
1554
1555 value = strchr(key, '=');
1556 if (!value)
1557 return -EINVAL;
1558
1559 *value = '\0';
1560
1561 if (isempty(++value))
1562 value = NULL;
1563
1564 /* Add the property to both sd_device::properties and sd_device::properties_db,
1565 * as this is called by only handle_db_line(). */
1566 r = device_add_property_aux(device, key, value, false);
1567 if (r < 0)
1568 return r;
1569
1570 return device_add_property_aux(device, key, value, true);
1571 }
1572
1573 int device_set_usec_initialized(sd_device *device, usec_t when) {
1574 char s[DECIMAL_STR_MAX(usec_t)];
1575 int r;
1576
1577 assert(device);
1578
1579 xsprintf(s, USEC_FMT, when);
1580
1581 r = device_add_property_internal(device, "USEC_INITIALIZED", s);
1582 if (r < 0)
1583 return r;
1584
1585 device->usec_initialized = when;
1586 return 0;
1587 }
1588
1589 static int handle_db_line(sd_device *device, char key, const char *value) {
1590 int r;
1591
1592 assert(device);
1593 assert(value);
1594
1595 switch (key) {
1596 case 'G': /* Any tag */
1597 case 'Q': /* Current tag */
1598 return device_add_tag(device, value, key == 'Q');
1599
1600 case 'S': {
1601 const char *path;
1602
1603 path = strjoina("/dev/", value);
1604 return device_add_devlink(device, path);
1605 }
1606 case 'E':
1607 return device_add_property_internal_from_string(device, value);
1608
1609 case 'I': {
1610 usec_t t;
1611
1612 r = safe_atou64(value, &t);
1613 if (r < 0)
1614 return r;
1615
1616 return device_set_usec_initialized(device, t);
1617 }
1618 case 'L':
1619 return safe_atoi(value, &device->devlink_priority);
1620
1621 case 'W':
1622 /* Deprecated. Previously, watch handle is both saved in database and /run/udev/watch.
1623 * However, the handle saved in database may not be updated when the handle is updated
1624 * or removed. Moreover, it is not necessary to store the handle within the database,
1625 * as its value becomes meaningless when udevd is restarted. */
1626 return 0;
1627
1628 case 'V':
1629 return safe_atou(value, &device->database_version);
1630
1631 default:
1632 log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key);
1633 return 0;
1634 }
1635 }
1636
1637 int device_get_device_id(sd_device *device, const char **ret) {
1638 assert(device);
1639 assert(ret);
1640
1641 if (!device->device_id) {
1642 _cleanup_free_ char *id = NULL;
1643 const char *subsystem;
1644 dev_t devnum;
1645 int ifindex, r;
1646
1647 r = sd_device_get_subsystem(device, &subsystem);
1648 if (r < 0)
1649 return r;
1650
1651 if (sd_device_get_devnum(device, &devnum) >= 0) {
1652 /* use dev_t — b259:131072, c254:0 */
1653 if (asprintf(&id, "%c" DEVNUM_FORMAT_STR,
1654 streq(subsystem, "block") ? 'b' : 'c',
1655 DEVNUM_FORMAT_VAL(devnum)) < 0)
1656 return -ENOMEM;
1657 } else if (sd_device_get_ifindex(device, &ifindex) >= 0) {
1658 /* use netdev ifindex — n3 */
1659 if (asprintf(&id, "n%u", (unsigned) ifindex) < 0)
1660 return -ENOMEM;
1661 } else {
1662 _cleanup_free_ char *sysname = NULL;
1663
1664 /* use $subsys:$sysname — pci:0000:00:1f.2
1665 * sd_device_get_sysname() has '!' translated, get it from devpath */
1666 r = path_extract_filename(device->devpath, &sysname);
1667 if (r < 0)
1668 return r;
1669 if (r == O_DIRECTORY)
1670 return -EINVAL;
1671
1672 if (streq(subsystem, "drivers")) {
1673 /* the 'drivers' pseudo-subsystem is special, and needs the real
1674 * subsystem encoded as well */
1675 assert(device->driver_subsystem);
1676 id = strjoin("+drivers:", device->driver_subsystem, ":", sysname);
1677 } else
1678 id = strjoin("+", subsystem, ":", sysname);
1679 if (!id)
1680 return -ENOMEM;
1681 }
1682
1683 if (!filename_is_valid(id))
1684 return -EINVAL;
1685
1686 device->device_id = TAKE_PTR(id);
1687 }
1688
1689 *ret = device->device_id;
1690 return 0;
1691 }
1692
1693 int device_read_db_internal_filename(sd_device *device, const char *filename) {
1694 _cleanup_free_ char *db = NULL;
1695 const char *value;
1696 size_t db_len;
1697 char key = '\0'; /* Unnecessary initialization to appease gcc-12.0.0-0.4.fc36 */
1698 int r;
1699
1700 enum {
1701 PRE_KEY,
1702 KEY,
1703 PRE_VALUE,
1704 VALUE,
1705 INVALID_LINE,
1706 } state = PRE_KEY;
1707
1708 assert(device);
1709 assert(filename);
1710
1711 r = read_full_file(filename, &db, &db_len);
1712 if (r < 0) {
1713 if (r == -ENOENT)
1714 return 0;
1715
1716 return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", filename);
1717 }
1718
1719 /* devices with a database entry are initialized */
1720 device->is_initialized = true;
1721
1722 device->db_loaded = true;
1723
1724 for (size_t i = 0; i < db_len; i++)
1725 switch (state) {
1726 case PRE_KEY:
1727 if (!strchr(NEWLINE, db[i])) {
1728 key = db[i];
1729
1730 state = KEY;
1731 }
1732
1733 break;
1734 case KEY:
1735 if (db[i] != ':') {
1736 log_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", key);
1737
1738 state = INVALID_LINE;
1739 } else {
1740 db[i] = '\0';
1741
1742 state = PRE_VALUE;
1743 }
1744
1745 break;
1746 case PRE_VALUE:
1747 value = &db[i];
1748
1749 state = VALUE;
1750
1751 break;
1752 case INVALID_LINE:
1753 if (strchr(NEWLINE, db[i]))
1754 state = PRE_KEY;
1755
1756 break;
1757 case VALUE:
1758 if (strchr(NEWLINE, db[i])) {
1759 db[i] = '\0';
1760 r = handle_db_line(device, key, value);
1761 if (r < 0)
1762 log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m",
1763 key, value);
1764
1765 state = PRE_KEY;
1766 }
1767
1768 break;
1769 default:
1770 return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL), "sd-device: invalid db syntax.");
1771 }
1772
1773 return 0;
1774 }
1775
1776 int device_read_db_internal(sd_device *device, bool force) {
1777 const char *id, *path;
1778 int r;
1779
1780 assert(device);
1781
1782 if (device->db_loaded || (!force && device->sealed))
1783 return 0;
1784
1785 r = device_get_device_id(device, &id);
1786 if (r < 0)
1787 return r;
1788
1789 path = strjoina("/run/udev/data/", id);
1790
1791 return device_read_db_internal_filename(device, path);
1792 }
1793
1794 _public_ int sd_device_get_is_initialized(sd_device *device) {
1795 int r;
1796
1797 assert_return(device, -EINVAL);
1798
1799 r = device_read_db(device);
1800 if (r == -ENOENT)
1801 /* The device may be already removed or renamed. */
1802 return false;
1803 if (r < 0)
1804 return r;
1805
1806 return device->is_initialized;
1807 }
1808
1809 _public_ int sd_device_get_usec_initialized(sd_device *device, uint64_t *ret) {
1810 int r;
1811
1812 assert_return(device, -EINVAL);
1813
1814 r = sd_device_get_is_initialized(device);
1815 if (r < 0)
1816 return r;
1817 if (r == 0)
1818 return -EBUSY;
1819
1820 if (device->usec_initialized == 0)
1821 return -ENODATA;
1822
1823 if (ret)
1824 *ret = device->usec_initialized;
1825
1826 return 0;
1827 }
1828
1829 _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *ret) {
1830 usec_t now_ts, ts;
1831 int r;
1832
1833 assert_return(device, -EINVAL);
1834
1835 r = sd_device_get_usec_initialized(device, &ts);
1836 if (r < 0)
1837 return r;
1838
1839 now_ts = now(CLOCK_MONOTONIC);
1840
1841 if (now_ts < ts)
1842 return -EIO;
1843
1844 if (ret)
1845 *ret = usec_sub_unsigned(now_ts, ts);
1846
1847 return 0;
1848 }
1849
1850 _public_ const char *sd_device_get_tag_first(sd_device *device) {
1851 void *v;
1852
1853 assert_return(device, NULL);
1854
1855 (void) device_read_db(device);
1856
1857 device->all_tags_iterator_generation = device->tags_generation;
1858 device->all_tags_iterator = ITERATOR_FIRST;
1859
1860 (void) set_iterate(device->all_tags, &device->all_tags_iterator, &v);
1861 return v;
1862 }
1863
1864 _public_ const char *sd_device_get_tag_next(sd_device *device) {
1865 void *v;
1866
1867 assert_return(device, NULL);
1868
1869 (void) device_read_db(device);
1870
1871 if (device->all_tags_iterator_generation != device->tags_generation)
1872 return NULL;
1873
1874 (void) set_iterate(device->all_tags, &device->all_tags_iterator, &v);
1875 return v;
1876 }
1877
1878 static bool device_database_supports_current_tags(sd_device *device) {
1879 assert(device);
1880
1881 (void) device_read_db(device);
1882
1883 /* The current tags (saved in Q field) feature is implemented in database version 1.
1884 * If the database version is 0, then the tags (NOT current tags, saved in G field) are not
1885 * sticky. Thus, we can safely bypass the operations for the current tags (Q) to tags (G). */
1886
1887 return device->database_version >= 1;
1888 }
1889
1890 _public_ const char *sd_device_get_current_tag_first(sd_device *device) {
1891 void *v;
1892
1893 assert_return(device, NULL);
1894
1895 if (!device_database_supports_current_tags(device))
1896 return sd_device_get_tag_first(device);
1897
1898 (void) device_read_db(device);
1899
1900 device->current_tags_iterator_generation = device->tags_generation;
1901 device->current_tags_iterator = ITERATOR_FIRST;
1902
1903 (void) set_iterate(device->current_tags, &device->current_tags_iterator, &v);
1904 return v;
1905 }
1906
1907 _public_ const char *sd_device_get_current_tag_next(sd_device *device) {
1908 void *v;
1909
1910 assert_return(device, NULL);
1911
1912 if (!device_database_supports_current_tags(device))
1913 return sd_device_get_tag_next(device);
1914
1915 (void) device_read_db(device);
1916
1917 if (device->current_tags_iterator_generation != device->tags_generation)
1918 return NULL;
1919
1920 (void) set_iterate(device->current_tags, &device->current_tags_iterator, &v);
1921 return v;
1922 }
1923
1924 _public_ const char *sd_device_get_devlink_first(sd_device *device) {
1925 void *v;
1926
1927 assert_return(device, NULL);
1928
1929 (void) device_read_db(device);
1930
1931 device->devlinks_iterator_generation = device->devlinks_generation;
1932 device->devlinks_iterator = ITERATOR_FIRST;
1933
1934 (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
1935 return v;
1936 }
1937
1938 _public_ const char *sd_device_get_devlink_next(sd_device *device) {
1939 void *v;
1940
1941 assert_return(device, NULL);
1942
1943 (void) device_read_db(device);
1944
1945 if (device->devlinks_iterator_generation != device->devlinks_generation)
1946 return NULL;
1947
1948 (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v);
1949 return v;
1950 }
1951
1952 int device_properties_prepare(sd_device *device) {
1953 int r;
1954
1955 assert(device);
1956
1957 r = device_read_uevent_file(device);
1958 if (r < 0)
1959 return r;
1960
1961 r = device_read_db(device);
1962 if (r < 0)
1963 return r;
1964
1965 if (device->property_devlinks_outdated) {
1966 _cleanup_free_ char *devlinks = NULL;
1967
1968 r = set_strjoin(device->devlinks, " ", false, &devlinks);
1969 if (r < 0)
1970 return r;
1971
1972 if (!isempty(devlinks)) {
1973 r = device_add_property_internal(device, "DEVLINKS", devlinks);
1974 if (r < 0)
1975 return r;
1976 }
1977
1978 device->property_devlinks_outdated = false;
1979 }
1980
1981 if (device->property_tags_outdated) {
1982 _cleanup_free_ char *tags = NULL;
1983
1984 r = set_strjoin(device->all_tags, ":", true, &tags);
1985 if (r < 0)
1986 return r;
1987
1988 if (!isempty(tags)) {
1989 r = device_add_property_internal(device, "TAGS", tags);
1990 if (r < 0)
1991 return r;
1992 }
1993
1994 tags = mfree(tags);
1995 r = set_strjoin(device->current_tags, ":", true, &tags);
1996 if (r < 0)
1997 return r;
1998
1999 if (!isempty(tags)) {
2000 r = device_add_property_internal(device, "CURRENT_TAGS", tags);
2001 if (r < 0)
2002 return r;
2003 }
2004
2005 device->property_tags_outdated = false;
2006 }
2007
2008 return 0;
2009 }
2010
2011 _public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
2012 const char *key;
2013 int r;
2014
2015 assert_return(device, NULL);
2016
2017 r = device_properties_prepare(device);
2018 if (r < 0)
2019 return NULL;
2020
2021 device->properties_iterator_generation = device->properties_generation;
2022 device->properties_iterator = ITERATOR_FIRST;
2023
2024 (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
2025 return key;
2026 }
2027
2028 _public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
2029 const char *key;
2030 int r;
2031
2032 assert_return(device, NULL);
2033
2034 r = device_properties_prepare(device);
2035 if (r < 0)
2036 return NULL;
2037
2038 if (device->properties_iterator_generation != device->properties_generation)
2039 return NULL;
2040
2041 (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
2042 return key;
2043 }
2044
2045 static int device_sysattrs_read_all_internal(sd_device *device, const char *subdir, Set **stack) {
2046 _cleanup_closedir_ DIR *dir = NULL;
2047 int r;
2048
2049 assert(device);
2050 assert(stack);
2051
2052 r = device_opendir(device, subdir, &dir);
2053 if (r == -ENOENT && subdir)
2054 return 0; /* Maybe, this is a child device, and is already removed. */
2055 if (r < 0)
2056 return r;
2057
2058 if (subdir) {
2059 if (faccessat(dirfd(dir), "uevent", F_OK, 0) >= 0)
2060 return 0; /* this is a child device, skipping */
2061 if (errno != ENOENT) {
2062 log_device_debug_errno(device, errno,
2063 "sd-device: Failed to access %s/uevent, ignoring sub-directory %s: %m",
2064 subdir, subdir);
2065 return 0;
2066 }
2067 }
2068
2069 FOREACH_DIRENT_ALL(de, dir, return -errno) {
2070 _cleanup_free_ char *p = NULL;
2071 struct stat statbuf;
2072
2073 if (dot_or_dot_dot(de->d_name))
2074 continue;
2075
2076 /* only handle symlinks, regular files, and directories */
2077 if (!IN_SET(de->d_type, DT_LNK, DT_REG, DT_DIR))
2078 continue;
2079
2080 if (subdir) {
2081 p = path_join(subdir, de->d_name);
2082 if (!p)
2083 return -ENOMEM;
2084 }
2085
2086 if (de->d_type == DT_DIR) {
2087 /* push the sub-directory into the stack, and read it later. */
2088 if (p)
2089 r = set_ensure_consume(stack, &path_hash_ops_free, TAKE_PTR(p));
2090 else
2091 r = set_put_strdup_full(stack, &path_hash_ops_free, de->d_name);
2092 if (r < 0)
2093 return r;
2094
2095 continue;
2096 }
2097
2098 if (fstatat(dirfd(dir), de->d_name, &statbuf, AT_SYMLINK_NOFOLLOW) < 0)
2099 continue;
2100
2101 if ((statbuf.st_mode & (S_IRUSR | S_IWUSR)) == 0)
2102 continue;
2103
2104 if (p)
2105 r = set_ensure_consume(&device->sysattrs, &path_hash_ops_free, TAKE_PTR(p));
2106 else
2107 r = set_put_strdup_full(&device->sysattrs, &path_hash_ops_free, de->d_name);
2108 if (r < 0)
2109 return r;
2110 }
2111
2112 return 0;
2113 }
2114
2115 static int device_sysattrs_read_all(sd_device *device) {
2116 _cleanup_set_free_ Set *stack = NULL;
2117 int r;
2118
2119 assert(device);
2120
2121 if (device->sysattrs_read)
2122 return 0;
2123
2124 r = device_sysattrs_read_all_internal(device, NULL, &stack);
2125 if (r < 0)
2126 return r;
2127
2128 for (;;) {
2129 _cleanup_free_ char *subdir = NULL;
2130
2131 subdir = set_steal_first(stack);
2132 if (!subdir)
2133 break;
2134
2135 r = device_sysattrs_read_all_internal(device, subdir, &stack);
2136 if (r < 0)
2137 return r;
2138 }
2139
2140 device->sysattrs_read = true;
2141
2142 return 0;
2143 }
2144
2145 _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
2146 void *v;
2147 int r;
2148
2149 assert_return(device, NULL);
2150
2151 if (!device->sysattrs_read) {
2152 r = device_sysattrs_read_all(device);
2153 if (r < 0) {
2154 errno = -r;
2155 return NULL;
2156 }
2157 }
2158
2159 device->sysattrs_iterator = ITERATOR_FIRST;
2160
2161 (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
2162 return v;
2163 }
2164
2165 _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
2166 void *v;
2167
2168 assert_return(device, NULL);
2169
2170 if (!device->sysattrs_read)
2171 return NULL;
2172
2173 (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
2174 return v;
2175 }
2176
2177 _public_ int sd_device_has_tag(sd_device *device, const char *tag) {
2178 assert_return(device, -EINVAL);
2179 assert_return(tag, -EINVAL);
2180
2181 (void) device_read_db(device);
2182
2183 return set_contains(device->all_tags, tag);
2184 }
2185
2186 _public_ int sd_device_has_current_tag(sd_device *device, const char *tag) {
2187 assert_return(device, -EINVAL);
2188 assert_return(tag, -EINVAL);
2189
2190 if (!device_database_supports_current_tags(device))
2191 return sd_device_has_tag(device, tag);
2192
2193 (void) device_read_db(device);
2194
2195 return set_contains(device->current_tags, tag);
2196 }
2197
2198 _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **ret_value) {
2199 const char *value;
2200 int r;
2201
2202 assert_return(device, -EINVAL);
2203 assert_return(key, -EINVAL);
2204
2205 r = device_properties_prepare(device);
2206 if (r < 0)
2207 return r;
2208
2209 value = ordered_hashmap_get(device->properties, key);
2210 if (!value)
2211 return -ENOENT;
2212
2213 if (ret_value)
2214 *ret_value = value;
2215 return 0;
2216 }
2217
2218 int device_get_property_bool(sd_device *device, const char *key) {
2219 const char *value;
2220 int r;
2221
2222 assert(device);
2223 assert(key);
2224
2225 r = sd_device_get_property_value(device, key, &value);
2226 if (r < 0)
2227 return r;
2228
2229 return parse_boolean(value);
2230 }
2231
2232 int device_get_property_int(sd_device *device, const char *key, int *ret) {
2233 const char *value;
2234 int r, v;
2235
2236 assert(device);
2237 assert(key);
2238
2239 r = sd_device_get_property_value(device, key, &value);
2240 if (r < 0)
2241 return r;
2242
2243 r = safe_atoi(value, &v);
2244 if (r < 0)
2245 return r;
2246
2247 if (ret)
2248 *ret = v;
2249 return 0;
2250 }
2251
2252 _public_ int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret) {
2253 const char *s;
2254 sd_id128_t id;
2255 int r;
2256
2257 assert_return(device, -EINVAL);
2258
2259 /* Retrieves the UUID attached to a uevent when triggering it from userspace via
2260 * sd_device_trigger_with_uuid() or an equivalent interface. Returns -ENOENT if the record is not
2261 * caused by a synthetic event and -ENODATA if it was but no UUID was specified */
2262
2263 r = sd_device_get_property_value(device, "SYNTH_UUID", &s);
2264 if (r < 0)
2265 return r;
2266
2267 if (streq(s, "0")) /* SYNTH_UUID=0 is set whenever a device is triggered by userspace without specifying a UUID */
2268 return -ENODATA;
2269
2270 r = sd_id128_from_string(s, &id);
2271 if (r < 0)
2272 return r;
2273
2274 if (ret)
2275 *ret = id;
2276
2277 return 0;
2278 }
2279
2280 void device_clear_sysattr_cache(sd_device *device) {
2281 device->sysattr_values = hashmap_free(device->sysattr_values);
2282 }
2283
2284 int device_cache_sysattr_value(sd_device *device, const char *key, char *value) {
2285 _unused_ _cleanup_free_ char *old_value = NULL;
2286 _cleanup_free_ char *new_key = NULL;
2287 int r;
2288
2289 assert(device);
2290 assert(key);
2291
2292 /* This takes the reference of the input value. The input value may be NULL.
2293 * This replaces the value if it already exists. */
2294
2295 /* First, remove the old cache entry. So, we do not need to clear cache on error. */
2296 old_value = hashmap_remove2(device->sysattr_values, key, (void **) &new_key);
2297 if (!new_key) {
2298 new_key = strdup(key);
2299 if (!new_key)
2300 return -ENOMEM;
2301 }
2302
2303 r = hashmap_ensure_put(&device->sysattr_values, &path_hash_ops_free_free, new_key, value);
2304 if (r < 0)
2305 return r;
2306
2307 TAKE_PTR(new_key);
2308
2309 return 0;
2310 }
2311
2312 int device_get_cached_sysattr_value(sd_device *device, const char *key, const char **ret_value) {
2313 const char *k = NULL, *value;
2314
2315 assert(device);
2316 assert(key);
2317
2318 value = hashmap_get2(device->sysattr_values, key, (void **) &k);
2319 if (!k)
2320 return -ESTALE; /* We have not read the attribute. */
2321 if (!value)
2322 return -ENOENT; /* We have looked up the attribute before and it did not exist. */
2323 if (ret_value)
2324 *ret_value = value;
2325 return 0;
2326 }
2327
2328 /* We cache all sysattr lookups. If an attribute does not exist, it is stored
2329 * with a NULL value in the cache, otherwise the returned string is stored */
2330 _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value) {
2331 _cleanup_free_ char *value = NULL, *path = NULL;
2332 const char *syspath;
2333 struct stat statbuf;
2334 int r;
2335
2336 assert_return(device, -EINVAL);
2337 assert_return(sysattr, -EINVAL);
2338
2339 /* look for possibly already cached result */
2340 r = device_get_cached_sysattr_value(device, sysattr, ret_value);
2341 if (r != -ESTALE)
2342 return r;
2343
2344 r = sd_device_get_syspath(device, &syspath);
2345 if (r < 0)
2346 return r;
2347
2348 path = path_join(syspath, sysattr);
2349 if (!path)
2350 return -ENOMEM;
2351
2352 if (lstat(path, &statbuf) < 0) {
2353 int k;
2354
2355 r = -errno;
2356
2357 /* remember that we could not access the sysattr */
2358 k = device_cache_sysattr_value(device, sysattr, NULL);
2359 if (k < 0)
2360 log_device_debug_errno(device, k,
2361 "sd-device: failed to cache attribute '%s' with NULL, ignoring: %m",
2362 sysattr);
2363
2364 return r;
2365 } else if (S_ISLNK(statbuf.st_mode)) {
2366 /* Some core links return only the last element of the target path,
2367 * these are just values, the paths should not be exposed. */
2368 if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) {
2369 r = readlink_value(path, &value);
2370 if (r < 0)
2371 return r;
2372 } else
2373 return -EINVAL;
2374 } else if (S_ISDIR(statbuf.st_mode))
2375 /* skip directories */
2376 return -EISDIR;
2377 else if (!(statbuf.st_mode & S_IRUSR))
2378 /* skip non-readable files */
2379 return -EPERM;
2380 else {
2381 size_t size;
2382
2383 /* Read attribute value, Some attributes contain embedded '\0'. So, it is necessary to
2384 * also get the size of the result. See issue #20025. */
2385 r = read_full_virtual_file(path, &value, &size);
2386 if (r < 0)
2387 return r;
2388
2389 /* drop trailing newlines */
2390 while (size > 0 && strchr(NEWLINE, value[--size]))
2391 value[size] = '\0';
2392 }
2393
2394 /* Unfortunately, we need to return 'const char*' instead of 'char*'. Hence, failure in caching
2395 * sysattr value is critical unlike the other places. */
2396 r = device_cache_sysattr_value(device, sysattr, value);
2397 if (r < 0) {
2398 log_device_debug_errno(device, r,
2399 "sd-device: failed to cache attribute '%s' with '%s'%s: %m",
2400 sysattr, value, ret_value ? "" : ", ignoring");
2401 if (ret_value)
2402 return r;
2403
2404 return 0;
2405 }
2406
2407 if (ret_value)
2408 *ret_value = value;
2409
2410 TAKE_PTR(value);
2411 return 0;
2412 }
2413
2414 int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value) {
2415 const char *value;
2416 int r;
2417
2418 r = sd_device_get_sysattr_value(device, sysattr, &value);
2419 if (r < 0)
2420 return r;
2421
2422 int v;
2423 r = safe_atoi(value, &v);
2424 if (r < 0)
2425 return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
2426
2427 if (ret_value)
2428 *ret_value = v;
2429 /* We return "true" if the value is positive. */
2430 return v > 0;
2431 }
2432
2433 int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) {
2434 const char *value;
2435 int r;
2436
2437 r = sd_device_get_sysattr_value(device, sysattr, &value);
2438 if (r < 0)
2439 return r;
2440
2441 unsigned v;
2442 r = safe_atou(value, &v);
2443 if (r < 0)
2444 return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
2445
2446 if (ret_value)
2447 *ret_value = v;
2448 /* We return "true" if the value is positive. */
2449 return v > 0;
2450 }
2451
2452 int device_get_sysattr_bool(sd_device *device, const char *sysattr) {
2453 const char *value;
2454 int r;
2455
2456 assert(device);
2457 assert(sysattr);
2458
2459 r = sd_device_get_sysattr_value(device, sysattr, &value);
2460 if (r < 0)
2461 return r;
2462
2463 return parse_boolean(value);
2464 }
2465
2466 static void device_remove_cached_sysattr_value(sd_device *device, const char *_key) {
2467 _cleanup_free_ char *key = NULL;
2468
2469 assert(device);
2470 assert(_key);
2471
2472 free(hashmap_remove2(device->sysattr_values, _key, (void **) &key));
2473 }
2474
2475 _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *_value) {
2476 _cleanup_free_ char *value = NULL, *path = NULL;
2477 const char *syspath;
2478 size_t len;
2479 int r;
2480
2481 assert_return(device, -EINVAL);
2482 assert_return(sysattr, -EINVAL);
2483
2484 /* Set the attribute and save it in the cache. */
2485
2486 if (!_value) {
2487 /* If input value is NULL, then clear cache and not write anything. */
2488 device_remove_cached_sysattr_value(device, sysattr);
2489 return 0;
2490 }
2491
2492 r = sd_device_get_syspath(device, &syspath);
2493 if (r < 0)
2494 return r;
2495
2496 path = path_join(syspath, sysattr);
2497 if (!path)
2498 return -ENOMEM;
2499
2500 len = strlen(_value);
2501
2502 /* drop trailing newlines */
2503 while (len > 0 && strchr(NEWLINE, _value[len - 1]))
2504 len --;
2505
2506 /* value length is limited to 4k */
2507 if (len > 4096)
2508 return -EINVAL;
2509
2510 value = strndup(_value, len);
2511 if (!value)
2512 return -ENOMEM;
2513
2514 r = write_string_file(path, value, WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_NOFOLLOW);
2515 if (r < 0) {
2516 /* On failure, clear cache entry, as we do not know how it fails. */
2517 device_remove_cached_sysattr_value(device, sysattr);
2518 return r;
2519 }
2520
2521 /* Do not cache action string written into uevent file. */
2522 if (streq(sysattr, "uevent"))
2523 return 0;
2524
2525 r = device_cache_sysattr_value(device, sysattr, value);
2526 if (r < 0)
2527 log_device_debug_errno(device, r,
2528 "sd-device: failed to cache attribute '%s' with '%s', ignoring: %m",
2529 sysattr, value);
2530 else
2531 TAKE_PTR(value);
2532
2533 return 0;
2534 }
2535
2536 _public_ int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) {
2537 _cleanup_free_ char *value = NULL;
2538 va_list ap;
2539 int r;
2540
2541 assert_return(device, -EINVAL);
2542 assert_return(sysattr, -EINVAL);
2543
2544 if (!format) {
2545 device_remove_cached_sysattr_value(device, sysattr);
2546 return 0;
2547 }
2548
2549 va_start(ap, format);
2550 r = vasprintf(&value, format, ap);
2551 va_end(ap);
2552
2553 if (r < 0)
2554 return -ENOMEM;
2555
2556 return sd_device_set_sysattr_value(device, sysattr, value);
2557 }
2558
2559 _public_ int sd_device_trigger(sd_device *device, sd_device_action_t action) {
2560 const char *s;
2561
2562 assert_return(device, -EINVAL);
2563
2564 s = device_action_to_string(action);
2565 if (!s)
2566 return -EINVAL;
2567
2568 /* This uses the simple no-UUID interface of kernel < 4.13 */
2569 return sd_device_set_sysattr_value(device, "uevent", s);
2570 }
2571
2572 _public_ int sd_device_trigger_with_uuid(
2573 sd_device *device,
2574 sd_device_action_t action,
2575 sd_id128_t *ret_uuid) {
2576
2577 const char *s, *j;
2578 sd_id128_t u;
2579 int r;
2580
2581 assert_return(device, -EINVAL);
2582
2583 /* If no one wants to know the UUID, use the simple interface from pre-4.13 times */
2584 if (!ret_uuid)
2585 return sd_device_trigger(device, action);
2586
2587 s = device_action_to_string(action);
2588 if (!s)
2589 return -EINVAL;
2590
2591 r = sd_id128_randomize(&u);
2592 if (r < 0)
2593 return r;
2594
2595 j = strjoina(s, " ", SD_ID128_TO_UUID_STRING(u));
2596
2597 r = sd_device_set_sysattr_value(device, "uevent", j);
2598 if (r < 0)
2599 return r;
2600
2601 *ret_uuid = u;
2602 return 0;
2603 }
2604
2605 _public_ int sd_device_open(sd_device *device, int flags) {
2606 _cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
2607 const char *devname, *subsystem = NULL;
2608 uint64_t q, diskseq = 0;
2609 struct stat st;
2610 dev_t devnum;
2611 int r;
2612
2613 assert_return(device, -EINVAL);
2614 assert_return(FLAGS_SET(flags, O_PATH) || !FLAGS_SET(flags, O_NOFOLLOW), -EINVAL);
2615
2616 r = sd_device_get_devname(device, &devname);
2617 if (r == -ENOENT)
2618 return -ENOEXEC;
2619 if (r < 0)
2620 return r;
2621
2622 r = sd_device_get_devnum(device, &devnum);
2623 if (r == -ENOENT)
2624 return -ENOEXEC;
2625 if (r < 0)
2626 return r;
2627
2628 r = sd_device_get_subsystem(device, &subsystem);
2629 if (r < 0 && r != -ENOENT)
2630 return r;
2631
2632 fd = open(devname, FLAGS_SET(flags, O_PATH) ? flags : O_CLOEXEC|O_NOFOLLOW|O_PATH);
2633 if (fd < 0)
2634 return -errno;
2635
2636 if (fstat(fd, &st) < 0)
2637 return -errno;
2638
2639 if (st.st_rdev != devnum)
2640 return -ENXIO;
2641
2642 if (streq_ptr(subsystem, "block") ? !S_ISBLK(st.st_mode) : !S_ISCHR(st.st_mode))
2643 return -ENXIO;
2644
2645 /* If flags has O_PATH, then we cannot check diskseq. Let's return earlier. */
2646 if (FLAGS_SET(flags, O_PATH))
2647 return TAKE_FD(fd);
2648
2649 /* If the device is not initialized, then we cannot determine if we should check diskseq through
2650 * ID_IGNORE_DISKSEQ property. Let's skip to check diskseq in that case. */
2651 r = sd_device_get_is_initialized(device);
2652 if (r < 0)
2653 return r;
2654 if (r > 0) {
2655 r = device_get_property_bool(device, "ID_IGNORE_DISKSEQ");
2656 if (r < 0 && r != -ENOENT)
2657 return r;
2658 if (r <= 0) {
2659 r = sd_device_get_diskseq(device, &diskseq);
2660 if (r < 0 && r != -ENOENT)
2661 return r;
2662 }
2663 }
2664
2665 fd2 = fd_reopen(fd, flags);
2666 if (fd2 < 0)
2667 return fd2;
2668
2669 if (diskseq == 0)
2670 return TAKE_FD(fd2);
2671
2672 r = fd_get_diskseq(fd2, &q);
2673 if (r < 0)
2674 return r;
2675
2676 if (q != diskseq)
2677 return -ENXIO;
2678
2679 return TAKE_FD(fd2);
2680 }
2681
2682 int device_opendir(sd_device *device, const char *subdir, DIR **ret) {
2683 _cleanup_closedir_ DIR *d = NULL;
2684 _cleanup_free_ char *path = NULL;
2685 const char *syspath;
2686 int r;
2687
2688 assert(device);
2689 assert(ret);
2690
2691 r = sd_device_get_syspath(device, &syspath);
2692 if (r < 0)
2693 return r;
2694
2695 if (subdir) {
2696 if (!path_is_safe(subdir))
2697 return -EINVAL;
2698
2699 path = path_join(syspath, subdir);
2700 if (!path)
2701 return -ENOMEM;
2702 }
2703
2704 d = opendir(path ?: syspath);
2705 if (!d)
2706 return -errno;
2707
2708 *ret = TAKE_PTR(d);
2709 return 0;
2710 }