Browse Source

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 <matthias.sohn@sap.com>
stable-5.1
Matthias Sohn 6 years ago
parent
commit
8a0ed8a004
  1. 2
      org.eclipse.jgit/.settings/.api_filters
  2. 2
      org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
  3. 12
      org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java

2
org.eclipse.jgit/.settings/.api_filters

@ -153,7 +153,7 @@
<resource path="src/org/eclipse/jgit/util/FileUtils.java" type="org.eclipse.jgit.util.FileUtils"> <resource path="src/org/eclipse/jgit/util/FileUtils.java" type="org.eclipse.jgit.util.FileUtils">
<filter id="1142947843"> <filter id="1142947843">
<message_arguments> <message_arguments>
<message_argument value="5.2.3"/> <message_argument value="5.1.8"/>
<message_argument value="touch(Path)"/> <message_argument value="touch(Path)"/>
</message_arguments> </message_arguments>
</filter> </filter>

2
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$ Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$
try { try {
Files.createFile(probe); Files.createFile(probe);
// ensure we always use the local system clock
FileUtils.touch(probe);
long wait = 512; long wait = 512;
long start = System.nanoTime(); long start = System.nanoTime();
FileTime t1 = Files.getLastModifiedTime(probe); FileTime t1 = Files.getLastModifiedTime(probe);

12
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.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.nio.channels.FileChannel;
import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.CopyOption; import java.nio.file.CopyOption;
import java.nio.file.Files; import java.nio.file.Files;
@ -57,6 +57,7 @@ import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption; import java.nio.file.LinkOption;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
@ -66,6 +67,7 @@ import java.nio.file.attribute.PosixFilePermission;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.Normalizer; import java.text.Normalizer;
import java.text.Normalizer.Form; import java.text.Normalizer.Form;
import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -916,11 +918,13 @@ public class FileUtils {
* @param f * @param f
* the file to touch * the file to touch
* @throws IOException * @throws IOException
* @since 5.2.3 * @since 5.1.8
*/ */
public static void touch(Path f) throws IOException { public static void touch(Path f) throws IOException {
try (OutputStream fos = Files.newOutputStream(f)) { try (FileChannel fc = FileChannel.open(f, StandardOpenOption.CREATE,
// touch the file StandardOpenOption.APPEND, StandardOpenOption.SYNC)) {
// touch
} }
Files.setLastModifiedTime(f, FileTime.from(Instant.now()));
} }
} }

Loading…
Cancel
Save