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