Do not follow symlinks when recursively deleting files.
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Mon, 8 Jun 2020 18:03:27 +0000 (21:03 +0300)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Mon, 8 Jun 2020 18:03:27 +0000 (21:03 +0300)
src/main/java/eu/svjatoslav/commons/file/IOHelper.java

index e187371..e23feae 100755 (executable)
@@ -6,36 +6,46 @@ package eu.svjatoslav.commons.file;
 
 import java.io.*;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.file.Files.isSymbolicLink;
+
 public class IOHelper {
 
     /**
-     * Deletes files and directories recursively. WARNING!!! Follows symlinks!!!
+     * Deletes files and directories recursively. Does not follow symlinks.
      *
      * @param file directory to delete with entire contents.
      * @throws IOException if filesystem error happens
      */
     public static void deleteRecursively(final File file) throws IOException {
+
         if (file.isDirectory()) {
+            deleteDirectory(file);
+            return;
+        }
+
+        if (file.isFile()){
+            if (!file.delete()) throw new IOException("Failed to delete file: " + file);
+        } else {
+            if (isSymbolicLink(file.toPath()) && !file.delete())
+                throw new IOException("Failed to delete symlink: " + file);
+        }
+    }
 
+    private static void deleteDirectory(File file) throws IOException {
+        // if file is symlink that points to directory, no not touch content
+        if (!isSymbolicLink(file.toPath())){
             File[] files = file.listFiles();
             if (files == null)
-                throw new RuntimeException("Failed to read directory content for: "
+                throw new IOException("Failed to read directory content for: "
                         + file);
 
             for (final File subFile : files)
                 deleteRecursively(subFile);
-
-            if (!file.delete())
-                throw new RuntimeException("Failed to delete directory: "
-                        + file);
-
-            return;
         }
 
-        if (file.isFile())
-            if (!file.delete())
-                throw new FileNotFoundException("Failed to delete file: "
-                        + file);
+        if (!file.delete())
+            throw new IOException("Failed to delete directory: " + file);
     }
 
     public static byte[] getFileContents(final File file)
@@ -49,10 +59,16 @@ public class IOHelper {
         return result;
     }
 
+    /**
+     * Expects file content to be in UTF-8 encoding.
+     * @param file file to read
+     * @return File content
+     * @throws IOException when file reading fails.
+     */
     public static String getFileContentsAsString(final File file)
             throws IOException {
         try {
-            return new String(getFileContents(file), "UTF-8");
+            return new String(getFileContents(file), UTF_8);
         } catch (final UnsupportedEncodingException exception) {
             throw new RuntimeException(exception);
         }