From 8418fcfedf8524d3e00263d9028dab5651cf9c00 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 16 Oct 2023 17:39:23 +0200 Subject: [PATCH] add some support for rename on case insensitive local filesystems Signed-off-by: Robin Appelman --- lib/private/Files/Storage/Local.php | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index eeb9e11b24e0f..0fca853da5987 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -74,6 +74,8 @@ class Local extends \OC\Files\Storage\Common { protected bool $unlinkOnTruncate; + protected bool $caseInsensitive = false; + public function __construct($arguments) { if (!isset($arguments['datadir']) || !is_string($arguments['datadir'])) { throw new \InvalidArgumentException('No data directory set for local storage'); @@ -93,6 +95,7 @@ public function __construct($arguments) { $this->config = \OC::$server->get(IConfig::class); $this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class); $this->defUMask = $this->config->getSystemValue('localstorage.umask', 0022); + $this->caseInsensitive = $this->config->getSystemValueBool('localstorage.case_insensitive', false); // support Write-Once-Read-Many file systems $this->unlinkOnTruncate = $this->config->getSystemValueBool('localstorage.unlink_on_truncate', false); @@ -162,6 +165,9 @@ public function opendir($path) { } public function is_dir($path) { + if ($this->caseInsensitive && !$this->file_exists($path)) { + return false; + } if (str_ends_with($path, '/')) { $path = substr($path, 0, -1); } @@ -169,6 +175,9 @@ public function is_dir($path) { } public function is_file($path) { + if ($this->caseInsensitive && !$this->file_exists($path)) { + return false; + } return is_file($this->getSourcePath($path)); } @@ -271,7 +280,13 @@ public function isUpdatable($path) { } public function file_exists($path) { - return file_exists($this->getSourcePath($path)); + if ($this->caseInsensitive) { + $fullPath = $this->getSourcePath($path); + $content = scandir(dirname($fullPath), SCANDIR_SORT_NONE); + return is_array($content) && array_search(basename($fullPath), $content) !== false; + } else { + return file_exists($this->getSourcePath($path)); + } } public function filemtime($path) { @@ -372,6 +387,11 @@ public function rename($source, $target): bool { } if (@rename($this->getSourcePath($source), $this->getSourcePath($target))) { + if ($this->caseInsensitive) { + if (mb_strtolower($target) === mb_strtolower($source) && !$this->file_exists($target)) { + return false; + } + } return true; } @@ -388,6 +408,11 @@ public function copy($source, $target) { } $result = copy($this->getSourcePath($source), $this->getSourcePath($target)); umask($oldMask); + if ($this->caseInsensitive) { + if (mb_strtolower($target) === mb_strtolower($source) && !$this->file_exists($target)) { + return false; + } + } return $result; } }