summaryrefslogtreecommitdiff
path: root/lib/fstat.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2017-04-29 14:55:22 +0200
committerBruno Haible <bruno@clisp.org>2017-04-29 22:51:56 +0200
commitfcb99f403746ba7f21b0180a149992b14d6c81bd (patch)
treeb8e2b912e3d924c62ffb3a0aacf0dd29917591bf /lib/fstat.c
parentf3f95f863f63eec80bfe4228719fb0afada5fa05 (diff)
downloadgnulib-fcb99f403746ba7f21b0180a149992b14d6c81bd.tar.gz
fstat: Fix time_t values on native Windows platforms.
* doc/posix-functions/fstat.texi: Mention the problem with st_*time. * lib/stat-w32.h: New file. * lib/stat-w32.c: New file. * lib/fstat.c: Don't include msvc-inval.h. Include msvc-nothrow.h, stat-w32.h instead. (fstat_nothrow): Remove function. (rpl_fstat): Implement by means of _gl_fstat_by_handle. * m4/fstat.m4 (gl_FUNC_FSTAT): On native Windows, set REPLACE_FSTAT always. (gl_PREREQ_FSTAT): Require gl_HEADER_SYS_STAT_H. * modules/fstat (Files): Add lib/stat-w32.h, lib/stat-w32.c. (Depends-on): Remove msvc-inval. Add pathmax, msvc-nothrow. (configure.ac): Also compile lib/stat-w32.c.
Diffstat (limited to 'lib/fstat.c')
-rw-r--r--lib/fstat.c68
1 files changed, 35 insertions, 33 deletions
diff --git a/lib/fstat.c b/lib/fstat.c
index a5aabc568e..a4896e3a77 100644
--- a/lib/fstat.c
+++ b/lib/fstat.c
@@ -23,20 +23,28 @@
/* Get the original definition of fstat. It might be defined as a macro. */
#include <sys/types.h>
#include <sys/stat.h>
-#if _GL_WINDOWS_64_BIT_ST_SIZE
-# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
-# define stat _stati64
-# undef fstat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
-# define fstat _fstati64
-#endif
#undef __need_system_sys_stat_h
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS_NATIVE
+# if _GL_WINDOWS_64_BIT_ST_SIZE
+# undef stat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
+# define stat _stati64
+# undef fstat /* avoid warning on mingw64 with _FILE_OFFSET_BITS=64 */
+# define fstat _fstati64
+# endif
+#endif
+
+#if !defined WINDOWS_NATIVE
+
static int
orig_fstat (int fd, struct stat *buf)
{
return fstat (fd, buf);
}
+#endif
+
/* Specification. */
/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
eliminates this include because of the preliminary #include <sys/stat.h>
@@ -45,32 +53,11 @@ orig_fstat (int fd, struct stat *buf)
#include <errno.h>
#include <unistd.h>
-
-#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
-# include "msvc-inval.h"
-#endif
-
-#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
-static int
-fstat_nothrow (int fd, struct stat *buf)
-{
- int result;
-
- TRY_MSVC_INVAL
- {
- result = orig_fstat (fd, buf);
- }
- CATCH_MSVC_INVAL
- {
- result = -1;
- errno = EBADF;
- }
- DONE_MSVC_INVAL;
-
- return result;
-}
-#else
-# define fstat_nothrow orig_fstat
+#ifdef WINDOWS_NATIVE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include "msvc-nothrow.h"
+# include "stat-w32.h"
#endif
int
@@ -84,5 +71,20 @@ rpl_fstat (int fd, struct stat *buf)
return stat (name, buf);
#endif
- return fstat_nothrow (fd, buf);
+#ifdef WINDOWS_NATIVE
+ /* Fill the fields ourselves, because the original fstat function returns
+ values for st_atime, st_mtime, st_ctime that depend on the current time
+ zone. See
+ <https://lists.gnu.org/archive/html/bug-gnulib/2017-04/msg00134.html> */
+ HANDLE h = (HANDLE) _get_osfhandle (fd);
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return _gl_fstat_by_handle (h, NULL, buf);
+#else
+ return orig_fstat (fd, buf);
+#endif
}