From dd651509b9082f3117000e168007d5e1e1e72d32 Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Tue, 16 Jan 2018 16:35:25 -0800 Subject: [PATCH] Update filetimes to nsec (#15872) --- .../Interop/Unix/System.Native/Interop.Stat.cs | 10 +++++-- src/pal/src/config.h.in | 1 + src/pal/src/configure.cmake | 1 + src/pal/src/file/file.cpp | 32 ++++++++++++++++++++++ src/pal/src/file/filetime.cpp | 6 ++-- src/pal/src/file/find.cpp | 18 ++++++++---- src/pal/src/include/pal/filetime.h | 9 ++++++ 7 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs index cda00ac..0ca199b 100644 --- a/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs +++ b/src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs @@ -24,9 +24,13 @@ internal static partial class Interop internal uint Gid; internal long Size; internal long ATime; + internal long ATimeNsec; internal long MTime; + internal long MTimeNsec; internal long CTime; + internal long CTimeNsec; internal long BirthTime; + internal long BirthTimeNsec; internal long Dev; internal long Ino; } @@ -49,13 +53,13 @@ internal static partial class Interop HasBirthTime = 1, } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat2", SetLastError = true)] internal static extern int FStat(SafeFileHandle fd, out FileStatus output); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", SetLastError = true)] + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat2", SetLastError = true)] internal static extern int Stat(string path, out FileStatus output); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", SetLastError = true)] + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat2", SetLastError = true)] internal static extern int LStat(string path, out FileStatus output); } } diff --git a/src/pal/src/config.h.in b/src/pal/src/config.h.in index 7968192..0ff6687 100644 --- a/src/pal/src/config.h.in +++ b/src/pal/src/config.h.in @@ -71,6 +71,7 @@ #cmakedefine01 HAVE_PR_SET_PTRACER #cmakedefine01 HAVE_STAT_TIMESPEC +#cmakedefine01 HAVE_STAT_TIM #cmakedefine01 HAVE_STAT_NSEC #cmakedefine01 HAVE_TM_GMTOFF diff --git a/src/pal/src/configure.cmake b/src/pal/src/configure.cmake index d1c7506..0f105ee 100644 --- a/src/pal/src/configure.cmake +++ b/src/pal/src/configure.cmake @@ -134,6 +134,7 @@ int main(int argc, char **argv) { }" HAVE_CPUSET_T) check_struct_has_member ("struct stat" st_atimespec "sys/types.h;sys/stat.h" HAVE_STAT_TIMESPEC) +check_struct_has_member ("struct stat" st_atim "sys/types.h;sys/stat.h" HAVE_STAT_TIM) check_struct_has_member ("struct stat" st_atimensec "sys/types.h;sys/stat.h" HAVE_STAT_NSEC) check_struct_has_member ("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) check_struct_has_member ("ucontext_t" uc_mcontext.gregs[0] ucontext.h HAVE_GREGSET_T) diff --git a/src/pal/src/file/file.cpp b/src/pal/src/file/file.cpp index 5db7d10..be6b342 100644 --- a/src/pal/src/file/file.cpp +++ b/src/pal/src/file/file.cpp @@ -1759,6 +1759,22 @@ GetFileAttributesExW( FILEUnixTimeToFileTime( stat_data.st_mtime, ST_MTIME_NSEC(&stat_data) ); + /* if Unix mtime is greater than atime, return mtime + as the last access time */ + if (CompareFileTime(&attr_data->ftLastAccessTime, + &attr_data->ftLastWriteTime) < 0) + { + attr_data->ftLastAccessTime = attr_data->ftLastWriteTime; + } + + /* if Unix ctime is greater than mtime, return mtime + as the create time */ + if (CompareFileTime(&attr_data->ftLastWriteTime, + &attr_data->ftCreationTime) < 0) + { + attr_data->ftCreationTime = attr_data->ftLastWriteTime; + } + /* Get the file size. GetFileSize is not used because it gets the size of an already-open file */ attr_data->nFileSizeLow = (DWORD) stat_data.st_size; @@ -4451,6 +4467,22 @@ GetFileInformationByHandle( FILEUnixTimeToFileTime( stat_data.st_mtime, ST_MTIME_NSEC(&stat_data) ); + /* if Unix mtime is greater than atime, return mtime + as the last access time */ + if (CompareFileTime(&lpFileInformation->ftLastAccessTime, + &lpFileInformation->ftLastWriteTime) < 0) + { + lpFileInformation->ftLastAccessTime = lpFileInformation->ftLastWriteTime; + } + + /* if Unix ctime is greater than mtime, return mtime + as the create time */ + if (CompareFileTime(&lpFileInformation->ftLastWriteTime, + &lpFileInformation->ftCreationTime) < 0) + { + lpFileInformation->ftCreationTime = lpFileInformation->ftLastWriteTime; + } + lpFileInformation->dwVolumeSerialNumber = stat_data.st_dev; /* Get the file size. GetFileSize is not used because it gets the diff --git a/src/pal/src/file/filetime.cpp b/src/pal/src/file/filetime.cpp index 6cc8dac..bc74686 100644 --- a/src/pal/src/file/filetime.cpp +++ b/src/pal/src/file/filetime.cpp @@ -42,11 +42,11 @@ if it exists, and are defined as 0 otherwise. -- -Also note that there is no analog to "creation time" on Unix systems. +Also note that there is no analog to "creation time" on Linux systems. Instead, we use the inode change time, which is set to the current time whenever mtime changes or when chmod, chown, etc. syscalls modify the -file status. - +file status; or mtime if older. Ideally we would use birthtime when +available. --*/ diff --git a/src/pal/src/file/find.cpp b/src/pal/src/file/find.cpp index 18bf8c4..efc6512 100644 --- a/src/pal/src/file/find.cpp +++ b/src/pal/src/file/find.cpp @@ -417,24 +417,32 @@ FindNextFileA( if ( stat_result ) { - lpFindFileData->ftCreationTime = + lpFindFileData->ftCreationTime = FILEUnixTimeToFileTime( stat_data.st_ctime, ST_CTIME_NSEC(&stat_data) ); - lpFindFileData->ftLastAccessTime = + lpFindFileData->ftLastAccessTime = FILEUnixTimeToFileTime( stat_data.st_atime, ST_ATIME_NSEC(&stat_data) ); - lpFindFileData->ftLastWriteTime = + lpFindFileData->ftLastWriteTime = FILEUnixTimeToFileTime( stat_data.st_mtime, ST_MTIME_NSEC(&stat_data) ); - /* if Unix mtime is greater than atime, return mtime + /* if Unix mtime is greater than atime, return mtime as the last access time */ - if (CompareFileTime(&lpFindFileData->ftLastAccessTime, + if (CompareFileTime(&lpFindFileData->ftLastAccessTime, &lpFindFileData->ftLastWriteTime) < 0) { lpFindFileData->ftLastAccessTime = lpFindFileData->ftLastWriteTime; } + /* if Unix ctime is greater than mtime, return mtime + as the create time */ + if (CompareFileTime(&lpFindFileData->ftLastWriteTime, + &lpFindFileData->ftCreationTime) < 0) + { + lpFindFileData->ftCreationTime = lpFindFileData->ftLastWriteTime; + } + /* get file size */ lpFindFileData->nFileSizeLow = (DWORD)stat_data.st_size; #if SIZEOF_OFF_T > 4 diff --git a/src/pal/src/include/pal/filetime.h b/src/pal/src/include/pal/filetime.h index cb37b41..29b53a8 100644 --- a/src/pal/src/include/pal/filetime.h +++ b/src/pal/src/include/pal/filetime.h @@ -38,6 +38,14 @@ extern "C" #else /* HAVE_STAT_TIMESPEC */ +#if HAVE_STAT_TIM + +#define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atim.tv_nsec) +#define ST_MTIME_NSEC(statstruct) ((statstruct)->st_mtim.tv_nsec) +#define ST_CTIME_NSEC(statstruct) ((statstruct)->st_ctim.tv_nsec) + +#else /* HAVE_STAT_TIM */ + #if HAVE_STAT_NSEC #define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atimensec) @@ -51,6 +59,7 @@ extern "C" #define ST_CTIME_NSEC(statstruct) 0 #endif /* HAVE_STAT_NSEC */ +#endif /* HAVE_STAT_TIM */ #endif /* HAVE_STAT_TIMESPEC */ FILETIME FILEUnixTimeToFileTime( time_t sec, long nsec ); -- 2.7.4