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 <errno.h>
10 #include <glob.h>
11 #include <stdbool.h>
12
13 #include <atf-c.h>
14
15 ATF_TC(glob_b_callback);
ATF_TC_HEAD(glob_b_callback,tc)16 ATF_TC_HEAD(glob_b_callback, tc)
17 {
18 atf_tc_set_md_var(tc, "descr",
19 "Test ability of callback block to suppress errors");
20 atf_tc_set_md_var(tc, "require.user", "unprivileged");
21 }
ATF_TC_BODY(glob_b_callback,tc)22 ATF_TC_BODY(glob_b_callback, tc)
23 {
24 static bool glob_callback_invoked;
25 static int (^errblk)(const char *, int) =
26 ^(const char *path, int err) {
27 ATF_CHECK_STREQ(path, "test/");
28 ATF_CHECK(err == EACCES);
29 glob_callback_invoked = true;
30 /* Suppress EACCES errors. */
31 return (0);
32 };
33 glob_t g;
34 int rv;
35
36 ATF_REQUIRE_EQ(0, mkdir("test", 0755));
37 ATF_REQUIRE_EQ(0, symlink("foo", "test/foo"));
38 ATF_REQUIRE_EQ(0, chmod("test", 0));
39
40 glob_callback_invoked = false;
41 rv = glob_b("test/*", 0, errblk, &g);
42 ATF_CHECK_MSG(glob_callback_invoked,
43 "glob(3) failed to invoke callback block");
44 ATF_CHECK_EQ_MSG(GLOB_NOMATCH, rv,
45 "callback function failed to suppress EACCES");
46 globfree(&g);
47
48 /* GLOB_ERR should ignore the suppressed error. */
49 glob_callback_invoked = false;
50 rv = glob_b("test/*", GLOB_ERR, errblk, &g);
51 ATF_CHECK_MSG(glob_callback_invoked,
52 "glob(3) failed to invoke callback block");
53 ATF_CHECK_EQ_MSG(GLOB_ABORTED, rv,
54 "GLOB_ERR didn't override callback block");
55 globfree(&g);
56 }
57
ATF_TP_ADD_TCS(tp)58 ATF_TP_ADD_TCS(tp)
59 {
60 ATF_TP_ADD_TC(tp, glob_b_callback);
61 return (atf_no_error());
62 }
63