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 <dirent.h> 10 #include <fcntl.h> 11 #include <stdlib.h> 12 13 #include <atf-c.h> 14 15 static void 16 scandir_blocks_prepare(const struct atf_tc *tc) 17 { 18 ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); 19 ATF_REQUIRE_EQ(0, mkdir("dir/dir", 0755)); 20 ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644))); 21 ATF_REQUIRE_EQ(0, symlink("file", "dir/link")); 22 ATF_REQUIRE_EQ(0, mkdir("dir/skip", 0755)); 23 } 24 25 static void 26 scandir_blocks_verify(const struct atf_tc *tc, int n, struct dirent **namelist) 27 { 28 ATF_REQUIRE_EQ_MSG(5, n, "return value is %d", n); 29 ATF_CHECK_STREQ("link", namelist[0]->d_name); 30 ATF_CHECK_STREQ("file", namelist[1]->d_name); 31 ATF_CHECK_STREQ("dir", namelist[2]->d_name); 32 ATF_CHECK_STREQ("..", namelist[3]->d_name); 33 ATF_CHECK_STREQ(".", namelist[4]->d_name); 34 } 35 36 ATF_TC(scandir_b_test); 37 ATF_TC_HEAD(scandir_b_test, tc) 38 { 39 atf_tc_set_md_var(tc, "descr", "Test scandir_b()"); 40 } 41 ATF_TC_BODY(scandir_b_test, tc) 42 { 43 struct dirent **namelist = NULL; 44 int i, ret; 45 46 scandir_blocks_prepare(tc); 47 ret = scandir_b("dir", &namelist, 48 ^(const struct dirent *ent) { 49 return (strcmp(ent->d_name, "skip") != 0); 50 }, 51 ^(const struct dirent **a, const struct dirent **b) { 52 return (strcmp((*b)->d_name, (*a)->d_name)); 53 }); 54 scandir_blocks_verify(tc, ret, namelist); 55 for (i = 0; i < ret; i++) 56 free(namelist[i]); 57 free(namelist); 58 } 59 60 ATF_TC(fdscandir_b_test); 61 ATF_TC_HEAD(fdscandir_b_test, tc) 62 { 63 atf_tc_set_md_var(tc, "descr", "Test fdscandir_b()"); 64 } 65 ATF_TC_BODY(fdscandir_b_test, tc) 66 { 67 struct dirent **namelist = NULL; 68 int fd, i, ret; 69 70 scandir_blocks_prepare(tc); 71 ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); 72 ret = fdscandir_b(fd, &namelist, 73 ^(const struct dirent *ent) { 74 return (strcmp(ent->d_name, "skip") != 0); 75 }, 76 ^(const struct dirent **a, const struct dirent **b) { 77 return (strcmp((*b)->d_name, (*a)->d_name)); 78 }); 79 scandir_blocks_verify(tc, ret, namelist); 80 for (i = 0; i < ret; i++) 81 free(namelist[i]); 82 free(namelist); 83 ATF_REQUIRE_EQ(0, close(fd)); 84 } 85 86 ATF_TC(scandirat_b_test); 87 ATF_TC_HEAD(scandirat_b_test, tc) 88 { 89 atf_tc_set_md_var(tc, "descr", "Test scandirat_b()"); 90 } 91 ATF_TC_BODY(scandirat_b_test, tc) 92 { 93 struct dirent **namelist = NULL; 94 int fd, i, ret; 95 96 scandir_blocks_prepare(tc); 97 ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_SEARCH)) >= 0); 98 ret = scandirat_b(fd, ".", &namelist, 99 ^(const struct dirent *ent) { 100 return (strcmp(ent->d_name, "skip") != 0); 101 }, 102 ^(const struct dirent **a, const struct dirent **b) { 103 return (strcmp((*b)->d_name, (*a)->d_name)); 104 }); 105 scandir_blocks_verify(tc, ret, namelist); 106 for (i = 0; i < ret; i++) 107 free(namelist[i]); 108 free(namelist); 109 ATF_REQUIRE_EQ(0, close(fd)); 110 } 111 112 ATF_TP_ADD_TCS(tp) 113 { 114 ATF_TP_ADD_TC(tp, scandir_b_test); 115 ATF_TP_ADD_TC(tp, fdscandir_b_test); 116 ATF_TP_ADD_TC(tp, scandirat_b_test); 117 return (atf_no_error()); 118 } 119