From 8a0ed8a00425f5b101296c7636ea032c9485d77c Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Wed, 26 Jun 2019 01:11:12 +0200 Subject: [PATCH] Use FileChannel.open to touch file and set mtime to now Use options - StandardOpenOption.CREATE to create touched file if not existing - StandardOpenOption.SYNC to enforce synch of data and meta data changes - StandardOpenOption.WRITE Also set mtime explicitly in FileUtils#touch to the current system time. This should fix that the previous implementation didn't work on - locally cached Windows network share (CSC-CACHE filesystem) mapped as a drive - nfsv4 mounts on Linux and that it didn't create unborn file like Linux command "touch". Apache common's and Guava's touch() use the same approach. Immediately after creating the probe file used to measure timestamp resolution touch it. This ensures we always use the local system clock when measuring filesystem timestamp resolution. This should prevent that clock skew could influence the measured timestamp resolution in case of a mounted network filesystem. Bug: 548598 Change-Id: Iaeaf5967963f582395a195aa637b8188bfadac60 Signed-off-by: Matthias Sohn --- org.eclipse.jgit/.settings/.api_filters | 2 +- org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java | 2 ++ .../src/org/eclipse/jgit/util/FileUtils.java | 12 ++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index d313e92a0..5f58e7e45 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -153,7 +153,7 @@ - + diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java index 687c7a4fd..64dbf5823 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -294,6 +294,8 @@ public abstract class FS { Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$ try { Files.createFile(probe); + // ensure we always use the local system clock + FileUtils.touch(probe); long wait = 512; long start = System.nanoTime(); FileTime t1 = Files.getLastModifiedTime(probe); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java index 9bba6ca8a..9650602fe 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java @@ -49,7 +49,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import java.io.File; import java.io.IOException; -import java.io.OutputStream; +import java.nio.channels.FileChannel; import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.CopyOption; import java.nio.file.Files; @@ -57,6 +57,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; @@ -66,6 +67,7 @@ import java.nio.file.attribute.PosixFilePermission; import java.text.MessageFormat; import java.text.Normalizer; import java.text.Normalizer.Form; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -916,11 +918,13 @@ public class FileUtils { * @param f * the file to touch * @throws IOException - * @since 5.2.3 + * @since 5.1.8 */ public static void touch(Path f) throws IOException { - try (OutputStream fos = Files.newOutputStream(f)) { - // touch the file + try (FileChannel fc = FileChannel.open(f, StandardOpenOption.CREATE, + StandardOpenOption.APPEND, StandardOpenOption.SYNC)) { + // touch } + Files.setLastModifiedTime(f, FileTime.from(Instant.now())); } }