mirror of
https://https.git.savannah.gnu.org/git/gnulib.git
synced 2026-09-01 02:34:55 +00:00
fdopendir: Fix fd leak and test failure on native Windows.
* lib/dirent-private.h: On mingw, define 'struct gl_directory' as a wrapper around the original DIR. On MSVC, add an 'fd_to_close' field to 'struct gl_directory'. * lib/dirent.in.h (DIR): Define when DIR_HAS_FD_MEMBER is 0, i.e. on both mingw and MSVC. (GNULIB_defined_DIR): New macro. (opendir): Avoid incompatible redeclaration. (readdir): Consider REPLACE_READDIR. (rewinddir): Consider REPLACE_REWINDDIR. * m4/dirent_h.m4 (gl_DIRENT_DIR): New macro. (gl_DIRENT_H): Invoke it. (gl_DIRENT_H_DEFAULTS): Initialize REPLACE_READDIR, REPLACE_REWINDDIR. * modules/dirent (Makefile.am): Substitute DIR_HAS_FD_MEMBER, REPLACE_READDIR, REPLACE_REWINDDIR. -- * lib/dirfd.c (dirfd): If GNULIB_defined_DIR, just use the 'fd_to_close' field. * m4/dirfd.m4 (gl_FUNC_DIRFD): Set HAVE_DIRFD. Don't set REPLACE_DIRFD to 1 if HAVE_DIRFD is 0. If DIR_HAS_FD_MEMBER is 0, ensure dirfd.c gets compiled. * modules/dirfd (Files): Add lib/dirent-private.h. (Depends-on, configure.ac): Simplify conditions. -- * lib/closedir.c: Include <stdlib.h> always, for free(). (closedir): If GNULIB_defined_DIR, arrange to call close(dirfd(dirp)) at the end. On mingw, call free() of dirp. Prefer testing HAVE_DIRENT_H, for consistency with dirent.h. * m4/closedir.m4 (gl_FUNC_CLOSEDIR): Don't set REPLACE_CLOSEDIR to 1 if HAVE_CLOSEDIR is 0. If DIR_HAS_FD_MEMBER is 0, ensure closedir.c gets compiled. -- * lib/opendir.c: Include <stdlib.h> always. Include <string.h>. (opendir): On mingw, allocate the 'struct gl_directory' through malloc. If GNULIB_defined_DIR, set the 'fd_to_close' field to -1. Prefer testing HAVE_DIRENT_H, for consistency with dirent.h. * m4/opendir.m4 (gl_FUNC_OPENDIR): Don't set REPLACE_OPENDIR to 1 if HAVE_OPENDIR is 0. If DIR_HAS_FD_MEMBER is 0, ensure opendir.c gets compiled. -- * lib/fdopendir.c (fdopendir): If GNULIB_defined_DIR, use a simple implementation based on opendir and the fchdir module. If __KLIBC__, don't define unused auxiliary functions. * modules/fdopendir (Files): Add lib/dirent-private.h. -- * lib/readdir.c (readdir): On mingw, redirect to the original readdir function. Prefer testing HAVE_DIRENT_H, for consistency with dirent.h. * m4/readdir.m4 (gl_FUNC_READDIR): If DIR_HAS_FD_MEMBER is 0, ensure readdir.c gets compiled. * modules/readdir (configure.ac): Consider REPLACE_READDIR. -- * lib/rewinddir.c (rewinddir): On mingw, redirect to the original rewinddir function. Prefer testing HAVE_DIRENT_H, for consistency with dirent.h. * m4/rewinddir.m4 (gl_FUNC_REWINDDIR): If DIR_HAS_FD_MEMBER is 0, ensure rewinddir.c gets compiled. * modules/rewinddir (configure.ac): Consider REPLACE_REWINDDIR. -- * lib/fchdir.c (dir_info_t): Remove a FIXME.
This commit is contained in:
@@ -1,3 +1,66 @@
|
||||
2023-04-26 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
fdopendir: Fix fd leak and test failure on native Windows.
|
||||
--
|
||||
* lib/dirent-private.h: On mingw, define 'struct gl_directory' as a
|
||||
wrapper around the original DIR. On MSVC, add an 'fd_to_close' field to
|
||||
'struct gl_directory'.
|
||||
* lib/dirent.in.h (DIR): Define when DIR_HAS_FD_MEMBER is 0, i.e. on
|
||||
both mingw and MSVC.
|
||||
(GNULIB_defined_DIR): New macro.
|
||||
(opendir): Avoid incompatible redeclaration.
|
||||
(readdir): Consider REPLACE_READDIR.
|
||||
(rewinddir): Consider REPLACE_REWINDDIR.
|
||||
* m4/dirent_h.m4 (gl_DIRENT_DIR): New macro.
|
||||
(gl_DIRENT_H): Invoke it.
|
||||
(gl_DIRENT_H_DEFAULTS): Initialize REPLACE_READDIR, REPLACE_REWINDDIR.
|
||||
* modules/dirent (Makefile.am): Substitute DIR_HAS_FD_MEMBER,
|
||||
REPLACE_READDIR, REPLACE_REWINDDIR.
|
||||
--
|
||||
* lib/dirfd.c (dirfd): If GNULIB_defined_DIR, just use the
|
||||
'fd_to_close' field.
|
||||
* m4/dirfd.m4 (gl_FUNC_DIRFD): Set HAVE_DIRFD. Don't set REPLACE_DIRFD
|
||||
to 1 if HAVE_DIRFD is 0. If DIR_HAS_FD_MEMBER is 0, ensure dirfd.c gets
|
||||
compiled.
|
||||
* modules/dirfd (Files): Add lib/dirent-private.h.
|
||||
(Depends-on, configure.ac): Simplify conditions.
|
||||
--
|
||||
* lib/closedir.c: Include <stdlib.h> always, for free().
|
||||
(closedir): If GNULIB_defined_DIR, arrange to call close(dirfd(dirp)) at
|
||||
the end. On mingw, call free() of dirp. Prefer testing HAVE_DIRENT_H,
|
||||
for consistency with dirent.h.
|
||||
* m4/closedir.m4 (gl_FUNC_CLOSEDIR): Don't set REPLACE_CLOSEDIR to 1 if
|
||||
HAVE_CLOSEDIR is 0. If DIR_HAS_FD_MEMBER is 0, ensure closedir.c gets
|
||||
compiled.
|
||||
--
|
||||
* lib/opendir.c: Include <stdlib.h> always. Include <string.h>.
|
||||
(opendir): On mingw, allocate the 'struct gl_directory' through malloc.
|
||||
If GNULIB_defined_DIR, set the 'fd_to_close' field to -1. Prefer
|
||||
testing HAVE_DIRENT_H, for consistency with dirent.h.
|
||||
* m4/opendir.m4 (gl_FUNC_OPENDIR): Don't set REPLACE_OPENDIR to 1 if
|
||||
HAVE_OPENDIR is 0. If DIR_HAS_FD_MEMBER is 0, ensure opendir.c gets
|
||||
compiled.
|
||||
--
|
||||
* lib/fdopendir.c (fdopendir): If GNULIB_defined_DIR, use a simple
|
||||
implementation based on opendir and the fchdir module. If __KLIBC__,
|
||||
don't define unused auxiliary functions.
|
||||
* modules/fdopendir (Files): Add lib/dirent-private.h.
|
||||
--
|
||||
* lib/readdir.c (readdir): On mingw, redirect to the original readdir
|
||||
function. Prefer testing HAVE_DIRENT_H, for consistency with dirent.h.
|
||||
* m4/readdir.m4 (gl_FUNC_READDIR): If DIR_HAS_FD_MEMBER is 0, ensure
|
||||
readdir.c gets compiled.
|
||||
* modules/readdir (configure.ac): Consider REPLACE_READDIR.
|
||||
--
|
||||
* lib/rewinddir.c (rewinddir): On mingw, redirect to the original
|
||||
rewinddir function. Prefer testing HAVE_DIRENT_H, for consistency with
|
||||
dirent.h.
|
||||
* m4/rewinddir.m4 (gl_FUNC_REWINDDIR): If DIR_HAS_FD_MEMBER is 0, ensure
|
||||
rewinddir.c gets compiled.
|
||||
* modules/rewinddir (configure.ac): Consider REPLACE_REWINDDIR.
|
||||
--
|
||||
* lib/fchdir.c (dir_info_t): Remove a FIXME.
|
||||
|
||||
2023-04-26 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
fchdir tests: Fix test failure on native Windows.
|
||||
|
||||
+19
-9
@@ -23,31 +23,37 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if HAVE_CLOSEDIR
|
||||
|
||||
/* Override closedir(), to keep track of the open file descriptors.
|
||||
Needed because there is a function dirfd(). */
|
||||
|
||||
#else
|
||||
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if GNULIB_defined_DIR
|
||||
# include "dirent-private.h"
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
closedir (DIR *dirp)
|
||||
#undef closedir
|
||||
{
|
||||
# if REPLACE_FCHDIR || REPLACE_DIRFD
|
||||
#if GNULIB_defined_DIR || REPLACE_FCHDIR || defined __KLIBC__
|
||||
int fd = dirfd (dirp);
|
||||
# endif
|
||||
#endif
|
||||
int retval;
|
||||
|
||||
#if HAVE_CLOSEDIR
|
||||
# undef closedir
|
||||
#if HAVE_DIRENT_H /* equivalent to HAVE_CLOSEDIR */
|
||||
|
||||
# if GNULIB_defined_DIR
|
||||
retval = closedir (dirp->real_dirp);
|
||||
if (retval >= 0)
|
||||
free (dirp);
|
||||
# else
|
||||
retval = closedir (dirp);
|
||||
# endif
|
||||
|
||||
# ifdef __KLIBC__
|
||||
if (!retval)
|
||||
@@ -63,9 +69,13 @@ closedir (DIR *dirp)
|
||||
|
||||
#endif
|
||||
|
||||
#if REPLACE_FCHDIR
|
||||
#if GNULIB_defined_DIR
|
||||
if (retval >= 0)
|
||||
close (fd);
|
||||
#elif REPLACE_FCHDIR
|
||||
if (retval >= 0)
|
||||
_gl_unregister_fd (fd);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
+28
-5
@@ -17,15 +17,36 @@
|
||||
#ifndef _DIRENT_PRIVATE_H
|
||||
#define _DIRENT_PRIVATE_H 1
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#if HAVE_DIRENT_H /* mingw */
|
||||
|
||||
/* Don't assume that UNICODE is not defined. */
|
||||
#undef WIN32_FIND_DATA
|
||||
#define WIN32_FIND_DATA WIN32_FIND_DATAA
|
||||
# undef DIR
|
||||
|
||||
struct gl_directory
|
||||
{
|
||||
/* File descriptor to close during closedir().
|
||||
Needed for implementing fdopendir(). */
|
||||
int fd_to_close;
|
||||
/* Pointer to the real DIR. */
|
||||
DIR *real_dirp;
|
||||
};
|
||||
|
||||
/* Restore definition from dirent.h. */
|
||||
# define DIR struct gl_directory
|
||||
|
||||
#else /* MSVC */
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
|
||||
/* Don't assume that UNICODE is not defined. */
|
||||
# undef WIN32_FIND_DATA
|
||||
# define WIN32_FIND_DATA WIN32_FIND_DATAA
|
||||
|
||||
struct gl_directory
|
||||
{
|
||||
/* File descriptor to close during closedir().
|
||||
Needed for implementing fdopendir(). */
|
||||
int fd_to_close;
|
||||
/* Status, or error code to produce in next readdir() call.
|
||||
-2 means the end of the directory is already reached,
|
||||
-1 means the entry was already filled by FindFirstFile,
|
||||
@@ -41,4 +62,6 @@ struct gl_directory
|
||||
char dir_name_mask[1];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _DIRENT_PRIVATE_H */
|
||||
|
||||
+37
-6
@@ -56,11 +56,24 @@ struct dirent
|
||||
# define DT_LNK 10 /* symbolic link */
|
||||
# define DT_SOCK 12 /* socket */
|
||||
# define DT_WHT 14 /* whiteout */
|
||||
typedef struct gl_directory DIR;
|
||||
# define GNULIB_defined_struct_dirent 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !@DIR_HAS_FD_MEMBER@
|
||||
# if !GNULIB_defined_DIR
|
||||
/* struct gl_directory is a type with a field 'int fd_to_close'.
|
||||
It is needed for implementing fdopendir(). */
|
||||
struct gl_directory;
|
||||
# if @HAVE_DIRENT_H@
|
||||
# define DIR struct gl_directory
|
||||
# else
|
||||
typedef struct gl_directory DIR;
|
||||
# endif
|
||||
# define GNULIB_defined_DIR 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
|
||||
that can be freed by passing them as the Ith argument to the
|
||||
function F. */
|
||||
@@ -149,7 +162,7 @@ _GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (opendir);
|
||||
#else
|
||||
# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined opendir
|
||||
# if @GNULIB_CLOSEDIR@ && !GNULIB_defined_DIR && __GNUC__ >= 11 && !defined opendir
|
||||
/* For -Wmismatched-dealloc: Associate opendir with closedir or
|
||||
rpl_closedir. */
|
||||
_GL_FUNCDECL_SYS (opendir, DIR *,
|
||||
@@ -167,10 +180,19 @@ _GL_WARN_ON_USE (opendir, "opendir is not portable - "
|
||||
#endif
|
||||
|
||||
#if @GNULIB_READDIR@
|
||||
# if !@HAVE_READDIR@
|
||||
# if @REPLACE_READDIR@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef readdir
|
||||
# define readdir rpl_readdir
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1)));
|
||||
_GL_CXXALIAS_RPL (readdir, struct dirent *, (DIR *dirp));
|
||||
# else
|
||||
# if !@HAVE_READDIR@
|
||||
_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1)));
|
||||
# endif
|
||||
# endif
|
||||
_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (readdir);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
# undef readdir
|
||||
@@ -181,10 +203,19 @@ _GL_WARN_ON_USE (readdir, "readdir is not portable - "
|
||||
#endif
|
||||
|
||||
#if @GNULIB_REWINDDIR@
|
||||
# if !@HAVE_REWINDDIR@
|
||||
# if @REPLACE_REWINDDIR@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef rewinddir
|
||||
# define rewinddir rpl_rewinddir
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1)));
|
||||
_GL_CXXALIAS_RPL (rewinddir, void, (DIR *dirp));
|
||||
# else
|
||||
# if !@HAVE_REWINDDIR@
|
||||
_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1)));
|
||||
# endif
|
||||
# endif
|
||||
_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (rewinddir);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
# undef rewinddir
|
||||
|
||||
+14
-3
@@ -22,6 +22,10 @@
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if GNULIB_defined_DIR
|
||||
# include "dirent-private.h"
|
||||
#endif
|
||||
|
||||
#ifdef __KLIBC__
|
||||
# include <stdlib.h>
|
||||
# include <io.h>
|
||||
@@ -78,11 +82,17 @@ _gl_unregister_dirp_fd (int fd)
|
||||
int
|
||||
dirfd (DIR *dir_p)
|
||||
{
|
||||
#if GNULIB_defined_DIR
|
||||
int fd = dir_p->fd_to_close;
|
||||
if (fd == -1)
|
||||
errno = EINVAL;
|
||||
return fd;
|
||||
#else
|
||||
int fd = DIR_TO_FD (dir_p);
|
||||
if (fd == -1)
|
||||
#ifndef __KLIBC__
|
||||
# ifndef __KLIBC__
|
||||
errno = ENOTSUP;
|
||||
#else
|
||||
# else
|
||||
{
|
||||
struct dirp_fd_list *dirp_fd;
|
||||
|
||||
@@ -92,7 +102,8 @@ dirfd (DIR *dir_p)
|
||||
|
||||
errno = EINVAL;
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
return fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
typedef struct
|
||||
{
|
||||
char *name; /* Absolute name of the directory, or NULL. */
|
||||
/* FIXME - add a DIR* member to make dirfd possible on mingw? */
|
||||
} dir_info_t;
|
||||
static dir_info_t *dirs;
|
||||
static size_t dirs_allocated;
|
||||
|
||||
+61
-36
@@ -25,44 +25,27 @@
|
||||
|
||||
#if !HAVE_FDOPENDIR
|
||||
|
||||
# include "openat.h"
|
||||
# include "openat-priv.h"
|
||||
# include "save-cwd.h"
|
||||
# if GNULIB_defined_DIR
|
||||
/* We are in control of the file descriptor of a DIR. */
|
||||
|
||||
# if GNULIB_DIRENT_SAFER
|
||||
# include "dirent--.h"
|
||||
# endif
|
||||
# include "dirent-private.h"
|
||||
|
||||
# ifndef REPLACE_FCHDIR
|
||||
# define REPLACE_FCHDIR 0
|
||||
# endif
|
||||
# if !REPLACE_FCHDIR
|
||||
# error "unexpected configuration: GNULIB_defined_DIR but fchdir not replaced"
|
||||
# endif
|
||||
|
||||
static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *);
|
||||
static DIR *fd_clone_opendir (int, struct saved_cwd const *);
|
||||
DIR *
|
||||
fdopendir (int fd)
|
||||
{
|
||||
char const *name = _gl_directory_name (fd);
|
||||
DIR *dirp = name ? opendir (name) : NULL;
|
||||
if (dirp != NULL)
|
||||
dirp->fd_to_close = fd;
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/* Replacement for POSIX fdopendir.
|
||||
# elif defined __KLIBC__
|
||||
|
||||
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 *
|
||||
@@ -96,7 +79,48 @@ fdopendir (int fd)
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
# else
|
||||
/* We are not in control of the file descriptor of a DIR, and therefore have to
|
||||
play tricks with file descriptors before and after a call to opendir(). */
|
||||
|
||||
# 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. */
|
||||
DIR *
|
||||
fdopendir (int fd)
|
||||
{
|
||||
@@ -119,7 +143,6 @@ 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
|
||||
@@ -188,7 +211,7 @@ fd_clone_opendir (int fd, struct saved_cwd const *cwd)
|
||||
if (proc_file != buf)
|
||||
free (proc_file);
|
||||
}
|
||||
# if REPLACE_FCHDIR
|
||||
# if REPLACE_FCHDIR
|
||||
if (! dir && EXPECTED_ERRNO (saved_errno))
|
||||
{
|
||||
char const *name = _gl_directory_name (fd);
|
||||
@@ -203,7 +226,7 @@ fd_clone_opendir (int fd, struct saved_cwd const *cwd)
|
||||
|
||||
return dp;
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
errno = saved_errno;
|
||||
return dir;
|
||||
}
|
||||
@@ -223,6 +246,8 @@ fd_clone_opendir (int fd, struct saved_cwd const *cwd)
|
||||
}
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#else /* HAVE_FDOPENDIR */
|
||||
|
||||
# include <errno.h>
|
||||
|
||||
+34
-5
@@ -29,13 +29,17 @@
|
||||
|
||||
#else
|
||||
|
||||
# include <stdlib.h>
|
||||
|
||||
# include "dirent-private.h"
|
||||
# include "filename.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if GNULIB_defined_DIR
|
||||
# include "dirent-private.h"
|
||||
#endif
|
||||
|
||||
#if REPLACE_FCHDIR
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
@@ -57,14 +61,37 @@
|
||||
|
||||
DIR *
|
||||
opendir (const char *dir_name)
|
||||
#undef opendir
|
||||
{
|
||||
#if HAVE_OPENDIR
|
||||
# undef opendir
|
||||
#if HAVE_DIRENT_H /* equivalent to HAVE_OPENDIR */
|
||||
DIR *dirp;
|
||||
|
||||
# if GNULIB_defined_DIR
|
||||
# undef DIR
|
||||
|
||||
dirp = (struct gl_directory *) malloc (sizeof (struct gl_directory));
|
||||
if (dirp == NULL)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DIR *real_dirp = opendir (dir_name);
|
||||
if (real_dirp == NULL)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
free (dirp);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dirp->fd_to_close = -1;
|
||||
dirp->real_dirp = real_dirp;
|
||||
# else
|
||||
dirp = opendir (dir_name);
|
||||
if (dirp == NULL)
|
||||
return NULL;
|
||||
# endif
|
||||
|
||||
# ifdef __KLIBC__
|
||||
{
|
||||
@@ -82,6 +109,7 @@ opendir (const char *dir_name)
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
char dir_name_mask[MAX_PATH + 1 + 1 + 1];
|
||||
@@ -154,6 +182,7 @@ opendir (const char *dir_name)
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
dirp->fd_to_close = -1;
|
||||
dirp->status = status;
|
||||
dirp->current = current;
|
||||
if (status == -1)
|
||||
|
||||
+8
-1
@@ -22,7 +22,9 @@
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dirent-private.h"
|
||||
#if GNULIB_defined_DIR
|
||||
# include "dirent-private.h"
|
||||
#endif
|
||||
|
||||
/* Don't assume that UNICODE is not defined. */
|
||||
#undef FindNextFile
|
||||
@@ -30,7 +32,11 @@
|
||||
|
||||
struct dirent *
|
||||
readdir (DIR *dirp)
|
||||
#undef readdir
|
||||
{
|
||||
#if HAVE_DIRENT_H /* equivalent to HAVE_READDIR */
|
||||
return readdir (dirp->real_dirp);
|
||||
#else
|
||||
char type;
|
||||
struct dirent *result;
|
||||
|
||||
@@ -99,4 +105,5 @@ readdir (DIR *dirp)
|
||||
result->d_type = type;
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
+8
-1
@@ -21,7 +21,9 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "dirent-private.h"
|
||||
#if GNULIB_defined_DIR
|
||||
# include "dirent-private.h"
|
||||
#endif
|
||||
|
||||
/* Don't assume that UNICODE is not defined. */
|
||||
#undef FindFirstFile
|
||||
@@ -29,7 +31,11 @@
|
||||
|
||||
void
|
||||
rewinddir (DIR *dirp)
|
||||
#undef rewinddir
|
||||
{
|
||||
#if HAVE_DIRENT_H /* equivalent to HAVE_REWINDDIR */
|
||||
rewinddir (dirp->real_dirp);
|
||||
#else
|
||||
/* Like in closedir(). */
|
||||
if (dirp->current != INVALID_HANDLE_VALUE)
|
||||
FindClose (dirp->current);
|
||||
@@ -50,4 +56,5 @@ rewinddir (DIR *dirp)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+18
-15
@@ -1,4 +1,4 @@
|
||||
# closedir.m4 serial 6
|
||||
# closedir.m4 serial 7
|
||||
dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -12,20 +12,23 @@ AC_DEFUN([gl_FUNC_CLOSEDIR],
|
||||
AC_CHECK_FUNCS([closedir])
|
||||
if test $ac_cv_func_closedir = no; then
|
||||
HAVE_CLOSEDIR=0
|
||||
fi
|
||||
dnl Replace closedir() for supporting the gnulib-defined fchdir() function,
|
||||
dnl to keep fchdir's bookkeeping up-to-date.
|
||||
m4_ifdef([gl_FUNC_FCHDIR], [
|
||||
gl_TEST_FCHDIR
|
||||
if test $HAVE_FCHDIR = 0; then
|
||||
if test $HAVE_CLOSEDIR = 1; then
|
||||
else
|
||||
dnl Replace closedir() on native Windows, to support fdopendir().
|
||||
AC_REQUIRE([gl_DIRENT_DIR])
|
||||
if test $DIR_HAS_FD_MEMBER = 0; then
|
||||
REPLACE_CLOSEDIR=1
|
||||
fi
|
||||
dnl Replace closedir() for supporting the gnulib-defined dirfd() function.
|
||||
case $host_os in
|
||||
os2*) REPLACE_CLOSEDIR=1 ;;
|
||||
esac
|
||||
dnl Replace closedir() for supporting the gnulib-defined fchdir() function,
|
||||
dnl to keep fchdir's bookkeeping up-to-date.
|
||||
m4_ifdef([gl_FUNC_FCHDIR], [
|
||||
gl_TEST_FCHDIR
|
||||
if test $HAVE_FCHDIR = 0; then
|
||||
REPLACE_CLOSEDIR=1
|
||||
fi
|
||||
fi
|
||||
])
|
||||
dnl Replace closedir() for supporting the gnulib-defined dirfd() function.
|
||||
case $host_os,$HAVE_CLOSEDIR in
|
||||
os2*,1)
|
||||
REPLACE_CLOSEDIR=1;;
|
||||
esac
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
||||
+20
-1
@@ -1,4 +1,4 @@
|
||||
# dirent_h.m4 serial 19
|
||||
# dirent_h.m4 serial 20
|
||||
dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -21,12 +21,29 @@ AC_DEFUN_ONCE([gl_DIRENT_H],
|
||||
fi
|
||||
AC_SUBST([HAVE_DIRENT_H])
|
||||
|
||||
gl_DIRENT_DIR
|
||||
|
||||
dnl Check for declarations of anything we want to poison if the
|
||||
dnl corresponding gnulib module is not in use.
|
||||
gl_WARN_ON_USE_PREPARE([[#include <dirent.h>
|
||||
]], [alphasort closedir dirfd fdopendir opendir readdir rewinddir scandir])
|
||||
])
|
||||
|
||||
dnl Determine whether <dirent.h> needs to override the DIR type.
|
||||
AC_DEFUN_ONCE([gl_DIRENT_DIR],
|
||||
[
|
||||
dnl Set DIR_HAS_FD_MEMBER if dirfd() works, i.e. not always returns -1,
|
||||
dnl or has the __KLIBC__ workaround as in lib/dirfd.c.
|
||||
dnl We could use the findings from gl_FUNC_DIRFD and gl_PREREQ_DIRFD, but
|
||||
dnl it's simpler since we know the affected platforms.
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
case "$host_os" in
|
||||
mingw*) DIR_HAS_FD_MEMBER=0 ;;
|
||||
*) DIR_HAS_FD_MEMBER=1 ;;
|
||||
esac
|
||||
AC_SUBST([DIR_HAS_FD_MEMBER])
|
||||
])
|
||||
|
||||
# gl_DIRENT_MODULE_INDICATOR([modulename])
|
||||
# sets the shell variable that indicates the presence of the given module
|
||||
# to a C preprocessor expression that will evaluate to 1.
|
||||
@@ -73,6 +90,8 @@ AC_DEFUN([gl_DIRENT_H_DEFAULTS],
|
||||
HAVE_SCANDIR=1; AC_SUBST([HAVE_SCANDIR])
|
||||
HAVE_ALPHASORT=1; AC_SUBST([HAVE_ALPHASORT])
|
||||
REPLACE_OPENDIR=0; AC_SUBST([REPLACE_OPENDIR])
|
||||
REPLACE_READDIR=0; AC_SUBST([REPLACE_READDIR])
|
||||
REPLACE_REWINDDIR=0; AC_SUBST([REPLACE_REWINDDIR])
|
||||
REPLACE_CLOSEDIR=0; AC_SUBST([REPLACE_CLOSEDIR])
|
||||
REPLACE_DIRFD=0; AC_SUBST([REPLACE_DIRFD])
|
||||
REPLACE_FDOPENDIR=0; AC_SUBST([REPLACE_FDOPENDIR])
|
||||
|
||||
+19
-10
@@ -1,4 +1,4 @@
|
||||
# serial 26 -*- Autoconf -*-
|
||||
# serial 27 -*- Autoconf -*-
|
||||
|
||||
dnl Find out how to get the file descriptor associated with an open DIR*.
|
||||
|
||||
@@ -12,7 +12,7 @@ dnl From Jim Meyering
|
||||
AC_DEFUN([gl_FUNC_DIRFD],
|
||||
[
|
||||
AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
|
||||
dnl Persuade glibc <dirent.h> to declare dirfd().
|
||||
AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
|
||||
@@ -36,15 +36,24 @@ AC_DEFUN([gl_FUNC_DIRFD],
|
||||
[gl_cv_func_dirfd_macro=yes],
|
||||
[gl_cv_func_dirfd_macro=no])])
|
||||
|
||||
# Use the replacement if we have no function or macro with that name,
|
||||
# or if OS/2 kLIBC whose dirfd() does not work.
|
||||
# Replace only if the system declares dirfd already.
|
||||
case $ac_cv_func_dirfd,$gl_cv_func_dirfd_macro,$host_os,$ac_cv_have_decl_dirfd in
|
||||
no,no,*,yes | *,*,os2*,yes)
|
||||
if test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no; then
|
||||
HAVE_DIRFD=0
|
||||
else
|
||||
HAVE_DIRFD=1
|
||||
dnl Replace only if the system declares dirfd already.
|
||||
if test $ac_cv_have_decl_dirfd = yes; then
|
||||
REPLACE_DIRFD=1
|
||||
AC_DEFINE([REPLACE_DIRFD], [1],
|
||||
[Define to 1 if gnulib's dirfd() replacement is used.]);;
|
||||
esac
|
||||
fi
|
||||
dnl Replace dirfd() on native Windows, to support fdopendir().
|
||||
AC_REQUIRE([gl_DIRENT_DIR])
|
||||
if test $DIR_HAS_FD_MEMBER = 0; then
|
||||
REPLACE_DIRFD=1
|
||||
fi
|
||||
dnl OS/2 kLIBC dirfd() does not work.
|
||||
case "$host_os" in
|
||||
os2*) REPLACE_DIRFD=1 ;;
|
||||
esac
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Prerequisites of lib/dirfd.c.
|
||||
|
||||
+19
-16
@@ -1,4 +1,4 @@
|
||||
# opendir.m4 serial 5
|
||||
# opendir.m4 serial 6
|
||||
dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -12,21 +12,24 @@ AC_DEFUN([gl_FUNC_OPENDIR],
|
||||
AC_CHECK_FUNCS([opendir])
|
||||
if test $ac_cv_func_opendir = no; then
|
||||
HAVE_OPENDIR=0
|
||||
fi
|
||||
dnl Replace opendir() for supporting the gnulib-defined fchdir() function,
|
||||
dnl to keep fchdir's bookkeeping up-to-date.
|
||||
m4_ifdef([gl_FUNC_FCHDIR], [
|
||||
gl_TEST_FCHDIR
|
||||
if test $HAVE_FCHDIR = 0; then
|
||||
if test $HAVE_OPENDIR = 1; then
|
||||
else
|
||||
dnl Replace opendir() on native Windows, to support fdopendir().
|
||||
AC_REQUIRE([gl_DIRENT_DIR])
|
||||
if test $DIR_HAS_FD_MEMBER = 0; then
|
||||
REPLACE_OPENDIR=1
|
||||
fi
|
||||
dnl Replace opendir() on OS/2 kLIBC to support dirfd() function replaced
|
||||
dnl by gnulib.
|
||||
case $host_os in
|
||||
os2*) REPLACE_OPENDIR=1 ;;
|
||||
esac
|
||||
dnl Replace opendir() for supporting the gnulib-defined fchdir() function,
|
||||
dnl to keep fchdir's bookkeeping up-to-date.
|
||||
m4_ifdef([gl_FUNC_FCHDIR], [
|
||||
gl_TEST_FCHDIR
|
||||
if test $HAVE_FCHDIR = 0; then
|
||||
REPLACE_OPENDIR=1
|
||||
fi
|
||||
fi
|
||||
])
|
||||
dnl Replace opendir() on OS/2 kLIBC to support dirfd() function replaced
|
||||
dnl by gnulib.
|
||||
case $host_os,$HAVE_OPENDIR in
|
||||
os2*,1)
|
||||
REPLACE_OPENDIR=1;;
|
||||
esac
|
||||
])
|
||||
fi
|
||||
])
|
||||
|
||||
+7
-1
@@ -1,4 +1,4 @@
|
||||
# readdir.m4 serial 1
|
||||
# readdir.m4 serial 2
|
||||
dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -11,5 +11,11 @@ AC_DEFUN([gl_FUNC_READDIR],
|
||||
AC_CHECK_FUNCS([readdir])
|
||||
if test $ac_cv_func_readdir = no; then
|
||||
HAVE_READDIR=0
|
||||
else
|
||||
dnl Replace readdir() on native Windows, to support fdopendir().
|
||||
AC_REQUIRE([gl_DIRENT_DIR])
|
||||
if test $DIR_HAS_FD_MEMBER = 0; then
|
||||
REPLACE_READDIR=1
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
+7
-1
@@ -1,4 +1,4 @@
|
||||
# rewinddir.m4 serial 1
|
||||
# rewinddir.m4 serial 2
|
||||
dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
@@ -11,5 +11,11 @@ AC_DEFUN([gl_FUNC_REWINDDIR],
|
||||
AC_CHECK_FUNCS([rewinddir])
|
||||
if test $ac_cv_func_rewinddir = no; then
|
||||
HAVE_REWINDDIR=0
|
||||
else
|
||||
dnl Replace rewinddir() on native Windows, to support fdopendir().
|
||||
AC_REQUIRE([gl_DIRENT_DIR])
|
||||
if test $DIR_HAS_FD_MEMBER = 0; then
|
||||
REPLACE_REWINDDIR=1
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
@@ -33,6 +33,7 @@ dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
|
||||
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
|
||||
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
|
||||
-e 's|@''NEXT_DIRENT_H''@|$(NEXT_DIRENT_H)|g' \
|
||||
-e 's/@''DIR_HAS_FD_MEMBER''@/$(DIR_HAS_FD_MEMBER)/g' \
|
||||
-e 's/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \
|
||||
-e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \
|
||||
-e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \
|
||||
@@ -51,6 +52,8 @@ dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
|
||||
-e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \
|
||||
-e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \
|
||||
-e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \
|
||||
-e 's|@''REPLACE_READDIR''@|$(REPLACE_READDIR)|g' \
|
||||
-e 's|@''REPLACE_REWINDDIR''@|$(REPLACE_REWINDDIR)|g' \
|
||||
-e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \
|
||||
-e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \
|
||||
-e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \
|
||||
|
||||
+3
-2
@@ -3,17 +3,18 @@ Retrieving the file descriptor of an open directory stream. (Unportable.)
|
||||
|
||||
Files:
|
||||
lib/dirfd.c
|
||||
lib/dirent-private.h
|
||||
m4/dirfd.m4
|
||||
|
||||
Depends-on:
|
||||
dirent
|
||||
extensions
|
||||
errno [test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no || test $REPLACE_DIRFD = 1]
|
||||
errno [test $HAVE_DIRFD = 0 || test $REPLACE_DIRFD = 1]
|
||||
|
||||
configure.ac:
|
||||
gl_FUNC_DIRFD
|
||||
gl_CONDITIONAL([GL_COND_OBJ_DIRFD],
|
||||
[test $ac_cv_func_dirfd = no && test $gl_cv_func_dirfd_macro = no || test $REPLACE_DIRFD = 1])
|
||||
[test $HAVE_DIRFD = 0 || test $REPLACE_DIRFD = 1])
|
||||
AM_COND_IF([GL_COND_OBJ_DIRFD], [
|
||||
gl_PREREQ_DIRFD
|
||||
])
|
||||
|
||||
@@ -3,6 +3,7 @@ Open a directory stream from a file descriptor.
|
||||
|
||||
Files:
|
||||
lib/fdopendir.c
|
||||
lib/dirent-private.h
|
||||
m4/fdopendir.m4
|
||||
|
||||
Depends-on:
|
||||
|
||||
+2
-1
@@ -12,7 +12,8 @@ largefile
|
||||
|
||||
configure.ac:
|
||||
gl_FUNC_READDIR
|
||||
gl_CONDITIONAL([GL_COND_OBJ_READDIR], [test $HAVE_READDIR = 0])
|
||||
gl_CONDITIONAL([GL_COND_OBJ_READDIR],
|
||||
[test $HAVE_READDIR = 0 || test $REPLACE_READDIR = 1])
|
||||
gl_DIRENT_MODULE_INDICATOR([readdir])
|
||||
|
||||
Makefile.am:
|
||||
|
||||
+2
-1
@@ -13,7 +13,8 @@ largefile
|
||||
|
||||
configure.ac:
|
||||
gl_FUNC_REWINDDIR
|
||||
gl_CONDITIONAL([GL_COND_OBJ_REWINDDIR], [test $HAVE_REWINDDIR = 0])
|
||||
gl_CONDITIONAL([GL_COND_OBJ_REWINDDIR],
|
||||
[test $HAVE_REWINDDIR = 0 || test $REPLACE_REWINDDIR = 1])
|
||||
gl_DIRENT_MODULE_INDICATOR([rewinddir])
|
||||
|
||||
Makefile.am:
|
||||
|
||||
Reference in New Issue
Block a user