6939260: (fs) BasicFileAttributes.lastModifiedTime() should return last modified time with higher precision
authoralanb
Fri, 18 Jan 2013 18:48:44 +0000
changeset 15275 6e5b8f8361eb
parent 15274 a77cdd5ea6e3
child 15276 bbddb82e66ce
6939260: (fs) BasicFileAttributes.lastModifiedTime() should return last modified time with higher precision Reviewed-by: chegar
jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java
jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c
jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java	Fri Jan 18 17:34:40 2013 +0000
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java	Fri Jan 18 18:48:44 2013 +0000
@@ -45,9 +45,12 @@
     private int     st_uid;
     private int     st_gid;
     private long    st_size;
-    private long    st_atime;
-    private long    st_mtime;
-    private long    st_ctime;
+    private long    st_atime_sec;
+    private long    st_atime_nsec;
+    private long    st_mtime_sec;
+    private long    st_mtime_nsec;
+    private long    st_ctime_sec;
+    private long    st_ctime_nsec;
 
     // created lazily
     private volatile UserPrincipal owner;
@@ -101,8 +104,20 @@
     int uid()   { return st_uid; }
     int gid()   { return st_gid; }
 
+    private static FileTime toFileTime(long sec, long nsec) {
+        if (nsec == 0) {
+            return FileTime.from(sec, TimeUnit.SECONDS);
+        } else {
+            // truncate to microseconds to avoid overflow with timestamps
+            // way out into the future. We can re-visit this if FileTime
+            // is updated to define a from(secs,nsecs) method.
+            long micro = sec*1000000L + nsec/1000L;
+            return FileTime.from(micro, TimeUnit.MICROSECONDS);
+        }
+    }
+
     FileTime ctime() {
-        return FileTime.from(st_ctime, TimeUnit.SECONDS);
+        return toFileTime(st_ctime_sec, st_ctime_nsec);
     }
 
     boolean isDevice() {
@@ -114,12 +129,12 @@
 
     @Override
     public FileTime lastModifiedTime() {
-        return FileTime.from(st_mtime, TimeUnit.SECONDS);
+        return toFileTime(st_mtime_sec, st_mtime_nsec);
     }
 
     @Override
     public FileTime lastAccessTime() {
-        return FileTime.from(st_atime, TimeUnit.SECONDS);
+        return toFileTime(st_atime_sec, st_atime_nsec);
     }
 
     @Override
--- a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Fri Jan 18 17:34:40 2013 +0000
+++ b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Fri Jan 18 18:48:44 2013 +0000
@@ -90,9 +90,12 @@
 static jfieldID attrs_st_uid;
 static jfieldID attrs_st_gid;
 static jfieldID attrs_st_size;
-static jfieldID attrs_st_atime;
-static jfieldID attrs_st_mtime;
-static jfieldID attrs_st_ctime;
+static jfieldID attrs_st_atime_sec;
+static jfieldID attrs_st_atime_nsec;
+static jfieldID attrs_st_mtime_sec;
+static jfieldID attrs_st_mtime_nsec;
+static jfieldID attrs_st_ctime_sec;
+static jfieldID attrs_st_ctime_nsec;
 
 static jfieldID attrs_f_frsize;
 static jfieldID attrs_f_blocks;
@@ -183,9 +186,12 @@
     attrs_st_uid = (*env)->GetFieldID(env, clazz, "st_uid", "I");
     attrs_st_gid = (*env)->GetFieldID(env, clazz, "st_gid", "I");
     attrs_st_size = (*env)->GetFieldID(env, clazz, "st_size", "J");
-    attrs_st_atime = (*env)->GetFieldID(env, clazz, "st_atime", "J");
-    attrs_st_mtime = (*env)->GetFieldID(env, clazz, "st_mtime", "J");
-    attrs_st_ctime = (*env)->GetFieldID(env, clazz, "st_ctime", "J");
+    attrs_st_atime_sec = (*env)->GetFieldID(env, clazz, "st_atime_sec", "J");
+    attrs_st_atime_nsec = (*env)->GetFieldID(env, clazz, "st_atime_nsec", "J");
+    attrs_st_mtime_sec = (*env)->GetFieldID(env, clazz, "st_mtime_sec", "J");
+    attrs_st_mtime_nsec = (*env)->GetFieldID(env, clazz, "st_mtime_nsec", "J");
+    attrs_st_ctime_sec = (*env)->GetFieldID(env, clazz, "st_ctime_sec", "J");
+    attrs_st_ctime_nsec = (*env)->GetFieldID(env, clazz, "st_ctime_nsec", "J");
 
     clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes");
     if (clazz == NULL) {
@@ -395,9 +401,15 @@
     (*env)->SetIntField(env, attrs, attrs_st_uid, (jint)buf->st_uid);
     (*env)->SetIntField(env, attrs, attrs_st_gid, (jint)buf->st_gid);
     (*env)->SetLongField(env, attrs, attrs_st_size, (jlong)buf->st_size);
-    (*env)->SetLongField(env, attrs, attrs_st_atime, (jlong)buf->st_atime);
-    (*env)->SetLongField(env, attrs, attrs_st_mtime, (jlong)buf->st_mtime);
-    (*env)->SetLongField(env, attrs, attrs_st_ctime, (jlong)buf->st_ctime);
+    (*env)->SetLongField(env, attrs, attrs_st_atime_sec, (jlong)buf->st_atime);
+    (*env)->SetLongField(env, attrs, attrs_st_mtime_sec, (jlong)buf->st_mtime);
+    (*env)->SetLongField(env, attrs, attrs_st_ctime_sec, (jlong)buf->st_ctime);
+
+#if (_POSIX_C_SOURCE >= 200809L) || defined(__solaris__)
+    (*env)->SetLongField(env, attrs, attrs_st_atime_nsec, (jlong)buf->st_atim.tv_nsec);
+    (*env)->SetLongField(env, attrs, attrs_st_mtime_nsec, (jlong)buf->st_mtim.tv_nsec);
+    (*env)->SetLongField(env, attrs, attrs_st_ctime_nsec, (jlong)buf->st_ctim.tv_nsec);
+#endif
 }
 
 JNIEXPORT void JNICALL
--- a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java	Fri Jan 18 17:34:40 2013 +0000
+++ b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java	Fri Jan 18 18:48:44 2013 +0000
@@ -49,9 +49,9 @@
         check(!attrs.isSymbolicLink(), "is not a link");
         check(!attrs.isOther(), "is not other");
 
-        // last-modified-time should match java.io.File
+        // last-modified-time should match java.io.File in seconds
         File f = new File(dir.toString());
-        check(f.lastModified() == attrs.lastModifiedTime().toMillis(),
+        check(f.lastModified()/1000 == attrs.lastModifiedTime().to(TimeUnit.SECONDS),
               "last-modified time should be the same");
     }
 
@@ -64,10 +64,10 @@
         check(!attrs.isSymbolicLink(), "is not a link");
         check(!attrs.isOther(), "is not other");
 
-        // size and last-modified-time should match java.io.File
+        // size and last-modified-time should match java.io.File in seconds
         File f = new File(file.toString());
         check(f.length() == attrs.size(), "size should be the same");
-        check(f.lastModified() == attrs.lastModifiedTime().toMillis(),
+        check(f.lastModified()/1000 == attrs.lastModifiedTime().to(TimeUnit.SECONDS),
               "last-modified time should be the same");
 
         // copy last-modified time and file create time from directory to file,