You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/01/16 20:55:55 UTC

[commons-io] branch master updated: IO-702 FileUtils.forceDelete does not delete invalid links. Testcase and fix (#187)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git


The following commit(s) were added to refs/heads/master by this push:
     new b1a84b2  IO-702 FileUtils.forceDelete does not delete invalid links. Testcase and fix (#187)
b1a84b2 is described below

commit b1a84b203fd73b591e4431ea7854caf592d2bd74
Author: Boris Unckel <bu...@mail.unckel.net>
AuthorDate: Sat Jan 16 21:55:10 2021 +0100

    IO-702 FileUtils.forceDelete does not delete invalid links. Testcase and fix (#187)
---
 .../commons/io/file/DeletingPathVisitor.java       | 21 ++++++++++++++++----
 .../io/FileUtilsDeleteDirectoryBaseTestCase.java   | 23 ++++++++++++++++++++++
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/commons/io/file/DeletingPathVisitor.java b/src/main/java/org/apache/commons/io/file/DeletingPathVisitor.java
index b6c85c5..e11379e 100644
--- a/src/main/java/org/apache/commons/io/file/DeletingPathVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/DeletingPathVisitor.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.LinkOption;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Arrays;
@@ -150,11 +151,23 @@ public class DeletingPathVisitor extends CountingPathVisitor {
 
     @Override
     public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
-        if (accept(file) && Files.exists(file, linkOptions)) {
-            if (overrideReadOnly) {
-                PathUtils.setReadOnly(file, false, linkOptions);
+        if (accept(file)) {
+            // delete files and valid links, respecting linkOptions
+            if (Files.exists(file, linkOptions)) {
+                if (overrideReadOnly) {
+                    PathUtils.setReadOnly(file, false, linkOptions);
+                }
+                Files.deleteIfExists(file);
+            }
+            // invalid links will survive previous delete, different approach needed:
+            if (Files.isSymbolicLink(file)) {
+                try {
+                    // deleteIfExists does not work for this case
+                    Files.delete(file);
+                } catch (NoSuchFileException e) {
+                    // ignore
+                }
             }
-            Files.deleteIfExists(file);
         }
         updateFileCounters(file, attrs);
         return FileVisitResult.CONTINUE;
diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java
index b99c1dd..c9e0cd2 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java
@@ -195,6 +195,29 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase {
     }
 
     @Test
+    public void testDeleteInvalidLinks() throws Exception {
+        File aFile = new File(top, "realParentDirA");
+        assertTrue(aFile.mkdir());
+        File bFile = new File(aFile, "realChildDirB");
+        assertTrue(bFile.mkdir());
+
+        File cFile = new File(top, "realParentDirC");
+        assertTrue(cFile.mkdir());
+        File dFile = new File(cFile, "realChildDirD");
+        assertTrue(dFile.mkdir());
+
+        File linkToC = new File(bFile, "linkToC");
+        Files.createSymbolicLink(linkToC.toPath(), cFile.toPath());
+
+        File linkToB = new File(dFile, "linkToB");
+        Files.createSymbolicLink(linkToB.toPath(), bFile.toPath());
+
+        FileUtils.deleteDirectory(aFile);
+        FileUtils.deleteDirectory(cFile);
+        assertEquals(0, top.list().length);
+    }
+
+    @Test
     public void testDeletesNested() throws Exception {
         final File nested = new File(top, "nested");
         assertTrue(nested.mkdirs());