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); 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 } 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 58 ATF_TP_ADD_TCS(tp) 59 { 60 ATF_TP_ADD_TC(tp, glob_b_callback); 61 return (atf_no_error()); 62 } 63