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