summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2017-05-13 02:51:05 +0200
committerBruno Haible <bruno@clisp.org>2017-05-13 02:51:54 +0200
commit7d2f35f7f976cc29baf22fd0d4d1d58fc870ce64 (patch)
tree5dc742225bf9ac0b554ff0dbd64e6ced0ea748ef
parent44fe2082cf3e604bf0b4fe7259d1edb7cce334da (diff)
downloadgnulib-7d2f35f7f976cc29baf22fd0d4d1d58fc870ce64.tar.gz
windows-stat-timespec: New module.
* modules/windows-stat-timespec: New file. * m4/windows-stat-timespec.m4: New file. * m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Set WINDOWS_STAT_TIMESPEC. * modules/sys_stat (Makefile.am): Substitute WINDOWS_STAT_TIMESPEC. * lib/sys_stat.in.h (struct stat) [WINDOWS_STAT_TIMESPEC]: Declare with fields st_atim, st_mtim, st_ctim. (st_atime, st_mtime, st_ctime): Define as macros. (_GL_WINDOWS_STAT_TIMESPEC): New macro. * lib/stat-w32.h (_gl_convert_FILETIME_to_timespec) [_GL_WINDOWS_STAT_TIMESPEC]: New declaration. * lib/stat-w32.c (_gl_convert_FILETIME_to_timespec) [_GL_WINDOWS_STAT_TIMESPEC]: New function. (_gl_convert_FILETIME_to_POSIX): Adjust coding style. (_gl_fstat_by_handle): If _GL_WINDOWS_STAT_TIMESPEC, convert the FILETIME to 'struct timespec', not 'time_t'. * lib/stat.c (rpl_stat): If _GL_WINDOWS_STAT_TIMESPEC, convert the FILETIME to 'struct timespec', not 'time_t'. * lib/stat-time.h (STAT_TIMESPEC): Define also if _GL_WINDOWS_STAT_TIMESPEC. * doc/windows-stat-timespec.texi: New file. * doc/gnulib.texi: Include it.
-rw-r--r--ChangeLog25
-rw-r--r--doc/gnulib.texi3
-rw-r--r--doc/windows-stat-timespec.texi13
-rw-r--r--lib/stat-time.h4
-rw-r--r--lib/stat-w32.c52
-rw-r--r--lib/stat-w32.h4
-rw-r--r--lib/stat.c6
-rw-r--r--lib/sys_stat.in.h6
-rw-r--r--m4/sys_stat_h.m410
-rw-r--r--m4/windows-stat-timespec.m416
-rw-r--r--modules/sys_stat1
-rw-r--r--modules/windows-stat-timespec28
12 files changed, 158 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 2eebc4c22b..72a0560baf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
2017-05-13 Bruno Haible <bruno@clisp.org>
+ windows-stat-timespec: New module.
+ * modules/windows-stat-timespec: New file.
+ * m4/windows-stat-timespec.m4: New file.
+ * m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Set WINDOWS_STAT_TIMESPEC.
+ * modules/sys_stat (Makefile.am): Substitute WINDOWS_STAT_TIMESPEC.
+ * lib/sys_stat.in.h (struct stat) [WINDOWS_STAT_TIMESPEC]: Declare with
+ fields st_atim, st_mtim, st_ctim.
+ (st_atime, st_mtime, st_ctime): Define as macros.
+ (_GL_WINDOWS_STAT_TIMESPEC): New macro.
+ * lib/stat-w32.h (_gl_convert_FILETIME_to_timespec)
+ [_GL_WINDOWS_STAT_TIMESPEC]: New declaration.
+ * lib/stat-w32.c (_gl_convert_FILETIME_to_timespec)
+ [_GL_WINDOWS_STAT_TIMESPEC]: New function.
+ (_gl_convert_FILETIME_to_POSIX): Adjust coding style.
+ (_gl_fstat_by_handle): If _GL_WINDOWS_STAT_TIMESPEC, convert the
+ FILETIME to 'struct timespec', not 'time_t'.
+ * lib/stat.c (rpl_stat): If _GL_WINDOWS_STAT_TIMESPEC, convert the
+ FILETIME to 'struct timespec', not 'time_t'.
+ * lib/stat-time.h (STAT_TIMESPEC): Define also if
+ _GL_WINDOWS_STAT_TIMESPEC.
+ * doc/windows-stat-timespec.texi: New file.
+ * doc/gnulib.texi: Include it.
+
+2017-05-13 Bruno Haible <bruno@clisp.org>
+
windows-stat-override: New module.
* lib/sys_stat.in.h (stat) [GNULIB_OVERRIDES_STRUCT_STAT]: Provide own
definition. Define GNULIB_defined_struct_stat.
diff --git a/doc/gnulib.texi b/doc/gnulib.texi
index d23ab9c068..094a98c42c 100644
--- a/doc/gnulib.texi
+++ b/doc/gnulib.texi
@@ -6323,12 +6323,15 @@ to POSIX that it can be treated like any other Unix-like platform.
@menu
* Libtool and Windows::
+* Precise file timestamps on Windows::
* Windows sockets::
* Native Windows Support without MSVC Support::
@end menu
@include windows-libtool.texi
+@include windows-stat-timespec.texi
+
@include windows-sockets.texi
@include windows-without-msvc.texi
diff --git a/doc/windows-stat-timespec.texi b/doc/windows-stat-timespec.texi
new file mode 100644
index 0000000000..8aebafc222
--- /dev/null
+++ b/doc/windows-stat-timespec.texi
@@ -0,0 +1,13 @@
+@node Precise file timestamps on Windows
+@section Precise file timestamps on Windows
+
+The module @samp{windows-stat-timespec} ensures that,
+on native Windows platforms, @code{struct stat} contains
+@code{st_atim}, @code{st_mtim}, @code{st_ctim} fields of type
+@code{struct timespec}, providing 100 ns resolution for the timestamps
+of files.
+
+Note: On some types of file systems, the timestamp resolution is limited
+by the file system. For example, on FAT file systems, @code{st_mtim}
+only has a resolution of 2 seconds. For more details, see
+@url{https://msdn.microsoft.com/en-us/library/ms724290.aspx}.
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 154d62a01f..88dcc7f3e0 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -43,8 +43,8 @@ extern "C" {
time respectively.
These macros are private to stat-time.h. */
-#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
-# ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
+#if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+# if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
# else
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
diff --git a/lib/stat-w32.c b/lib/stat-w32.c
index 4818a57a8c..515311d834 100644
--- a/lib/stat-w32.c
+++ b/lib/stat-w32.c
@@ -53,6 +53,32 @@ initialize (void)
}
/* Converts a FILETIME to GMT time since 1970-01-01 00:00:00. */
+#if _GL_WINDOWS_STAT_TIMESPEC
+struct timespec
+_gl_convert_FILETIME_to_timespec (const FILETIME *ft)
+{
+ struct timespec result;
+ /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
+ unsigned long long since_1601 =
+ ((unsigned long long) ft->dwHighDateTime << 32)
+ | (unsigned long long) ft->dwLowDateTime;
+ if (since_1601 == 0)
+ {
+ result.tv_sec = 0;
+ result.tv_nsec = 0;
+ }
+ else
+ {
+ /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89
+ leap years, in total 134774 days. */
+ unsigned long long since_1970 =
+ since_1601 - (unsigned long long) 134774 * (unsigned long long) 86400 * (unsigned long long) 10000000;
+ result.tv_sec = since_1970 / (unsigned long long) 10000000;
+ result.tv_nsec = (unsigned long) (since_1970 % (unsigned long long) 10000000) * 100;
+ }
+ return result;
+}
+#else
time_t
_gl_convert_FILETIME_to_POSIX (const FILETIME *ft)
{
@@ -62,12 +88,16 @@ _gl_convert_FILETIME_to_POSIX (const FILETIME *ft)
| (unsigned long long) ft->dwLowDateTime;
if (since_1601 == 0)
return 0;
- /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap
- years, in total 134774 days. */
- unsigned long long since_1970 =
- since_1601 - (unsigned long long) 134774 * (unsigned long long) 86400 * (unsigned long long) 10000000;
- return since_1970 / (unsigned long long) 10000000;
+ else
+ {
+ /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89
+ leap years, in total 134774 days. */
+ unsigned long long since_1970 =
+ since_1601 - (unsigned long long) 134774 * (unsigned long long) 86400 * (unsigned long long) 10000000;
+ return since_1970 / (unsigned long long) 10000000;
+ }
}
+#endif
/* Fill *BUF with information about the file designated by H.
PATH is the file name, if known, otherwise NULL.
@@ -218,9 +248,15 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
<https://msdn.microsoft.com/en-us/library/aa364953.aspx>
<https://msdn.microsoft.com/en-us/library/aa364217.aspx>
The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
+#if _GL_WINDOWS_STAT_TIMESPEC
+ buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime);
+ buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime);
+ buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime);
+#else
buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime);
buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime);
buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime);
+#endif
return 0;
}
@@ -245,9 +281,15 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
}
else
buf->st_size = 0;
+#if _GL_WINDOWS_STAT_TIMESPEC
+ buf->st_atim.tv_sec = 0; buf->st_atim.tv_nsec = 0;
+ buf->st_mtim.tv_sec = 0; buf->st_mtim.tv_nsec = 0;
+ buf->st_ctim.tv_sec = 0; buf->st_ctim.tv_nsec = 0;
+#else
buf->st_atime = 0;
buf->st_mtime = 0;
buf->st_ctime = 0;
+#endif
return 0;
}
else
diff --git a/lib/stat-w32.h b/lib/stat-w32.h
index 68cac29f91..54268432cd 100644
--- a/lib/stat-w32.h
+++ b/lib/stat-w32.h
@@ -18,7 +18,11 @@
#define _STAT_W32_H 1
/* Converts a FILETIME to GMT time since 1970-01-01 00:00:00. */
+#if _GL_WINDOWS_STAT_TIMESPEC
+extern struct timespec _gl_convert_FILETIME_to_timespec (const FILETIME *ft);
+#else
extern time_t _gl_convert_FILETIME_to_POSIX (const FILETIME *ft);
+#endif
/* Fill *BUF with information about the file designated by H.
PATH is the file name, if known, otherwise NULL.
diff --git a/lib/stat.c b/lib/stat.c
index 6e4d788ab7..199e216cc5 100644
--- a/lib/stat.c
+++ b/lib/stat.c
@@ -264,9 +264,15 @@ rpl_stat (char const *name, struct stat *buf)
buf->st_size = ((long long) info.nFileSizeHigh << 32) | (long long) info.nFileSizeLow;
/* st_atime, st_mtime, st_ctime. */
+# if _GL_WINDOWS_STAT_TIMESPEC
+ buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime);
+ buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime);
+ buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime);
+# else
buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime);
buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime);
buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime);
+# endif
FindClose (h);
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index ef689b984f..24d08068fa 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -108,7 +108,7 @@ struct stat
blkcnt_t st_blocks;
# endif
-# if 0
+# if @WINDOWS_STAT_TIMESPEC@
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
@@ -118,10 +118,12 @@ struct stat
time_t st_ctime;
# endif
};
-# if 0
+# if @WINDOWS_STAT_TIMESPEC@
# define st_atime st_atim.tv_sec
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
+ /* Indicator, for gnulib internal purposes. */
+# define _GL_WINDOWS_STAT_TIMESPEC 1
# endif
# define GNULIB_defined_struct_stat 1
# endif
diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
index f0f443e9d8..155667df30 100644
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,4 +1,4 @@
-# sys_stat_h.m4 serial 29 -*- Autoconf -*-
+# sys_stat_h.m4 serial 30 -*- Autoconf -*-
dnl Copyright (C) 2006-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -19,6 +19,14 @@ AC_DEFUN([gl_HEADER_SYS_STAT_H],
dnl Ensure the type mode_t gets defined.
AC_REQUIRE([AC_TYPE_MODE_T])
+ dnl Whether to enable precise timestamps in 'struct stat'.
+ m4_ifdef([gl_WINDOWS_STAT_TIMESPEC], [
+ AC_REQUIRE([gl_WINDOWS_STAT_TIMESPEC])
+ ], [
+ WINDOWS_STAT_TIMESPEC=0
+ ])
+ AC_SUBST([WINDOWS_STAT_TIMESPEC])
+
dnl Whether to override 'struct stat'.
m4_ifdef([gl_LARGEFILE], [
AC_REQUIRE([gl_LARGEFILE])
diff --git a/m4/windows-stat-timespec.m4 b/m4/windows-stat-timespec.m4
new file mode 100644
index 0000000000..cc758d23d5
--- /dev/null
+++ b/m4/windows-stat-timespec.m4
@@ -0,0 +1,16 @@
+# windows-stat-timespec.m4 serial 1
+dnl Copyright (C) 2017 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.
+
+dnl Enable precise timestamps in 'struct stat' on native Windows platforms.
+
+AC_DEFUN([gl_WINDOWS_STAT_TIMESPEC],
+[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ case "$host_os" in
+ mingw*) WINDOWS_STAT_TIMESPEC=1 ;;
+ *) WINDOWS_STAT_TIMESPEC=0 ;;
+ esac
+])
diff --git a/modules/sys_stat b/modules/sys_stat
index 2e0aa75844..867cc85498 100644
--- a/modules/sys_stat
+++ b/modules/sys_stat
@@ -33,6 +33,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
-e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
-e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
+ -e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \
-e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \
-e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
-e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
diff --git a/modules/windows-stat-timespec b/modules/windows-stat-timespec
new file mode 100644
index 0000000000..d7d44fba28
--- /dev/null
+++ b/modules/windows-stat-timespec
@@ -0,0 +1,28 @@
+Description:
+On native Windows platforms, ensure that 'struct stat' contains
+st_atim, st_mtim, st_ctim fields of type 'struct timespec', providing
+100 ns resolution for the timestamps of files.
+
+Comment:
+This module should not be used as a dependency from a test module,
+otherwise when this module occurs as a tests-related module, it will
+have side effects on the compilation of the main modules in lib/.
+
+Files:
+m4/windows-stat-timespec.m4
+
+Depends-on:
+windows-stat-override
+
+configure.ac:
+AC_REQUIRE([gl_WINDOWS_STAT_TIMESPEC])
+
+Makefile.am:
+
+Include:
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible