/* provide a replacement fdopendir function
- Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* written by Jim Meyering */
If this function returns successfully, FD is under control of the
dirent.h system, and the caller should not close or modify the state of
FD other than by the dirent.h functions. */
+# ifdef __KLIBC__
+# include <InnoTekLIBC/backend.h>
+
+DIR *
+fdopendir (int fd)
+{
+ char path[_MAX_PATH];
+ DIR *dirp;
+
+ /* Get a path from fd */
+ if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
+ return NULL;
+
+ dirp = opendir (path);
+ if (!dirp)
+ return NULL;
+
+ /* Unregister fd registered by opendir() */
+ _gl_unregister_dirp_fd (dirfd (dirp));
+
+ /* Register our fd */
+ if (_gl_register_dirp_fd (fd, dirp))
+ {
+ int saved_errno = errno;
+
+ closedir (dirp);
+
+ errno = saved_errno;
+
+ dirp = NULL;
+ }
+
+ return dirp;
+}
+# else
DIR *
fdopendir (int fd)
{
return dir;
}
+# endif
/* Like fdopendir, except that if OLDER_DUPFD is not -1, it is known
to be a dup of FD which is less than FD - 1 and which will be
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_FCHDIR or CWD is null, 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). */
static DIR *
if (! dir && EXPECTED_ERRNO (saved_errno))
{
char const *name = _gl_directory_name (fd);
- return (name ? opendir (name) : NULL);
+ 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;