1
0
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:
Bruno Haible
2023-04-27 01:42:25 +02:00
parent d70f555e34
commit 3f0950f65a
21 changed files with 373 additions and 115 deletions
+63
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
])
+3
View File
@@ -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
View File
@@ -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
])
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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: