diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 7bb4a2b4f7..492917b915 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1661,11 +1661,13 @@ class View { /** * @param string $path the path of the file to lock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise + * @throws \OCP\Lock\LockedException if the path is already locked */ private function lockPath($path, $type) { $absolutePath = $this->getAbsolutePath($path); if (!$this->shouldLockFile($absolutePath)) { - return; + return false; } $mount = $this->getMount($path); @@ -1676,16 +1678,20 @@ class View { $this->lockingProvider ); } + + return true; } /** * @param string $path the path of the file to lock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise + * @throws \OCP\Lock\LockedException if the path is already locked */ private function changeLock($path, $type) { $absolutePath = $this->getAbsolutePath($path); if (!$this->shouldLockFile($absolutePath)) { - return; + return false; } $mount = $this->getMount($path); @@ -1696,16 +1702,19 @@ class View { $this->lockingProvider ); } + + return true; } /** * @param string $path the path of the file to unlock, relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise */ private function unlockPath($path, $type) { $absolutePath = $this->getAbsolutePath($path); if (!$this->shouldLockFile($absolutePath)) { - return; + return false; } $mount = $this->getMount($path); @@ -1716,6 +1725,8 @@ class View { $this->lockingProvider ); } + + return true; } /** @@ -1723,13 +1734,14 @@ class View { * * @param string $path the path of the file to lock relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise */ public function lockFile($path, $type) { $path = '/' . trim($path, '/'); $absolutePath = $this->getAbsolutePath($path); if (!$this->shouldLockFile($absolutePath)) { - return; + return false; } $this->lockPath($path, $type); @@ -1738,6 +1750,8 @@ class View { foreach ($parents as $parent) { $this->lockPath($parent, ILockingProvider::LOCK_SHARED); } + + return true; } /** @@ -1745,13 +1759,14 @@ class View { * * @param string $path the path of the file to lock relative to the view * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE + * @return bool False if the path is excluded from locking, true otherwise */ public function unlockFile($path, $type) { $path = rtrim($path, '/'); $absolutePath = $this->getAbsolutePath($path); if (!$this->shouldLockFile($absolutePath)) { - return; + return false; } $this->unlockPath($path, $type); @@ -1760,6 +1775,8 @@ class View { foreach ($parents as $parent) { $this->unlockPath($parent, ILockingProvider::LOCK_SHARED); } + + return true; } /** diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 06a42d6343..1050c36d29 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -1086,25 +1086,87 @@ class View extends \Test\TestCase { * e.g. reading from a folder that's being renamed * * @expectedException \OCP\Lock\LockedException + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix */ - public function testReadFromWriteLockedPath() { - $view = new \OC\Files\View(); + public function testReadFromWriteLockedPath($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files', $rootPath); + $pathPrefix = str_replace('{folder}', 'files', $pathPrefix); + + $view = new \OC\Files\View($rootPath); $storage = new Temporary(array()); \OC\Files\Filesystem::mount($storage, [], '/'); - $view->lockFile('/foo/bar', ILockingProvider::LOCK_EXCLUSIVE); - $view->lockFile('/foo/bar/asd', ILockingProvider::LOCK_SHARED); + $this->assertTrue($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE)); + $view->lockFile($pathPrefix . '/foo/bar/asd', ILockingProvider::LOCK_SHARED); + } + + /** + * Reading from a files_encryption folder that's being renamed + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix + */ + public function testReadFromWriteUnlockablePath($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files_encryption', $rootPath); + $pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix); + + $view = new \OC\Files\View($rootPath); + $storage = new Temporary(array()); + \OC\Files\Filesystem::mount($storage, [], '/'); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE)); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar/asd', ILockingProvider::LOCK_SHARED)); } /** * e.g. writing a file that's being downloaded * * @expectedException \OCP\Lock\LockedException + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix */ - public function testWriteToReadLockedFile() { - $view = new \OC\Files\View(); + public function testWriteToReadLockedFile($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files', $rootPath); + $pathPrefix = str_replace('{folder}', 'files', $pathPrefix); + + $view = new \OC\Files\View($rootPath); $storage = new Temporary(array()); \OC\Files\Filesystem::mount($storage, [], '/'); - $view->lockFile('/foo/bar', ILockingProvider::LOCK_SHARED); - $view->lockFile('/foo/bar', ILockingProvider::LOCK_EXCLUSIVE); + $this->assertTrue($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_SHARED)); + $view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE); + } + + /** + * Writing a file that's being downloaded + * + * @dataProvider dataLockPaths + * + * @param string $rootPath + * @param string $pathPrefix + */ + public function testWriteToReadUnlockableFile($rootPath, $pathPrefix) { + $rootPath = str_replace('{folder}', 'files_encryption', $rootPath); + $pathPrefix = str_replace('{folder}', 'files_encryption', $pathPrefix); + + $view = new \OC\Files\View($rootPath); + $storage = new Temporary(array()); + \OC\Files\Filesystem::mount($storage, [], '/'); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_SHARED)); + $this->assertFalse($view->lockFile($pathPrefix . '/foo/bar', ILockingProvider::LOCK_EXCLUSIVE)); + } + + public function dataLockPaths() { + return [ + ['/testuser/{folder}', ''], + ['/testuser', '/{folder}'], + ['', '/testuser/{folder}'], + ]; } }