From fe1a289c2d305e0c1e853045898d3abfe4f949e6 Mon Sep 17 00:00:00 2001 From: Dillard Blom Date: Thu, 8 Oct 2026 20:46:14 +0200 Subject: [PATCH] Backend: an existing folder that cannot be listed is an error, not empty Read as empty, a catalog/ or index/ folder would make an existing repository look new. --- lib/Backend/LocalBackend.php | 5 ++++- lib/Backend/StorageBackend.php | 3 ++- tests/Unit/Backend/StorageBackendListTest.php | 10 ++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/Backend/LocalBackend.php b/lib/Backend/LocalBackend.php index 7fdb122..1a577bb 100644 --- a/lib/Backend/LocalBackend.php +++ b/lib/Backend/LocalBackend.php @@ -114,7 +114,10 @@ final class LocalBackend implements IBackend { } $result = []; $names = scandir($base); - foreach ($names === false ? [] : $names as $name) { + if ($names === false) { + throw new BackendException('Cannot list ' . $dir); + } + foreach ($names as $name) { if ($name !== '.' && $name !== '..' && !StorageBackend::isTemporary($name)) { $result[] = trim($dir, '/') . '/' . $name; } diff --git a/lib/Backend/StorageBackend.php b/lib/Backend/StorageBackend.php index e273888..58f53e2 100644 --- a/lib/Backend/StorageBackend.php +++ b/lib/Backend/StorageBackend.php @@ -140,7 +140,8 @@ final class StorageBackend implements IBackend { } $dh = $this->storage->opendir($abs); if ($dh === false) { - return []; + // An existing folder read as empty would look like a new repository. + throw new BackendException('Cannot list ' . $dir); } $cut = $this->base === '' ? 0 : strlen($this->base) + 1; $result = []; diff --git a/tests/Unit/Backend/StorageBackendListTest.php b/tests/Unit/Backend/StorageBackendListTest.php index 8c4deee..da2b93e 100644 --- a/tests/Unit/Backend/StorageBackendListTest.php +++ b/tests/Unit/Backend/StorageBackendListTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace OCA\NgBackup\Tests\Unit\Backend; +use OCA\NgBackup\Backend\BackendException; use OCA\NgBackup\Backend\StorageBackend; use OCA\NgBackup\Tests\Unit\TempDirTrait; use OCP\Files\Storage\IStorage; @@ -44,4 +45,13 @@ class StorageBackendListTest extends TestCase { $storage->expects($this->never())->method('opendir'); $this->assertSame([], (new StorageBackend($storage, 'repo'))->listFiles('snapshots')); } + + public function testAnUnreadableFolderIsAnErrorNotEmpty(): void { + $storage = $this->createMock(IStorage::class); + $storage->method('instanceOfStorage')->willReturn(false); + $storage->method('is_dir')->willReturn(true); + $storage->method('opendir')->willReturn(false); + $this->expectException(BackendException::class); + (new StorageBackend($storage, 'repo'))->listFiles('catalog'); + } }