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_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_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 static int 37 scandir_select(const struct dirent *ent) 38 { 39 return (strcmp(ent->d_name, "skip") != 0); 40 } 41 42 static int 43 scandir_compare(const struct dirent **a, const struct dirent **b) 44 { 45 return (strcmp((*b)->d_name, (*a)->d_name)); 46 } 47 48 ATF_TC(scandir_test); 49 ATF_TC_HEAD(scandir_test, tc) 50 { 51 atf_tc_set_md_var(tc, "descr", "Test scandir()"); 52 } 53 ATF_TC_BODY(scandir_test, tc) 54 { 55 struct dirent **namelist = NULL; 56 int i, ret; 57 58 scandir_prepare(tc); 59 ret = scandir("dir", &namelist, scandir_select, scandir_compare); 60 scandir_verify(tc, ret, namelist); 61 for (i = 0; i < ret; i++) 62 free(namelist[i]); 63 free(namelist); 64 } 65 66 ATF_TC(fscandir_test); 67 ATF_TC_HEAD(fscandir_test, tc) 68 { 69 atf_tc_set_md_var(tc, "descr", "Test fscandir()"); 70 } 71 ATF_TC_BODY(fscandir_test, tc) 72 { 73 struct dirent **namelist = NULL; 74 int fd, i, ret; 75 76 scandir_prepare(tc); 77 ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); 78 ret = fscandir(fd, &namelist, scandir_select, scandir_compare); 79 scandir_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_test); 87 ATF_TC_HEAD(scandirat_test, tc) 88 { 89 atf_tc_set_md_var(tc, "descr", "Test scandirat()"); 90 } 91 ATF_TC_BODY(scandirat_test, tc) 92 { 93 struct dirent **namelist = NULL; 94 int fd, i, ret; 95 96 scandir_prepare(tc); 97 ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_SEARCH)) >= 0); 98 ret = scandirat(fd, ".", &namelist, scandir_select, scandir_compare); 99 scandir_verify(tc, ret, namelist); 100 for (i = 0; i < ret; i++) 101 free(namelist[i]); 102 free(namelist); 103 ATF_REQUIRE_EQ(0, close(fd)); 104 } 105 106 static int 107 scandir_none(const struct dirent *ent __unused) 108 { 109 return (0); 110 } 111 112 ATF_TC(scandir_none); 113 ATF_TC_HEAD(scandir_none, tc) 114 { 115 atf_tc_set_md_var(tc, "descr", 116 "Test scandir() when no entries are selected"); 117 } 118 ATF_TC_BODY(scandir_none, tc) 119 { 120 struct dirent **namelist = NULL; 121 122 ATF_REQUIRE_EQ(0, scandir(".", &namelist, scandir_none, alphasort)); 123 ATF_REQUIRE(namelist); 124 free(namelist); 125 } 126 127 ATF_TP_ADD_TCS(tp) 128 { 129 ATF_TP_ADD_TC(tp, scandir_test); 130 ATF_TP_ADD_TC(tp, fscandir_test); 131 ATF_TP_ADD_TC(tp, scandirat_test); 132 ATF_TP_ADD_TC(tp, scandir_none); 133 return (atf_no_error()); 134 } 135