+/* Like fdopendir, except the result controls a clone of FD. It is
+ 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)
+{
+ if (REPLACE_FCHDIR || ! cwd)
+ {
+ DIR *dir = NULL;
+ int saved_errno = EOPNOTSUPP;
+ char buf[OPENAT_BUFFER_SIZE];
+ char *proc_file = openat_proc_name (buf, fd, ".");
+ if (proc_file)
+ {
+ dir = opendir (proc_file);
+ saved_errno = errno;
+ if (proc_file != buf)
+ free (proc_file);
+ }
+# if REPLACE_FCHDIR
+ if (! dir && EXPECTED_ERRNO (saved_errno))
+ {
+ char const *name = _gl_directory_name (fd);
+ DIR *dp = name ? opendir (name) : NULL;
+
+ /* The caller has done an elaborate dance to arrange for opendir to
+ consume just the right file descriptor. If dirfd returns -1,
+ though, we're on a system like mingw where opendir does not
+ consume a file descriptor. Consume it via 'dup' instead. */
+ if (dp && dirfd (dp) < 0)
+ dup (fd);
+
+ return dp;
+ }
+# endif
+ errno = saved_errno;
+ return dir;
+ }
+ else
+ {
+ if (fchdir (fd) != 0)
+ return NULL;
+ else
+ {
+ DIR *dir = opendir (".");
+ int saved_errno = errno;
+ if (restore_cwd (cwd) != 0)
+ openat_restore_fail (errno);
+ errno = saved_errno;
+ return dir;
+ }
+ }