Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/gen/fts_options_test.c
39534 views
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
#include <stdbool.h>
12
#include <stdio.h>
13
#include <stdlib.h>
14
#include <unistd.h>
15
16
#include <atf-c.h>
17
18
#include "fts_test.h"
19
20
static char *all_paths[] = {
21
"dir",
22
"dirl",
23
"file",
24
"filel",
25
"dead",
26
"noent",
27
NULL
28
};
29
30
/*
31
* Prepare the files and directories we will be inspecting.
32
*/
33
static void
34
fts_options_prepare(const struct atf_tc *tc)
35
{
36
ATF_REQUIRE_EQ(0, mkdir("dir", 0755));
37
ATF_REQUIRE_EQ(0, close(creat("file", 0644)));
38
ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644)));
39
ATF_REQUIRE_EQ(0, symlink("..", "dir/up"));
40
ATF_REQUIRE_EQ(0, symlink("dir", "dirl"));
41
ATF_REQUIRE_EQ(0, symlink("file", "filel"));
42
ATF_REQUIRE_EQ(0, symlink("noent", "dead"));
43
}
44
45
ATF_TC(fts_options_logical);
46
ATF_TC_HEAD(fts_options_logical, tc)
47
{
48
atf_tc_set_md_var(tc, "descr", "FTS_LOGICAL");
49
}
50
ATF_TC_BODY(fts_options_logical, tc)
51
{
52
fts_options_prepare(tc);
53
fts_test(tc, &(struct fts_testcase){
54
all_paths,
55
FTS_LOGICAL,
56
(struct fts_expect[]){
57
{ FTS_DL, "dead", "dead" },
58
{ FTS_D, "dir", "dir" },
59
{ FTS_F, "file", "dir/file" },
60
{ FTS_D, "up", "dir/up" },
61
{ FTS_DL, "dead", "dir/up/dead" },
62
{ FTS_DC, "dir", "dir/up/dir" },
63
{ FTS_DC, "dirl", "dir/up/dirl" },
64
{ FTS_F, "file", "dir/up/file" },
65
{ FTS_F, "filel", "dir/up/filel" },
66
{ FTS_DP, "up", "dir/up" },
67
{ FTS_DP, "dir", "dir" },
68
{ FTS_D, "dirl", "dirl" },
69
{ FTS_F, "file", "dirl/file" },
70
{ FTS_D, "up", "dirl/up" },
71
{ FTS_DL, "dead", "dirl/up/dead" },
72
{ FTS_DC, "dir", "dirl/up/dir" },
73
{ FTS_DC, "dirl", "dirl/up/dirl" },
74
{ FTS_F, "file", "dirl/up/file" },
75
{ FTS_F, "filel", "dirl/up/filel" },
76
{ FTS_DP, "up", "dirl/up" },
77
{ FTS_DP, "dirl", "dirl" },
78
{ FTS_F, "file", "file" },
79
{ FTS_F, "filel", "filel" },
80
{ FTS_NS, "noent", "noent" },
81
{ 0 }
82
},
83
});
84
}
85
86
ATF_TC(fts_options_logical_nostat);
87
ATF_TC_HEAD(fts_options_logical_nostat, tc)
88
{
89
atf_tc_set_md_var(tc, "descr", "FTS_LOGICAL | FTS_NOSTAT");
90
}
91
ATF_TC_BODY(fts_options_logical_nostat, tc)
92
{
93
/*
94
* While FTS_LOGICAL is not documented as being incompatible with
95
* FTS_NOSTAT, and FTS does not clear FTS_NOSTAT if FTS_LOGICAL is
96
* set, FTS_LOGICAL effectively nullifies FTS_NOSTAT by overriding
97
* the follow check in fts_stat(). In theory, FTS could easily be
98
* changed to only stat links (to check what they point to) in the
99
* FTS_LOGICAL | FTS_NOSTAT case, which would produce a different
100
* result here, so keep the test around in case that ever happens.
101
*/
102
atf_tc_expect_fail("FTS_LOGICAL nullifies FTS_NOSTAT");
103
fts_options_prepare(tc);
104
fts_test(tc, &(struct fts_testcase){
105
all_paths,
106
FTS_LOGICAL | FTS_NOSTAT,
107
(struct fts_expect[]){
108
{ FTS_DL, "dead", "dead" },
109
{ FTS_D, "dir", "dir" },
110
{ FTS_NSOK, "file", "dir/file" },
111
{ FTS_D, "up", "dir/up" },
112
{ FTS_DL, "dead", "dir/up/dead" },
113
{ FTS_DC, "dir", "dir/up/dir" },
114
{ FTS_DC, "dirl", "dir/up/dirl" },
115
{ FTS_NSOK, "file", "dir/up/file" },
116
{ FTS_NSOK, "filel", "dir/up/filel" },
117
{ FTS_DP, "up", "dir/up" },
118
{ FTS_DP, "dir", "dir" },
119
{ FTS_D, "dirl", "dirl" },
120
{ FTS_NSOK, "file", "dirl/file" },
121
{ FTS_D, "up", "dirl/up" },
122
{ FTS_DL, "dead", "dirl/up/dead" },
123
{ FTS_DC, "dir", "dirl/up/dir" },
124
{ FTS_DC, "dirl", "dirl/up/dirl" },
125
{ FTS_NSOK, "file", "dirl/up/file" },
126
{ FTS_NSOK, "filel", "dirl/up/filel" },
127
{ FTS_DP, "up", "dirl/up" },
128
{ FTS_DP, "dirl", "dirl" },
129
{ FTS_F, "file", "file" },
130
{ FTS_F, "filel", "filel" },
131
{ FTS_NS, "noent", "noent" },
132
{ 0 }
133
},
134
});
135
}
136
137
ATF_TC(fts_options_logical_seedot);
138
ATF_TC_HEAD(fts_options_logical_seedot, tc)
139
{
140
atf_tc_set_md_var(tc, "descr", "FTS_LOGICAL | FTS_SEEDOT");
141
}
142
ATF_TC_BODY(fts_options_logical_seedot, tc)
143
{
144
fts_options_prepare(tc);
145
fts_test(tc, &(struct fts_testcase){
146
all_paths,
147
FTS_LOGICAL | FTS_SEEDOT,
148
(struct fts_expect[]){
149
{ FTS_DL, "dead", "dead" },
150
{ FTS_D, "dir", "dir" },
151
{ FTS_DOT, ".", "dir/." },
152
{ FTS_DOT, "..", "dir/.." },
153
{ FTS_F, "file", "dir/file" },
154
{ FTS_D, "up", "dir/up" },
155
{ FTS_DOT, ".", "dir/up/." },
156
{ FTS_DOT, "..", "dir/up/.." },
157
{ FTS_DL, "dead", "dir/up/dead" },
158
{ FTS_DC, "dir", "dir/up/dir" },
159
{ FTS_DC, "dirl", "dir/up/dirl" },
160
{ FTS_F, "file", "dir/up/file" },
161
{ FTS_F, "filel", "dir/up/filel" },
162
{ FTS_DP, "up", "dir/up" },
163
{ FTS_DP, "dir", "dir" },
164
{ FTS_D, "dirl", "dirl" },
165
{ FTS_DOT, ".", "dirl/." },
166
{ FTS_DOT, "..", "dirl/.." },
167
{ FTS_F, "file", "dirl/file" },
168
{ FTS_D, "up", "dirl/up" },
169
{ FTS_DOT, ".", "dirl/up/." },
170
{ FTS_DOT, "..", "dirl/up/.." },
171
{ FTS_DL, "dead", "dirl/up/dead" },
172
{ FTS_DC, "dir", "dirl/up/dir" },
173
{ FTS_DC, "dirl", "dirl/up/dirl" },
174
{ FTS_F, "file", "dirl/up/file" },
175
{ FTS_F, "filel", "dirl/up/filel" },
176
{ FTS_DP, "up", "dirl/up" },
177
{ FTS_DP, "dirl", "dirl" },
178
{ FTS_F, "file", "file" },
179
{ FTS_F, "filel", "filel" },
180
{ FTS_NS, "noent", "noent" },
181
{ 0 }
182
},
183
});
184
}
185
186
ATF_TC(fts_options_physical);
187
ATF_TC_HEAD(fts_options_physical, tc)
188
{
189
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL");
190
}
191
ATF_TC_BODY(fts_options_physical, tc)
192
{
193
fts_options_prepare(tc);
194
fts_test(tc, &(struct fts_testcase){
195
all_paths,
196
FTS_PHYSICAL,
197
(struct fts_expect[]){
198
{ FTS_SL, "dead", "dead" },
199
{ FTS_D, "dir", "dir" },
200
{ FTS_F, "file", "file" },
201
{ FTS_SL, "up", "up" },
202
{ FTS_DP, "dir", "dir" },
203
{ FTS_SL, "dirl", "dirl" },
204
{ FTS_F, "file", "file" },
205
{ FTS_SL, "filel", "filel" },
206
{ FTS_NS, "noent", "noent" },
207
{ 0 }
208
},
209
});
210
}
211
212
ATF_TC(fts_options_physical_nochdir);
213
ATF_TC_HEAD(fts_options_physical_nochdir, tc)
214
{
215
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_NOCHDIR");
216
}
217
ATF_TC_BODY(fts_options_physical_nochdir, tc)
218
{
219
fts_options_prepare(tc);
220
fts_test(tc, &(struct fts_testcase){
221
all_paths,
222
FTS_PHYSICAL | FTS_NOCHDIR,
223
(struct fts_expect[]){
224
{ FTS_SL, "dead", "dead" },
225
{ FTS_D, "dir", "dir" },
226
{ FTS_F, "file", "dir/file" },
227
{ FTS_SL, "up", "dir/up" },
228
{ FTS_DP, "dir", "dir" },
229
{ FTS_SL, "dirl", "dirl" },
230
{ FTS_F, "file", "file" },
231
{ FTS_SL, "filel", "filel" },
232
{ FTS_NS, "noent", "noent" },
233
{ 0 }
234
},
235
});
236
}
237
238
ATF_TC(fts_options_physical_comfollow);
239
ATF_TC_HEAD(fts_options_physical_comfollow, tc)
240
{
241
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_COMFOLLOW");
242
}
243
ATF_TC_BODY(fts_options_physical_comfollow, tc)
244
{
245
fts_options_prepare(tc);
246
fts_test(tc, &(struct fts_testcase){
247
all_paths,
248
FTS_PHYSICAL | FTS_COMFOLLOW,
249
(struct fts_expect[]){
250
{ FTS_DL, "dead", "dead" },
251
{ FTS_D, "dir", "dir" },
252
{ FTS_F, "file", "file" },
253
{ FTS_SL, "up", "up" },
254
{ FTS_DP, "dir", "dir" },
255
{ FTS_D, "dirl", "dirl" },
256
{ FTS_F, "file", "file" },
257
{ FTS_SL, "up", "up" },
258
{ FTS_DP, "dirl", "dirl" },
259
{ FTS_F, "file", "file" },
260
{ FTS_F, "filel", "filel" },
261
{ FTS_NS, "noent", "noent" },
262
{ 0 }
263
},
264
});
265
}
266
267
ATF_TC(fts_options_physical_comfollowdir);
268
ATF_TC_HEAD(fts_options_physical_comfollowdir, tc)
269
{
270
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_COMFOLLOWDIR");
271
}
272
ATF_TC_BODY(fts_options_physical_comfollowdir, tc)
273
{
274
fts_options_prepare(tc);
275
fts_test(tc, &(struct fts_testcase){
276
all_paths,
277
FTS_PHYSICAL | FTS_COMFOLLOWDIR,
278
(struct fts_expect[]){
279
{ FTS_DL, "dead", "dead" },
280
{ FTS_D, "dir", "dir" },
281
{ FTS_F, "file", "file" },
282
{ FTS_SL, "up", "up" },
283
{ FTS_DP, "dir", "dir" },
284
{ FTS_D, "dirl", "dirl" },
285
{ FTS_F, "file", "file" },
286
{ FTS_SL, "up", "up" },
287
{ FTS_DP, "dirl", "dirl" },
288
{ FTS_F, "file", "file" },
289
{ FTS_SL, "filel", "filel" },
290
{ FTS_NS, "noent", "noent" },
291
{ 0 }
292
},
293
});
294
}
295
296
ATF_TC(fts_options_physical_nostat);
297
ATF_TC_HEAD(fts_options_physical_nostat, tc)
298
{
299
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_NOSTAT");
300
}
301
ATF_TC_BODY(fts_options_physical_nostat, tc)
302
{
303
fts_options_prepare(tc);
304
fts_test(tc, &(struct fts_testcase){
305
all_paths,
306
FTS_PHYSICAL | FTS_NOSTAT,
307
(struct fts_expect[]){
308
{ FTS_SL, "dead", "dead" },
309
{ FTS_D, "dir", "dir" },
310
{ FTS_NSOK, "file", "file" },
311
{ FTS_NSOK, "up", "up" },
312
{ FTS_DP, "dir", "dir" },
313
{ FTS_SL, "dirl", "dirl" },
314
{ FTS_F, "file", "file" },
315
{ FTS_SL, "filel", "filel" },
316
{ FTS_NS, "noent", "noent" },
317
{ 0 }
318
},
319
});
320
}
321
322
ATF_TC(fts_options_physical_nostat_type);
323
ATF_TC_HEAD(fts_options_physical_nostat_type, tc)
324
{
325
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_NOSTAT_TYPE");
326
}
327
ATF_TC_BODY(fts_options_physical_nostat_type, tc)
328
{
329
fts_options_prepare(tc);
330
fts_test(tc, &(struct fts_testcase){
331
all_paths,
332
FTS_PHYSICAL | FTS_NOSTAT_TYPE,
333
(struct fts_expect[]){
334
{ FTS_SL, "dead", "dead" },
335
{ FTS_D, "dir", "dir" },
336
{ FTS_F, "file", "file" },
337
{ FTS_SL, "up", "up" },
338
{ FTS_DP, "dir", "dir" },
339
{ FTS_SL, "dirl", "dirl" },
340
{ FTS_F, "file", "file" },
341
{ FTS_SL, "filel", "filel" },
342
{ FTS_NS, "noent", "noent" },
343
{ 0 }
344
},
345
});
346
}
347
348
ATF_TC(fts_options_physical_seedot);
349
ATF_TC_HEAD(fts_options_physical_seedot, tc)
350
{
351
atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_SEEDOT");
352
}
353
ATF_TC_BODY(fts_options_physical_seedot, tc)
354
{
355
fts_options_prepare(tc);
356
fts_test(tc, &(struct fts_testcase){
357
all_paths,
358
FTS_PHYSICAL | FTS_SEEDOT,
359
(struct fts_expect[]){
360
{ FTS_SL, "dead", "dead" },
361
{ FTS_D, "dir", "dir" },
362
{ FTS_DOT, ".", "." },
363
{ FTS_DOT, "..", ".." },
364
{ FTS_F, "file", "file" },
365
{ FTS_SL, "up", "up" },
366
{ FTS_DP, "dir", "dir" },
367
{ FTS_SL, "dirl", "dirl" },
368
{ FTS_F, "file", "file" },
369
{ FTS_SL, "filel", "filel" },
370
{ FTS_NS, "noent", "noent" },
371
{ 0 }
372
},
373
});
374
}
375
376
/*
377
* TODO: Add tests for FTS_XDEV and FTS_WHITEOUT
378
*/
379
380
ATF_TP_ADD_TCS(tp)
381
{
382
fts_check_debug();
383
ATF_TP_ADD_TC(tp, fts_options_logical);
384
ATF_TP_ADD_TC(tp, fts_options_logical_nostat);
385
ATF_TP_ADD_TC(tp, fts_options_logical_seedot);
386
ATF_TP_ADD_TC(tp, fts_options_physical);
387
ATF_TP_ADD_TC(tp, fts_options_physical_nochdir);
388
ATF_TP_ADD_TC(tp, fts_options_physical_comfollow);
389
ATF_TP_ADD_TC(tp, fts_options_physical_comfollowdir);
390
ATF_TP_ADD_TC(tp, fts_options_physical_nostat);
391
ATF_TP_ADD_TC(tp, fts_options_physical_nostat_type);
392
ATF_TP_ADD_TC(tp, fts_options_physical_seedot);
393
return (atf_no_error());
394
}
395
396