1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "device-internal.h"
9 #include "device-private.h"
10 #include "device-util.h"
11 #include "errno-util.h"
16 #include "mount-util.h"
17 #include "mountpoint-util.h"
18 #include "nulstr-util.h"
19 #include "path-util.h"
20 #include "process-util.h"
23 #include "stat-util.h"
24 #include "string-util.h"
26 #include "tmpfile-util.h"
27 #include "udev-util.h"
32 /* For issue #37711 */
35 return (void) log_tests_skipped("not running as root");
37 ASSERT_OK(r
= safe_fork("(mdio_bus)", FORK_CLOSE_ALL_FDS
|FORK_DEATHSIG_SIGTERM
|FORK_REOPEN_LOG
|FORK_LOG
|FORK_WAIT
|FORK_NEW_MOUNTNS
|FORK_MOUNTNS_SLAVE
, NULL
));
39 const char *syspath
= "/sys/bus/mdio_bus/drivers/Qualcomm Atheros AR8031!AR8033";
40 const char *id
= "+drivers:mdio_bus:Qualcomm Atheros AR8031!AR8033";
43 int (*getter
)(sd_device
*, const char**);
46 { sd_device_get_syspath
, syspath
},
47 { sd_device_get_device_id
, id
},
48 { sd_device_get_subsystem
, "drivers" },
49 { sd_device_get_driver_subsystem
, "mdio_bus" },
50 { sd_device_get_sysname
, "Qualcomm Atheros AR8031/AR8033" },
53 ASSERT_OK_ERRNO(setenv("SYSTEMD_DEVICE_VERIFY_SYSFS", "0", /* overwrite = */ false));
54 ASSERT_OK(mount_nofollow_verbose(LOG_ERR
, "tmpfs", "/sys/bus/", "tmpfs", 0, NULL
));
55 r
= mkdir_p(syspath
, 0755);
56 if (ERRNO_IS_NEG_PRIVILEGE(r
)) {
57 log_tests_skipped("Lacking privileges to create %s", syspath
);
62 _cleanup_free_
char *uevent
= path_join(syspath
, "uevent");
63 ASSERT_NOT_NULL(uevent
);
64 ASSERT_OK(touch(uevent
));
66 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
67 ASSERT_OK(sd_device_new_from_syspath(&dev
, syspath
));
69 FOREACH_ELEMENT(t
, table
) {
72 ASSERT_OK(t
->getter(dev
, &v
));
73 ASSERT_STREQ(v
, t
->val
);
76 dev
= sd_device_unref(dev
);
77 ASSERT_OK(sd_device_new_from_device_id(&dev
, id
));
79 FOREACH_ELEMENT(t
, table
) {
82 ASSERT_OK(t
->getter(dev
, &v
));
83 ASSERT_STREQ(v
, t
->val
);
90 static void test_sd_device_one(sd_device
*d
) {
91 _cleanup_(sd_device_unrefp
) sd_device
*dev
= NULL
;
92 const char *syspath
, *sysname
, *subsystem
= NULL
, *devname
, *val
;
93 bool is_block
= false;
98 ASSERT_OK(sd_device_get_syspath(d
, &syspath
));
99 ASSERT_NOT_NULL(path_startswith(syspath
, "/sys"));
100 ASSERT_OK(sd_device_get_sysname(d
, &sysname
));
102 log_info("%s(%s)", __func__
, syspath
);
104 ASSERT_OK(sd_device_new_from_syspath(&dev
, syspath
));
105 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
106 ASSERT_STREQ(syspath
, val
);
107 ASSERT_NULL(dev
= sd_device_unref(dev
));
109 ASSERT_OK(sd_device_new_from_path(&dev
, syspath
));
110 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
111 ASSERT_STREQ(syspath
, val
);
112 ASSERT_NULL(dev
= sd_device_unref(dev
));
114 r
= sd_device_get_ifindex(d
, &ifindex
);
116 ASSERT_ERROR(r
, ENOENT
);
118 ASSERT_GT(ifindex
, 0);
121 ASSERT_OK(device_get_ifname(d
, &ifname
));
122 ASSERT_NOT_NULL(endswith(syspath
, ifname
));
123 if (strchr(sysname
, '/'))
124 ASSERT_FALSE(streq(ifname
, sysname
));
126 ASSERT_STREQ(ifname
, sysname
);
128 r
= sd_device_new_from_ifindex(&dev
, ifindex
);
130 ASSERT_ERROR(r
, ENODEV
);
131 log_device_warning_errno(d
, r
,
132 "Failed to create sd-device object from ifindex %i. "
133 "Maybe running on a non-host network namespace.", ifindex
);
135 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
136 ASSERT_STREQ(syspath
, val
);
137 ASSERT_NULL(dev
= sd_device_unref(dev
));
140 /* This does not require the interface really exists on the network namespace.
141 * Hence, this should always succeed. */
142 ASSERT_OK(sd_device_new_from_ifname(&dev
, sysname
));
143 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
144 ASSERT_STREQ(syspath
, val
);
145 ASSERT_NULL(dev
= sd_device_unref(dev
));
148 r
= sd_device_get_subsystem(d
, &subsystem
);
150 ASSERT_ERROR(r
, ENOENT
);
152 const char *name
, *id
;
154 if (streq(subsystem
, "drivers")) {
155 const char *driver_subsystem
;
156 ASSERT_OK(sd_device_get_driver_subsystem(d
, &driver_subsystem
));
157 name
= strjoina(driver_subsystem
, ":", sysname
);
161 r
= sd_device_new_from_subsystem_sysname(&dev
, subsystem
, name
);
163 ASSERT_ERROR(r
, ETOOMANYREFS
);
165 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
166 ASSERT_STREQ(syspath
, val
);
167 ASSERT_NULL(dev
= sd_device_unref(dev
));
170 /* The device ID depends on subsystem. */
171 ASSERT_OK(sd_device_get_device_id(d
, &id
));
172 r
= sd_device_new_from_device_id(&dev
, id
);
174 if (r
== -ENODEV
&& ifindex
> 0)
175 log_device_warning_errno(d
, r
,
176 "Failed to create sd-device object from device ID \"%s\". "
177 "Maybe running on a non-host network namespace.", id
);
179 ASSERT_ERROR(r
, ETOOMANYREFS
);
181 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
182 ASSERT_STREQ(syspath
, val
);
183 ASSERT_NULL(dev
= sd_device_unref(dev
));
186 /* These require udev database, and reading database requires device ID. */
187 ASSERT_OK(r
= sd_device_get_is_initialized(d
));
189 r
= sd_device_get_usec_since_initialized(d
, &usec
);
191 ASSERT_ERROR(r
, ENODATA
);
196 r
= sd_device_get_property_value(d
, "ID_NET_DRIVER", &val
);
198 ASSERT_ERROR(r
, ENOENT
);
201 if (streq(subsystem
, "drm")) {
202 const char *edid_content
;
203 size_t edid_size
= 0;
205 r
= sd_device_get_sysattr_value_with_size(d
, "edid", &edid_content
, &edid_size
);
207 ASSERT_ERROR(r
, ENOENT
);
209 /* at least 128 if monitor is connected, otherwise 0 */
210 ASSERT_TRUE(edid_size
== 0 || edid_size
>= 128);
213 is_block
= streq_ptr(subsystem
, "block");
215 r
= sd_device_get_devname(d
, &devname
);
217 ASSERT_ERROR(r
, ENOENT
);
219 r
= sd_device_new_from_devname(&dev
, devname
);
221 ASSERT_TRUE(r
== -ENODEV
|| ERRNO_IS_NEG_PRIVILEGE(r
));
223 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
224 ASSERT_STREQ(syspath
, val
);
225 ASSERT_NULL(dev
= sd_device_unref(dev
));
228 r
= sd_device_new_from_path(&dev
, devname
);
230 ASSERT_TRUE(r
== -ENODEV
|| ERRNO_IS_NEG_PRIVILEGE(r
));
232 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
233 ASSERT_STREQ(syspath
, val
);
234 ASSERT_NULL(dev
= sd_device_unref(dev
));
236 _cleanup_close_
int fd
= -EBADF
;
237 fd
= sd_device_open(d
, O_CLOEXEC
| O_NONBLOCK
| (is_block
? O_RDONLY
: O_NOCTTY
| O_PATH
));
238 ASSERT_TRUE(fd
>= 0 || ERRNO_IS_NEG_PRIVILEGE(fd
));
242 r
= sd_device_get_devnum(d
, &devnum
);
244 ASSERT_ERROR(r
, ENOENT
);
246 _cleanup_free_
char *p
= NULL
;
248 ASSERT_GT(major(devnum
), 0U);
250 ASSERT_OK(sd_device_new_from_devnum(&dev
, is_block
? 'b' : 'c', devnum
));
251 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
252 ASSERT_STREQ(syspath
, val
);
253 ASSERT_NULL(dev
= sd_device_unref(dev
));
255 ASSERT_OK(asprintf(&p
, "/dev/%s/%u:%u", is_block
? "block" : "char", major(devnum
), minor(devnum
)));
256 ASSERT_OK(sd_device_new_from_devname(&dev
, p
));
257 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
258 ASSERT_STREQ(syspath
, val
);
259 ASSERT_NULL(dev
= sd_device_unref(dev
));
261 ASSERT_OK(sd_device_new_from_path(&dev
, p
));
262 ASSERT_OK(sd_device_get_syspath(dev
, &val
));
263 ASSERT_STREQ(syspath
, val
);
264 ASSERT_NULL(dev
= sd_device_unref(dev
));
267 ASSERT_OK(sd_device_get_devpath(d
, &val
));
269 r
= sd_device_get_devtype(d
, NULL
);
271 ASSERT_ERROR(r
, ENOENT
);
273 r
= sd_device_get_driver(d
, NULL
);
275 ASSERT_ERROR(r
, ENOENT
);
277 r
= sd_device_get_sysnum(d
, &val
);
279 ASSERT_ERROR(r
, ENOENT
);
281 ASSERT_TRUE(val
> sysname
);
282 ASSERT_TRUE(val
< sysname
+ strlen(sysname
));
283 ASSERT_TRUE(in_charset(val
, DIGITS
));
284 ASSERT_FALSE(ascii_isdigit(val
[-1]));
286 r
= device_get_sysnum_unsigned(d
, NULL
);
288 ASSERT_ERROR(r
, ERANGE
); /* sysnum may be too large. */
291 r
= sd_device_get_sysattr_value(d
, "nsid", NULL
);
293 ASSERT_TRUE(ERRNO_IS_NEG_PRIVILEGE(r
) || IN_SET(r
, -ENOENT
, -EINVAL
));
296 ASSERT_OK(r
= device_get_sysattr_unsigned(d
, "nsid", &x
));
297 ASSERT_EQ(x
> 0, r
> 0);
301 static void exclude_problematic_devices(sd_device_enumerator
*e
) {
302 /* On some CI environments, it seems some loop block devices and corresponding bdi devices sometimes
303 * disappear during running this test. Let's exclude them here for stability. */
304 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "bdi", false));
305 ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e
, "loop*"));
306 /* On CentOS CI, systemd-networkd-tests.py may be running when this test is invoked. The networkd
307 * test creates and removes many network interfaces, and may interfere with this test. */
308 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "net", false));
311 TEST(sd_device_enumerator_devices
) {
312 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
314 ASSERT_OK(sd_device_enumerator_new(&e
));
315 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
316 exclude_problematic_devices(e
);
319 test_sd_device_one(d
);
322 TEST(sd_device_enumerator_subsystems
) {
323 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
325 ASSERT_OK(sd_device_enumerator_new(&e
));
326 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
327 FOREACH_SUBSYSTEM(e
, d
)
328 test_sd_device_one(d
);
331 static void test_sd_device_enumerator_filter_subsystem_one(
332 const char *subsystem
,
334 unsigned *ret_n_new_dev
,
335 unsigned *ret_n_removed_dev
) {
337 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
338 unsigned n_new_dev
= 0, n_removed_dev
= 0;
341 ASSERT_OK(sd_device_enumerator_new(&e
));
342 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, subsystem
, true));
343 ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e
, "loop*"));
345 FOREACH_DEVICE(e
, d
) {
349 ASSERT_OK(sd_device_get_syspath(d
, &syspath
));
350 t
= hashmap_remove(h
, syspath
);
353 log_warning("New device found: subsystem:%s syspath:%s", subsystem
, syspath
);
357 ASSERT_NULL(sd_device_unref(t
));
360 HASHMAP_FOREACH(dev
, h
) {
363 ASSERT_OK(sd_device_get_syspath(dev
, &syspath
));
364 log_warning("Device removed: subsystem:%s syspath:%s", subsystem
, syspath
);
367 ASSERT_NULL(sd_device_unref(dev
));
372 *ret_n_new_dev
= n_new_dev
;
373 *ret_n_removed_dev
= n_removed_dev
;
376 static bool test_sd_device_enumerator_filter_subsystem_trial(void) {
377 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
378 _cleanup_hashmap_free_ Hashmap
*subsystems
= NULL
;
379 unsigned n_new_dev
= 0, n_removed_dev
= 0;
383 ASSERT_NOT_NULL((subsystems
= hashmap_new(&string_hash_ops
)));
384 ASSERT_OK(sd_device_enumerator_new(&e
));
385 exclude_problematic_devices(e
);
387 FOREACH_DEVICE(e
, d
) {
388 const char *syspath
, *subsystem
;
391 ASSERT_OK(sd_device_get_syspath(d
, &syspath
));
393 r
= sd_device_get_subsystem(d
, &subsystem
);
395 ASSERT_ERROR(r
, ENOENT
);
399 h
= hashmap_get(subsystems
, subsystem
);
402 ASSERT_NOT_NULL((str
= strdup(subsystem
)));
403 ASSERT_NOT_NULL((h
= hashmap_new(&string_hash_ops
)));
404 ASSERT_OK(hashmap_put(subsystems
, str
, h
));
407 ASSERT_OK(hashmap_put(h
, syspath
, d
));
408 ASSERT_NOT_NULL(sd_device_ref(d
));
410 log_debug("Added subsystem:%s syspath:%s", subsystem
, syspath
);
413 while ((h
= hashmap_steal_first_key_and_value(subsystems
, (void**) &s
))) {
416 test_sd_device_enumerator_filter_subsystem_one(s
, TAKE_PTR(h
), &n
, &m
);
424 log_warning("%u new devices are found in re-scan", n_new_dev
);
425 if (n_removed_dev
> 0)
426 log_warning("%u devices removed in re-scan", n_removed_dev
);
428 return n_new_dev
+ n_removed_dev
== 0;
431 static bool test_sd_device_enumerator_filter_subsystem_trial_many(void) {
432 for (unsigned i
= 0; i
< 20; i
++) {
433 log_debug("%s(): trial %u", __func__
, i
);
434 if (test_sd_device_enumerator_filter_subsystem_trial())
441 static int on_inotify(sd_event_source
*s
, const struct inotify_event
*event
, void *userdata
) {
442 if (test_sd_device_enumerator_filter_subsystem_trial_many())
443 return sd_event_exit(sd_event_source_get_event(s
), 0);
445 return sd_event_exit(sd_event_source_get_event(s
), -EBUSY
);
448 TEST(sd_device_enumerator_filter_subsystem
) {
449 /* The test test_sd_device_enumerator_filter_subsystem_trial() is quite racy. Let's run the function
450 * several times after the udev queue becomes empty. */
452 if (!udev_available() || (access("/run/udev", F_OK
) < 0 && errno
== ENOENT
)) {
453 ASSERT_TRUE(test_sd_device_enumerator_filter_subsystem_trial_many());
457 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
458 ASSERT_OK(sd_event_default(&event
));
459 ASSERT_OK(sd_event_add_inotify(event
, NULL
, "/run/udev" , IN_DELETE
, on_inotify
, NULL
));
461 if (udev_queue_is_empty() == 0) {
462 log_debug("udev queue is not empty, waiting for all queued events to be processed.");
463 ASSERT_OK(sd_event_loop(event
));
465 ASSERT_TRUE(test_sd_device_enumerator_filter_subsystem_trial_many());
468 TEST(sd_device_enumerator_add_match_sysattr
) {
469 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
473 ASSERT_OK(sd_device_enumerator_new(&e
));
474 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
475 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "net", true));
476 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "1", true));
477 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "hoge", true));
478 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "foo", true));
479 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "bar", false));
480 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "baz", false));
482 ASSERT_NOT_NULL((dev
= sd_device_enumerator_get_device_first(e
)));
483 ASSERT_OK(sd_device_get_ifindex(dev
, &ifindex
));
484 ASSERT_EQ(ifindex
, 1);
486 ASSERT_NULL(sd_device_enumerator_get_device_next(e
));
489 TEST(sd_device_enumerator_add_match_property
) {
490 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
494 ASSERT_OK(sd_device_enumerator_new(&e
));
495 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
496 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "net", true));
497 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "1", true));
498 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "IFINDE*", "1*"));
499 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "IFINDE*", "hoge"));
500 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "IFINDE*", NULL
));
501 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "AAAAA", "BBBB"));
502 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "FOOOO", NULL
));
504 ASSERT_NOT_NULL((dev
= sd_device_enumerator_get_device_first(e
)));
505 ASSERT_OK(sd_device_get_ifindex(dev
, &ifindex
));
506 ASSERT_EQ(ifindex
, 1);
509 TEST(sd_device_enumerator_add_match_property_required
) {
510 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
514 ASSERT_OK(sd_device_enumerator_new(&e
));
515 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
516 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "net", true));
517 ASSERT_OK(sd_device_enumerator_add_match_sysattr(e
, "ifindex", "1", true));
518 ASSERT_OK(sd_device_enumerator_add_match_property_required(e
, "IFINDE*", "1*"));
520 /* Only one required match which should be satisfied. */
521 ASSERT_NOT_NULL((dev
= sd_device_enumerator_get_device_first(e
)));
522 ASSERT_OK(sd_device_get_ifindex(dev
, &ifindex
));
523 ASSERT_EQ(ifindex
, 1);
525 /* Now let's add a bunch of garbage properties which should not be satisfied. */
526 ASSERT_OK(sd_device_enumerator_add_match_property_required(e
, "IFINDE*", "hoge"));
527 ASSERT_OK(sd_device_enumerator_add_match_property_required(e
, "IFINDE*", NULL
));
528 ASSERT_OK(sd_device_enumerator_add_match_property_required(e
, "AAAAA", "BBBB"));
529 ASSERT_OK(sd_device_enumerator_add_match_property_required(e
, "FOOOO", NULL
));
531 ASSERT_NULL(sd_device_enumerator_get_device_first(e
));
534 static void check_parent_match(sd_device_enumerator
*e
, sd_device
*dev
) {
538 ASSERT_OK(sd_device_get_syspath(dev
, &syspath
));
540 FOREACH_DEVICE(e
, d
) {
543 ASSERT_OK(sd_device_get_syspath(d
, &s
));
544 if (streq(s
, syspath
)) {
551 log_device_debug(dev
, "not enumerated, already removed??");
552 /* If the original device not found, then the device should be already removed. */
553 ASSERT_FAIL(access(syspath
, F_OK
));
554 ASSERT_EQ(errno
, ENOENT
);
558 TEST(sd_device_enumerator_add_match_parent
) {
559 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
560 /* Some devices have thousands of children. Avoid spending too much time in the double loop below. */
561 unsigned iterations
= 200;
564 ASSERT_OK(sd_device_enumerator_new(&e
));
565 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
566 exclude_problematic_devices(e
);
568 if (!slow_tests_enabled())
569 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "block", true));
571 FOREACH_DEVICE(e
, dev
) {
572 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*p
= NULL
;
576 if (iterations
-- == 0)
579 ASSERT_OK(sd_device_get_syspath(dev
, &syspath
));
581 r
= sd_device_get_parent(dev
, &parent
);
583 ASSERT_TRUE(ERRNO_IS_NEG_DEVICE_ABSENT(r
));
587 log_debug("> %s", syspath
);
589 ASSERT_OK(sd_device_enumerator_new(&p
));
590 ASSERT_OK(sd_device_enumerator_allow_uninitialized(p
));
591 ASSERT_OK(sd_device_enumerator_add_match_parent(p
, parent
));
593 check_parent_match(p
, dev
);
595 /* If the device does not have subsystem, then it is not enumerated. */
596 r
= sd_device_get_subsystem(parent
, NULL
);
598 ASSERT_ERROR(r
, ENOENT
);
601 check_parent_match(p
, parent
);
605 TEST(sd_device_enumerator_add_all_parents
) {
606 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
609 /* STEP 1: enumerate all block devices without all_parents() */
610 ASSERT_OK(sd_device_enumerator_new(&e
));
611 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
613 /* filter in only a subsystem */
614 ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e
, "loop*"));
615 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "block", true));
616 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "DEVTYPE", "partition"));
618 unsigned devices_count_with_parents
= 0;
619 unsigned devices_count_without_parents
= 0;
620 FOREACH_DEVICE(e
, dev
) {
621 ASSERT_OK_POSITIVE(device_is_subsystem_devtype(dev
, "block", "partition"));
622 devices_count_without_parents
++;
625 log_debug("found %u devices", devices_count_without_parents
);
627 /* STEP 2: enumerate again with all_parents() */
628 ASSERT_OK(sd_device_enumerator_add_all_parents(e
));
630 unsigned not_filtered_parent_count
= 0;
631 FOREACH_DEVICE(e
, dev
) {
632 ASSERT_OK(r
= device_is_subsystem_devtype(dev
, "block", "partition"));
634 not_filtered_parent_count
++;
635 devices_count_with_parents
++;
637 log_debug("found %u devices out of %u that would have been excluded without all_parents()",
638 not_filtered_parent_count
,
639 devices_count_with_parents
);
640 ASSERT_EQ(devices_count_with_parents
, devices_count_without_parents
+ not_filtered_parent_count
);
643 TEST(sd_device_get_child
) {
644 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
645 /* Some devices have thousands of children. Avoid spending too much time in the double loop below. */
646 unsigned iterations
= 3000;
649 ASSERT_OK(sd_device_enumerator_new(&e
));
650 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
651 exclude_problematic_devices(e
);
653 if (!slow_tests_enabled())
654 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "block", true));
656 FOREACH_DEVICE(e
, dev
) {
657 const char *syspath
, *parent_syspath
, *expected_suffix
, *suffix
;
661 ASSERT_OK(sd_device_get_syspath(dev
, &syspath
));
663 r
= sd_device_get_parent(dev
, &parent
);
665 ASSERT_TRUE(ERRNO_IS_NEG_DEVICE_ABSENT(r
));
669 ASSERT_OK(sd_device_get_syspath(parent
, &parent_syspath
));
670 ASSERT_NOT_NULL((expected_suffix
= path_startswith(syspath
, parent_syspath
)));
672 log_debug("> %s", syspath
);
674 FOREACH_DEVICE_CHILD_WITH_SUFFIX(parent
, child
, suffix
) {
677 if (iterations
-- == 0)
680 ASSERT_NOT_NULL(child
);
681 ASSERT_NOT_NULL(suffix
);
683 if (!streq(suffix
, expected_suffix
))
686 ASSERT_OK(sd_device_get_syspath(child
, &s
));
687 ASSERT_STREQ(s
, syspath
);
695 TEST(sd_device_new_from_nulstr
) {
696 const char *devlinks
=
697 "/dev/disk/by-partuuid/1290d63a-42cc-4c71-b87c-xxxxxxxxxxxx\0"
698 "/dev/disk/by-path/pci-0000:00:0f.0-scsi-0:0:0:0-part3\0"
699 "/dev/disk/by-label/Arch\\x20Linux\0"
700 "/dev/disk/by-uuid/a07b87e5-4af5-4a59-bde9-yyyyyyyyyyyy\0"
701 "/dev/disk/by-partlabel/Arch\\x20Linux\0"
704 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
, *from_nulstr
= NULL
;
705 _cleanup_free_
char *nulstr_copy
= NULL
;
709 ASSERT_OK(sd_device_new_from_syspath(&device
, "/sys/class/net/lo"));
711 /* Yeah, of course, setting devlink to the loopback interface is nonsense. But this is just a
712 * test for generating and parsing nulstr. For issue #17772. */
713 NULSTR_FOREACH(devlink
, devlinks
) {
714 log_device_info(device
, "setting devlink: %s", devlink
);
715 ASSERT_OK(device_add_devlink(device
, devlink
));
716 ASSERT_TRUE(set_contains(device
->devlinks
, devlink
));
719 /* For issue #23799 */
720 ASSERT_OK(device_add_tag(device
, "tag1", false));
721 ASSERT_OK(device_add_tag(device
, "tag2", false));
722 ASSERT_OK(device_add_tag(device
, "current-tag1", true));
723 ASSERT_OK(device_add_tag(device
, "current-tag2", true));
725 /* These properties are necessary for device_new_from_nulstr(). See device_verify(). */
726 ASSERT_OK(device_add_property_internal(device
, "SEQNUM", "1"));
727 ASSERT_OK(device_add_property_internal(device
, "ACTION", "change"));
729 ASSERT_OK(device_get_properties_nulstr(device
, &nulstr
, &len
));
730 ASSERT_NOT_NULL((nulstr_copy
= newdup(char, nulstr
, len
)));
731 ASSERT_OK(device_new_from_nulstr(&from_nulstr
, nulstr_copy
, len
));
733 ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr
, "tag1"));
734 ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr
, "tag2"));
735 ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr
, "current-tag1"));
736 ASSERT_OK_POSITIVE(sd_device_has_tag(from_nulstr
, "current-tag2"));
737 ASSERT_OK_ZERO(sd_device_has_current_tag(from_nulstr
, "tag1"));
738 ASSERT_OK_ZERO(sd_device_has_current_tag(from_nulstr
, "tag2"));
739 ASSERT_OK_POSITIVE(sd_device_has_current_tag(from_nulstr
, "current-tag1"));
740 ASSERT_OK_POSITIVE(sd_device_has_current_tag(from_nulstr
, "current-tag2"));
742 NULSTR_FOREACH(devlink
, devlinks
) {
743 log_device_info(from_nulstr
, "checking devlink: %s", devlink
);
744 ASSERT_TRUE(set_contains(from_nulstr
->devlinks
, devlink
));
748 TEST(sd_device_new_from_path
) {
749 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*e
= NULL
;
750 _cleanup_(rm_rf_physical_and_freep
) char *tmpdir
= NULL
;
753 ASSERT_OK(mkdtemp_malloc("/tmp/test-sd-device.XXXXXXX", &tmpdir
));
755 ASSERT_OK(sd_device_enumerator_new(&e
));
756 ASSERT_OK(sd_device_enumerator_allow_uninitialized(e
));
757 ASSERT_OK(sd_device_enumerator_add_match_subsystem(e
, "block", true));
758 ASSERT_OK(sd_device_enumerator_add_nomatch_sysname(e
, "loop*"));
759 ASSERT_OK(sd_device_enumerator_add_match_property(e
, "DEVNAME", "*"));
761 FOREACH_DEVICE(e
, dev
) {
762 _cleanup_(sd_device_unrefp
) sd_device
*d
= NULL
;
763 const char *syspath
, *devpath
, *sysname
, *s
;
764 _cleanup_free_
char *path
= NULL
;
766 ASSERT_OK(sd_device_get_sysname(dev
, &sysname
));
768 log_debug("%s(%s)", __func__
, sysname
);
770 ASSERT_OK(sd_device_get_syspath(dev
, &syspath
));
771 ASSERT_OK(sd_device_new_from_path(&d
, syspath
));
772 ASSERT_OK(sd_device_get_syspath(d
, &s
));
773 ASSERT_STREQ(s
, syspath
);
774 ASSERT_NULL(d
= sd_device_unref(d
));
776 ASSERT_OK(sd_device_get_devname(dev
, &devpath
));
777 r
= sd_device_new_from_path(&d
, devpath
);
779 ASSERT_TRUE(r
== -ENODEV
|| ERRNO_IS_NEG_PRIVILEGE(r
));
781 ASSERT_OK(sd_device_get_syspath(d
, &s
));
782 ASSERT_STREQ(s
, syspath
);
783 ASSERT_NULL(d
= sd_device_unref(d
));
786 ASSERT_NOT_NULL((path
= path_join(tmpdir
, sysname
)));
787 ASSERT_OK_ERRNO(symlink(syspath
, path
));
788 ASSERT_OK(sd_device_new_from_path(&d
, path
));
789 ASSERT_OK(sd_device_get_syspath(d
, &s
));
790 ASSERT_STREQ(s
, syspath
);
794 static void test_devname_from_devnum_one(const char *path
) {
795 _cleanup_free_
char *resolved
= NULL
;
798 log_debug("> %s", path
);
800 if (stat(path
, &st
) < 0) {
801 log_notice("Path %s not found, skipping test", path
);
805 ASSERT_OK(devname_from_devnum(st
.st_mode
, st
.st_rdev
, &resolved
));
806 ASSERT_TRUE(path_equal(path
, resolved
));
807 ASSERT_NULL(resolved
= mfree(resolved
));
808 ASSERT_OK(devname_from_stat_rdev(&st
, &resolved
));
809 ASSERT_TRUE(path_equal(path
, resolved
));
812 TEST(devname_from_devnum
) {
813 test_devname_from_devnum_one("/dev/null");
814 test_devname_from_devnum_one("/dev/zero");
815 test_devname_from_devnum_one("/dev/full");
816 test_devname_from_devnum_one("/dev/random");
817 test_devname_from_devnum_one("/dev/urandom");
818 test_devname_from_devnum_one("/dev/tty");
820 if (is_device_node("/run/systemd/inaccessible/blk") > 0) {
821 test_devname_from_devnum_one("/run/systemd/inaccessible/chr");
822 test_devname_from_devnum_one("/run/systemd/inaccessible/blk");
826 static int intro(void) {
827 if (path_is_mount_point("/sys") <= 0)
828 return log_tests_skipped("/sys is not mounted");
833 DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO
, intro
);