ADDITIONAL SYSTEM INFORMATION :
Windows 10.0.19045
tested on Java 17, 18, 21-ea
A DESCRIPTION OF THE PROBLEM :
BasicFileAttributes.isSymbolicLink returns false for symlinks, while Files.isSymbolicLink correctly reports true
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
create a symlink.
walk over it with FileVisitOption.FOLLOW_LINKS
read BasicFileAttributes.isSymbolicLink
note: i tried to use isSymbolicLink() to faster detect cycles: A FileSystemLoopException can only occur if symlinks are involved. On windows the check for cycles is very slow for big directory structures O(n^2). java.nio.file.FileTreeWalker.wouldLoop(Path, Object) should fast return false if the path is not a symbolic link . - however such a fast check does not work if the flag is wrong.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
attrs.isSymbolicLink:true Files.isSymbolicLink: true
cycle detected
ACTUAL -
attrs.isSymbolicLink:false Files.isSymbolicLink: true
cycle detected
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Set;
public class TestSymlink {
public static void main(String[] args) throws IOException {
Path tempDir = Files.createTempDirectory("testdir");
tempDir.toFile().deleteOnExit();
Path symbolicLink = Files.createSymbolicLink(tempDir.resolve("mysymlink"), tempDir);
symbolicLink.toFile().deleteOnExit();
Files.walkFileTree(symbolicLink, Set.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<java.nio.file.Path>() {
public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) {
if (dir.equals(symbolicLink)) {
System.out.println("attrs.isSymbolicLink:" + attrs.isSymbolicLink()
+ " Files.isSymbolicLink: " + Files.isSymbolicLink(dir));
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
});
Files.walkFileTree(tempDir, Set.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<java.nio.file.Path>() {
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
if (exc instanceof FileSystemLoopException) {
System.out.println("cycle detected (expected): " + file);
return FileVisitResult.CONTINUE;
}
throw exc;
}
});
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
use Files.isSymbolicLink instead of BasicFileAttributes.isSymbolicLink
FREQUENCY : always
Windows 10.0.19045
tested on Java 17, 18, 21-ea
A DESCRIPTION OF THE PROBLEM :
BasicFileAttributes.isSymbolicLink returns false for symlinks, while Files.isSymbolicLink correctly reports true
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
create a symlink.
walk over it with FileVisitOption.FOLLOW_LINKS
read BasicFileAttributes.isSymbolicLink
note: i tried to use isSymbolicLink() to faster detect cycles: A FileSystemLoopException can only occur if symlinks are involved. On windows the check for cycles is very slow for big directory structures O(n^2). java.nio.file.FileTreeWalker.wouldLoop(Path, Object) should fast return false if the path is not a symbolic link . - however such a fast check does not work if the flag is wrong.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
attrs.isSymbolicLink:true Files.isSymbolicLink: true
cycle detected
ACTUAL -
attrs.isSymbolicLink:false Files.isSymbolicLink: true
cycle detected
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Set;
public class TestSymlink {
public static void main(String[] args) throws IOException {
Path tempDir = Files.createTempDirectory("testdir");
tempDir.toFile().deleteOnExit();
Path symbolicLink = Files.createSymbolicLink(tempDir.resolve("mysymlink"), tempDir);
symbolicLink.toFile().deleteOnExit();
Files.walkFileTree(symbolicLink, Set.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<java.nio.file.Path>() {
public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs) {
if (dir.equals(symbolicLink)) {
System.out.println("attrs.isSymbolicLink:" + attrs.isSymbolicLink()
+ " Files.isSymbolicLink: " + Files.isSymbolicLink(dir));
return FileVisitResult.SKIP_SUBTREE;
}
return FileVisitResult.CONTINUE;
}
});
Files.walkFileTree(tempDir, Set.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<java.nio.file.Path>() {
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
if (exc instanceof FileSystemLoopException) {
System.out.println("cycle detected (expected): " + file);
return FileVisitResult.CONTINUE;
}
throw exc;
}
});
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
use Files.isSymbolicLink instead of BasicFileAttributes.isSymbolicLink
FREQUENCY : always