Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8301213

Files.walkFileTree invokes preVisitDirectory with the attributes of the directory rather sym link when following links

XMLWordPrintable

    • generic
    • generic

      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


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: