<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/05245713afdafa11a8b98a476fc47a2085864e58">https://github.com/macports/macports-legacy-support/commit/05245713afdafa11a8b98a476fc47a2085864e58</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 05245713afdafa11a8b98a476fc47a2085864e58
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Thu Nov 28 17:55:35 2024 -0800

<span style='display:block; white-space:pre;color:#404040;'>    Add tests for *stat*() functions.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    This currently excludes the fstatat*() tests, until the known issue is
</span><span style='display:block; white-space:pre;color:#404040;'>    fixed.
</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;'>    Fails on 10.4 prior to statxx addition.
</span><span style='display:block; white-space:pre;color:#404040;'>    Passes on all platforms with statxx.
</span>---
 Makefile               |  13 +++
 test/.gitignore        |   1 +
 test/test_stat.c       | 263 +++++++++++++++++++++++++++++++++++++++++++++++++
 test/test_stat.c_link  |   1 +
 test/test_stat_ino32.c |  28 ++++++
 test/test_stat_ino64.c |  10 ++
 6 files changed, 316 insertions(+)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/Makefile b/Makefile
</span><span style='display:block; white-space:pre;color:#808080;'>index ee2a1eb..c669251 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/Makefile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/Makefile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -173,6 +173,9 @@ REALPATHRUNS    := $(patsubst \
</span> FDOPENDIRSRCS_C := $(wildcard $(TESTNAMEPREFIX)fdopendir*.c)
 FDOPENDIRRUNS   := $(patsubst \
                      $(TESTNAMEPREFIX)%.c,$(TESTRUNPREFIX)%,$(FDOPENDIRSRCS_C))
<span style='display:block; white-space:pre;background:#e0ffe0;'>+STATXXSRCS_C    := $(wildcard $(TESTNAMEPREFIX)stat*.c)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+STATXXRUNS      := $(patsubst \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                     $(TESTNAMEPREFIX)%.c,$(TESTRUNPREFIX)%,$(STATXXSRCS_C))
</span> 
 # Tests that are only run manually
 MANTESTDIR       = manual_tests
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -370,6 +373,12 @@ $(TESTNAMEPREFIX)realpath_compat.o: $(TESTNAMEPREFIX)realpath.c
</span> $(TESTNAMEPREFIX)fdopendir_ino32.o: $(TESTNAMEPREFIX)fdopendir.c
 $(TESTNAMEPREFIX)fdopendir_ino64.o: $(TESTNAMEPREFIX)fdopendir.c
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# The stat_ino?? tests include the stat source
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+$(TESTNAMEPREFIX)stat_darwin.o: $(TESTNAMEPREFIX)stat.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+$(TESTNAMEPREFIX)stat_ino32.o: $(TESTNAMEPREFIX)stat.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+$(TESTNAMEPREFIX)stat_ino64.o: $(TESTNAMEPREFIX)stat.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+$(TESTNAMEPREFIX)stat_ino64_darwin.o: $(TESTNAMEPREFIX)stat.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> # Provide a target for all "darwin_c" tests
 $(XTESTRUNPREFIX)darwin_c_all: $(DARWINRUNS)
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -382,6 +391,9 @@ $(TESTRUNPREFIX)realpath_all: $(REALPATHRUNS)
</span> # Provide a target for all "fdopendir" tests
 $(TESTRUNPREFIX)fdopendir_all: $(FDOPENDIRRUNS)
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# Provide a target for all "stat" tests
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+$(TESTRUNPREFIX)stat_all: $(STATXXRUNS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> $(MANTESTRUNS): $(MANRUNPREFIX)%: $(MANTESTPREFIX)%
        $< $(TEST_ARGS)
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -443,6 +455,7 @@ clean: $(MANRUNPREFIX)clean test_clean
</span> .PHONY: $(MANRUNPREFIX)clean test_clean xtest_clean
 .PHONY: $(XTESTRUNPREFIX)scandir_all
 .PHONY: $(TESTRUNPREFIX)fdopendir_all
<span style='display:block; white-space:pre;background:#e0ffe0;'>+.PHONY: $(TESTRUNPREFIX)stat_all
</span> .PHONY: install install-headers install-lib install-dlib install-slib
 .PHONY: tiger-bins install-tiger
 .PHONY: allobjs dlibobjs slibobjs syslibobjs
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/.gitignore b/test/.gitignore
</span><span style='display:block; white-space:pre;color:#808080;'>index 0df309e..a8d8ea3 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/.gitignore
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/.gitignore
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4,3 +4,4 @@
</span> !*.cpp
 !do_test_faccessat_setuid
 !*.txt
<span style='display:block; white-space:pre;background:#e0ffe0;'>+!*_link
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_stat.c b/test/test_stat.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..9a38563
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_stat.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,263 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2024 Frederick H. G. Wright II <fw@fwright.net>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Permission to use, copy, modify, and distribute this software for any
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * purpose with or without fee is hereby granted, provided that the above
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * copyright notice and this permission notice appear in all copies.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
</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;'>+/* This provides some tests of the *stat() functions. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <assert.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 <stdio.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdint.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <string.h>
</span><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><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/stat.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Make sure we always have a "struct stat64" */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if !__MPLS_HAVE_STAT64
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+struct stat64 __DARWIN_STRUCT_STAT64;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Structure accommodating both struct stat sizes, with padding for check */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef struct safe_stat_s  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  struct stat_s {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct stat s;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    uint64_t pad;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } s;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  struct stat64_s {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct stat64 s;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    uint64_t pad;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } s64;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+} safe_stat_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static safe_stat_t stat_buf, stat_copy, stat_link_copy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int stat_err;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static const uint64_t pad_val = 0xDEADBEEFDEADBEEFULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static const char *source = __FILE__;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static const char *source_link = __FILE__ "_link";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+stat_init(int ino64)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!ino64) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    stat_buf.s.pad = pad_val;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    stat_buf.s64.pad = pad_val;
</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;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+copy_stat_std(int link)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  safe_stat_t *dest = link ? &stat_link_copy : &stat_copy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  dest->s = stat_buf.s;
</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;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+copy_stat_64(int link)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  safe_stat_t *dest = link ? &stat_link_copy : &stat_copy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  dest->s64 = stat_buf.s64;
</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;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+copy_stat(int ino64, int link)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!ino64) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    copy_stat_std(link);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    copy_stat_64(link);
</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;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ts_equal(const struct timespec *a, const struct timespec *b)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return a->tv_sec == b->tv_sec && a->tv_nsec == b->tv_nsec;
</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;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+check_copy_std(int link)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  const safe_stat_t *copy = link ? &stat_link_copy : &stat_copy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_dev == copy->s.s.st_dev);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_ino == copy->s.s.st_ino);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_mode == copy->s.s.st_mode);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_nlink == copy->s.s.st_nlink);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_uid == copy->s.s.st_uid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_gid == copy->s.s.st_gid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_rdev == copy->s.s.st_rdev);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Don't check atime, since this test may change it. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(ts_equal(&stat_buf.s.s.st_mtimespec, &copy->s.s.st_mtimespec));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(ts_equal(&stat_buf.s.s.st_ctimespec, &copy->s.s.st_ctimespec));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __DARWIN_64_BIT_INO_T
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(ts_equal(&stat_buf.s.s.st_birthtimespec,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                  &copy->s.s.st_birthtimespec));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __DARWIN_64_BIT_INO_T */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_size == copy->s.s.st_size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_blocks == copy->s.s.st_blocks);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_blksize == copy->s.s.st_blksize);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_flags == copy->s.s.st_flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s.s.st_gen == copy->s.s.st_gen);
</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;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+check_copy_64(int link)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  const safe_stat_t *copy = link ? &stat_link_copy : &stat_copy;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_dev == copy->s64.s.st_dev);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_mode == copy->s64.s.st_mode);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_nlink == copy->s64.s.st_nlink);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_ino == copy->s64.s.st_ino);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_uid == copy->s64.s.st_uid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_gid == copy->s64.s.st_gid);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_rdev == copy->s64.s.st_rdev);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Don't check atime, since this test may change it. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(ts_equal(&stat_buf.s64.s.st_mtimespec, &copy->s64.s.st_mtimespec));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(ts_equal(&stat_buf.s64.s.st_ctimespec, &copy->s64.s.st_ctimespec));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(ts_equal(&stat_buf.s64.s.st_birthtimespec,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                  &copy->s64.s.st_birthtimespec));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_size == copy->s64.s.st_size);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_blocks == copy->s64.s.st_blocks);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_blksize == copy->s64.s.st_blksize);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_flags == copy->s64.s.st_flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(stat_buf.s64.s.st_gen == copy->s64.s.st_gen);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Don't check reserved fields. */
</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;'>+static void
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+check_copy(int ino64, int link)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!ino64) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    check_copy_std(link);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    check_copy_64(link);
</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;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+check_err(const char *name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (stat_err) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    perror(name);
</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;'>+  return 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;'>+static mode_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+get_mode(int ino64)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (!ino64) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    assert(stat_buf.s.pad == pad_val);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return stat_buf.s.s.st_mode;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    assert(stat_buf.s64.pad == pad_val);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return stat_buf.s64.s.st_mode;
</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;'>+int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+main(int argc, char *argv[])
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int verbose = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  FILE *fp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (argc > 1 && !strcmp(argv[1], "-v")) verbose = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf("%s starting.\n", basename(argv[0]));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf(" source = %s, link = %s\n", source, source_link);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf(" struct stat has %d-bit st_ino\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           (int) sizeof(stat_buf.s.s.st_ino) * 8);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf(" struct stat64 has %d-bit st_ino\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           (int) sizeof(stat_buf.s64.s.st_ino) * 8);
</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;'>+  if (verbose) printf("  testing 'stat'\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = stat(source, &stat_buf.s.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("stat")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISREG(get_mode(0)) && "stat expected regular file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  copy_stat(0, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'stat' of link\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = stat(source_link, &stat_buf.s.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("stat of link")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISREG(get_mode(0)) && "stat of link expected regular file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  check_copy(0, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'lstat'\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = lstat(source_link, &stat_buf.s.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("lstat")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISLNK(get_mode(0)) && "lstat expected symlink");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  copy_stat(0, 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'fstat'\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Use fopen() to steer clear of open()/close() variant issues. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert((fp = fopen(source_link, "r")) != NULL && "open of source failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = fstat(fileno(fp), &stat_buf.s.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("fstat")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISREG(get_mode(0)) && "fstat expected regular file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  check_copy(0, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  (void) fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if __MPLS_HAVE_STAT64
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'stat64'\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = stat64(source, &stat_buf.s64.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("stat64")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISREG(get_mode(1)) && "stat64 expected regular file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  copy_stat(1, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'stat64' of link\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = stat64(source_link, &stat_buf.s64.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("stat64 of link")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISREG(get_mode(1)) && "stat64 of link expected regular file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  check_copy(1, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'lstat64'\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = lstat64(source_link, &stat_buf.s64.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("lstat64")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISLNK(get_mode(1)) && "lstat64 expected symlink");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  copy_stat(1, 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("  testing 'fstat64'\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* Use fopen() to steer clear of open()/close() variant issues. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert((fp = fopen(source_link, "r")) != NULL && "open of source failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_init(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  stat_err = fstat64(fileno(fp), &stat_buf.s64.s);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (check_err("fstat64")) return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  assert(S_ISREG(get_mode(1)) && "fstat64 expected regular file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  check_copy(1, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  (void) fclose(fp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MPLS_HAVE_STAT64 */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  printf("%s succeeded.\n", basename(argv[0]));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_stat.c_link b/test/test_stat.c_link
</span>new file mode 120000
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..c710dc0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_stat.c_link
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+test_stat.c
</span>\ No newline at end of file
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_stat_ino32.c b/test/test_stat_ino32.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..05206c3
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_stat_ino32.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,28 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Version of test_stat with 32-bit inodes (if possible).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * This only works on ppc/x86.  Later platforms (e.g. arm64) only
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * support 64-bit inodes.
</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;'>+#if !defined(__ppc__) && !defined(__ppc64__) \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    && !defined(__i386__) && !defined(__x86_64__)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <libgen.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdio.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+main(int argc, char *argv[])
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  (void) argc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  printf("%s is only supported on ppc/x86.\n", basename(argv[0]));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return 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;'>+#else /* ppc/x86 */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define _DARWIN_NO_64_BIT_INODE 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "test_stat.c"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* ppc/x86 */
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_stat_ino64.c b/test/test_stat_ino64.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..4757b7d
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_stat_ino64.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,10 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Version of test_stat with 64-bit inodes (if possible).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * This is primarily for 10.5, where 64-bit inodes are supported
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * but not the default.
</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;'>+#define _DARWIN_USE_64_BIT_INODE 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include "test_stat.c"
</span></pre><pre style='margin:0'>

</pre>