]> BookStack Code Mirror - system-cli/commitdiff
Addressed further symlink issues
authorDan Brown <redacted>
Mon, 22 May 2023 09:20:38 +0000 (10:20 +0100)
committerDan Brown <redacted>
Mon, 22 May 2023 09:20:38 +0000 (10:20 +0100)
Specifically updating recursive deletion/copy handling to ignore symlink
directories. This is so symlinks remain so that content is stored in the
actual desired symlinked locations upon restore, rather than new
non-sym-link equivilents (Which could loose data in scenarios like
within docker containers where data is symlinked to volume locations).

Tested on a dev linuxserver docker environment, which specific checking
of file handling before/after restore of backup.

src/Services/Directories.php

index 8886c602d6f8d2b61bc70fb70ee4a44c65a700e6..7f931e157323ec7dfd164d7d5c3d0caf63603858 100644 (file)
@@ -4,6 +4,7 @@ namespace Cli\Services;
 use FilesystemIterator;
 use RecursiveDirectoryIterator;
 use RecursiveIteratorIterator;
+use SplFileInfo;
 
 class Directories
 {
@@ -16,7 +17,9 @@ class Directories
 
     public static function copy(string $src, string $target): void
     {
-        mkdir($target);
+        if (!file_exists($target)) {
+            mkdir($target);
+        }
 
         /** @var RecursiveDirectoryIterator $files */
         $files = new RecursiveIteratorIterator(
@@ -24,14 +27,16 @@ class Directories
             RecursiveIteratorIterator::SELF_FIRST
         );
 
-        /** @var \SplFileInfo $fileinfo */
+        /** @var SplFileInfo $fileinfo */
         foreach ($files as $fileinfo) {
             $srcPath = $fileinfo->getRealPath();
             $subPath = $files->getSubPathName();
             $destPath = Paths::join($target, $subPath);
-            if ($fileinfo->isDir()) {
+            $result = true;
+            if ($fileinfo->isDir() && !file_exists($destPath)) {
+                echo $destPath . "\n";
                 $result = mkdir($destPath);
-            } else {
+            } else if ($fileinfo->isFile()) {
                 $result = copy($srcPath, $destPath);
             }
 
@@ -41,6 +46,11 @@ class Directories
         }
     }
 
+    /**
+     * Delete the contents of the given directory.
+     * Will not delete symlinked folders to ensure that symlinks remain consistent,
+     * but will aim to delete contents of symlinked folders.
+     */
     public static function delete(string $dir): void
     {
         $files = new RecursiveIteratorIterator(
@@ -48,11 +58,19 @@ class Directories
             RecursiveIteratorIterator::CHILD_FIRST
         );
 
+        $links = '::';
+
+        /** @var SplFileInfo $fileinfo */
         foreach ($files as $fileinfo) {
             $path = $fileinfo->getRealPath();
+            $result = true;
             if ($fileinfo->isDir()) {
-                $result = rmdir($path);
-            } else {
+                if ($fileinfo->isLink()) {
+                    $links .= $fileinfo->getPath() . '::';
+                } else if (!str_contains($links, '::' . $path)) {
+                    $result = rmdir($path);
+                }
+            } else if ($fileinfo->isFile()) {
                 $result = unlink($path);
             }
 
@@ -61,6 +79,8 @@ class Directories
             }
         }
 
-        rmdir($dir);
+        if ($links === '::') {
+            rmdir($dir);
+        }
     }
 }
\ No newline at end of file