# HG changeset patch # User bpb # Date 1569437092 25200 # Node ID 21a03fa2f6b6137c9a25e695b9779234e16a9382 # Parent f4abe950c3b0f8d4484083e67711015326cca341 8231174: (fs) FileTime should have 100ns resolution (win) Reviewed-by: alanb diff -r f4abe950c3b0 -r 21a03fa2f6b6 src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Wed Sep 25 11:10:05 2019 -0700 +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java Wed Sep 25 11:44:52 2019 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2019, 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 @@ -108,8 +108,9 @@ private static final short OFFSETOF_FIND_DATA_SIZELOW = 32; private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36; - // used to adjust values between Windows and java epoch - private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; + // used to adjust values between Windows and java epochs + private static final long WINDOWS_EPOCH_IN_MICROS = -11644473600000000L; + private static final long WINDOWS_EPOCH_IN_100NS = -116444736000000000L; // indicates if accurate metadata is required (interesting on NTFS only) private static final boolean ensureAccurateMetadata; @@ -137,24 +138,23 @@ * since January 1, 1601 to a FileTime. */ static FileTime toFileTime(long time) { - // 100ns -> us - time /= 10L; - // adjust to java epoch - time += WINDOWS_EPOCH_IN_MICROSECONDS; - return FileTime.from(time, TimeUnit.MICROSECONDS); + try { + long adjusted = Math.addExact(time, WINDOWS_EPOCH_IN_100NS); + long nanos = Math.multiplyExact(adjusted, 100L); + return FileTime.from(nanos, TimeUnit.NANOSECONDS); + } catch (ArithmeticException e) { + long micros = Math.addExact(time/10L, WINDOWS_EPOCH_IN_MICROS); + return FileTime.from(micros, TimeUnit.MICROSECONDS); + } } /** - * Convert FileTime to 64-bit value representing the number of 100-nanosecond - * intervals since January 1, 1601. + * Convert FileTime to 64-bit value representing the number of + * 100-nanosecond intervals since January 1, 1601. */ static long toWindowsTime(FileTime time) { - long value = time.to(TimeUnit.MICROSECONDS); - // adjust to Windows epoch+= 11644473600000000L; - value -= WINDOWS_EPOCH_IN_MICROSECONDS; - // us -> 100ns - value *= 10L; - return value; + long adjusted = time.to(TimeUnit.NANOSECONDS)/100L; + return adjusted - WINDOWS_EPOCH_IN_100NS; } /** diff -r f4abe950c3b0 -r 21a03fa2f6b6 test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java --- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java Wed Sep 25 11:10:05 2019 -0700 +++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/SetTimesNanos.java Wed Sep 25 11:44:52 2019 -0700 @@ -22,9 +22,9 @@ */ /* @test - * @bug 8181493 + * @bug 8181493 8231174 * @summary Verify that nanosecond precision is maintained for file timestamps - * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "solaris") + * @requires (os.family == "linux") | (os.family == "mac") | (os.family == "solaris") | (os.family == "windows") * @modules java.base/sun.nio.fs:+open */ @@ -40,14 +40,21 @@ import java.util.concurrent.TimeUnit; public class SetTimesNanos { + private static final boolean IS_WINDOWS = + System.getProperty("os.name").startsWith("Windows"); + public static void main(String[] args) throws Exception { - // Check whether futimens() system call is supported - Class unixNativeDispatcherClass = Class.forName("sun.nio.fs.UnixNativeDispatcher"); - Method futimensSupported = unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); - futimensSupported.setAccessible(true); - if (!(boolean)futimensSupported.invoke(null)) { - System.err.println("futimens() system call not supported; skipping test"); - return; + if (!IS_WINDOWS) { + // Check whether futimens() system call is supported + Class unixNativeDispatcherClass = + Class.forName("sun.nio.fs.UnixNativeDispatcher"); + Method futimensSupported = + unixNativeDispatcherClass.getDeclaredMethod("futimensSupported"); + futimensSupported.setAccessible(true); + if (!(boolean)futimensSupported.invoke(null)) { + System.err.println("futimens() not supported; skipping test"); + return; + } } Path dirPath = Path.of("test"); @@ -56,7 +63,8 @@ System.out.format("FileStore: \"%s\" on %s (%s)%n", dir, store.name(), store.type()); - Set testedTypes = Set.of("apfs", "ext4", "xfs", "zfs"); + Set testedTypes = IS_WINDOWS ? + Set.of("NTFS") : Set.of("apfs", "ext4", "xfs", "zfs"); if (!testedTypes.contains(store.type())) { System.err.format("%s not in %s; skipping test", store.type(), testedTypes); return; @@ -77,6 +85,11 @@ Files.getFileAttributeView(path, BasicFileAttributeView.class); view.setTimes(pathTime, pathTime, null); + // Windows file time resolution is 100ns so truncate + if (IS_WINDOWS) { + timeNanos = 100L*(timeNanos/100L); + } + // Read attributes BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);