Update filetimes to nsec (#15872)
authorDan Moseley <danmose@microsoft.com>
Wed, 17 Jan 2018 00:35:25 +0000 (16:35 -0800)
committerJan Kotas <jkotas@microsoft.com>
Wed, 17 Jan 2018 00:35:25 +0000 (16:35 -0800)
src/mscorlib/shared/Interop/Unix/System.Native/Interop.Stat.cs
src/pal/src/config.h.in
src/pal/src/configure.cmake
src/pal/src/file/file.cpp
src/pal/src/file/filetime.cpp
src/pal/src/file/find.cpp
src/pal/src/include/pal/filetime.h

index cda00ac..0ca199b 100644 (file)
@@ -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);
     }
 }
index 7968192..0ff6687 100644 (file)
@@ -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
 
index d1c7506..0f105ee 100644 (file)
@@ -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)
index 5db7d10..be6b342 100644 (file)
@@ -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
index 6cc8dac..bc74686 100644 (file)
@@ -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.
 
 
 --*/
index 18bf8c4..efc6512 100644 (file)
@@ -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
index cb37b41..29b53a8 100644 (file)
@@ -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 );