14d7c31bcSBojan Novković /*-
24d7c31bcSBojan Novković * Copyright (c) 2025 Klara, Inc.
34d7c31bcSBojan Novković *
44d7c31bcSBojan Novković * SPDX-License-Identifier: BSD-2-Clause
54d7c31bcSBojan Novković */
64d7c31bcSBojan Novković
74d7c31bcSBojan Novković #include <sys/stat.h>
84d7c31bcSBojan Novković
94d7c31bcSBojan Novković #include <errno.h>
104d7c31bcSBojan Novković #include <glob.h>
11*7fe39becSDag-Erling Smørgrav #include <stdbool.h>
124d7c31bcSBojan Novković
134d7c31bcSBojan Novković #include <atf-c.h>
144d7c31bcSBojan Novković
15*7fe39becSDag-Erling Smørgrav ATF_TC(glob_b_callback);
ATF_TC_HEAD(glob_b_callback,tc)16*7fe39becSDag-Erling Smørgrav ATF_TC_HEAD(glob_b_callback, tc)
174d7c31bcSBojan Novković {
18*7fe39becSDag-Erling Smørgrav atf_tc_set_md_var(tc, "descr",
19*7fe39becSDag-Erling Smørgrav "Test ability of callback block to suppress errors");
20*7fe39becSDag-Erling Smørgrav atf_tc_set_md_var(tc, "require.user", "unprivileged");
21*7fe39becSDag-Erling Smørgrav }
ATF_TC_BODY(glob_b_callback,tc)22*7fe39becSDag-Erling Smørgrav ATF_TC_BODY(glob_b_callback, tc)
23*7fe39becSDag-Erling Smørgrav {
24*7fe39becSDag-Erling Smørgrav static bool glob_callback_invoked;
25*7fe39becSDag-Erling Smørgrav static int (^errblk)(const char *, int) =
264d7c31bcSBojan Novković ^(const char *path, int err) {
27*7fe39becSDag-Erling Smørgrav ATF_CHECK_STREQ(path, "test/");
28*7fe39becSDag-Erling Smørgrav ATF_CHECK(err == EACCES);
29*7fe39becSDag-Erling Smørgrav glob_callback_invoked = true;
304d7c31bcSBojan Novković /* Suppress EACCES errors. */
314d7c31bcSBojan Novković return (0);
324d7c31bcSBojan Novković };
33*7fe39becSDag-Erling Smørgrav glob_t g;
34*7fe39becSDag-Erling Smørgrav int rv;
354d7c31bcSBojan Novković
36*7fe39becSDag-Erling Smørgrav ATF_REQUIRE_EQ(0, mkdir("test", 0755));
37*7fe39becSDag-Erling Smørgrav ATF_REQUIRE_EQ(0, symlink("foo", "test/foo"));
38*7fe39becSDag-Erling Smørgrav ATF_REQUIRE_EQ(0, chmod("test", 0));
39*7fe39becSDag-Erling Smørgrav
40*7fe39becSDag-Erling Smørgrav glob_callback_invoked = false;
414d7c31bcSBojan Novković rv = glob_b("test/*", 0, errblk, &g);
42*7fe39becSDag-Erling Smørgrav ATF_CHECK_MSG(glob_callback_invoked,
434d7c31bcSBojan Novković "glob(3) failed to invoke callback block");
44*7fe39becSDag-Erling Smørgrav ATF_CHECK_EQ_MSG(GLOB_NOMATCH, rv,
45*7fe39becSDag-Erling Smørgrav "callback function failed to suppress EACCES");
46*7fe39becSDag-Erling Smørgrav globfree(&g);
474d7c31bcSBojan Novković
484d7c31bcSBojan Novković /* GLOB_ERR should ignore the suppressed error. */
49*7fe39becSDag-Erling Smørgrav glob_callback_invoked = false;
504d7c31bcSBojan Novković rv = glob_b("test/*", GLOB_ERR, errblk, &g);
51*7fe39becSDag-Erling Smørgrav ATF_CHECK_MSG(glob_callback_invoked,
52*7fe39becSDag-Erling Smørgrav "glob(3) failed to invoke callback block");
53*7fe39becSDag-Erling Smørgrav ATF_CHECK_EQ_MSG(GLOB_ABORTED, rv,
54*7fe39becSDag-Erling Smørgrav "GLOB_ERR didn't override callback block");
55*7fe39becSDag-Erling Smørgrav globfree(&g);
564d7c31bcSBojan Novković }
574d7c31bcSBojan Novković
ATF_TP_ADD_TCS(tp)584d7c31bcSBojan Novković ATF_TP_ADD_TCS(tp)
594d7c31bcSBojan Novković {
60*7fe39becSDag-Erling Smørgrav ATF_TP_ADD_TC(tp, glob_b_callback);
614d7c31bcSBojan Novković return (atf_no_error());
624d7c31bcSBojan Novković }
63