diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index 6406beaeebc0b..b46913e707291 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -149,6 +149,9 @@ public function is_file($path) { 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); diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index ea773007ba6d7..37a0d45fa89a7 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -1002,7 +1002,17 @@ public function fopen($path, $mode) { \OC::$server->getLogger()->info('Trying to open a file with a mode other than "r" or "w" can cause severe performance issues with some backends'); } - 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 eed8bca957fa5..b2c8d40946f6a 100644 --- a/tests/lib/Files/ViewTest.php +++ b/tests/lib/Files/ViewTest.php @@ -2711,4 +2711,23 @@ public function testCacheExtension() { $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')); + } }