bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

windows-stat-timespec: new module


From: Bruno Haible
Subject: windows-stat-timespec: new module
Date: Sat, 13 May 2017 02:52:32 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-75-generic; KDE/5.18.0; x86_64; ; )

The windows-stat-timespec module turns the timestamps in 'struct stat'
to 'struct timespec', on native Windows.


2017-05-13  Bruno Haible  <address@hidden>

        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.

diff --git a/doc/gnulib.texi b/doc/gnulib.texi
index d23ab9c..094a98c 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
 
address@hidden 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 0000000..8aebafc
--- /dev/null
+++ b/doc/windows-stat-timespec.texi
@@ -0,0 +1,13 @@
address@hidden Precise file timestamps on Windows
address@hidden Precise file timestamps on Windows
+
+The module @samp{windows-stat-timespec} ensures that,
+on native Windows platforms, @code{struct stat} contains
address@hidden, @code{st_mtim}, @code{st_ctim} fields of type
address@hidden 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
address@hidden://msdn.microsoft.com/en-us/library/ms724290.aspx}.
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 154d62a..88dcc7f 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 4818a57..515311d 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 68cac29..5426843 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 6e4d788..199e216 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 ef689b9..24d0806 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 f0f443e..155667d 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 0000000..cc758d2
--- /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 2e0aa75..867cc85 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 0000000..d7d44fb
--- /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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]