diff options
author | Bruno Haible <bruno@clisp.org> | 2023-04-27 01:42:25 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2023-04-27 01:42:25 +0200 |
commit | 3f0950f65abb5162c42b51a9bb32c9e87deeb405 (patch) | |
tree | bd2794c98d44013cf67c6b39c0863054315ebd68 /lib/closedir.c | |
parent | d70f555e34d9f4a9110e65dd5669fce701a61929 (diff) | |
download | gnulib-3f0950f65abb5162c42b51a9bb32c9e87deeb405.tar.gz |
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.
Diffstat (limited to 'lib/closedir.c')
-rw-r--r-- | lib/closedir.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/lib/closedir.c b/lib/closedir.c index 0e004afeca..3777e9f70d 100644 --- a/lib/closedir.c +++ b/lib/closedir.c @@ -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; } |