From cea188a39a8ff08d3611ce50627400db059e127f Mon Sep 17 00:00:00 2001 From: alanb Date: Fri, 18 Jan 2013 18:48:44 +0000 Subject: [PATCH] 6939260: (fs) BasicFileAttributes.lastModifiedTime() should return last modified time with higher precision Reviewed-by: chegar --- .../sun/nio/fs/UnixFileAttributes.java | 27 +++++++++++++---- .../native/sun/nio/fs/UnixNativeDispatcher.c | 30 +++++++++++++------ .../BasicFileAttributeView/Basic.java | 8 ++--- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java b/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java index a6b79953a..b61b5d6e4 100644 --- a/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java +++ b/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java @@ -45,9 +45,12 @@ class UnixFileAttributes 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 @@ class UnixFileAttributes 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 @@ class UnixFileAttributes @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 diff --git a/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c b/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c index 45d1191c4..eb4698183 100644 --- a/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c +++ b/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c @@ -90,9 +90,12 @@ static jfieldID attrs_st_nlink; 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 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this) 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 @@ static void prepAttributes(JNIEnv* env, struct stat64* buf, jobject attrs) { (*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 diff --git a/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java b/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java index dd005c2c3..40792dfde 100644 --- a/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java +++ b/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java @@ -49,9 +49,9 @@ public class Basic { 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 @@ public class Basic { 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, -- GitLab