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