Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/getdirentries_test.c
39483 views
1
/*-
2
* Copyright (c) 2025 Klara, Inc.
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*/
6
7
#include <sys/stat.h>
8
#include <sys/mount.h>
9
10
#include <dirent.h>
11
#include <fcntl.h>
12
#include <errno.h>
13
#include <stdint.h>
14
15
#include <atf-c.h>
16
17
ATF_TC(getdirentries_ok);
18
ATF_TC_HEAD(getdirentries_ok, tc)
19
{
20
atf_tc_set_md_var(tc, "descr", "Successfully read a directory.");
21
}
22
ATF_TC_BODY(getdirentries_ok, tc)
23
{
24
char dbuf[4096];
25
struct dirent *d;
26
off_t base;
27
ssize_t ret;
28
int dd, n;
29
30
ATF_REQUIRE_EQ(0, mkdir("dir", 0755));
31
ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);
32
ATF_REQUIRE((ret = getdirentries(dd, dbuf, sizeof(dbuf), &base)) > 0);
33
ATF_REQUIRE_EQ(0, getdirentries(dd, dbuf, sizeof(dbuf), &base));
34
ATF_REQUIRE_EQ(base, lseek(dd, 0, SEEK_CUR));
35
ATF_CHECK_EQ(0, close(dd));
36
for (n = 0, d = (struct dirent *)dbuf;
37
d < (struct dirent *)(dbuf + ret);
38
d = (struct dirent *)((char *)d + d->d_reclen), n++)
39
/* nothing */ ;
40
ATF_CHECK_EQ((struct dirent *)(dbuf + ret), d);
41
ATF_CHECK_EQ(2, n);
42
}
43
44
ATF_TC(getdirentries_ebadf);
45
ATF_TC_HEAD(getdirentries_ebadf, tc)
46
{
47
atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "
48
"from an invalid descriptor.");
49
}
50
ATF_TC_BODY(getdirentries_ebadf, tc)
51
{
52
char dbuf[4096];
53
off_t base;
54
int fd;
55
56
ATF_REQUIRE((fd = open("file", O_CREAT | O_WRONLY, 0644)) >= 0);
57
ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base));
58
ATF_CHECK_EQ(EBADF, errno);
59
ATF_REQUIRE_EQ(0, close(fd));
60
ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base));
61
ATF_CHECK_EQ(EBADF, errno);
62
}
63
64
ATF_TC(getdirentries_efault);
65
ATF_TC_HEAD(getdirentries_efault, tc)
66
{
67
atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "
68
"to an invalid buffer.");
69
}
70
ATF_TC_BODY(getdirentries_efault, tc)
71
{
72
char dbuf[4096];
73
off_t base, *basep;
74
int dd;
75
76
ATF_REQUIRE_EQ(0, mkdir("dir", 0755));
77
ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);
78
ATF_REQUIRE_EQ(-1, getdirentries(dd, NULL, sizeof(dbuf), &base));
79
ATF_CHECK_EQ(EFAULT, errno);
80
basep = NULL;
81
basep++;
82
ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), basep));
83
ATF_CHECK_EQ(EFAULT, errno);
84
ATF_CHECK_EQ(0, close(dd));
85
}
86
87
ATF_TC(getdirentries_einval);
88
ATF_TC_HEAD(getdirentries_einval, tc)
89
{
90
atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "
91
"with various invalid parameters.");
92
}
93
ATF_TC_BODY(getdirentries_einval, tc)
94
{
95
struct statfs fsb;
96
char dbuf[4096];
97
off_t base;
98
ssize_t ret;
99
int dd;
100
101
ATF_REQUIRE_EQ(0, mkdir("dir", 0755));
102
ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);
103
ATF_REQUIRE_EQ(0, fstatfs(dd, &fsb));
104
/* nbytes too small */
105
ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, 8, &base));
106
ATF_CHECK_EQ(EINVAL, errno);
107
/* nbytes too big */
108
ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, SIZE_MAX, &base));
109
ATF_CHECK_EQ(EINVAL, errno);
110
/* invalid position */
111
ATF_REQUIRE((ret = getdirentries(dd, dbuf, sizeof(dbuf), &base)) > 0);
112
ATF_REQUIRE_EQ(0, getdirentries(dd, dbuf, sizeof(dbuf), &base));
113
ATF_REQUIRE(base > 0);
114
ATF_REQUIRE_EQ(base + 3, lseek(dd, 3, SEEK_CUR));
115
/* known to fail on ufs (FFS2) and zfs, and work on tmpfs */
116
if (strcmp(fsb.f_fstypename, "ufs") == 0 ||
117
strcmp(fsb.f_fstypename, "zfs") == 0) {
118
atf_tc_expect_fail("incorrectly returns 0 instead of EINVAL "
119
"on %s", fsb.f_fstypename);
120
}
121
ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), &base));
122
ATF_CHECK_EQ(EINVAL, errno);
123
ATF_CHECK_EQ(0, close(dd));
124
}
125
126
ATF_TC(getdirentries_enoent);
127
ATF_TC_HEAD(getdirentries_enoent, tc)
128
{
129
atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "
130
"after it is deleted.");
131
}
132
ATF_TC_BODY(getdirentries_enoent, tc)
133
{
134
char dbuf[4096];
135
off_t base;
136
int dd;
137
138
ATF_REQUIRE_EQ(0, mkdir("dir", 0755));
139
ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);
140
ATF_REQUIRE_EQ(0, rmdir("dir"));
141
ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), &base));
142
ATF_CHECK_EQ(ENOENT, errno);
143
}
144
145
ATF_TC(getdirentries_enotdir);
146
ATF_TC_HEAD(getdirentries_enotdir, tc)
147
{
148
atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "
149
"from a descriptor not associated with a directory.");
150
}
151
ATF_TC_BODY(getdirentries_enotdir, tc)
152
{
153
char dbuf[4096];
154
off_t base;
155
int fd;
156
157
ATF_REQUIRE((fd = open("file", O_CREAT | O_RDWR, 0644)) >= 0);
158
ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base));
159
ATF_CHECK_EQ(ENOTDIR, errno);
160
ATF_CHECK_EQ(0, close(fd));
161
}
162
163
ATF_TP_ADD_TCS(tp)
164
{
165
ATF_TP_ADD_TC(tp, getdirentries_ok);
166
ATF_TP_ADD_TC(tp, getdirentries_ebadf);
167
ATF_TP_ADD_TC(tp, getdirentries_efault);
168
ATF_TP_ADD_TC(tp, getdirentries_einval);
169
ATF_TP_ADD_TC(tp, getdirentries_enoent);
170
ATF_TP_ADD_TC(tp, getdirentries_enotdir);
171
return (atf_no_error());
172
}
173
174