1f0ac5e91SDag-Erling Smørgrav /*-
2f0ac5e91SDag-Erling Smørgrav * Copyright (c) 2025 Klara, Inc.
3f0ac5e91SDag-Erling Smørgrav *
4f0ac5e91SDag-Erling Smørgrav * SPDX-License-Identifier: BSD-2-Clause
5f0ac5e91SDag-Erling Smørgrav */
6f0ac5e91SDag-Erling Smørgrav
7f0ac5e91SDag-Erling Smørgrav #include <sys/stat.h>
8f0ac5e91SDag-Erling Smørgrav
9f0ac5e91SDag-Erling Smørgrav #include <fcntl.h>
10f0ac5e91SDag-Erling Smørgrav #include <fts.h>
11f0ac5e91SDag-Erling Smørgrav
12f0ac5e91SDag-Erling Smørgrav #include <atf-c.h>
13f0ac5e91SDag-Erling Smørgrav
14f0ac5e91SDag-Erling Smørgrav /*
15f0ac5e91SDag-Erling Smørgrav * Create two directories with three files each in lexicographical order,
16f0ac5e91SDag-Erling Smørgrav * then call FTS with a sort block that sorts in reverse lexicographical
17f0ac5e91SDag-Erling Smørgrav * order. This has the least chance of getting a false positive due to
18f0ac5e91SDag-Erling Smørgrav * differing file system semantics. UFS will return the files in the
19f0ac5e91SDag-Erling Smørgrav * order they were created while ZFS will sort them lexicographically; in
20f0ac5e91SDag-Erling Smørgrav * both cases, the order we expect is the reverse.
21f0ac5e91SDag-Erling Smørgrav */
22*782a611aSDag-Erling Smørgrav ATF_TC(fts_blocks_test);
ATF_TC_HEAD(fts_blocks_test,tc)23*782a611aSDag-Erling Smørgrav ATF_TC_HEAD(fts_blocks_test, tc)
24*782a611aSDag-Erling Smørgrav {
25*782a611aSDag-Erling Smørgrav atf_tc_set_md_var(tc, "descr",
26*782a611aSDag-Erling Smørgrav "Test FTS with a block in lieu of a comparison function");
27*782a611aSDag-Erling Smørgrav }
ATF_TC_BODY(fts_blocks_test,tc)28f0ac5e91SDag-Erling Smørgrav ATF_TC_BODY(fts_blocks_test, tc)
29f0ac5e91SDag-Erling Smørgrav {
30f0ac5e91SDag-Erling Smørgrav char *args[] = {
31f0ac5e91SDag-Erling Smørgrav "bar", "foo", NULL
32f0ac5e91SDag-Erling Smørgrav };
33f0ac5e91SDag-Erling Smørgrav char *paths[] = {
34f0ac5e91SDag-Erling Smørgrav "foo", "z", "y", "x", "foo",
35f0ac5e91SDag-Erling Smørgrav "bar", "c", "b", "a", "bar",
36f0ac5e91SDag-Erling Smørgrav NULL
37f0ac5e91SDag-Erling Smørgrav };
38f0ac5e91SDag-Erling Smørgrav char **expect = paths;
39f0ac5e91SDag-Erling Smørgrav FTS *fts;
40f0ac5e91SDag-Erling Smørgrav FTSENT *ftse;
41f0ac5e91SDag-Erling Smørgrav
42f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, mkdir("bar", 0755));
43f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, close(creat("bar/a", 0644)));
44f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, close(creat("bar/b", 0644)));
45f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, close(creat("bar/c", 0644)));
46f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, mkdir("foo", 0755));
47f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, close(creat("foo/x", 0644)));
48f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, close(creat("foo/y", 0644)));
49f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ(0, close(creat("foo/z", 0644)));
50f0ac5e91SDag-Erling Smørgrav fts = fts_open_b(args, 0,
51f0ac5e91SDag-Erling Smørgrav ^(const FTSENT * const *a, const FTSENT * const *b) {
52f0ac5e91SDag-Erling Smørgrav return (strcmp((*b)->fts_name, (*a)->fts_name));
53f0ac5e91SDag-Erling Smørgrav });
54f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_MSG(fts != NULL, "fts_open_b(): %m");
55f0ac5e91SDag-Erling Smørgrav while ((ftse = fts_read(fts)) != NULL && *expect != NULL) {
56f0ac5e91SDag-Erling Smørgrav ATF_CHECK_STREQ(*expect, ftse->fts_name);
57f0ac5e91SDag-Erling Smørgrav expect++;
58f0ac5e91SDag-Erling Smørgrav }
59f0ac5e91SDag-Erling Smørgrav ATF_CHECK_EQ(NULL, ftse);
60f0ac5e91SDag-Erling Smørgrav ATF_CHECK_EQ(NULL, *expect);
61f0ac5e91SDag-Erling Smørgrav ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m");
62f0ac5e91SDag-Erling Smørgrav }
63f0ac5e91SDag-Erling Smørgrav
ATF_TP_ADD_TCS(tp)64f0ac5e91SDag-Erling Smørgrav ATF_TP_ADD_TCS(tp)
65f0ac5e91SDag-Erling Smørgrav {
66f0ac5e91SDag-Erling Smørgrav ATF_TP_ADD_TC(tp, fts_blocks_test);
67f0ac5e91SDag-Erling Smørgrav return (atf_no_error());
68f0ac5e91SDag-Erling Smørgrav }
69