Bug in File.getLastModified()
Seán Coffey
sean.coffey at oracle.com
Fri Mar 31 18:01:32 UTC 2017
Hi Brian,
I think it's worth fixing unless there are objections. I see Stuart's
comment about compatibility and wonder if we've any examples of such
applications.
I just put together a patch [1] for this. I'm still figuring out how
nanoseconds get recorded for macosx. stat64.st_mtimespec.tv_nsec seems
to return 0 for me. We'd have to check the ppc/s390 ports also.
If successful, I might start an RFR for it. I think I found an issue
with how Files.getLastModifiedTime handles a timestamp of Long.MAX_VALUE
also. I might follow that up as a NIO issue. I don't think macosx
returns millisecond resolution for the nio Files case either.
regards,
Sean.
[1]
diff --git a/src/solaris/native/java/io/UnixFileSystem_md.c
b/src/solaris/native/java/io/UnixFileSystem_md.c
--- a/src/solaris/native/java/io/UnixFileSystem_md.c
+++ b/src/solaris/native/java/io/UnixFileSystem_md.c
@@ -208,7 +208,12 @@
WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
struct stat64 sb;
if (stat64(path, &sb) == 0) {
- rv = 1000 * (jlong)sb.st_mtime;
+ rv = (jlong)sb.st_mtime * 1000;
+#ifndef MACOSX
+ rv += (jlong)sb.st_mtim.tv_nsec / 1000000;
+#else
+ rv += (jlong)sb.st_mtimespec.tv_nsec / 1000000;
+#endif
}
} END_PLATFORM_STRING(env, path);
return rv;
@@ -393,8 +398,11 @@
/* Preserve access time */
tv[0].tv_sec = sb.st_atime;
- tv[0].tv_usec = 0;
-
+#ifndef MACOSX
+ tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
+#else
+ tv[0].tv_usec = sb.st_atimespec.tv_nsec / 1000;
+#endif
/* Change last-modified time */
tv[1].tv_sec = time / 1000;
tv[1].tv_usec = (time % 1000) * 1000;
diff --git a/test/java/io/File/GetLastModified.java
b/test/java/io/File/GetLastModified.java
new file mode 100644
--- /dev/null
+++ b/test/java/io/File/GetLastModified.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8177809
+ * @summary File.lastModified() is losing milliseconds (always ends in 000)
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+public class GetLastModified {
+ private static final long[] LM = { 1490606336718L,
+ 100L, 3000000000L /*, Long.MAX_VALUE */ };
+
+ public static void main(String[] args) throws IOException {
+ boolean fail = false;
+ File f = new File("GetLastModified.txt");
+ f.createNewFile();
+
+ for (int i = 0; i < LM.length; i++) {
+ f.setLastModified(LM[i]);
+ System.out.println("==============================");
+ System.out.printf("Test f.lastModified [%s]: %b\n",
+ f.lastModified(), f.lastModified() == LM[i]);
+ long filesMillis =
Files.getLastModifiedTime(f.toPath()).toMillis();
+ System.out.printf("Test Files.getLastModifiedTime [%s]: %b\n",
+ filesMillis, filesMillis == LM[i]);
+ if (f.lastModified() != LM[i] || filesMillis != LM[i]) {
+ fail = true;
+ }
+ }
+ f.delete();
+ if (fail) {
+ throw new RuntimeException("Unexpected time stamps");
+ }
+ }
+}
On 31/03/17 16:03, Brian Burkhalter wrote:
> Hi Ricardo,
>
> Thanks for reading the specification verbiage closely. I think you
> have a point. I’d like to read what others think about this.
>
> Regards,
>
> Brian
>
> On Mar 31, 2017, at 1:35 AM, Ricardo Almeida <ric.almeida at gmail.com
> <mailto:ric.almeida at gmail.com>> wrote:
>
>> Just to add another though...
>>
>> I was just double-reading the documentation and it says:
>>
>> "All platforms support file-modification times to the nearest second,
>> but some provide more precision. The argument will be truncated to fit
>> the supported precision."
>>
>> So, if the platform supports it, the argument is NOT truncated...
>> Next we have:
>>
>> "the next invocation of the lastModified() method will return the
>> (possibly truncated) time argument that was passed to this method"
>>
>> The way I read this sentence, it is 100% related with the first
>> sentence. It should return the value that was applied... if the system
>> supports only second precision, it is truncated. Otherwise, it should
>> return the not truncated value.
>
More information about the core-libs-dev
mailing list