[glib: 1/5] W32: support nanoseconds in stat timestamps
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/5] W32: support nanoseconds in stat timestamps
- Date: Fri, 6 Mar 2020 12:58:26 +0000 (UTC)
commit 4fec9af198420720f0385e2e39fb52b1862a1b3f
Author: РуÑлан Ижбулатов <lrn1986 gmail com>
Date: Sun Jan 19 14:21:33 2020 +0000
W32: support nanoseconds in stat timestamps
Expand our private statbuf structure with st_mtim, st_atim and st_ctim
fields, which are structs that contain tv_sec and tv_nsec fields,
representing a timestamp with 1-second precision (same value as st_mtime, st_atime
and st_ctime) and a fraction of a second (in nanoseconds) that adds nanosecond
precision to the timestamp.
Because FILEETIME only has 100ns precision, this won't be very precise,
but it's better than nothing.
The private _g_win32_filetime_to_unix_time() function is modified
to also return the nanoseconds-remainder along with the seconds timestamp.
The timestamp struct that we're using is named gtimespec to ensure that
it doesn't clash with any existing timespec structs (MinGW-w64 has one,
MSVC doesn't).
gio/glocalfileinfo.c | 9 +++++----
glib/gstdio.c | 33 +++++++++++++++++++++------------
glib/gstdioprivate.h | 14 +++++++++++---
3 files changed, 37 insertions(+), 19 deletions(-)
---
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index 52455672a..866ff8db3 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -126,7 +126,7 @@ _g_local_file_info_create_etag (GLocalFileStat *statbuf)
sec = statbuf->st_mtime;
#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
usec = statbuf->st_mtimensec / 1000;
-#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) || defined (G_OS_WIN32)
usec = statbuf->st_mtim.tv_nsec / 1000;
#else
usec = 0;
@@ -1004,14 +1004,14 @@ set_info_from_stat (GFileInfo *info,
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, statbuf->st_mtime);
#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC,
statbuf->st_mtimensec / 1000);
-#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) || defined (G_OS_WIN32)
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC,
statbuf->st_mtim.tv_nsec / 1000);
#endif
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atime);
#if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC)
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atimensec
/ 1000);
-#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
+#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC) || defined (G_OS_WIN32)
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC,
statbuf->st_atim.tv_nsec / 1000);
#endif
@@ -1040,7 +1040,8 @@ set_info_from_stat (GFileInfo *info,
#elif defined (HAVE_STRUCT_STAT_ST_BIRTHTIM)
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_birthtim);
#elif defined (G_OS_WIN32)
- _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_ctime);
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_ctim.tv_sec);
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED_USEC,
statbuf->st_ctim.tv_nsec / 1000);
#endif
if (_g_file_attribute_matcher_matches_id (attribute_matcher,
diff --git a/glib/gstdio.c b/glib/gstdio.c
index d950d2d54..4d6404884 100644
--- a/glib/gstdio.c
+++ b/glib/gstdio.c
@@ -168,7 +168,8 @@ _g_win32_fix_mode (wchar_t *mode)
* of a signed 64-bit integer (can be negative).
*/
static gint64
-_g_win32_filetime_to_unix_time (FILETIME *ft)
+_g_win32_filetime_to_unix_time (const FILETIME *ft,
+ gint32 *nsec)
{
gint64 result;
/* 1 unit of FILETIME is 100ns */
@@ -179,7 +180,12 @@ _g_win32_filetime_to_unix_time (FILETIME *ft)
const gint64 filetime_unix_epoch_offset = 116444736000000000;
result = ((gint64) ft->dwLowDateTime) | (((gint64) ft->dwHighDateTime) << 32);
- return (result - filetime_unix_epoch_offset) / hundreds_of_usec_per_sec;
+ result -= filetime_unix_epoch_offset;
+
+ if (nsec)
+ *nsec = (result % hundreds_of_usec_per_sec) * 100;
+
+ return result / hundreds_of_usec_per_sec;
}
# ifdef _MSC_VER
@@ -206,10 +212,10 @@ _g_win32_filetime_to_unix_time (FILETIME *ft)
* Tries to reproduce the behaviour and quirks of MS C runtime stat().
*/
static int
-_g_win32_fill_statbuf_from_handle_info (const wchar_t *filename,
- const wchar_t *filename_target,
- BY_HANDLE_FILE_INFORMATION *handle_info,
- struct __stat64 *statbuf)
+_g_win32_fill_statbuf_from_handle_info (const wchar_t *filename,
+ const wchar_t *filename_target,
+ const BY_HANDLE_FILE_INFORMATION *handle_info,
+ struct __stat64 *statbuf)
{
wchar_t drive_letter_w = 0;
size_t drive_letter_size = MB_CUR_MAX;
@@ -291,9 +297,9 @@ _g_win32_fill_statbuf_from_handle_info (const wchar_t *filename,
statbuf->st_nlink = handle_info->nNumberOfLinks;
statbuf->st_uid = statbuf->st_gid = 0;
statbuf->st_size = (((guint64) handle_info->nFileSizeHigh) << 32) | handle_info->nFileSizeLow;
- statbuf->st_ctime = _g_win32_filetime_to_unix_time (&handle_info->ftCreationTime);
- statbuf->st_mtime = _g_win32_filetime_to_unix_time (&handle_info->ftLastWriteTime);
- statbuf->st_atime = _g_win32_filetime_to_unix_time (&handle_info->ftLastAccessTime);
+ statbuf->st_ctime = _g_win32_filetime_to_unix_time (&handle_info->ftCreationTime, NULL);
+ statbuf->st_mtime = _g_win32_filetime_to_unix_time (&handle_info->ftLastWriteTime, NULL);
+ statbuf->st_atime = _g_win32_filetime_to_unix_time (&handle_info->ftLastAccessTime, NULL);
return 0;
}
@@ -320,9 +326,12 @@ _g_win32_fill_privatestat (const struct __stat64 *statbuf,
buf->reparse_tag = reparse_tag;
- buf->st_ctime = statbuf->st_ctime;
- buf->st_atime = statbuf->st_atime;
- buf->st_mtime = statbuf->st_mtime;
+ buf->st_ctim.tv_sec = _g_win32_filetime_to_unix_time (&handle_info->ftCreationTime, &buf->st_ctim.tv_nsec);
+ buf->st_mtim.tv_sec = _g_win32_filetime_to_unix_time (&handle_info->ftLastWriteTime,
&buf->st_mtim.tv_nsec);
+ buf->st_atim.tv_sec = _g_win32_filetime_to_unix_time (&handle_info->ftLastAccessTime,
&buf->st_atim.tv_nsec);
+ buf->st_ctime = buf->st_ctim.tv_sec;
+ buf->st_mtime = buf->st_mtim.tv_sec;
+ buf->st_atime = buf->st_atim.tv_sec;
}
/* Read the link data from a symlink/mountpoint represented
diff --git a/glib/gstdioprivate.h b/glib/gstdioprivate.h
index 71565388a..5583cdd3e 100644
--- a/glib/gstdioprivate.h
+++ b/glib/gstdioprivate.h
@@ -23,6 +23,11 @@ G_BEGIN_DECLS
#if defined (G_OS_WIN32)
+typedef struct _gtimespec {
+ guint64 tv_sec;
+ guint32 tv_nsec;
+} gtimespec;
+
struct _GWin32PrivateStat
{
guint32 volume_serial;
@@ -38,9 +43,12 @@ struct _GWin32PrivateStat
guint16 st_gid;
guint32 st_nlink;
guint64 st_size;
- guint64 st_ctime;
- guint64 st_atime;
- guint64 st_mtime;
+ gint64 st_ctime;
+ gint64 st_atime;
+ gint64 st_mtime;
+ gtimespec st_ctim;
+ gtimespec st_atim;
+ gtimespec st_mtim;
};
typedef struct _GWin32PrivateStat GWin32PrivateStat;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]