<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.
</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/384b03e085f80de52d67729d0295b06b55702541">https://github.com/macports/macports-legacy-support/commit/384b03e085f80de52d67729d0295b06b55702541</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 384b03e085f80de52d67729d0295b06b55702541
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Thu Jul 3 15:34:19 2025 -0700
<span style='display:block; white-space:pre;color:#404040;'> test_faccessat: Make parallelizable.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> Makes created directory name unique.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> Also adds success/failure message.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> TESTED:
</span><span style='display:block; white-space:pre;color:#404040;'> Passes on all platforms, including running in parallel.
</span>---
test/test_faccessat.c | 737 ++++++++++++++++++++++++++------------------------
1 file changed, 378 insertions(+), 359 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_faccessat.c b/test/test_faccessat.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 7f29431..afe8303 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/test_faccessat.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_faccessat.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,5 +1,6 @@
</span> /*
* Copyright (C) 2023 raf <raf@raf.org>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2025 Frederick H. G. Wright II <fw@fwright.net>
</span> *
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -14,373 +15,391 @@
</span> * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <stdio.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <unistd.h>
</span> #include <errno.h>
#include <fcntl.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <grp.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <libgen.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <pwd.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdio.h>
</span> #include <string.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <unistd.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/param.h>
</span> #include <sys/stat.h>
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <pwd.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <grp.h>
</span>
#ifndef TEST_TEMP
#define TEST_TEMP "/dev/null"
#endif
<span style='display:block; white-space:pre;background:#ffe0e0;'>-int main(int ac, char **av)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int main(int argc, char *argv[])
</span> {
<span style='display:block; white-space:pre;background:#ffe0e0;'>- int failures = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- uid_t real_uid = getuid();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- uid_t effective_uid = geteuid();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- uid_t real_gid = getgid();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- uid_t effective_gid = getegid();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // When supplied with arguments, compare faccessat() against access().
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // We can't test AT_EACCESS here because access() can't do that.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // But some tests will be setuid, some setgid, and some neither.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // See test/do_test_faccessat_setuid for details.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (ac > 1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // For each file, test all modes in isolation and in all combinations
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int modes[8] = { F_OK, R_OK, W_OK, X_OK, R_OK|W_OK, W_OK|X_OK, X_OK|R_OK, R_OK|W_OK|X_OK };
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int a, m;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- for (a = 1; a < ac; ++a)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- for (m = 0; m < 8; ++m)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int faccessat_rc = faccessat(AT_FDCWD, av[a], modes[m], 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int faccessat_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int access_rc = access(av[a], modes[m]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int access_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (faccessat_rc != access_rc || (faccessat_rc < 0 && faccessat_errno != access_errno))
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (!failures)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "faccessat_setuid: uid=%s euid=%s gid=%s egid=%s\n",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getpwuid(real_uid) ? getpwuid(real_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getpwuid(effective_uid) ? getpwuid(effective_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getgrgid(real_gid) ? getgrgid(real_gid)->gr_name : "?",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getgrgid(effective_gid) ? getgrgid(effective_gid)->gr_name : "?"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- ++failures;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "faccessat(%s, %s%s%s%s) fail: %d %s != %d %s\n",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- av[a],
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- (modes[m] == F_OK) ? "F" : "",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- (modes[m] & R_OK) ? "R" : "",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- (modes[m] & W_OK) ? "W" : "",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- (modes[m] & X_OK) ? "X" : "",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- faccessat_rc,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- (faccessat_rc == -1) ? strerror(faccessat_errno) : "",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- access_rc,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- (access_rc == -1) ? strerror(access_errno) : ""
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- char buf[1024];
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- snprintf(buf, 1024, "/bin/ls -l %s", av[a]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- system(buf);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(av[0]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return (failures) ? 1 : 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // Without arguments, just create readable/writable/executable/inaccessible
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // files and test faccessat() with and without AT_EACCESS. This is part of
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // the automatic tests, but as part of manual testing might be setuid.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // Instead of comparing against access(), these tests have explicit expected
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // results.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #define TMP TEST_TEMP "/tmp"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- const char *readable_path = TMP "/readable";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- const char *writable_path = TMP "/writable";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- const char *executable_path = TMP "/executable";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- const char *inaccessible_path = TMP "/inaccessible";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- const char *nonexistent_path = TMP "/nonexistent";
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Create TEST_TEMP/tmp directory if not already there (see make test_faccessat_setuid) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int mkdir_rc = mkdir(TMP, 0700);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int mkdir_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (mkdir_rc == -1 && mkdir_errno != EEXIST)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "failed to create tmp directory %s: %s\n", TMP, strerror(errno));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Create readable/writable/executable/inaccessible files (owned by effective user) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_fd = creat(readable_path, 0400);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (readable_fd == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "failed to create readable file %s: %s\n", readable_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- rmdir(TMP);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- close(readable_fd);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_fd = creat(writable_path, 0200);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (writable_fd == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "failed to create writable file %s: %s\n", writable_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- rmdir(TMP);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- close(writable_fd);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_fd = creat(executable_path, 0100);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (executable_fd == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "failed to create executable file %s: %s\n", executable_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(writable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- rmdir(TMP);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- close(executable_fd);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_fd = creat(inaccessible_path, 0000);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (inaccessible_fd == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "failed to create inaccessible file %s: %s\n", inaccessible_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(writable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(executable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- rmdir(TMP);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- close(inaccessible_fd);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test faccessat() with no flags and with AT_EACCESS */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int dfd = open(".", O_RDONLY); errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_rok = faccessat(dfd, readable_path, R_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_rok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_wok = faccessat(dfd, writable_path, W_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_wok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_xok = faccessat(dfd, executable_path, X_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_xok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_rok = faccessat(dfd, inaccessible_path, R_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_rok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_wok = faccessat(dfd, inaccessible_path, W_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_wok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_xok = faccessat(dfd, inaccessible_path, X_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_xok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_erok = faccessat(dfd, readable_path, R_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_erok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_ewok = faccessat(dfd, writable_path, W_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_ewok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_exok = faccessat(dfd, executable_path, X_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_exok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_erok = faccessat(dfd, inaccessible_path, R_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_erok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_ewok = faccessat(dfd, inaccessible_path, W_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_ewok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_exok = faccessat(dfd, inaccessible_path, X_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_exok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_fok = faccessat(dfd, readable_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_fok = faccessat(dfd, writable_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_fok = faccessat(dfd, executable_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_fok = faccessat(dfd, inaccessible_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_efok = faccessat(dfd, readable_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int readable_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_efok = faccessat(dfd, writable_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int writable_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_efok = faccessat(dfd, executable_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int executable_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_efok = faccessat(dfd, inaccessible_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int inaccessible_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int nonexistent_fok = faccessat(dfd, nonexistent_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int nonexistent_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int nonexistent_efok = faccessat(dfd, nonexistent_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int nonexistent_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- close (dfd);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- #define TEST(cond, message, e) if (!(cond)) { errno = 0; fprintf(stderr, "%s %s\n", message, (e) ? strerror(e) : ""); ++failures; }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test F_OK */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_fok == 0, "root: faccessat(readable F_OK) does not exist = FAIL", readable_fok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_fok == 0, "root: faccessat(writable F_OK) does not exist = FAIL", writable_fok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_fok == 0, "root: faccessat(executable F_OK) does not exist = FAIL", executable_fok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_fok == 0, "root: faccessat(inaccessible F_OK) does not exist = FAIL", inaccessible_fok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_efok == 0, "root: faccessat(readable F_OK AT_EACCESS) does not exist = FAIL", readable_efok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_efok == 0, "root: faccessat(writable F_OK AT_EACCESS) does not exist = FAIL", writable_efok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_efok == 0, "root: faccessat(executable F_OK AT_EACCESS) does not exist = FAIL", executable_efok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_efok == 0, "root: faccessat(inaccessible F_OK AT_EACCESS) does not exist = FAIL", inaccessible_efok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(nonexistent_fok == -1, "root: faccessat(nonexistent F_OK) does exist = FAIL", nonexistent_fok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(nonexistent_efok == -1, "root: faccessat(nonexistent F_OK AT_EACCESS) does exist = FAIL", nonexistent_efok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test non-setuid program */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (real_uid == effective_uid)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test as non-root user */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (real_uid != 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_rok == 0, "not root: faccessat(readable R_OK) is unreadable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_wok == 0, "not root: faccessat(writable W_OK) is unwritable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_xok == 0, "not root: faccessat(executable X_OK) is unexecutable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_rok == -1, "not root: faccessat(inaccessible R_OK) is readable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_wok == -1, "not root: faccessat(inaccessible W_OK) is writable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_xok == -1, "not root: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* This isn't meaningful because uid == euid */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_erok == 0, "not root: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_ewok == 0, "not root: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_exok == 0, "not root: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_erok == -1, "not root: faccessat(inaccessible R_OK AT_EACCESS) is readable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_ewok == -1, "not root: faccessat(inaccessible W_OK AT_EACCESS) is writable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_exok == -1, "not root: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test as root user */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_rok == 0, "root: faccessat(readable R_OK) is unreadable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_wok == 0, "root: faccessat(writable W_OK) is unwritable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_xok == 0, "root: faccessat(executable X_OK) is unexecutable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_rok == 0, "root: faccessat(inaccessible R_OK) is unreadable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_wok == 0, "root: faccessat(inaccessible W_OK) is unwritable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_xok == -1, "root: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* This isn't meaningful because uid == euid */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_erok == 0, "root: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_ewok == 0, "root: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_exok == 0, "root: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_erok == 0, "root: faccessat(inaccessible R_OK AT_EACCESS) is unreadable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_ewok == 0, "root: faccessat(inaccessible W_OK AT_EACCESS) is unwritable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_exok == -1, "root: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test setuid root program */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Note: Must be setuid root, run as non-root, linked using absolute path */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- else if (real_uid != 0 && effective_uid == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_rok == -1, "setuid root: non-root user: faccessat(readable R_OK) is readable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_wok == -1, "setuid root: non-root user: faccessat(writable W_OK) is writable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_xok == -1, "setuid root: non-root user: faccessat(executable X_OK) is executable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_rok == -1, "setuid root: non-root user: faccessat(inaccessible R_OK) is readable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_wok == -1, "setuid root: non-root user: faccessat(inaccessible W_OK) is writable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_xok == -1, "setuid root: non-root user: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* This is meaningful because uid != euid */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_erok == 0, "setuid root: non-root user: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_ewok == 0, "setuid root: non-root user: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_exok == 0, "setuid root: non-root user: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_erok == 0, "setuid root: non-root user: faccessat(inaccessible R_OK AT_EACCESS) is unreadable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_ewok == 0, "setuid root: non-root user: faccessat(inaccessible W_OK AT_EACCESS) is unwritable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_exok == -1, "setuid root: non-root user: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test setuid non-root program */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Note: Must be setuid, run as non-root other user, linked using absolute path */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- else if (real_uid != 0 && effective_uid != real_uid)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_rok == -1, "setuid non-root: non-root other user: faccessat(readable R_OK) is readable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_wok == -1, "setuid non-root: non-root other user: faccessat(writable W_OK) is writable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_xok == -1, "setuid non-root: non-root other user: faccessat(executable X_OK) is executable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_rok == -1, "setuid non-root: non-root other user: faccessat(inaccessible R_OK) is readable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_wok == -1, "setuid non-root: non-root other user: faccessat(inaccessible W_OK) is writable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_xok == -1, "setuid non-root: non-root other user: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* This is meaningful because uid != euid */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(readable_erok == 0, "setuid non-root: non-root other user: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(writable_ewok == 0, "setuid non-root: non-root other user: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(executable_exok == 0, "setuid non-root: non-root other user: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_erok == -1, "setuid non-root: non-root other user: faccessat(inaccessible R_OK AT_EACCESS) is readable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_ewok == -1, "setuid non-root: non-root other user: faccessat(inaccessible W_OK AT_EACCESS) is writable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(inaccessible_exok == -1, "setuid non-root: non-root other user: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Report any unexpected situation (won't happen) */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- else
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "This uid/euid combination isn't currently tested.\n");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- ++failures;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Only show the test files and process permissions if there were failures */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (failures)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- fprintf(stderr, "faccessat_setuid: uid=%s euid=%s gid=%s egid=%s\n",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getpwuid(real_uid) ? getpwuid(real_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getpwuid(effective_uid) ? getpwuid(effective_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getgrgid(real_gid) ? getgrgid(real_gid)->gr_name : "?",
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- getgrgid(effective_gid) ? getgrgid(effective_gid)->gr_name : "?"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- );
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- system("/bin/ls -l " TEST_TEMP "/tmp/*ble");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Test argument validation */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_pathname_rc = faccessat(AT_FDCWD, NULL, R_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_pathname_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_dirfd_rc = faccessat(-1, "pathname", R_OK, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_dirfd_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_mode_rc = faccessat(AT_FDCWD, "pathname", -1, 0); // Apple doesn't check this
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_mode_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_flag_rc = faccessat(AT_FDCWD, "pathname", R_OK, -1);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- int check_flag_errno = errno;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_pathname_rc == -1, "check pathname failed", 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (check_pathname_rc == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_pathname_errno == EFAULT, "check pathname errno wrong (should be EFAULT)", check_pathname_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_dirfd_rc == -1, "check dirfd failed", 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (check_dirfd_rc == -1) // On 10.14 this is EBADF. On 10.4 it's ENOENT
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_dirfd_errno == EBADF || check_dirfd_errno == ENOENT, "check dirfd errno wrong (should be EBADF or ENOENT)", check_dirfd_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_mode_rc == -1, "check mode failed", 0) // Apple doesn't check this argument - failure is ENOENT/EPERM
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- //if (check_mode_rc == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- // TEST(check_mode_errno == EINVAL, "check mode errno wrong (should be EINVAL)", check_mode_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (check_mode_rc == -1) // On 10.14 this is ENOENT. On 10.6 it's EPERM
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_mode_errno == ENOENT || check_mode_errno == EPERM, "check mode errno wrong (should be ENOENT or EPERM)", check_mode_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_flag_rc == -1, "check flag failed", 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (check_flag_rc == -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- TEST(check_flag_errno == EINVAL, "check flag errno wrong (should be EINVAL)", check_flag_errno)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Cleanup */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(writable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(executable_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(inaccessible_path);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- rmdir(TMP);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- /* Delete test/test_faccessat_setuid. Don't wait for make clean. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- if (real_uid != effective_uid || real_gid != effective_gid)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- unlink(av[0]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- return (failures) ? 1 : 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int failures = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ uid_t real_uid = getuid();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ uid_t effective_uid = geteuid();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ uid_t real_gid = getgid();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ uid_t effective_gid = getegid();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ pid_t pid = getpid();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *progname = basename(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char tmpdir[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char readable_path[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char writable_path[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char executable_path[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char inaccessible_path[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char nonexistent_path[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // When supplied with arguments, compare faccessat() against access().
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // We can't test AT_EACCESS here because access() can't do that.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // But some tests will be setuid, some setgid, and some neither.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // See manual_tests/do_test_faccessat_setuid.sh for details.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (argc > 1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // For each file, test all modes in isolation and in all combinations
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int modes[8] = { F_OK, R_OK, W_OK, X_OK, R_OK|W_OK, W_OK|X_OK, X_OK|R_OK, R_OK|W_OK|X_OK };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int a, m;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (a = 1; a < argc; ++a)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ for (m = 0; m < 8; ++m)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int faccessat_rc = faccessat(AT_FDCWD, argv[a], modes[m], 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int faccessat_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int access_rc = access(argv[a], modes[m]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int access_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (faccessat_rc != access_rc || (faccessat_rc < 0 && faccessat_errno != access_errno))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!failures)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "faccessat_setuid: uid=%s euid=%s gid=%s egid=%s\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getpwuid(real_uid) ? getpwuid(real_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getpwuid(effective_uid) ? getpwuid(effective_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getgrgid(real_gid) ? getgrgid(real_gid)->gr_name : "?",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getgrgid(effective_gid) ? getgrgid(effective_gid)->gr_name : "?"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ++failures;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "faccessat(%s, %s%s%s%s) fail: %d %s != %d %s\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ argv[a],
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (modes[m] == F_OK) ? "F" : "",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (modes[m] & R_OK) ? "R" : "",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (modes[m] & W_OK) ? "W" : "",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (modes[m] & X_OK) ? "X" : "",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ faccessat_rc,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (faccessat_rc == -1) ? strerror(faccessat_errno) : "",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ access_rc,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (access_rc == -1) ? strerror(access_errno) : ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char buf[1024];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ snprintf(buf, 1024, "/bin/ls -l %s", argv[a]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ system(buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf("%s %s.\n", progname, failures ? "failed" : "passed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (failures) ? 1 : 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // Without arguments, just create readable/writable/executable/inaccessible
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // files and test faccessat() with and without AT_EACCESS. This is part of
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // the automatic tests, but as part of manual testing might be setuid.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // Instead of comparing against access(), these tests have explicit expected
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // results.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (void) snprintf(tmpdir, sizeof(tmpdir), TEST_TEMP "/%s-%u",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ progname, pid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #define SETUP_PATH(name) \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ (void) snprintf(name##_path, sizeof(name##_path), "%s/" #name, tmpdir)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SETUP_PATH(readable);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SETUP_PATH(writable);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SETUP_PATH(executable);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SETUP_PATH(inaccessible);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SETUP_PATH(nonexistent);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Create temporary directory if not already there (see make test_faccessat_setuid) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int mkdir_rc = mkdir(tmpdir, 0700);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int mkdir_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mkdir_rc == -1 && mkdir_errno != EEXIST)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "failed to create tmp directory %s: %s\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ tmpdir, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Create readable/writable/executable/inaccessible files (owned by effective user) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_fd = creat(readable_path, 0400);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (readable_fd == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "failed to create readable file %s: %s\n", readable_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rmdir(tmpdir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ close(readable_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_fd = creat(writable_path, 0200);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (writable_fd == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "failed to create writable file %s: %s\n", writable_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rmdir(tmpdir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ close(writable_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_fd = creat(executable_path, 0100);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (executable_fd == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "failed to create executable file %s: %s\n", executable_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(writable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rmdir(tmpdir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ close(executable_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_fd = creat(inaccessible_path, 0000);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (inaccessible_fd == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "failed to create inaccessible file %s: %s\n", inaccessible_path, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(writable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(executable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rmdir(tmpdir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ close(inaccessible_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test faccessat() with no flags and with AT_EACCESS */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int dfd = open(".", O_RDONLY); errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_rok = faccessat(dfd, readable_path, R_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_rok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_wok = faccessat(dfd, writable_path, W_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_wok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_xok = faccessat(dfd, executable_path, X_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_xok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_rok = faccessat(dfd, inaccessible_path, R_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_rok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_wok = faccessat(dfd, inaccessible_path, W_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_wok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_xok = faccessat(dfd, inaccessible_path, X_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_xok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_erok = faccessat(dfd, readable_path, R_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_erok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_ewok = faccessat(dfd, writable_path, W_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_ewok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_exok = faccessat(dfd, executable_path, X_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_exok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_erok = faccessat(dfd, inaccessible_path, R_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_erok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_ewok = faccessat(dfd, inaccessible_path, W_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_ewok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_exok = faccessat(dfd, inaccessible_path, X_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_exok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_fok = faccessat(dfd, readable_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_fok = faccessat(dfd, writable_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_fok = faccessat(dfd, executable_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_fok = faccessat(dfd, inaccessible_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_efok = faccessat(dfd, readable_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int readable_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_efok = faccessat(dfd, writable_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int writable_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_efok = faccessat(dfd, executable_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int executable_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_efok = faccessat(dfd, inaccessible_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int inaccessible_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int nonexistent_fok = faccessat(dfd, nonexistent_path, F_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int nonexistent_fok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int nonexistent_efok = faccessat(dfd, nonexistent_path, F_OK, AT_EACCESS);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int nonexistent_efok_errno = errno; errno = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ close (dfd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #define TEST(cond, message, e) if (!(cond)) { errno = 0; fprintf(stderr, "%s %s\n", message, (e) ? strerror(e) : ""); ++failures; }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test F_OK */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_fok == 0, "root: faccessat(readable F_OK) does not exist = FAIL", readable_fok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_fok == 0, "root: faccessat(writable F_OK) does not exist = FAIL", writable_fok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_fok == 0, "root: faccessat(executable F_OK) does not exist = FAIL", executable_fok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_fok == 0, "root: faccessat(inaccessible F_OK) does not exist = FAIL", inaccessible_fok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_efok == 0, "root: faccessat(readable F_OK AT_EACCESS) does not exist = FAIL", readable_efok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_efok == 0, "root: faccessat(writable F_OK AT_EACCESS) does not exist = FAIL", writable_efok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_efok == 0, "root: faccessat(executable F_OK AT_EACCESS) does not exist = FAIL", executable_efok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_efok == 0, "root: faccessat(inaccessible F_OK AT_EACCESS) does not exist = FAIL", inaccessible_efok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(nonexistent_fok == -1, "root: faccessat(nonexistent F_OK) does exist = FAIL", nonexistent_fok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(nonexistent_efok == -1, "root: faccessat(nonexistent F_OK AT_EACCESS) does exist = FAIL", nonexistent_efok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test non-setuid program */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (real_uid == effective_uid)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test as non-root user */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (real_uid != 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_rok == 0, "not root: faccessat(readable R_OK) is unreadable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_wok == 0, "not root: faccessat(writable W_OK) is unwritable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_xok == 0, "not root: faccessat(executable X_OK) is unexecutable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_rok == -1, "not root: faccessat(inaccessible R_OK) is readable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_wok == -1, "not root: faccessat(inaccessible W_OK) is writable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_xok == -1, "not root: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* This isn't meaningful because uid == euid */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_erok == 0, "not root: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_ewok == 0, "not root: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_exok == 0, "not root: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_erok == -1, "not root: faccessat(inaccessible R_OK AT_EACCESS) is readable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_ewok == -1, "not root: faccessat(inaccessible W_OK AT_EACCESS) is writable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_exok == -1, "not root: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test as root user */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_rok == 0, "root: faccessat(readable R_OK) is unreadable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_wok == 0, "root: faccessat(writable W_OK) is unwritable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_xok == 0, "root: faccessat(executable X_OK) is unexecutable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_rok == 0, "root: faccessat(inaccessible R_OK) is unreadable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_wok == 0, "root: faccessat(inaccessible W_OK) is unwritable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_xok == -1, "root: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* This isn't meaningful because uid == euid */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_erok == 0, "root: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_ewok == 0, "root: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_exok == 0, "root: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_erok == 0, "root: faccessat(inaccessible R_OK AT_EACCESS) is unreadable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_ewok == 0, "root: faccessat(inaccessible W_OK AT_EACCESS) is unwritable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_exok == -1, "root: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test setuid root program */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Note: Must be setuid root, run as non-root, linked using absolute path */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (real_uid != 0 && effective_uid == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_rok == -1, "setuid root: non-root user: faccessat(readable R_OK) is readable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_wok == -1, "setuid root: non-root user: faccessat(writable W_OK) is writable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_xok == -1, "setuid root: non-root user: faccessat(executable X_OK) is executable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_rok == -1, "setuid root: non-root user: faccessat(inaccessible R_OK) is readable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_wok == -1, "setuid root: non-root user: faccessat(inaccessible W_OK) is writable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_xok == -1, "setuid root: non-root user: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* This is meaningful because uid != euid */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_erok == 0, "setuid root: non-root user: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_ewok == 0, "setuid root: non-root user: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_exok == 0, "setuid root: non-root user: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_erok == 0, "setuid root: non-root user: faccessat(inaccessible R_OK AT_EACCESS) is unreadable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_ewok == 0, "setuid root: non-root user: faccessat(inaccessible W_OK AT_EACCESS) is unwritable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_exok == -1, "setuid root: non-root user: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test setuid non-root program */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Note: Must be setuid, run as non-root other user, linked using absolute path */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (real_uid != 0 && effective_uid != real_uid)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_rok == -1, "setuid non-root: non-root other user: faccessat(readable R_OK) is readable = FAIL", readable_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_wok == -1, "setuid non-root: non-root other user: faccessat(writable W_OK) is writable = FAIL", writable_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_xok == -1, "setuid non-root: non-root other user: faccessat(executable X_OK) is executable = FAIL", executable_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_rok == -1, "setuid non-root: non-root other user: faccessat(inaccessible R_OK) is readable = FAIL", inaccessible_rok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_wok == -1, "setuid non-root: non-root other user: faccessat(inaccessible W_OK) is writable = FAIL", inaccessible_wok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_xok == -1, "setuid non-root: non-root other user: faccessat(inaccessible X_OK) is executable = FAIL", inaccessible_xok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* This is meaningful because uid != euid */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(readable_erok == 0, "setuid non-root: non-root other user: faccessat(readable R_OK AT_EACCESS) is unreadable = FAIL", readable_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(writable_ewok == 0, "setuid non-root: non-root other user: faccessat(writable W_OK AT_EACCESS) is unwritable = FAIL", writable_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(executable_exok == 0, "setuid non-root: non-root other user: faccessat(executable X_OK AT_EACCESS) is unexecutable = FAIL", executable_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_erok == -1, "setuid non-root: non-root other user: faccessat(inaccessible R_OK AT_EACCESS) is readable = FAIL", inaccessible_erok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_ewok == -1, "setuid non-root: non-root other user: faccessat(inaccessible W_OK AT_EACCESS) is writable = FAIL", inaccessible_ewok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(inaccessible_exok == -1, "setuid non-root: non-root other user: faccessat(inaccessible X_OK AT_EACCESS) is executable = FAIL", inaccessible_exok_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Report any unexpected situation (won't happen) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "This uid/euid combination isn't currently tested.\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ++failures;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Only show the test files and process permissions if there were failures */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (failures)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "faccessat_setuid: uid=%s euid=%s gid=%s egid=%s\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getpwuid(real_uid) ? getpwuid(real_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getpwuid(effective_uid) ? getpwuid(effective_uid)->pw_name : "?",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getgrgid(real_gid) ? getgrgid(real_gid)->gr_name : "?",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ getgrgid(effective_gid) ? getgrgid(effective_gid)->gr_name : "?"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ );
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ system("/bin/ls -l " TEST_TEMP "/tmp/*ble");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Test argument validation */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_pathname_rc = faccessat(AT_FDCWD, NULL, R_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_pathname_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_dirfd_rc = faccessat(-1, "pathname", R_OK, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_dirfd_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_mode_rc = faccessat(AT_FDCWD, "pathname", -1, 0); // Apple doesn't check this
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_mode_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_flag_rc = faccessat(AT_FDCWD, "pathname", R_OK, -1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int check_flag_errno = errno;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_pathname_rc == -1, "check pathname failed", 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (check_pathname_rc == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_pathname_errno == EFAULT, "check pathname errno wrong (should be EFAULT)", check_pathname_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_dirfd_rc == -1, "check dirfd failed", 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (check_dirfd_rc == -1) // On 10.14 this is EBADF. On 10.4 it's ENOENT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_dirfd_errno == EBADF || check_dirfd_errno == ENOENT, "check dirfd errno wrong (should be EBADF or ENOENT)", check_dirfd_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_mode_rc == -1, "check mode failed", 0) // Apple doesn't check this argument - failure is ENOENT/EPERM
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ //if (check_mode_rc == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // TEST(check_mode_errno == EINVAL, "check mode errno wrong (should be EINVAL)", check_mode_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (check_mode_rc == -1) // On 10.14 this is ENOENT. On 10.6 it's EPERM
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_mode_errno == ENOENT || check_mode_errno == EPERM, "check mode errno wrong (should be ENOENT or EPERM)", check_mode_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_flag_rc == -1, "check flag failed", 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (check_flag_rc == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ TEST(check_flag_errno == EINVAL, "check flag errno wrong (should be EINVAL)", check_flag_errno)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Cleanup */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(readable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(writable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(executable_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(inaccessible_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (mkdir_rc == 0)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rmdir(tmpdir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Delete test/test_faccessat_setuid. Don't wait for make clean. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (real_uid != effective_uid || real_gid != effective_gid)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ unlink(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf("%s %s.\n", progname, failures ? "failed" : "passed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return (failures) ? 1 : 0;
</span> }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-/* vi:set noet ts=4 sw=4: */
</span></pre><pre style='margin:0'>
</pre>