From b8b1551c89b0aa1540cf2d3fb7a2038293420c30 Mon Sep 17 00:00:00 2001 From: pk7243959-wq Date: Tue, 6 Oct 2026 02:52:07 +0530 Subject: [PATCH 1/2] fix(preview): handle null location id in deletePreview --- lib/private/Preview/Storage/ObjectStorePreviewStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/Preview/Storage/ObjectStorePreviewStorage.php b/lib/private/Preview/Storage/ObjectStorePreviewStorage.php index 037588e72c825..6418729ed556e 100644 --- a/lib/private/Preview/Storage/ObjectStorePreviewStorage.php +++ b/lib/private/Preview/Storage/ObjectStorePreviewStorage.php @@ -80,7 +80,7 @@ public function readPreview(Preview $preview): mixed { #[Override] public function deletePreview(Preview $preview): void { - if (defined('PHPUNIT_RUN') && $preview->getLocationId() === null) { + if ($preview->getLocationId() === null) { // Should only be the case in unit tests when adding dummy previews in the database. return; } From 0e1c174c36f5d25b1943281f672ebf37df588200 Mon Sep 17 00:00:00 2001 From: pk7243959-wq Date: Wed, 7 Oct 2026 02:34:02 +0530 Subject: [PATCH 2/2] fix(files_external): verify SMB root reachability on NotFound --- apps/files_external/lib/Lib/Storage/SMB.php | 50 ++++++++++++--------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/apps/files_external/lib/Lib/Storage/SMB.php b/apps/files_external/lib/Lib/Storage/SMB.php index 9628335c804f9..2443a22d233a7 100644 --- a/apps/files_external/lib/Lib/Storage/SMB.php +++ b/apps/files_external/lib/Lib/Storage/SMB.php @@ -175,8 +175,10 @@ protected function getFileInfo(string $path): IFileInfo { $this->throwUnavailable($e); } catch (InvalidArgumentException $e) { $this->throwUnavailable($e); - } catch (NotFoundException $e) { + } catch (NotFoundException $e) { + $this->assertRootAvailable($path, $e); throw new \OCP\Files\NotFoundException($e->getMessage(), 0, $e); + } } catch (ForbiddenException $e) { // with php-smbclient, this exception is thrown when the provided password is invalid. // we check if we can stat the root, which should only fail in authentication failures @@ -194,31 +196,34 @@ protected function getFileInfo(string $path): IFileInfo { } /** - * @throws StorageAuthException + * A missing share (NT_STATUS_BAD_NETWORK_NAME, e.g. when the backing dataset is locked) + * is reported by php-smbclient as a plain NotFound for every path. Before reporting a path + * as not found, make sure the storage root itself is reachable, otherwise the scanner + * would remove the whole storage from the cache. + * + * @throws StorageNotAvailableException */ - protected function throwUnavailable(\Exception $e): never { - $this->logger->error('Error while getting file info', ['exception' => $e]); - throw new StorageAuthException($e->getMessage(), $e); + private function assertRootAvailable(string $fullPath, \Exception $e): void { + $rootPath = $this->buildPath(''); + if (ltrim($fullPath, '/') !== ltrim($rootPath, '/')) { + try { + $this->share->stat($rootPath); + return; + } catch (\Exception $rootException) { + $e = $rootException; + } + } + $this->logger->warning('Storage root not reachable, marking storage as unavailable', ['exception' => $e]); + throw new StorageNotAvailableException($e->getMessage(), StorageNotAvailableException::STATUS_ERROR, $e); } /** - * get the acl from fileinfo that is relevant for the configured user + * @throws StorageAuthException + * @throws StorageNotAvailableException */ - private function getACL(IFileInfo $file): ?ACL { - try { - $acls = $file->getAcls(); - } catch (Exception $e) { - $this->logger->warning('Error while getting file acls', ['exception' => $e]); - return null; - } - foreach ($acls as $user => $acl) { - [, $user] = $this->splitUser($user); // strip domain - if ($user === $this->server->getAuth()->getUsername()) { - return $acl; - } - } - - return null; + protected function throwUnavailable(\Exception $e): never { + $this->logger->warning('Storage not available', ['exception' => $e]); + throw new StorageNotAvailableException($e->getMessage(), StorageNotAvailableException::STATUS_ERROR, $e); } /** @@ -272,7 +277,8 @@ protected function getFolderContents(string $path): iterable { $this->logger->error('Error while getting folder content', ['exception' => $e]); throw new StorageNotAvailableException($e->getMessage(), (int)$e->getCode(), $e); } catch (NotFoundException $e) { - throw new \OCP\Files\NotFoundException($e->getMessage(), 0, $e); + $this->assertRootAvailable($path, $e); + throw new \OCP\Files\NotFoundException($e->getMessage(), 0, $e); } }