xref: /freebsd/lib/libc/tests/gen/glob_blocks_test.c (revision 7fe39bec801a08f541d0111219fe8701a6a20cf1)
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