From 929844fdf73dc016e1f478e9c2c9ab1854344250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Wed, 8 Aug 2018 21:39:43 +0000 Subject: [PATCH 1/2] W32: correctly use st_ctime On Windows st_ctime field is the file creation time. POSIX mandates that field to be the file state change time. Naturally, glib code interpreted st_ctime as POSIX suggested, and the result was bad. Fix this by introducing special W32-only logic for setting attributes from st_ctime field. Fixes issue #1452. --- gio/glocalfileinfo.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index b3e29374a..651992f5b 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -1005,13 +1005,20 @@ 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 - + +#ifndef G_OS_WIN32 + /* Microsoft uses st_ctime for file creation time, + * instead of file change time: + * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions#generic-text-routine-mappings + * Thank you, Microsoft! + */ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, statbuf->st_ctime); #if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC) _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC) _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctim.tv_nsec / 1000); #endif +#endif #if defined (HAVE_STRUCT_STAT_ST_BIRTHTIME) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_birthtime); @@ -1023,6 +1030,8 @@ set_info_from_stat (GFileInfo *info, _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_birthtime); #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); #endif if (_g_file_attribute_matcher_matches_id (attribute_matcher, From 075bb0f7511ee83266f823359ad3feec098f2298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Wed, 8 Aug 2018 21:42:45 +0000 Subject: [PATCH 2/2] W32: consider NTFS mounpoints to be symlinks While mountpoints are *not* symlinks, strictly speaking, they works in a similar enough way, so consider them to be symlinks for the purpose of querying local file info. --- gio/glocalfileinfo.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index 651992f5b..9cf7ff845 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -961,7 +961,8 @@ set_info_from_stat (GFileInfo *info, else if (S_ISLNK (statbuf->st_mode)) file_type = G_FILE_TYPE_SYMBOLIC_LINK; #elif defined (G_OS_WIN32) - if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK) + if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK || + statbuf->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT) file_type = G_FILE_TYPE_SYMBOLIC_LINK; #endif @@ -1808,7 +1809,9 @@ _g_local_file_info_get (const char *basename, is_symlink = stat_ok && S_ISLNK (statbuf.st_mode); #elif defined (G_OS_WIN32) /* glib already checked the FILE_ATTRIBUTE_REPARSE_POINT for us */ - is_symlink = stat_ok && statbuf.reparse_tag == IO_REPARSE_TAG_SYMLINK; + is_symlink = stat_ok && + (statbuf.reparse_tag == IO_REPARSE_TAG_SYMLINK || + statbuf.reparse_tag == IO_REPARSE_TAG_MOUNT_POINT); #else is_symlink = FALSE; #endif @@ -2191,7 +2194,9 @@ set_unix_mode (char *filename, GWin32PrivateStat statbuf; res = GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (filename, &statbuf); - is_symlink = (res == 0 && statbuf.reparse_tag == IO_REPARSE_TAG_SYMLINK); + is_symlink = (res == 0 && + (statbuf.reparse_tag == IO_REPARSE_TAG_SYMLINK || + statbuf.reparse_tag == IO_REPARSE_TAG_MOUNT_POINT)); #endif if (is_symlink) {