summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-09-13 01:37:35 +0200
committerBruno Haible <bruno@clisp.org>2011-09-13 01:39:18 +0200
commit994c21f30d225cd35a8fa57851df8bc6bd66d97f (patch)
tree9973bc77402821c421aa3340575345b81a357687
parentfcb7180c0ff873e26b9ea0aa7ef753df20104384 (diff)
downloadgnulib-994c21f30d225cd35a8fa57851df8bc6bd66d97f.tar.gz
New modules 'opendir', 'readdir', 'rewinddir', 'closedir'.
* lib/dirent.in.h (struct dirent): New type. (DT_UNKNOWN, DT_FIFO, DT_CHR, DT_DIR, DT_BLK, DT_REG, DT_LNK, DT_SOCK, DT_WHT): New macros. (DIR): New type. (opendir, closedir): Declare only if the module 'opendir' is enabled. (readdir, rewinddir): New declarations. * lib/dirent-private.h: New file. * lib/opendir.c: New file. * lib/readdir.c: New file. * lib/rewinddir.c: New file. * lib/closedir.c: New file. * lib/fchdir.c (rpl_closedir, rpl_opendir): Remove functions. * m4/opendir.m4: New file. * m4/readdir.m4: New file. * m4/rewinddir.m4: New file. * m4/closedir.m4: New file. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Don't set REPLACE_OPENDIR, REPLACE_CLOSEDIR here. * m4/dirent_h.m4 (gl_DIRENT_H): Also check whether closedir, opendir, readdir, rewinddir are declared. (gl_DIRENT_H_DEFAULTS): Initialize GNULIB_OPENDIR, GNULIB_READDIR, GNULIB_REWINDDIR, GNULIB_CLOSEDIR, HAVE_OPENDIR, HAVE_READDIR, HAVE_REWINDDIR, HAVE_CLOSEDIR. * modules/dirent (Makefile.am): Substitute GNULIB_OPENDIR, GNULIB_READDIR, GNULIB_REWINDDIR, GNULIB_CLOSEDIR, HAVE_OPENDIR, HAVE_READDIR, HAVE_REWINDDIR, HAVE_CLOSEDIR. * modules/opendir: New file. * modules/readdir: New file. * modules/rewinddir: New file. * modules/closedir: New file. * doc/posix-functions/opendir.texi: Mention the 'opendir' module. * doc/posix-functions/readdir.texi: Mention the 'readdir' module. * doc/posix-functions/rewinddir.texi: Mention the 'rewinddir' module. * doc/posix-functions/closedir.texi: Mention the 'closedir' module. * NEWS: Mention the 'fchdir' change.
-rw-r--r--ChangeLog39
-rw-r--r--NEWS6
-rw-r--r--doc/posix-functions/closedir.texi8
-rw-r--r--doc/posix-functions/opendir.texi8
-rw-r--r--doc/posix-functions/readdir.texi8
-rw-r--r--doc/posix-functions/rewinddir.texi8
-rw-r--r--lib/closedir.c63
-rw-r--r--lib/dirent-private.h40
-rw-r--r--lib/dirent.in.h111
-rw-r--r--lib/fchdir.c36
-rw-r--r--lib/opendir.c143
-rw-r--r--lib/readdir.c98
-rw-r--r--lib/rewinddir.c49
-rw-r--r--m4/closedir.m423
-rw-r--r--m4/dirent_h.m414
-rw-r--r--m4/fchdir.m44
-rw-r--r--m4/opendir.m423
-rw-r--r--m4/readdir.m415
-rw-r--r--m4/rewinddir.m415
-rw-r--r--modules/closedir28
-rw-r--r--modules/dirent10
-rw-r--r--modules/opendir30
-rw-r--r--modules/readdir29
-rw-r--r--modules/rewinddir30
24 files changed, 761 insertions, 77 deletions
diff --git a/ChangeLog b/ChangeLog
index 30af537ca0..3c177306cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2011-09-12 Bruno Haible <bruno@clisp.org>
+
+ New modules 'opendir', 'readdir', 'rewinddir', 'closedir'.
+ * lib/dirent.in.h (struct dirent): New type.
+ (DT_UNKNOWN, DT_FIFO, DT_CHR, DT_DIR, DT_BLK, DT_REG, DT_LNK, DT_SOCK,
+ DT_WHT): New macros.
+ (DIR): New type.
+ (opendir, closedir): Declare only if the module 'opendir' is enabled.
+ (readdir, rewinddir): New declarations.
+ * lib/dirent-private.h: New file.
+ * lib/opendir.c: New file.
+ * lib/readdir.c: New file.
+ * lib/rewinddir.c: New file.
+ * lib/closedir.c: New file.
+ * lib/fchdir.c (rpl_closedir, rpl_opendir): Remove functions.
+ * m4/opendir.m4: New file.
+ * m4/readdir.m4: New file.
+ * m4/rewinddir.m4: New file.
+ * m4/closedir.m4: New file.
+ * m4/fchdir.m4 (gl_FUNC_FCHDIR): Don't set REPLACE_OPENDIR,
+ REPLACE_CLOSEDIR here.
+ * m4/dirent_h.m4 (gl_DIRENT_H): Also check whether closedir, opendir,
+ readdir, rewinddir are declared.
+ (gl_DIRENT_H_DEFAULTS): Initialize GNULIB_OPENDIR, GNULIB_READDIR,
+ GNULIB_REWINDDIR, GNULIB_CLOSEDIR, HAVE_OPENDIR, HAVE_READDIR,
+ HAVE_REWINDDIR, HAVE_CLOSEDIR.
+ * modules/dirent (Makefile.am): Substitute GNULIB_OPENDIR,
+ GNULIB_READDIR, GNULIB_REWINDDIR, GNULIB_CLOSEDIR, HAVE_OPENDIR,
+ HAVE_READDIR, HAVE_REWINDDIR, HAVE_CLOSEDIR.
+ * modules/opendir: New file.
+ * modules/readdir: New file.
+ * modules/rewinddir: New file.
+ * modules/closedir: New file.
+ * doc/posix-functions/opendir.texi: Mention the 'opendir' module.
+ * doc/posix-functions/readdir.texi: Mention the 'readdir' module.
+ * doc/posix-functions/rewinddir.texi: Mention the 'rewinddir' module.
+ * doc/posix-functions/closedir.texi: Mention the 'closedir' module.
+ * NEWS: Mention the 'fchdir' change.
+
2011-09-11 Bruno Haible <bruno@clisp.org>
asm-underscore.m4: Support for MSVC.
diff --git a/NEWS b/NEWS
index 3905383581..16c5a3528f 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,12 @@ User visible incompatible changes
Date Modules Changes
+2011-09-12 fchdir This module no longer overrides the functions
+ opendir() and closedir(), unless the modules
+ 'opendir' and 'closedir' are in use, respectively.
+ If you use opendir(), please use module 'opendir'.
+ If you use closedir(), please use module 'closedir'.
+
2011-08-04 pathmax The header file "pathmax.h" no longer defines
PATH_MAX on GNU/Hurd. Please use one of the methods
listed in pathmax.h to ensure your package is
diff --git a/doc/posix-functions/closedir.texi b/doc/posix-functions/closedir.texi
index 487a179b48..c8a1d386df 100644
--- a/doc/posix-functions/closedir.texi
+++ b/doc/posix-functions/closedir.texi
@@ -4,15 +4,15 @@
POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/closedir.html}
-Gnulib module: ---
+Gnulib module: closedir
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on some platforms:
+MSVC 9.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-This function is missing on some platforms:
-MSVC 9.
@end itemize
diff --git a/doc/posix-functions/opendir.texi b/doc/posix-functions/opendir.texi
index feb1af5469..661790cc49 100644
--- a/doc/posix-functions/opendir.texi
+++ b/doc/posix-functions/opendir.texi
@@ -4,18 +4,18 @@
POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/opendir.html}
-Gnulib module: ---
+Gnulib module: opendir
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on some platforms:
+MSVC 9.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@item
-This function is missing on some platforms:
-MSVC 9.
-@item
On platforms where @code{off_t} is a 32-bit type, this function may not
work correctly on huge directories larger than 2 GB. Also, on platforms
where @code{ino_t} is a 32-bit type, this function may report inode numbers
diff --git a/doc/posix-functions/readdir.texi b/doc/posix-functions/readdir.texi
index 5325fd9a41..a69b06843a 100644
--- a/doc/posix-functions/readdir.texi
+++ b/doc/posix-functions/readdir.texi
@@ -4,18 +4,18 @@
POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/readdir.html}
-Gnulib module: ---
+Gnulib module: readdir
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on some platforms:
+MSVC 9.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@item
-This function is missing on some platforms:
-MSVC 9.
-@item
On platforms where @code{off_t} is a 32-bit type, this function may not
work correctly on huge directories larger than 2 GB. Also, on platforms
where @code{ino_t} is a 32-bit type, this function may report inode numbers
diff --git a/doc/posix-functions/rewinddir.texi b/doc/posix-functions/rewinddir.texi
index 6f789ce9b3..47f8d4c029 100644
--- a/doc/posix-functions/rewinddir.texi
+++ b/doc/posix-functions/rewinddir.texi
@@ -4,18 +4,18 @@
POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/rewinddir.html}
-Gnulib module: ---
+Gnulib module: rewinddir
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on some platforms:
+MSVC 9.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
@item
-This function is missing on some platforms:
-MSVC 9.
-@item
On platforms where @code{long int} is a 32-bit type, this function may not
work correctly on huge directories larger than 2 GB. The fix is to use
the @code{AC_SYS_LARGEFILE} macro (only on MacOS X systems).
diff --git a/lib/closedir.c b/lib/closedir.c
new file mode 100644
index 0000000000..700d60eeb4
--- /dev/null
+++ b/lib/closedir.c
@@ -0,0 +1,63 @@
+/* Stop reading the entries of a directory.
+ Copyright (C) 2006-2011 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.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>
+
+# include "dirent-private.h"
+
+#endif
+
+int
+closedir (DIR *dirp)
+{
+# if REPLACE_FCHDIR
+ int fd = dirfd (dirp);
+# endif
+ int retval;
+
+#if HAVE_CLOSEDIR
+# undef closedir
+
+ retval = closedir (dirp);
+
+#else
+
+ if (dirp->current != INVALID_HANDLE_VALUE)
+ FindClose (dirp->current);
+ free (dirp);
+
+ retval = 0;
+
+#endif
+
+#if REPLACE_FCHDIR
+ if (retval >= 0)
+ _gl_unregister_fd (fd);
+#endif
+ return retval;
+}
diff --git a/lib/dirent-private.h b/lib/dirent-private.h
new file mode 100644
index 0000000000..74632ff39b
--- /dev/null
+++ b/lib/dirent-private.h
@@ -0,0 +1,40 @@
+/* Private details of the DIR type.
+ Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _DIRENT_PRIVATE_H
+#define _DIRENT_PRIVATE_H 1
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+struct gl_directory
+{
+ /* 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,
+ 0 means the entry needs to be filled using FindNextFile.
+ A positive value is an error code. */
+ int status;
+ /* Handle, reading the directory, at current position. */
+ HANDLE current;
+ /* Found directory entry. */
+ WIN32_FIND_DATA entry;
+ /* Argument to pass to FindFirstFile. It consists of the absolutized
+ directory name, followed by a directory separator and the wildcards. */
+ char dir_name_mask[1];
+};
+
+#endif /* _DIRENT_PRIVATE_H */
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index a8b3f490ab..cbcf841df2 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -32,6 +32,29 @@
/* Get ino_t. Needed on some systems, including glibc 2.8. */
#include <sys/types.h>
+#if !@HAVE_DIRENT_H@
+/* Define types DIR and 'struct dirent'. */
+# if !GNULIB_defined_struct_dirent
+struct dirent
+{
+ char d_type;
+ char d_name[1];
+};
+/* Possible values for 'd_type'. */
+# define DT_UNKNOWN 0
+# define DT_FIFO 1 /* FIFO */
+# define DT_CHR 2 /* character device */
+# define DT_DIR 4 /* directory */
+# define DT_BLK 6 /* block device */
+# define DT_REG 8 /* regular file */
+# 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
+
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
/* The definition of _GL_ARG_NONNULL is copied here. */
@@ -41,16 +64,79 @@
/* Declare overridden functions. */
-#if @REPLACE_CLOSEDIR@
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
-# define closedir rpl_closedir
+#if @GNULIB_OPENDIR@
+# if @REPLACE_OPENDIR@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef opendir
+# define opendir rpl_opendir
+# endif
+_GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name));
+# else
+# if !@HAVE_OPENDIR@
+_GL_FUNCDECL_SYS (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name));
+# endif
+_GL_CXXALIASWARN (opendir);
+#elif defined GNULIB_POSIXCHECK
+# undef opendir
+# if HAVE_RAW_DECL_OPENDIR
+_GL_WARN_ON_USE (opendir, "opendir is not portable - "
+ "use gnulib module opendir for portability");
+# endif
+#endif
+
+#if @GNULIB_READDIR@
+# if !@HAVE_READDIR@
+_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp));
+_GL_CXXALIASWARN (readdir);
+#elif defined GNULIB_POSIXCHECK
+# undef readdir
+# if HAVE_RAW_DECL_READDIR
+_GL_WARN_ON_USE (readdir, "readdir is not portable - "
+ "use gnulib module readdir for portability");
# endif
-_GL_FUNCDECL_RPL (closedir, int, (DIR *) _GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (closedir, int, (DIR *));
-#else
-_GL_CXXALIAS_SYS (closedir, int, (DIR *));
#endif
+
+#if @GNULIB_REWINDDIR@
+# if !@HAVE_REWINDDIR@
+_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp));
+_GL_CXXALIASWARN (rewinddir);
+#elif defined GNULIB_POSIXCHECK
+# undef rewinddir
+# if HAVE_RAW_DECL_REWINDDIR
+_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - "
+ "use gnulib module rewinddir for portability");
+# endif
+#endif
+
+#if @GNULIB_CLOSEDIR@
+# if @REPLACE_CLOSEDIR@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef closedir
+# define closedir rpl_closedir
+# endif
+_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp));
+# else
+# if !@HAVE_CLOSEDIR@
+_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp));
+# endif
_GL_CXXALIASWARN (closedir);
+#elif defined GNULIB_POSIXCHECK
+# undef closedir
+# if HAVE_RAW_DECL_CLOSEDIR
+_GL_WARN_ON_USE (closedir, "closedir is not portable - "
+ "use gnulib module closedir for portability");
+# endif
+#endif
#if @GNULIB_DIRFD@
/* Return the file descriptor associated with the given directory stream,
@@ -111,17 +197,6 @@ _GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - "
# endif
#endif
-#if @REPLACE_OPENDIR@
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
-# define opendir rpl_opendir
-# endif
-_GL_FUNCDECL_RPL (opendir, DIR *, (const char *) _GL_ARG_NONNULL ((1)));
-_GL_CXXALIAS_RPL (opendir, DIR *, (const char *));
-#else
-_GL_CXXALIAS_SYS (opendir, DIR *, (const char *));
-#endif
-_GL_CXXALIASWARN (opendir);
-
#if @GNULIB_SCANDIR@
/* Scan the directory DIR, calling FILTER on each directory entry.
Entries for which FILTER returns nonzero are individually malloc'd,
diff --git a/lib/fchdir.c b/lib/fchdir.c
index 6dd704f625..e13ba2249d 100644
--- a/lib/fchdir.c
+++ b/lib/fchdir.c
@@ -211,42 +211,6 @@ rpl_fstat (int fd, struct stat *statbuf)
}
#endif
-/* Override opendir() and closedir(), to keep track of the open file
- descriptors. Needed because there is a function dirfd(). */
-
-int
-rpl_closedir (DIR *dp)
-#undef closedir
-{
- int fd = dirfd (dp);
- int retval = closedir (dp);
-
- if (retval >= 0)
- _gl_unregister_fd (fd);
- return retval;
-}
-
-DIR *
-rpl_opendir (const char *filename)
-#undef opendir
-{
- DIR *dp;
-
- dp = opendir (filename);
- if (dp != NULL)
- {
- int fd = dirfd (dp);
- if (0 <= fd && _gl_register_fd (fd, filename) != fd)
- {
- int saved_errno = errno;
- closedir (dp);
- errno = saved_errno;
- return NULL;
- }
- }
- return dp;
-}
-
/* Override dup(), to keep track of open file descriptors. */
int
diff --git a/lib/opendir.c b/lib/opendir.c
new file mode 100644
index 0000000000..cb7f67c101
--- /dev/null
+++ b/lib/opendir.c
@@ -0,0 +1,143 @@
+/* Start reading the entries of a directory.
+ Copyright (C) 2006-2011 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.h>
+
+#if HAVE_OPENDIR
+
+/* Override opendir(), to keep track of the open file descriptors.
+ Needed because there is a function dirfd(). */
+
+#else
+
+# include <errno.h>
+# include <stddef.h>
+# include <stdlib.h>
+
+# include "dirent-private.h"
+# include "filename.h"
+
+#endif
+
+DIR *
+opendir (const char *dir_name)
+{
+#if HAVE_OPENDIR
+# undef opendir
+ DIR *dirp;
+
+ dirp = opendir (dir_name);
+ if (dirp == NULL)
+ return NULL;
+
+#else
+
+ char dir_name_mask[MAX_PATH + 1 + 1 + 1];
+ int status;
+ HANDLE current;
+ WIN32_FIND_DATA entry;
+ struct gl_directory *dirp;
+
+ if (dir_name[0] == '\0')
+ {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ /* Make the dir_name absolute, so that we continue reading the same
+ directory if the current directory changed between this opendir()
+ call and a subsequent rewinddir() call. */
+ if (!GetFullPathName (dir_name, MAX_PATH, dir_name_mask, NULL))
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Append the mask.
+ "*" and "*.*" appear to be equivalent. */
+ {
+ char *p;
+
+ p = dir_name_mask + strlen (dir_name_mask);
+ if (p > dir_name_mask && !ISSLASH (p[-1]))
+ *p++ = '\\';
+ *p++ = '*';
+ *p = '\0';
+ }
+
+ /* Start searching the directory. */
+ status = -1;
+ current = FindFirstFile (dir_name_mask, &entry);
+ if (current == INVALID_HANDLE_VALUE)
+ {
+ switch (GetLastError ())
+ {
+ case ERROR_FILE_NOT_FOUND:
+ status = -2;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ return NULL;
+ case ERROR_DIRECTORY:
+ errno = ENOTDIR;
+ return NULL;
+ case ERROR_ACCESS_DENIED:
+ errno = EACCES;
+ return NULL;
+ default:
+ errno = EIO;
+ return NULL;
+ }
+ }
+
+ /* Allocate the result. */
+ dirp =
+ (struct gl_directory *)
+ malloc (offsetof (struct gl_directory, dir_name_mask[0])
+ + strlen (dir_name_mask) + 1);
+ if (dirp == NULL)
+ {
+ if (current != INVALID_HANDLE_VALUE)
+ FindClose (current);
+ errno = ENOMEM;
+ return NULL;
+ }
+ dirp->status = status;
+ dirp->current = current;
+ if (status == -1)
+ memcpy (&dirp->entry, &entry, sizeof (WIN32_FIND_DATA));
+ strcpy (dirp->dir_name_mask, dir_name_mask);
+
+#endif
+
+#if REPLACE_FCHDIR
+ {
+ int fd = dirfd (dirp);
+ if (0 <= fd && _gl_register_fd (fd, dir_name) != fd)
+ {
+ int saved_errno = errno;
+ closedir (dirp);
+ errno = saved_errno;
+ return NULL;
+ }
+ }
+#endif
+
+ return dirp;
+}
diff --git a/lib/readdir.c b/lib/readdir.c
new file mode 100644
index 0000000000..04858b0080
--- /dev/null
+++ b/lib/readdir.c
@@ -0,0 +1,98 @@
+/* Read the next entry of a directory.
+ Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+#include "dirent-private.h"
+
+struct dirent *
+readdir (DIR *dirp)
+{
+ char type;
+ struct dirent *result;
+
+ /* There is no need to add code to produce entries for "." and "..".
+ According to the POSIX:2008 section "4.12 Pathname Resolution"
+ <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html>
+ "." and ".." are syntactic entities.
+ POSIX also says:
+ "If entries for dot or dot-dot exist, one entry shall be returned
+ for dot and one entry shall be returned for dot-dot; otherwise,
+ they shall not be returned." */
+
+ switch (dirp->status)
+ {
+ case -2:
+ /* End of directory already reached. */
+ return NULL;
+ case -1:
+ break;
+ case 0:
+ if (!FindNextFile (dirp->current, &dirp->entry))
+ {
+ switch (GetLastError ())
+ {
+ case ERROR_NO_MORE_FILES:
+ dirp->status = -2;
+ return NULL;
+ default:
+ errno = EIO;
+ return NULL;
+ }
+ }
+ break;
+ default:
+ errno = dirp->status;
+ return NULL;
+ }
+
+ dirp->status = 0;
+
+ if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ type = DT_DIR;
+ else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ type = DT_LNK;
+ else if ((dirp->entry.dwFileAttributes
+ & ~(FILE_ATTRIBUTE_READONLY
+ | FILE_ATTRIBUTE_HIDDEN
+ | FILE_ATTRIBUTE_SYSTEM
+ | FILE_ATTRIBUTE_ARCHIVE
+ | FILE_ATTRIBUTE_NORMAL
+ | FILE_ATTRIBUTE_TEMPORARY
+ | FILE_ATTRIBUTE_SPARSE_FILE
+ | FILE_ATTRIBUTE_COMPRESSED
+ | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
+ | FILE_ATTRIBUTE_ENCRYPTED)) == 0)
+ /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but
+ they cannot occur here. */
+ type = DT_REG;
+ else
+ type = DT_UNKNOWN;
+
+ /* Reuse the memory of dirp->entry for the result. */
+ result =
+ (struct dirent *)
+ ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0]));
+ result->d_type = type;
+
+ return result;
+}
diff --git a/lib/rewinddir.c b/lib/rewinddir.c
new file mode 100644
index 0000000000..bfb91084bf
--- /dev/null
+++ b/lib/rewinddir.c
@@ -0,0 +1,49 @@
+/* Restart reading the entries of a directory from the beginning.
+ Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.h>
+
+#include <errno.h>
+
+#include "dirent-private.h"
+
+void
+rewinddir (DIR *dirp)
+{
+ /* Like in closedir(). */
+ if (dirp->current != INVALID_HANDLE_VALUE)
+ FindClose (dirp->current);
+
+ /* Like in opendir(). */
+ dirp->status = -1;
+ dirp->current = FindFirstFile (dirp->dir_name_mask, &dirp->entry);
+ if (dirp->current == INVALID_HANDLE_VALUE)
+ {
+ switch (GetLastError ())
+ {
+ case ERROR_FILE_NOT_FOUND:
+ dirp->status = -2;
+ break;
+ default:
+ /* Save the error code for the next readdir() call. */
+ dirp->status = ENOENT;
+ break;
+ }
+ }
+}
diff --git a/m4/closedir.m4 b/m4/closedir.m4
new file mode 100644
index 0000000000..1b7912a30b
--- /dev/null
+++ b/m4/closedir.m4
@@ -0,0 +1,23 @@
+# closedir.m4 serial 1
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_CLOSEDIR],
+[
+ AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+ 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
+ REPLACE_CLOSEDIR=1
+ fi
+ ])
+])
diff --git a/m4/dirent_h.m4 b/m4/dirent_h.m4
index 5ecfd83058..ab45170b99 100644
--- a/m4/dirent_h.m4
+++ b/m4/dirent_h.m4
@@ -1,4 +1,4 @@
-# dirent_h.m4 serial 15
+# dirent_h.m4 serial 16
dnl Copyright (C) 2008-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -24,7 +24,7 @@ AC_DEFUN([gl_DIRENT_H],
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 dirfd fdopendir scandir])
+ ]], [alphasort closedir dirfd fdopendir opendir readdir rewinddir scandir])
])
AC_DEFUN([gl_DIRENT_MODULE_INDICATOR],
@@ -39,18 +39,26 @@ AC_DEFUN([gl_DIRENT_MODULE_INDICATOR],
AC_DEFUN([gl_DIRENT_H_DEFAULTS],
[
AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) dnl for REPLACE_FCHDIR
+ GNULIB_OPENDIR=0; AC_SUBST([GNULIB_OPENDIR])
+ GNULIB_READDIR=0; AC_SUBST([GNULIB_READDIR])
+ GNULIB_REWINDDIR=0; AC_SUBST([GNULIB_REWINDDIR])
+ GNULIB_CLOSEDIR=0; AC_SUBST([GNULIB_CLOSEDIR])
GNULIB_DIRFD=0; AC_SUBST([GNULIB_DIRFD])
GNULIB_FDOPENDIR=0; AC_SUBST([GNULIB_FDOPENDIR])
GNULIB_SCANDIR=0; AC_SUBST([GNULIB_SCANDIR])
GNULIB_ALPHASORT=0; AC_SUBST([GNULIB_ALPHASORT])
dnl Assume proper GNU behavior unless another module says otherwise.
+ HAVE_OPENDIR=1; AC_SUBST([HAVE_OPENDIR])
+ HAVE_READDIR=1; AC_SUBST([HAVE_READDIR])
+ HAVE_REWINDDIR=1; AC_SUBST([HAVE_REWINDDIR])
+ HAVE_CLOSEDIR=1; AC_SUBST([HAVE_CLOSEDIR])
HAVE_DECL_DIRFD=1; AC_SUBST([HAVE_DECL_DIRFD])
HAVE_DECL_FDOPENDIR=1;AC_SUBST([HAVE_DECL_FDOPENDIR])
HAVE_FDOPENDIR=1; AC_SUBST([HAVE_FDOPENDIR])
HAVE_SCANDIR=1; AC_SUBST([HAVE_SCANDIR])
HAVE_ALPHASORT=1; AC_SUBST([HAVE_ALPHASORT])
+ REPLACE_OPENDIR=0; AC_SUBST([REPLACE_OPENDIR])
REPLACE_CLOSEDIR=0; AC_SUBST([REPLACE_CLOSEDIR])
REPLACE_DIRFD=0; AC_SUBST([REPLACE_DIRFD])
REPLACE_FDOPENDIR=0; AC_SUBST([REPLACE_FDOPENDIR])
- REPLACE_OPENDIR=0; AC_SUBST([REPLACE_OPENDIR])
])
diff --git a/m4/fchdir.m4 b/m4/fchdir.m4
index a387dbb4f9..e742a0732a 100644
--- a/m4/fchdir.m4
+++ b/m4/fchdir.m4
@@ -1,4 +1,4 @@
-# fchdir.m4 serial 17
+# fchdir.m4 serial 18
dnl Copyright (C) 2006-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -24,8 +24,6 @@ AC_DEFUN([gl_FUNC_FCHDIR],
dnl We must also replace anything that can manipulate a directory fd,
dnl to keep our bookkeeping up-to-date. We don't have to replace
dnl fstatat, since no platform has fstatat but lacks fchdir.
- REPLACE_OPENDIR=1
- REPLACE_CLOSEDIR=1
REPLACE_DUP=1
AC_CACHE_CHECK([whether open can visit directories],
[gl_cv_func_open_directory_works],
diff --git a/m4/opendir.m4 b/m4/opendir.m4
new file mode 100644
index 0000000000..fa315b9837
--- /dev/null
+++ b/m4/opendir.m4
@@ -0,0 +1,23 @@
+# opendir.m4 serial 1
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_OPENDIR],
+[
+ AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+ 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
+ REPLACE_OPENDIR=1
+ fi
+ ])
+])
diff --git a/m4/readdir.m4 b/m4/readdir.m4
new file mode 100644
index 0000000000..cfeed08907
--- /dev/null
+++ b/m4/readdir.m4
@@ -0,0 +1,15 @@
+# readdir.m4 serial 1
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_READDIR],
+[
+ AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+ AC_CHECK_FUNCS([readdir])
+ if test $ac_cv_func_readdir = no; then
+ HAVE_READDIR=0
+ fi
+])
diff --git a/m4/rewinddir.m4 b/m4/rewinddir.m4
new file mode 100644
index 0000000000..b9b6b3d0b3
--- /dev/null
+++ b/m4/rewinddir.m4
@@ -0,0 +1,15 @@
+# rewinddir.m4 serial 1
+dnl Copyright (C) 2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_REWINDDIR],
+[
+ AC_REQUIRE([gl_DIRENT_H_DEFAULTS])
+
+ AC_CHECK_FUNCS([rewinddir])
+ if test $ac_cv_func_rewinddir = no; then
+ HAVE_REWINDDIR=0
+ fi
+])
diff --git a/modules/closedir b/modules/closedir
new file mode 100644
index 0000000000..1ebff9ccad
--- /dev/null
+++ b/modules/closedir
@@ -0,0 +1,28 @@
+Description:
+closedir() function: stop reading the entries of a directory
+
+Files:
+lib/closedir.c
+lib/dirent-private.h
+m4/closedir.m4
+
+Depends-on:
+dirent
+
+configure.ac:
+gl_FUNC_CLOSEDIR
+if test $HAVE_CLOSEDIR = 0 || test $REPLACE_CLOSEDIR = 1; then
+ AC_LIBOBJ([closedir])
+fi
+gl_DIRENT_MODULE_INDICATOR([closedir])
+
+Makefile.am:
+
+Include:
+<dirent.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
diff --git a/modules/dirent b/modules/dirent
index 0fdf94b37a..6f615b496a 100644
--- a/modules/dirent
+++ b/modules/dirent
@@ -29,19 +29,27 @@ 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/@''GNULIB_OPENDIR''@/$(GNULIB_OPENDIR)/g' \
+ -e 's/@''GNULIB_READDIR''@/$(GNULIB_READDIR)/g' \
+ -e 's/@''GNULIB_REWINDDIR''@/$(GNULIB_REWINDDIR)/g' \
+ -e 's/@''GNULIB_CLOSEDIR''@/$(GNULIB_CLOSEDIR)/g' \
-e 's/@''GNULIB_DIRFD''@/$(GNULIB_DIRFD)/g' \
-e 's/@''GNULIB_FDOPENDIR''@/$(GNULIB_FDOPENDIR)/g' \
-e 's/@''GNULIB_SCANDIR''@/$(GNULIB_SCANDIR)/g' \
-e 's/@''GNULIB_ALPHASORT''@/$(GNULIB_ALPHASORT)/g' \
+ -e 's/@''HAVE_OPENDIR''@/$(HAVE_OPENDIR)/g' \
+ -e 's/@''HAVE_READDIR''@/$(HAVE_READDIR)/g' \
+ -e 's/@''HAVE_REWINDDIR''@/$(HAVE_REWINDDIR)/g' \
+ -e 's/@''HAVE_CLOSEDIR''@/$(HAVE_CLOSEDIR)/g' \
-e 's|@''HAVE_DECL_DIRFD''@|$(HAVE_DECL_DIRFD)|g' \
-e 's|@''HAVE_DECL_FDOPENDIR''@|$(HAVE_DECL_FDOPENDIR)|g' \
-e 's|@''HAVE_FDOPENDIR''@|$(HAVE_FDOPENDIR)|g' \
-e 's|@''HAVE_SCANDIR''@|$(HAVE_SCANDIR)|g' \
-e 's|@''HAVE_ALPHASORT''@|$(HAVE_ALPHASORT)|g' \
+ -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \
-e 's|@''REPLACE_CLOSEDIR''@|$(REPLACE_CLOSEDIR)|g' \
-e 's|@''REPLACE_DIRFD''@|$(REPLACE_DIRFD)|g' \
-e 's|@''REPLACE_FDOPENDIR''@|$(REPLACE_FDOPENDIR)|g' \
- -e 's|@''REPLACE_OPENDIR''@|$(REPLACE_OPENDIR)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
diff --git a/modules/opendir b/modules/opendir
new file mode 100644
index 0000000000..ede6d48a3d
--- /dev/null
+++ b/modules/opendir
@@ -0,0 +1,30 @@
+Description:
+opendir() function: start reading the entries of a directory
+
+Files:
+lib/opendir.c
+lib/dirent-private.h
+m4/opendir.m4
+
+Depends-on:
+dirent
+largefile
+filename [test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1]
+
+configure.ac:
+gl_FUNC_OPENDIR
+if test $HAVE_OPENDIR = 0 || test $REPLACE_OPENDIR = 1; then
+ AC_LIBOBJ([opendir])
+fi
+gl_DIRENT_MODULE_INDICATOR([opendir])
+
+Makefile.am:
+
+Include:
+<dirent.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
diff --git a/modules/readdir b/modules/readdir
new file mode 100644
index 0000000000..487a888a1c
--- /dev/null
+++ b/modules/readdir
@@ -0,0 +1,29 @@
+Description:
+readdir() function: read the next entry of a directory
+
+Files:
+lib/readdir.c
+lib/dirent-private.h
+m4/readdir.m4
+
+Depends-on:
+dirent
+largefile
+
+configure.ac:
+gl_FUNC_READDIR
+if test $HAVE_READDIR = 0; then
+ AC_LIBOBJ([readdir])
+fi
+gl_DIRENT_MODULE_INDICATOR([readdir])
+
+Makefile.am:
+
+Include:
+<dirent.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
diff --git a/modules/rewinddir b/modules/rewinddir
new file mode 100644
index 0000000000..050cfe8ccf
--- /dev/null
+++ b/modules/rewinddir
@@ -0,0 +1,30 @@
+Description:
+rewinddir() function: restart reading the entries of a directory from the
+beginning
+
+Files:
+lib/rewinddir.c
+lib/dirent-private.h
+m4/rewinddir.m4
+
+Depends-on:
+dirent
+largefile
+
+configure.ac:
+gl_FUNC_REWINDDIR
+if test $HAVE_REWINDDIR = 0; then
+ AC_LIBOBJ([rewinddir])
+fi
+gl_DIRENT_MODULE_INDICATOR([rewinddir])
+
+Makefile.am:
+
+Include:
+<dirent.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible