mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
Merge branch 'w32-fileinfo-mtime-usec' into 'master'
Support nanoseconds in stat timestamps on Windows See merge request GNOME/glib!1329
This commit is contained in:
commit
42c7e89228
@ -123,6 +123,10 @@ _g_local_file_info_create_etag (GLocalFileStat *statbuf)
|
||||
{
|
||||
glong sec, usec;
|
||||
|
||||
#if defined (G_OS_WIN32)
|
||||
sec = statbuf->st_mtim.tv_sec;
|
||||
usec = statbuf->st_mtim.tv_nsec / 1000;
|
||||
#else
|
||||
sec = statbuf->st_mtime;
|
||||
#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
|
||||
usec = statbuf->st_mtimensec / 1000;
|
||||
@ -130,6 +134,7 @@ _g_local_file_info_create_etag (GLocalFileStat *statbuf)
|
||||
usec = statbuf->st_mtim.tv_nsec / 1000;
|
||||
#else
|
||||
usec = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return g_strdup_printf ("%lu:%lu", sec, usec);
|
||||
@ -1000,7 +1005,13 @@ set_info_from_stat (GFileInfo *info,
|
||||
statbuf->allocated_size);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (G_OS_WIN32)
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, statbuf->st_mtim.tv_sec);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtim.tv_nsec / 1000);
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atim.tv_sec);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000);
|
||||
#else
|
||||
_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);
|
||||
@ -1014,6 +1025,7 @@ set_info_from_stat (GFileInfo *info,
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
/* Microsoft uses st_ctime for file creation time,
|
||||
@ -1040,7 +1052,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,
|
||||
@ -2122,7 +2135,7 @@ get_uint32 (const GFileAttributeValue *value,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_UTIMES
|
||||
#if defined (HAVE_UTIMES) || defined (G_OS_WIN32)
|
||||
static gboolean
|
||||
get_uint64 (const GFileAttributeValue *value,
|
||||
guint64 *val_out,
|
||||
@ -2355,7 +2368,180 @@ set_symlink (char *filename,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIMES
|
||||
#if defined (G_OS_WIN32)
|
||||
/* From
|
||||
* https://support.microsoft.com/en-ca/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime
|
||||
* FT = UT * 10000000 + 116444736000000000.
|
||||
* Converts unix epoch time (a signed 64-bit integer) to FILETIME.
|
||||
* Can optionally use a more precise timestamp that has
|
||||
* a fraction of a second expressed in nanoseconds.
|
||||
* UT must be between January 1st of year 1601 and December 31st of year 30827.
|
||||
* nsec must be non-negative and < 1000000000.
|
||||
* Returns TRUE if conversion succeeded, FALSE otherwise.
|
||||
*
|
||||
* The function that does the reverse can be found in
|
||||
* glib/gstdio.c.
|
||||
*/
|
||||
static gboolean
|
||||
_g_win32_unix_time_to_filetime (gint64 ut,
|
||||
gint32 nsec,
|
||||
FILETIME *ft,
|
||||
GError **error)
|
||||
{
|
||||
gint64 result;
|
||||
/* 1 unit of FILETIME is 100ns */
|
||||
const gint64 hundreds_of_usec_per_sec = 10000000;
|
||||
/* The difference between January 1, 1601 UTC (FILETIME epoch) and UNIX epoch
|
||||
* in hundreds of nanoseconds.
|
||||
*/
|
||||
const gint64 filetime_unix_epoch_offset = 116444736000000000;
|
||||
/* This is the maximum timestamp that SYSTEMTIME can
|
||||
* represent (last millisecond of the year 30827).
|
||||
* Since FILETIME and SYSTEMTIME are both used on Windows,
|
||||
* we use this as a limit (FILETIME can support slightly
|
||||
* larger interval, up to year 30828).
|
||||
*/
|
||||
const gint64 max_systemtime = 0x7fff35f4f06c58f0;
|
||||
|
||||
g_return_val_if_fail (ft != NULL, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
if (nsec < 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
_("Extra nanoseconds %d for UNIX timestamp %lld are negative"),
|
||||
nsec, ut);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nsec >= hundreds_of_usec_per_sec * 100)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
_("Extra nanoseconds %d for UNIX timestamp %lld reach 1 second"),
|
||||
nsec, ut);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ut >= (G_MAXINT64 / hundreds_of_usec_per_sec) ||
|
||||
(ut * hundreds_of_usec_per_sec) >= (G_MAXINT64 - filetime_unix_epoch_offset))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
_("UNIX timestamp %lld does not fit into 64 bits"),
|
||||
ut);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = ut * hundreds_of_usec_per_sec + filetime_unix_epoch_offset + nsec / 100;
|
||||
|
||||
if (result >= max_systemtime || result < 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
_("UNIX timestamp %lld is outside of the range supported by Windows"),
|
||||
ut);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ft->dwLowDateTime = (DWORD) (result);
|
||||
ft->dwHighDateTime = (DWORD) (result >> 32);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_mtime_atime (const char *filename,
|
||||
const GFileAttributeValue *mtime_value,
|
||||
const GFileAttributeValue *mtime_usec_value,
|
||||
const GFileAttributeValue *atime_value,
|
||||
const GFileAttributeValue *atime_usec_value,
|
||||
GError **error)
|
||||
{
|
||||
BOOL res;
|
||||
guint64 val = 0;
|
||||
guint32 val_usec = 0;
|
||||
gunichar2 *filename_utf16;
|
||||
SECURITY_ATTRIBUTES sec = { sizeof (SECURITY_ATTRIBUTES), NULL, FALSE };
|
||||
HANDLE file_handle;
|
||||
FILETIME mtime;
|
||||
FILETIME atime;
|
||||
FILETIME *p_mtime = NULL;
|
||||
FILETIME *p_atime = NULL;
|
||||
DWORD gle;
|
||||
|
||||
/* ATIME */
|
||||
if (atime_value)
|
||||
{
|
||||
if (!get_uint64 (atime_value, &val, error))
|
||||
return FALSE;
|
||||
val_usec = 0;
|
||||
if (atime_usec_value &&
|
||||
!get_uint32 (atime_usec_value, &val_usec, error))
|
||||
return FALSE;
|
||||
if (!_g_win32_unix_time_to_filetime (val, val_usec, &atime, error))
|
||||
return FALSE;
|
||||
p_atime = &atime;
|
||||
}
|
||||
|
||||
/* MTIME */
|
||||
if (mtime_value)
|
||||
{
|
||||
if (!get_uint64 (mtime_value, &val, error))
|
||||
return FALSE;
|
||||
val_usec = 0;
|
||||
if (mtime_usec_value &&
|
||||
!get_uint32 (mtime_usec_value, &val_usec, error))
|
||||
return FALSE;
|
||||
if (!_g_win32_unix_time_to_filetime (val, val_usec, &mtime, error))
|
||||
return FALSE;
|
||||
p_mtime = &mtime;
|
||||
}
|
||||
|
||||
filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, error);
|
||||
|
||||
if (filename_utf16 == NULL)
|
||||
{
|
||||
g_prefix_error (error,
|
||||
_("File name “%s” cannot be converted to UTF-16"),
|
||||
filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file_handle = CreateFileW (filename_utf16,
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
&sec,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
gle = GetLastError ();
|
||||
g_clear_pointer (&filename_utf16, g_free);
|
||||
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
g_io_error_from_errno (gle),
|
||||
_("File “%s” cannot be opened: Windows Error %lu"),
|
||||
filename, gle);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = SetFileTime (file_handle, NULL, p_atime, p_mtime);
|
||||
gle = GetLastError ();
|
||||
CloseHandle (file_handle);
|
||||
|
||||
if (!res)
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
g_io_error_from_errno (gle),
|
||||
_("Error setting modification or access time for file “%s”: %lu"),
|
||||
filename, gle);
|
||||
|
||||
return res;
|
||||
}
|
||||
#elif defined (HAVE_UTIMES)
|
||||
static int
|
||||
lazy_stat (char *filename,
|
||||
struct stat *statbuf,
|
||||
@ -2535,7 +2721,7 @@ _g_local_file_info_set_attribute (char *filename,
|
||||
return set_symlink (filename, &value, error);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIMES
|
||||
#if defined (HAVE_UTIMES) || defined (G_OS_WIN32)
|
||||
else if (strcmp (attribute, G_FILE_ATTRIBUTE_TIME_MODIFIED) == 0)
|
||||
return set_mtime_atime (filename, &value, NULL, NULL, NULL, error);
|
||||
else if (strcmp (attribute, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC) == 0)
|
||||
@ -2602,9 +2788,11 @@ _g_local_file_info_set_attributes (char *filename,
|
||||
GFileAttributeValue *value;
|
||||
#ifdef G_OS_UNIX
|
||||
GFileAttributeValue *uid, *gid;
|
||||
#ifdef HAVE_UTIMES
|
||||
#endif
|
||||
#if defined (HAVE_UTIMES) || defined (G_OS_WIN32)
|
||||
GFileAttributeValue *mtime, *mtime_usec, *atime, *atime_usec;
|
||||
#endif
|
||||
#if defined (G_OS_UNIX) || defined (G_OS_WIN32)
|
||||
GFileAttributeStatus status;
|
||||
#endif
|
||||
gboolean res;
|
||||
@ -2675,7 +2863,7 @@ _g_local_file_info_set_attributes (char *filename,
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_UTIMES
|
||||
#if defined (HAVE_UTIMES) || defined (G_OS_WIN32)
|
||||
/* Group all time settings into one call
|
||||
* Change times as the last thing to avoid it changing due to metadata changes
|
||||
*/
|
||||
|
@ -229,6 +229,13 @@ test_internal_enhanced_stdio (void)
|
||||
{ 0x62AB5D82, 0xFDC1, 0x4DC3, { 0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97 } };
|
||||
static const GUID folder_id_users =
|
||||
{ 0x0762D272, 0xC50A, 0x4BB0, { 0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80 } };
|
||||
GDateTime *dt = NULL, *dt2 = NULL;
|
||||
GTimeSpan ts;
|
||||
/* Just before SYSTEMTIME limit (Jan 1 30827) */
|
||||
const gint64 one_sec_before_systemtime_limit = 910670515199;
|
||||
gboolean retval;
|
||||
GError *local_error = NULL;
|
||||
|
||||
|
||||
programdata_dir_w = NULL;
|
||||
SHGetKnownFolderPath (&folder_id_programdata, 0, NULL, &programdata_dir_w);
|
||||
@ -552,7 +559,8 @@ test_internal_enhanced_stdio (void)
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE ","
|
||||
G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
|
||||
G_FILE_ATTRIBUTE_ID_FILE ","
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED ","
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
|
||||
@ -560,7 +568,8 @@ test_internal_enhanced_stdio (void)
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE ","
|
||||
G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
|
||||
G_FILE_ATTRIBUTE_ID_FILE ","
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED ","
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
|
||||
@ -568,11 +577,13 @@ test_internal_enhanced_stdio (void)
|
||||
g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_ID_FILE));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC));
|
||||
|
||||
g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_SIZE));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_ID_FILE));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED));
|
||||
g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC));
|
||||
|
||||
size_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE);
|
||||
alsize_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
|
||||
@ -604,6 +615,56 @@ test_internal_enhanced_stdio (void)
|
||||
*/
|
||||
g_assert_cmpuint (time_p0, >, G_GUINT64_CONSTANT (0xFFFFFFFF));
|
||||
|
||||
dt = g_file_info_get_modification_date_time (fi_p0);
|
||||
g_assert_nonnull (dt);
|
||||
dt2 = g_date_time_add (dt, G_USEC_PER_SEC / 100 * 200);
|
||||
g_object_unref (fi_p0);
|
||||
fi_p0 = g_file_info_new ();
|
||||
g_file_info_set_modification_date_time (fi_p0, dt2);
|
||||
|
||||
g_assert_true (g_file_set_attributes_from_info (gf_p0,
|
||||
fi_p0,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL,
|
||||
NULL));
|
||||
g_date_time_unref (dt2);
|
||||
g_object_unref (fi_p0);
|
||||
fi_p0 = g_file_query_info (gf_p0,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED ","
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
dt2 = g_file_info_get_modification_date_time (fi_p0);
|
||||
ts = g_date_time_difference (dt2, dt);
|
||||
g_assert_cmpint (ts, >, 0);
|
||||
g_assert_cmpint (ts, <, G_USEC_PER_SEC / 100 * 300);
|
||||
|
||||
g_date_time_unref (dt);
|
||||
g_date_time_unref (dt2);
|
||||
|
||||
g_file_info_set_attribute_uint64 (fi_p0,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED,
|
||||
one_sec_before_systemtime_limit);
|
||||
g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
|
||||
g_assert_true (g_file_set_attributes_from_info (gf_p0,
|
||||
fi_p0,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
g_file_info_set_attribute_uint64 (fi_p0,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED,
|
||||
one_sec_before_systemtime_limit + G_USEC_PER_SEC * 2);
|
||||
g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
|
||||
retval = g_file_set_attributes_from_info (gf_p0,
|
||||
fi_p0,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL,
|
||||
&local_error);
|
||||
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
|
||||
g_assert_false (retval);
|
||||
g_clear_error (&local_error);
|
||||
|
||||
g_object_unref (fi_p0);
|
||||
g_object_unref (fi_p1);
|
||||
g_object_unref (gf_p0);
|
||||
|
@ -99,7 +99,11 @@ test_validity (void)
|
||||
thumbnail_path = g_test_get_filename (G_TEST_DIST, "thumbnails",
|
||||
tests[i].filename, NULL);
|
||||
file_uri = g_strconcat ("file:///tmp/", tests[i].filename, NULL);
|
||||
#ifdef G_OS_WIN32
|
||||
stat_buf.st_mtim.tv_sec = tests[i].mtime;
|
||||
#else
|
||||
stat_buf.st_mtime = tests[i].mtime;
|
||||
#endif
|
||||
stat_buf.st_size = tests[i].size;
|
||||
|
||||
result = thumbnail_verify (thumbnail_path, file_uri, &stat_buf);
|
||||
|
@ -232,7 +232,11 @@ thumbnail_verify (const char *thumbnail_path,
|
||||
return FALSE;
|
||||
|
||||
expected_info.uri = file_uri;
|
||||
#ifdef G_OS_WIN32
|
||||
expected_info.mtime = (guint64) file_stat_buf->st_mtim.tv_sec;
|
||||
#else
|
||||
expected_info.mtime = (guint64) file_stat_buf->st_mtime;
|
||||
#endif
|
||||
expected_info.size = file_stat_buf->st_size;
|
||||
|
||||
file = g_mapped_file_new (thumbnail_path, FALSE, NULL);
|
||||
|
@ -166,9 +166,13 @@ _g_win32_fix_mode (wchar_t *mode)
|
||||
* UT = (FT - 116444736000000000) / 10000000.
|
||||
* Converts FILETIME to unix epoch time in form
|
||||
* of a signed 64-bit integer (can be negative).
|
||||
*
|
||||
* The function that does the reverse can be found in
|
||||
* gio/glocalfileinfo.c.
|
||||
*/
|
||||
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 +183,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 +215,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 +300,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 +329,9 @@ _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);
|
||||
}
|
||||
|
||||
/* Read the link data from a symlink/mountpoint represented
|
||||
@ -1322,9 +1331,9 @@ g_stat (const gchar *filename,
|
||||
buf->st_gid = w32_buf.st_gid;
|
||||
buf->st_rdev = w32_buf.st_dev;
|
||||
buf->st_size = w32_buf.st_size;
|
||||
buf->st_atime = w32_buf.st_atime;
|
||||
buf->st_mtime = w32_buf.st_mtime;
|
||||
buf->st_ctime = w32_buf.st_ctime;
|
||||
buf->st_atime = w32_buf.st_atim.tv_sec;
|
||||
buf->st_mtime = w32_buf.st_mtim.tv_sec;
|
||||
buf->st_ctime = w32_buf.st_ctim.tv_sec;
|
||||
|
||||
return retval;
|
||||
#else
|
||||
@ -1371,9 +1380,9 @@ g_lstat (const gchar *filename,
|
||||
buf->st_gid = w32_buf.st_gid;
|
||||
buf->st_rdev = w32_buf.st_dev;
|
||||
buf->st_size = w32_buf.st_size;
|
||||
buf->st_atime = w32_buf.st_atime;
|
||||
buf->st_mtime = w32_buf.st_mtime;
|
||||
buf->st_ctime = w32_buf.st_ctime;
|
||||
buf->st_atime = w32_buf.st_atim.tv_sec;
|
||||
buf->st_mtime = w32_buf.st_mtim.tv_sec;
|
||||
buf->st_ctime = w32_buf.st_ctim.tv_sec;
|
||||
|
||||
return retval;
|
||||
#else
|
||||
|
@ -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,9 @@ struct _GWin32PrivateStat
|
||||
guint16 st_gid;
|
||||
guint32 st_nlink;
|
||||
guint64 st_size;
|
||||
guint64 st_ctime;
|
||||
guint64 st_atime;
|
||||
guint64 st_mtime;
|
||||
gtimespec st_ctim;
|
||||
gtimespec st_atim;
|
||||
gtimespec st_mtim;
|
||||
};
|
||||
|
||||
typedef struct _GWin32PrivateStat GWin32PrivateStat;
|
||||
|
Loading…
Reference in New Issue
Block a user