mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 07:56:17 +01:00
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).
This commit is contained in:
parent
0d3d3e1d84
commit
4fec9af198
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user