Thanks, could you please try the following patch? This is a gnulib patch, so it also fixes modules/fdopendir -- you needn't worry about that part of the patch, as it doesn't apply to coreutils. I'm CC'ing this possible patch to bug-gnulib to give the Gnulib people a heads-up.
By the way, do you happen to know why OS X doesn't yet support fdopendir? It's been in the standard for ages. Do the OSX maintainers plan to implement it eventually? ---- Break a recursive loop between fdopendir and save_cwd. Reported for OS X 10.8 by Assaf Gordon in <http://bugs.gnu.org/13516>. * lib/fdopendir.c [!HAVE_FDOPENDIR]: Don't include save-cwd.h. (fdopendir): Don't try to invoke getcwd via save_cwd, since it invokes us. Instead, merely open the working directory and return a failure indication if that fails. (fdopendir_with_dup): Second arg is now a fd (or -1), not a struct saved_cwd * (or 0). All uses changed. * modules/fdopendir (Depends-on): Remove save-cwd. diff --git a/lib/fdopendir.c b/lib/fdopendir.c index 63e06b9..25e984b 100644 --- a/lib/fdopendir.c +++ b/lib/fdopendir.c @@ -27,7 +27,6 @@ # include "openat.h" # include "openat-priv.h" -# include "save-cwd.h" # if GNULIB_DIRENT_SAFER # include "dirent--.h" @@ -37,15 +36,15 @@ # define REPLACE_FCHDIR 0 # endif -static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *); -static DIR *fd_clone_opendir (int, struct saved_cwd const *); +static DIR *fdopendir_with_dup (int, int, int); +static DIR *fd_clone_opendir (int, int); /* Replacement for POSIX fdopendir. First, try to simulate it via opendir ("/proc/self/fd/..."). Failing that, simulate it by using fchdir metadata, or by doing - save_cwd/fchdir/opendir(".")/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), + open(".")/fchdir/opendir(".")/fchdir. + If the final fchdir fails (relatively unlikely), then give a diagnostic and exit nonzero. If successful, the resulting stream is based on FD in @@ -65,19 +64,19 @@ static DIR *fd_clone_opendir (int, struct saved_cwd const *); DIR * fdopendir (int fd) { - DIR *dir = fdopendir_with_dup (fd, -1, NULL); + DIR *dir = fdopendir_with_dup (fd, -1, -1); if (! REPLACE_FCHDIR && ! dir) { int saved_errno = errno; if (EXPECTED_ERRNO (saved_errno)) { - struct saved_cwd cwd; - if (save_cwd (&cwd) != 0) - openat_save_fail (errno); - dir = fdopendir_with_dup (fd, -1, &cwd); + int cwd = open (".", O_SEARCH); + if (cwd < 0) + return 0; + dir = fdopendir_with_dup (fd, -1, cwd); saved_errno = errno; - free_cwd (&cwd); + close (cwd); errno = saved_errno; } } @@ -93,11 +92,11 @@ fdopendir (int fd) That way, barring race conditions, fd_clone_opendir returns a stream whose file descriptor is FD. - If REPLACE_CHDIR or CWD is null, use opendir ("/proc/self/fd/...", + If REPLACE_CHDIR or CWD < 0, use opendir ("/proc/self/fd/...", falling back on fchdir metadata. Otherwise, CWD is a saved version - of the working directory; use fchdir/opendir(".")/restore_cwd(CWD). */ + of the working directory; use fchdir/opendir(".")/fchdir(CWD). */ static DIR * -fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd) +fdopendir_with_dup (int fd, int older_dupfd, int cwd) { int dupfd = dup (fd); if (dupfd < 0 && errno == EMFILE) @@ -137,9 +136,9 @@ fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd) the caller's responsibility both to close FD and (if the result is not null) to closedir the result. */ static DIR * -fd_clone_opendir (int fd, struct saved_cwd const *cwd) +fd_clone_opendir (int fd, int cwd) { - if (REPLACE_FCHDIR || ! cwd) + if (REPLACE_FCHDIR || cwd < 0) { DIR *dir = NULL; int saved_errno = EOPNOTSUPP; @@ -170,7 +169,7 @@ fd_clone_opendir (int fd, struct saved_cwd const *cwd) { DIR *dir = opendir ("."); int saved_errno = errno; - if (restore_cwd (cwd) != 0) + if (fchdir (cwd) != 0) openat_restore_fail (errno); errno = saved_errno; return dir; diff --git a/modules/fdopendir b/modules/fdopendir index ee9a875..3d99472 100644 --- a/modules/fdopendir +++ b/modules/fdopendir @@ -15,7 +15,6 @@ fchdir [test $HAVE_FDOPENDIR = 0] fstat [test $HAVE_FDOPENDIR = 0] openat-die [test $HAVE_FDOPENDIR = 0] opendir [test $HAVE_FDOPENDIR = 0] -save-cwd [test $HAVE_FDOPENDIR = 0] configure.ac: gl_FUNC_FDOPENDIR