]> Savannah Git Hosting - gnulib.git/commitdiff
windows-stat-timespec: New module.
authorBruno Haible <bruno@clisp.org>
Sat, 13 May 2017 00:51:05 +0000 (02:51 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 13 May 2017 00:51:54 +0000 (02:51 +0200)
* 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.

12 files changed:
ChangeLog
doc/gnulib.texi
doc/windows-stat-timespec.texi [new file with mode: 0644]
lib/stat-time.h
lib/stat-w32.c
lib/stat-w32.h
lib/stat.c
lib/sys_stat.in.h
m4/sys_stat_h.m4
m4/windows-stat-timespec.m4 [new file with mode: 0644]
modules/sys_stat
modules/windows-stat-timespec [new file with mode: 0644]

index 2eebc4c22b190f1b2467f87f2f3781b07995e0e2..72a0560baf754dbe29c037cf2f7dc47386eebc63 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+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.
index d23ab9c06817c8e91d851138418970b5cd34b873..094a98c42c4af251d2ec5f1fcf0195b71919b16a 100644 (file)
@@ -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 (file)
index 0000000..8aebafc
--- /dev/null
@@ -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}.
index 154d62a01f548dfc12b1da3aacfe90ec633f4abc..88dcc7f3e0d630a52fdec4d639b63840d7bcffce 100644 (file)
@@ -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)
index 4818a57a8c625918cecb155eaef0e766d327af69..515311d8349ede92291107aab72db6e31631054f 100644 (file)
@@ -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
index 68cac29f91c2edcc763cbb11b2e97fa5325f2295..54268432cd438e37d3e3c3c4ead3d250a29b150c 100644 (file)
 #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.
index 6e4d788ab7348a6a4ba5e93bb356f55eee834e1e..199e216cc5d4bc745b841f1b69d4cd908452d0c0 100644 (file)
@@ -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);
 
index ef689b984f4268a86f094ca04e79c30f219f61e9..24d08068fa52a4c1660d6e1250db497450aba273 100644 (file)
@@ -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
index f0f443e9d80344c9c151f22c61926f9f8ab9a059..155667df30f6cd106af87b41f6b4cead025a3f02 100644 (file)
@@ -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 (file)
index 0000000..cc758d2
--- /dev/null
@@ -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
+])
index 2e0aa758449210592fc297bc6998834e6dde25cf..867cc8549818cd72ed6031fae2865b75d2e3ef69 100644 (file)
@@ -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 (file)
index 0000000..d7d44fb
--- /dev/null
@@ -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