diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php index 6a954378d02..91e49d331e9 100644 --- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php @@ -1151,7 +1151,7 @@ class FileTest extends TestCase { $info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [ 'permissions' => \OCP\Constants::PERMISSION_ALL, - 'type' => FileInfo::TYPE_FOLDER, + 'type' => FileInfo::TYPE_FILE, ], null); $file = new \OCA\DAV\Connector\Sabre\File($view, $info); @@ -1172,7 +1172,7 @@ class FileTest extends TestCase { $info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [ 'permissions' => \OCP\Constants::PERMISSION_ALL, - 'type' => FileInfo::TYPE_FOLDER, + 'type' => FileInfo::TYPE_FILE, ], null); $file = new \OCA\DAV\Connector\Sabre\File($view, $info); diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 2a7e30cada6..62a04292e23 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -166,6 +166,9 @@ class Local extends \OC\Files\Storage\Common { public function stat($path) { $fullPath = $this->getSourcePath($path); clearstatcache(true, $fullPath); + if (!file_exists($fullPath)) { + return false; + } $statResult = @stat($fullPath); if (PHP_INT_SIZE === 4 && $statResult && !$this->is_dir($path)) { $filesize = $this->filesize($path); @@ -388,11 +391,15 @@ class Local extends \OC\Files\Storage\Common { } public function fopen($path, $mode) { + $sourcePath = $this->getSourcePath($path); + if (!file_exists($sourcePath) && $mode === 'r') { + return false; + } $oldMask = umask($this->defUMask); if (($mode === 'w' || $mode === 'w+') && $this->unlinkOnTruncate) { $this->unlink($path); } - $result = fopen($this->getSourcePath($path), $mode); + $result = @fopen($sourcePath, $mode); umask($oldMask); return $result; } diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 294912e698b..986aecf556f 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -1003,7 +1003,17 @@ class View { $this->logger->info('Trying to open a file with a mode other than "r" or "w" can cause severe performance issues with some backends', ['app' => 'core']); } - return $this->basicOperation('fopen', $path, $hooks, $mode); + $handle = $this->basicOperation('fopen', $path, $hooks, $mode); + if (!is_resource($handle) && $mode === 'r') { + // trying to read a file that isn't on disk, check if the cache is out of sync and rescan if needed + $mount = $this->getMount($path); + $internalPath = $mount->getInternalPath($this->getAbsolutePath($path)); + $storage = $mount->getStorage(); + if ($storage->getCache()->inCache($internalPath) && !$storage->file_exists($path)) { + $this->writeUpdate($storage, $internalPath); + } + } + return $handle; } /** diff --git a/tests/lib/Files/ViewTest.php b/tests/lib/Files/ViewTest.php index 86101d79a1e..2189e7c09f4 100644 --- a/tests/lib/Files/ViewTest.php +++ b/tests/lib/Files/ViewTest.php @@ -2709,4 +2709,23 @@ class ViewTest extends \Test\TestCase { $this->assertEquals(25, $info->getUploadTime()); $this->assertEquals(0, $info->getCreationTime()); } + + public function testFopenGone() { + $storage = new Temporary([]); + $scanner = $storage->getScanner(); + $storage->file_put_contents('foo.txt', 'bar'); + $scanner->scan(''); + $cache = $storage->getCache(); + + Filesystem::mount($storage, [], '/test/'); + $view = new View('/test'); + + $storage->unlink('foo.txt'); + + $this->assertTrue($cache->inCache('foo.txt')); + + $this->assertFalse($view->fopen('foo.txt', 'r')); + + $this->assertFalse($cache->inCache('foo.txt')); + } }