<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>