summaryrefslogtreecommitdiffstats
path: root/lib/private/files/view.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/files/view.php')
-rw-r--r--lib/private/files/view.php97
1 files changed, 85 insertions, 12 deletions
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index b98842f5eb7..483dc610523 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -535,25 +535,40 @@ class View {
) {
$path = $this->getRelativePath($absolutePath);
+ $this->lockFile($path, ILockingProvider::LOCK_SHARED);
+
$exists = $this->file_exists($path);
$run = true;
if ($this->shouldEmitHooks($path)) {
$this->emit_file_hooks_pre($exists, $path, $run);
}
if (!$run) {
+ $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
return false;
}
- $target = $this->fopen($path, 'w');
+
+ $this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
+
+ /** @var \OC\Files\Storage\Storage $storage */
+ list($storage, $internalPath) = $this->resolvePath($path);
+ $target = $storage->fopen($internalPath, 'w');
if ($target) {
- list ($count, $result) = \OC_Helper::streamCopy($data, $target);
+ list (, $result) = \OC_Helper::streamCopy($data, $target);
fclose($target);
fclose($data);
+
+ $this->changeLock($path, ILockingProvider::LOCK_SHARED);
+
$this->updater->update($path);
+
+ $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
+
if ($this->shouldEmitHooks($path) && $result !== false) {
$this->emit_file_hooks_post($exists, $path);
}
return $result;
} else {
+ $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
return false;
}
} else {
@@ -1661,52 +1676,74 @@ 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 false;
+ }
+
$mount = $this->getMount($path);
if ($mount) {
$mount->getStorage()->acquireLock(
- $mount->getInternalPath(
- $this->getAbsolutePath($path)
- ),
+ $mount->getInternalPath($absolutePath),
$type,
$this->lockingProvider
);
}
+
+ return true;
}
/**
+ * Change the lock type
+ *
* @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) {
+ public function changeLock($path, $type) {
+ $absolutePath = $this->getAbsolutePath($path);
+ if (!$this->shouldLockFile($absolutePath)) {
+ return false;
+ }
+
$mount = $this->getMount($path);
if ($mount) {
$mount->getStorage()->changeLock(
- $mount->getInternalPath(
- $this->getAbsolutePath($path)
- ),
+ $mount->getInternalPath($absolutePath),
$type,
$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 false;
+ }
+
$mount = $this->getMount($path);
if ($mount) {
$mount->getStorage()->releaseLock(
- $mount->getInternalPath(
- $this->getAbsolutePath($path)
- ),
+ $mount->getInternalPath($absolutePath),
$type,
$this->lockingProvider
);
}
+
+ return true;
}
/**
@@ -1714,15 +1751,24 @@ 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 false;
+ }
+
$this->lockPath($path, $type);
$parents = $this->getParents($path);
foreach ($parents as $parent) {
$this->lockPath($parent, ILockingProvider::LOCK_SHARED);
}
+
+ return true;
}
/**
@@ -1730,14 +1776,41 @@ 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 false;
+ }
+
$this->unlockPath($path, $type);
$parents = $this->getParents($path);
foreach ($parents as $parent) {
$this->unlockPath($parent, ILockingProvider::LOCK_SHARED);
}
+
+ return true;
+ }
+
+ /**
+ * Only lock files in data/user/files/
+ *
+ * @param string $path Absolute path to the file/folder we try to (un)lock
+ * @return bool
+ */
+ protected function shouldLockFile($path) {
+ $path = Filesystem::normalizePath($path);
+
+ $pathSegments = explode('/', $path);
+ if (isset($pathSegments[2])) {
+ // E.g.: /username/files/path-to-file
+ return $pathSegments[2] === 'files';
+ }
+
+ return true;
}
}