<pre style='margin:0'>
Ken (kencu) pushed a commit to branch master
in repository macports-legacy-support.

</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/8889f27039e355c2ccadda0240ddd540302e382f">https://github.com/macports/macports-legacy-support/commit/8889f27039e355c2ccadda0240ddd540302e382f</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new 8889f27  Fix fdopendir so dirfd stays open until closedir (for fstatat etc)
</span>8889f27 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 8889f27039e355c2ccadda0240ddd540302e382f
</span>Author: raf <raf@raf.org>
AuthorDate: Tue Jul 18 00:35:32 2023 +1000

<span style='display:block; white-space:pre;color:#404040;'>    Fix fdopendir so dirfd stays open until closedir (for fstatat etc)
</span>---
 Makefile                 |   4 +-
 README.md                |   5 +-
 include/dirent.h         |  51 +++++++++++-
 src/best_fchdir.c        |   6 +-
 src/fdopendir.c          | 128 ++++++++++++++++++++---------
 test/test_fdopendir.c    |  26 ++++++
 test/test_fmemopen.c     |   4 +-
 test/test_traverse.c     | 184 ++++++++++++++++++++++++++++++++++++++++++
 test/test_traverse_cwd.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 566 insertions(+), 46 deletions(-)

<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 8d3e67a..a4cd05b 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;'>@@ -54,7 +54,7 @@ FORCE_ARCH      ?=
</span> ARCHFLAGS       ?=
 LIPO            ?= lipo
 CC              ?= cc $(ARCHFLAGS)
<span style='display:block; white-space:pre;background:#ffe0e0;'>-CFLAGS          ?= -Os -Wall
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+CFLAGS          ?= -Os -Wall -Wno-deprecated-declarations
</span> DLIBCFLAGS      ?= -fPIC
 SLIBCFLAGS      ?=
 CXX             ?= c++ $(ARCHFLAGS)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -84,7 +84,7 @@ FIND_LIBHEADERS := find $(SRCINCDIR) -type f \( -name '*.h' -o \
</span> LIBHEADERS      := $(shell $(FIND_LIBHEADERS))
 ALLHEADERS      := $(LIBHEADERS) $(wildcard $(SRCDIR)/*.h)
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-MULTISRCS       := $(SRCDIR)/fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+MULTISRCS       := # Used to have $(SRCDIR)/fdopendir.c because it used struct stat
</span> ADDSRCS         := $(SRCDIR)/add_symbols.c
 LIBSRCS         := $(filter-out $(MULTISRCS) $(ADDSRCS),$(wildcard $(SRCDIR)/*.c))
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/README.md b/README.md
</span><span style='display:block; white-space:pre;color:#808080;'>index d7dce54..e0c8c23 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/README.md
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/README.md
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -41,7 +41,10 @@ Wrapped headers and replaced functions are:
</span>   </tr>
   <tr>
     <td><code>dirent.h</code></td>
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    <td>Adds <code>fdopendir</code> function</td>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <td>Adds <code>fdopendir</code> function, and wraps <code>opendir</code>,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <code>readdir</code>, <code>readdir_r</code>, <code>rewinddir</code>,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <code>seekdir</code>, <code>telldir</code>, <code>dirfd</code>, and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    <code>closedir</code>, to support <code>fdopendir</code></td>
</span>     <td>OSX10.9</td>
   </tr>
   <tr>
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/dirent.h b/include/dirent.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 9e66955..983417b 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/dirent.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/dirent.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,6 +1,7 @@
</span> 
 /*
  * Copyright (c) 2019
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2023 raf <raf@raf.org>, Tavian Barnes <tavianator@tavianator.com>
</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;'>@@ -27,6 +28,14 @@
</span> /* fdopendir */
 #if __MP_LEGACY_SUPPORT_FDOPENDIR__
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Wrapper struct for DIR */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef struct __MP_LEGACY_SUPPORT_DIR __MP_LEGACY_SUPPORT_DIR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+struct __MP_LEGACY_SUPPORT_DIR {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    DIR *__mpls_dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int __mpls_dirfd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define DIR __MP_LEGACY_SUPPORT_DIR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> __MP__BEGIN_DECLS
 
 #ifndef __DARWIN_ALIAS_I
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -35,7 +44,47 @@ extern DIR *fdopendir(int fd) __DARWIN_ALIAS(fdopendir);
</span> extern DIR *fdopendir(int fd) __DARWIN_ALIAS_I(fdopendir);
 #endif
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-__MP__END_DECLS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Wrapper functions/macros to support fdopendir */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+extern DIR *__mpls_opendir(const char *name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+extern int __mpls_closedir(DIR *dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+extern int __mpls_dirfd(DIR *dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define opendir(name)      __mpls_opendir(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define closedir(dir)      __mpls_closedir(dir)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifndef __MP_LEGACY_SUPPORT_NO_DIRFD_MACRO
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#undef dirfd
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define dirfd(dir)         __mpls_dirfd(dir)
</span> #endif
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static inline struct dirent *__mpls_readdir(DIR *dir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return readdir(dir->__mpls_dir);
</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 inline int __mpls_readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return readdir_r(dir->__mpls_dir, entry, result);
</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 inline void __mpls_rewinddir(DIR *dir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    rewinddir(dir->__mpls_dir);
</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 inline void __mpls_seekdir(DIR *dir, long loc) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    seekdir(dir->__mpls_dir, loc);
</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 inline long __mpls_telldir(DIR *dir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return telldir(dir->__mpls_dir);
</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 readdir __mpls_readdir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define readdir_r __mpls_readdir_r
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define rewinddir __mpls_rewinddir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define seekdir __mpls_seekdir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define telldir __mpls_telldir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__MP__END_DECLS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MP_LEGACY_SUPPORT_FDOPENDIR__ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> #endif /* _MACPORTS_DIRENT_H_ */
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/best_fchdir.c b/src/best_fchdir.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 47417da..7ef41e7 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/best_fchdir.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/best_fchdir.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,5 +1,6 @@
</span> /*-
  * Copyright (c) 2019
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2023 raf <raf@raf.org>
</span>  *
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -30,7 +31,10 @@ int best_fchdir(int dirfd)
</span>   return syscall(SYS___pthread_fchdir, dirfd);
 #else
 /* Tiger does not have kernel support for __pthread_fchdir, so we have to fall back to fchdir */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-/* unless we can come up with a per-thread compatible implementation that works on Tiger */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* unless we can come up with a per-thread compatible implementation that works on Tiger. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Accept dirfd == -1 (which is meaningful for __pthread_fchdir) but do nothing with it. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (dirfd == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return 0;
</span>   return syscall(SYS_fchdir, dirfd);
 #endif
 }
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/fdopendir.c b/src/fdopendir.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 940f4ef..f6c7f46 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,6 +1,7 @@
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-/*-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span>  * Copyright (c) 2019
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2023 raf <raf@raf.org>, Tavian Barnes <tavianator@tavianator.com>
</span>  *
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -22,11 +23,15 @@
</span> 
 #include "common-priv.h"
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#define __MP_LEGACY_SUPPORT_NO_DIRFD_MACRO
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span> #include <dirent.h>
 #include <sys/errno.h>
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <sys/stat.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <unistd.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <fcntl.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#undef DIR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#undef opendir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#undef closedir
</span> 
 
 /*
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -34,62 +39,107 @@
</span>  *
  * https://www.freebsd.org/cgi/man.cgi?query=fdopendir&sektion=3
  * https://linux.die.net/man/3/fdopendir
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * On success, this function returns allocated memory that must be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * deallocated by __mpls_closedir() (see closedir() macro in <dirent.h>).
</span>  */
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-DIR *fdopendir(int dirfd) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    DIR *dir;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    struct stat st;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    int oldCWD = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+__MP_LEGACY_SUPPORT_DIR *fdopendir(int dirfd) {
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (fstat(dirfd, &st) < 0)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Check dirfd here (for macos-10.4, see _ATCALL() and best_fchdir()) */
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (!S_ISDIR(st.st_mode)) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        errno = ENOTDIR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (dirfd != AT_FDCWD && dirfd < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        errno = EBADF;
</span>         return 0;
     }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (dirfd == AT_FDCWD) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        dir = opendir (".");
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        /* dirfd can be closed only upon success */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (dir) PROTECT_ERRNO(close(dirfd));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        return dir;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Open the supplied directory safely */
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    oldCWD = open(".", O_RDONLY);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (oldCWD == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    DIR *dir = _ATCALL(dirfd, ".", NULL, opendir("."));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!dir)
</span>         return 0;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if(best_fchdir(dirfd) < 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (oldCWD != -1) PROTECT_ERRNO(close(oldCWD));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Wrap it and return it (with the supplied directory file descriptor) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    __MP_LEGACY_SUPPORT_DIR *mplsdir = malloc(sizeof(*mplsdir));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!mplsdir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)closedir(dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        errno = ENOMEM;
</span>         return 0;
     }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    dir = opendir (".");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    mplsdir->__mpls_dir = dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    mplsdir->__mpls_dirfd = dirfd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return mplsdir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (best_fchdir(oldCWD) < 0) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (dir) PROTECT_ERRNO(closedir(dir));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if (oldCWD != -1) PROTECT_ERRNO(close(oldCWD));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Wrapped version of opendir() for fdopendir() compatibility
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * On success, this function returns allocated memory that must be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * deallocated by __mpls_closedir() (see closedir() macro in <dirent.h>).
</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;'>+__MP_LEGACY_SUPPORT_DIR *__mpls_opendir(const char *name) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    DIR *dir = opendir(name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!dir)
</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;'>+    __MP_LEGACY_SUPPORT_DIR *mplsdir = malloc(sizeof(*mplsdir));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!mplsdir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)closedir(dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        errno = ENOMEM;
</span>         return 0;
     }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (oldCWD != -1)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        PROTECT_ERRNO(close(oldCWD));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    mplsdir->__mpls_dir = dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    mplsdir->__mpls_dirfd = -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return mplsdir;
</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;'>+ * Wrapped version of closedir() for fdopendir() compatibility (see
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * closedir() macro in <dirent.h>).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * This function deallocates memory that was allocated by fdopendir() or
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * __mpls_opendir().
</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 __mpls_closedir(__MP_LEGACY_SUPPORT_DIR *mplsdir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!mplsdir) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        errno = EBADF;
</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;'>+    int rc = closedir(mplsdir->__mpls_dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (mplsdir->__mpls_dirfd != AT_FDCWD && mplsdir->__mpls_dirfd != -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        PROTECT_ERRNO(close(mplsdir->__mpls_dirfd));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    free(mplsdir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return rc;
</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;'>+ * Wrapped version of dirfd() for fdopendir() compatibility because dirfd()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * itself is already a macro (see dirfd() macro in <dirent.h>).
</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 __mpls_dirfd(__MP_LEGACY_SUPPORT_DIR *mplsdir) {
</span> 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Return the supplied directory file descriptor if there was one */
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    /*
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     * FIXME -- this recently added bit makes the fdopendir tests fail on Tiger.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     * check the whole commit where it was added to make sure it is
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     * doing the proper thing on all systems. Probably need more extensive tests
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     * to execise the whole system more aggressively.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-     */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (mplsdir->__mpls_dirfd != AT_FDCWD && mplsdir->__mpls_dirfd != -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return mplsdir->__mpls_dirfd;
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    /* dirfd can be closed only upon success */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (dir && dirfd != -1) PROTECT_ERRNO(close(dirfd));
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Otherwise call the underlying dirfd() macro */
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    return dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return dirfd(mplsdir->__mpls_dir);
</span> }
 
 #endif /* __MP_LEGACY_SUPPORT_FDOPENDIR__ */
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_fdopendir.c b/test/test_fdopendir.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 0cdd856..a83d7e6 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/test_fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,6 +1,7 @@
</span> 
 /*
  * Copyright (c) 2019
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Copyright (c) 2023 raf <raf@raf.org>
</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;'>@@ -15,9 +16,11 @@
</span>  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span> #include <dirent.h>
 #include <sys/stat.h>
 #include <sys/types.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/errno.h>
</span> #include <unistd.h>
 #include <limits.h>
 #include <fcntl.h>
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -55,6 +58,29 @@ int main() {
</span>     }
 
     close(dfd);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Try to use fdopendir with stdin - Should fail with ENOTDIR */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((dir = fdopendir(STDIN_FILENO))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "fdopendir(stdin) should have failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)closedir(dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else if (errno != ENOTDIR) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("fdopendir(stdin) should have failed with ENOTDIR");
</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;'>+    /* Try to use fdopendir with -1 - Should fail with EBADF */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((dir = fdopendir(-1))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "fdopendir(-1) should have failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)closedir(dir);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else if (errno != EBADF) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("fdopendir(-1) should have failed with EBADF");
</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>     return 0;
 }
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_fmemopen.c b/test/test_fmemopen.c
</span><span style='display:block; white-space:pre;color:#808080;'>index f7be90a..081d0b9 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/test_fmemopen.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_fmemopen.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -108,10 +108,10 @@ test_autoalloc()
</span>      * Let fmemopen allocate the buffer.
      */
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    char str[] = "A quick test";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* char str[] = "A quick test"; */
</span>     FILE *fp;
     long pos;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    size_t nofw, nofr, i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    size_t nofw, i;
</span>     int rc;
 
     /* Open a FILE * using fmemopen. */
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_traverse.c b/test/test_traverse.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..6d94112
</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_traverse.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,184 @@
</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;'>+ * Copyright (c) 2023 raf <raf@raf.org>
</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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * SUCH DAMAGE.
</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 directory traversal with macports legacysupport.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This test creates ".test.dir", ".test.dir/subdir" and ".test.dir/subdir/file".
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+It then traverses the ".test.dir" directory.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+It then deletes ".test.dir" and its contents.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+The output should look something like:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  cwd (before traverse) /.../macports-legacy-support  
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fstatat(parent_fd=-2, .test.dir) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  openat(parent_fd=-2, .test.dir) = dir_fd=3 ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fdopendir(dir_fd=3) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  entry subdir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fstatat(parent_fd=3, subdir) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  openat(parent_fd=3, subdir) = dir_fd=4 ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fdopendir(dir_fd=4) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  entry file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fstatat(parent_fd=4, file) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  cwd (after traverse)  /.../macports-legacy-support
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This differs from test/test_traverse_cwd.c which
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+chdirs to the named directory and then traverses "."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+rather than a named directory. Originally, these
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+exhibited different errors.
</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;'>+#include <stdlib.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 <unistd.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 <errno.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <fcntl.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <dirent.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;'>+int traverse(int parent_fd, const char *name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Test: fstatat(AT_FDCWD, .test.dir) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct stat statbuf[1];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (fstatat(parent_fd, name, statbuf, AT_SYMLINK_NOFOLLOW) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "fstatat(parent_fd=%d, %s) failed: %s\n", parent_fd, name, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return EXIT_FAILURE;
</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;'>+    printf("fstatat(parent_fd=%d, %s) ok\n", parent_fd, name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* If it's a directory, process its entries */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((statbuf->st_mode & S_IFMT) == S_IFDIR)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Open it with openat() */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int dir_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if ((dir_fd = openat(parent_fd, name, O_RDONLY)) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            fprintf(stderr, "openat(parent_fd=%d, %s) failed: %s\n", parent_fd, name, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return EXIT_FAILURE;
</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;'>+        printf("openat(parent_fd=%d, %s) = dir_fd=%d ok\n", parent_fd, name, dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Open it for traversing with fdopendir() */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        DIR *dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (!(dir = fdopendir(dir_fd)))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            fprintf(stderr, "fdopendir(dir_fd=%d, .test.dir) failed\n", dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            close(dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return EXIT_FAILURE;
</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;'>+        printf("fdopendir(dir_fd=%d) ok\n", dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Apply recursively to this directory's entries */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        struct dirent *entry;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        while ((entry = readdir(dir)))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            printf("entry %s\n", entry->d_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (traverse(dir_fd, entry->d_name) == EXIT_FAILURE)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                return EXIT_FAILURE;
</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;'>+        closedir(dir);
</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;'>+    return EXIT_SUCCESS;
</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 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;'>+    /* Prepare: Create a directory */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    system("rm -rf .test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (mkdir(".test.dir", (mode_t)0755) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("mkdir(.test.dir) failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        exit(EXIT_FAILURE);
</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;'>+    /* And a directory within it */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (mkdir(".test.dir/subdir", (mode_t)0755) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("mkdir(.test.dir/subdir) failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir(".test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        exit(EXIT_FAILURE);
</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;'>+    /* And a file within that */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((fd = creat(".test.dir/subdir/file", (mode_t)0644)) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("creat(.test.dir/subdir/file) failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir(".test.dir/subdir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir(".test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        exit(EXIT_FAILURE);
</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(fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Test directory traversal */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char cwdbuf1[BUFSIZ];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf("cwd (before traverse) %s\n", getcwd(cwdbuf1, BUFSIZ));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int rc = traverse(AT_FDCWD, ".test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char cwdbuf2[BUFSIZ];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf("cwd (after traverse)  %s\n", getcwd(cwdbuf2, BUFSIZ));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (strcmp(cwdbuf1, cwdbuf2)) /* Originally, this happened on macos-10.4 */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "Directory has changed while traversing!\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        rc = EXIT_FAILURE;
</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;'>+    /* Cleanup */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (unlink(".test.dir/subdir/file") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("unlink .test.dir/subdir/file failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (rmdir(".test.dir/subdir") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("rmdir .test.dir/subdir failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (rmdir(".test.dir") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("rmdir .test.dir failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return rc;
</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;color:#808080;'>diff --git a/test/test_traverse_cwd.c b/test/test_traverse_cwd.c
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 0000000..8c01bb4
</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_traverse_cwd.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,204 @@
</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;'>+ * Copyright (c) 2023 raf <raf@raf.org>
</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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * SUCH DAMAGE.
</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 directory traversal with macports legacysupport.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This test creates ".test.dir", ".test.dir/subdir" and ".test.dir/subdir/file".
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+It then chdirs into ".test.dir" and then traverses ".".
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+It then chdirs to ".." afterwards.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+It then deletes ".test.dir" and its contents.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+The output should look something like:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fstatat(parent_fd=-2, .) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  openat(parent_fd=-2, .) = dir_fd=3 ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fdopendir(dir_fd=3) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  entry subdir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fstatat(parent_fd=3, subdir) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  openat(parent_fd=3, subdir) = dir_fd=4 ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fdopendir(dir_fd=4) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  entry file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  fstatat(parent_fd=4, file) ok
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  cwd (before cd ..) /Users/.../macports-legacy-support/.test.dir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  cwd (after cd ..)  /Users/.../macports-legacy-support
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This differs from test/test_traverse.c which traverses a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+named directory rather than ".". Originally, these
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+exhibited different errors.
</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;'>+#include <stdlib.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 <unistd.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 <errno.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <fcntl.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <dirent.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;'>+int traverse(int parent_fd, const char *name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Test: fstatat(AT_FDCWD, .test.dir) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    struct stat statbuf[1];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (fstatat(parent_fd, name, statbuf, AT_SYMLINK_NOFOLLOW) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "fstatat(parent_fd=%d, %s) failed: %s\n", parent_fd, name, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return EXIT_FAILURE;
</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;'>+    printf("fstatat(parent_fd=%d, %s) ok\n", parent_fd, name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* If it's a directory, process its entries */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((statbuf->st_mode & S_IFMT) == S_IFDIR)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Open it with openat() */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        int dir_fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if ((dir_fd = openat(parent_fd, name, O_RDONLY)) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            fprintf(stderr, "openat(parent_fd=%d, %s) failed: %s\n", parent_fd, name, strerror(errno));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return EXIT_FAILURE;
</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;'>+        printf("openat(parent_fd=%d, %s) = dir_fd=%d ok\n", parent_fd, name, dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Open it for traversing with fdopendir() */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        DIR *dir;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (!(dir = fdopendir(dir_fd)))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            fprintf(stderr, "fdopendir(dir_fd=%d, dir) failed\n", dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            close(dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            return EXIT_FAILURE;
</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;'>+        printf("fdopendir(dir_fd=%d) ok\n", dir_fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Apply recursively to this directory's entries */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        struct dirent *entry;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        while ((entry = readdir(dir)))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            printf("entry %s\n", entry->d_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (traverse(dir_fd, entry->d_name) == EXIT_FAILURE)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                return EXIT_FAILURE;
</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;'>+        closedir(dir);
</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;'>+    return EXIT_SUCCESS;
</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 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;'>+    /* Prepare: Create a directory */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    system("rm -rf .test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (mkdir(".test.dir", (mode_t)0755) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("mkdir(.test.dir) failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        exit(EXIT_FAILURE);
</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;'>+    /* And a directory within it */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (mkdir(".test.dir/subdir", (mode_t)0755) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("mkdir(.test.dir/subdir) failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir(".test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        exit(EXIT_FAILURE);
</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;'>+    /* And a file within that */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int fd;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if ((fd = creat(".test.dir/subdir/file", (mode_t)0644)) == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("creat(.test.dir/subdir/file) failed\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir(".test.dir/subdir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir(".test.dir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        exit(EXIT_FAILURE);
</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(fd);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* Test directory traversal */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    fprintf(stderr, "cd .test.dir\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (chdir(".test.dir") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("chdir(.test.dir) failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int rc = traverse(AT_FDCWD, ".");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char cwdbuf1[BUFSIZ];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    char cwdbuf2[BUFSIZ];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf("cwd (before cd ..) %s\n", getcwd(cwdbuf1, BUFSIZ));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (chdir("..") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("chdir .. failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    printf("cwd (after cd ..)  %s\n", getcwd(cwdbuf2, BUFSIZ));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!strcmp(cwdbuf1, cwdbuf2))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "Post-traversal chdir(..) silently failed to change directory!\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "Replacing best_fchdir() in fdopendir() with fchdir() fixes this badly.\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "Using _ATCALL for opendir fixes this properly.\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        rc = EXIT_FAILURE;
</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;'>+    /* Cleanup */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (unlink(".test.dir/subdir/file") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("unlink .test.dir/subdir/file failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (rmdir(".test.dir/subdir") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("rmdir .test.dir/subdir failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (rmdir(".test.dir") == -1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        perror("rmdir .test.dir failed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    /* If the above cleanup didn't work (because chdir .. silently failed to work) */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (!strcmp(cwdbuf1, cwdbuf2))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        fprintf(stderr, "Cleaning up\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)unlink("../.test.dir/subdir/file");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir("../.test.dir/subdir");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        (void)rmdir("../.test.dir");
</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;'>+    return rc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span></pre><pre style='margin:0'>

</pre>