From 521aeb4a9cd965720fccdd3af8172a62ff75846e Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 3 Aug 2023 23:09:17 +0200 Subject: [PATCH] Allow ext storage Local to go unavailable Whenever an external storage of type Local points at a non-existing directory, process this as a StorageNotAvailable instead of returning 404. This makes desktop clients ignore the folder instead of deleting it when it becomes unavailable. The code change was limited to external storages to avoid issues during setup and with the default home storage. Signed-off-by: Vincent Petry --- apps/files_external/lib/Lib/Backend/Local.php | 6 ++++++ lib/private/Files/Storage/Local.php | 7 +++++++ tests/lib/Files/Storage/LocalTest.php | 11 +++++++++++ 3 files changed, 24 insertions(+) diff --git a/apps/files_external/lib/Lib/Backend/Local.php b/apps/files_external/lib/Lib/Backend/Local.php index 88b251360d678..37a4b0458a976 100644 --- a/apps/files_external/lib/Lib/Backend/Local.php +++ b/apps/files_external/lib/Lib/Backend/Local.php @@ -26,8 +26,10 @@ use OCA\Files_External\Lib\Auth\AuthMechanism; use OCA\Files_External\Lib\Auth\NullMechanism; use OCA\Files_External\Lib\DefinitionParameter; +use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\Service\BackendService; use OCP\IL10N; +use OCP\IUser; class Local extends Backend { public function __construct(IL10N $l, NullMechanism $legacyAuth) { @@ -45,4 +47,8 @@ public function __construct(IL10N $l, NullMechanism $legacyAuth) { ->setLegacyAuthMechanism($legacyAuth) ; } + + public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) { + $storage->setBackendOption('isExternal', true); + } } diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index fb62a53d89407..8e5c15c523c98 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -51,6 +51,7 @@ use OCP\Files\GenericFileException; use OCP\Files\IMimeTypeDetector; use OCP\Files\Storage\IStorage; +use OCP\Files\StorageNotAvailableException; use OCP\IConfig; use OCP\Util; use Psr\Log\LoggerInterface; @@ -95,6 +96,12 @@ public function __construct($arguments) { // support Write-Once-Read-Many file systems $this->unlinkOnTruncate = $this->config->getSystemValueBool('localstorage.unlink_on_truncate', false); + + if (isset($arguments['isExternal']) && $arguments['isExternal'] && !$this->stat('')) { + // data dir not accessible or available, can happen when using an external storage of type Local + // on an unmounted system mount point + throw new StorageNotAvailableException('Local storage path does not exist "' . $this->getSourcePath('') . '"'); + } } public function __destruct() { diff --git a/tests/lib/Files/Storage/LocalTest.php b/tests/lib/Files/Storage/LocalTest.php index e324d2b28db06..1190a2b2da043 100644 --- a/tests/lib/Files/Storage/LocalTest.php +++ b/tests/lib/Files/Storage/LocalTest.php @@ -139,4 +139,15 @@ public function testWriteUmaskCopy() { umask($oldMask); $this->assertTrue($this->instance->isUpdatable('test.txt')); } + + public function testUnavailableExternal() { + $this->expectException(\OCP\Files\StorageNotAvailableException::class); + $this->instance = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir . '/unexist', 'isExternal' => true]); + } + + public function testUnavailableNonExternal() { + $this->instance = new \OC\Files\Storage\Local(['datadir' => $this->tmpDir . '/unexist']); + // no exception thrown + $this->assertNotNull($this->instance); + } }