summaryrefslogtreecommitdiff
path: root/cross/lib/fdopendir.c
diff options
context:
space:
mode:
Diffstat (limited to 'cross/lib/fdopendir.c')
-rw-r--r--cross/lib/fdopendir.c249
1 files changed, 0 insertions, 249 deletions
diff --git a/cross/lib/fdopendir.c b/cross/lib/fdopendir.c
deleted file mode 100644
index aa841e3e819..00000000000
--- a/cross/lib/fdopendir.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/* provide a replacement fdopendir function
- Copyright (C) 2004-2023 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
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- 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 <https://www.gnu.org/licenses/>. */
-
-/* written by Jim Meyering */
-
-#include <config.h>
-
-#include <dirent.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#if !HAVE_FDOPENDIR
-
-# include "openat.h"
-# include "openat-priv.h"
-# include "save-cwd.h"
-
-# if GNULIB_DIRENT_SAFER
-# include "dirent--.h"
-# endif
-
-# ifndef REPLACE_FCHDIR
-# 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 *);
-
-/* 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),
- then give a diagnostic and exit nonzero.
-
- If successful, the resulting stream is based on FD in
- implementations where streams are based on file descriptors and in
- applications where no other thread or signal handler allocates or
- frees file descriptors. In other cases, consult dirfd on the result
- to find out whether FD is still being used.
-
- Otherwise, this function works just like POSIX fdopendir.
-
- W A R N I N G:
-
- Unlike other fd-related functions, this one places constraints on FD.
- 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)
-{
- DIR *dir = fdopendir_with_dup (fd, -1, NULL);
-
- 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);
- saved_errno = errno;
- free_cwd (&cwd);
- errno = saved_errno;
- }
- }
-
- 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
- closed by the caller and not otherwise used by the caller. This
- function makes sure that FD is closed and all file descriptors less
- than FD are open, and then calls fd_clone_opendir on a dup of FD.
- That way, barring race conditions, fd_clone_opendir returns a
- stream whose file descriptor is 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 *
-fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd)
-{
- int dupfd = dup (fd);
- if (dupfd < 0 && errno == EMFILE)
- dupfd = older_dupfd;
- if (dupfd < 0)
- return NULL;
- else
- {
- DIR *dir;
- int saved_errno;
- if (dupfd < fd - 1 && dupfd != older_dupfd)
- {
- dir = fdopendir_with_dup (fd, dupfd, cwd);
- saved_errno = errno;
- }
- else
- {
- close (fd);
- dir = fd_clone_opendir (dupfd, cwd);
- saved_errno = errno;
- if (! dir)
- {
- int fd1 = dup (dupfd);
- if (fd1 != fd)
- openat_save_fail (fd1 < 0 ? errno : EBADF);
- }
- }
-
- if (dupfd != older_dupfd)
- close (dupfd);
- errno = saved_errno;
- return dir;
- }
-}
-
-/* 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;
- }
- }
-}
-
-#else /* HAVE_FDOPENDIR */
-
-# include <errno.h>
-# include <sys/stat.h>
-
-# undef fdopendir
-
-/* Like fdopendir, but work around GNU/Hurd bug by validating FD. */
-
-DIR *
-rpl_fdopendir (int fd)
-{
- struct stat st;
- if (fstat (fd, &st))
- return NULL;
- if (!S_ISDIR (st.st_mode))
- {
- errno = ENOTDIR;
- return NULL;
- }
- return fdopendir (fd);
-}
-
-#endif /* HAVE_FDOPENDIR */