diff options
author | Lukas Reschke <lukas@owncloud.com> | 2015-02-26 16:35:13 +0100 |
---|---|---|
committer | Lukas Reschke <lukas@owncloud.com> | 2015-02-26 16:35:13 +0100 |
commit | 9baf758150e348f7e1f0edf57bb432a0cbf6ff1b (patch) | |
tree | c9cf57bc8a7dbe4eb1c03b98933814e2177f110b /lib | |
parent | 2d9886d1c31801156c74935d4a38d6f6959dc66c (diff) | |
parent | 232de3bdc093e839048d5b00d7f08ecc87ba7908 (diff) | |
download | nextcloud-server-9baf758150e348f7e1f0edf57bb432a0cbf6ff1b.tar.gz nextcloud-server-9baf758150e348f7e1f0edf57bb432a0cbf6ff1b.zip |
Merge pull request #14503 from owncloud/quota-preventdatalossforfailedmove
Fix file move/copy when storage space is not enough
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/files/view.php | 44 | ||||
-rw-r--r-- | lib/private/helper.php | 16 |
2 files changed, 47 insertions, 13 deletions
diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 7de7ef7b32c..e4732f8bb3d 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -574,8 +574,11 @@ class View { } /** - * @param string $path1 - * @param string $path2 + * Rename/move a file or folder from the source path to target path. + * + * @param string $path1 source path + * @param string $path2 target path + * * @return bool|mixed */ public function rename($path1, $path2) { @@ -617,7 +620,7 @@ class View { $mount = $manager->find($absolutePath1 . $postFix1); $storage1 = $mount->getStorage(); $internalPath1 = $mount->getInternalPath($absolutePath1 . $postFix1); - list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); + list($storage2, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($internalPath1 === '' and $mount instanceof MoveableMount) { if ($this->isTargetAllowed($absolutePath2)) { /** @@ -646,8 +649,10 @@ class View { } else { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); - list($count, $result) = \OC_Helper::streamCopy($source, $target); - $this->touch($path2, $this->filemtime($path1)); + list(, $result) = \OC_Helper::streamCopy($source, $target); + if ($result !== false) { + $this->touch($path2, $this->filemtime($path1)); + } // close open handle - especially $source is necessary because unlink below will // throw an exception on windows because the file is locked @@ -656,6 +661,11 @@ class View { if ($result !== false) { $result &= $storage1->unlink($internalPath1); + } else { + // delete partially written target file + $storage2->unlink($internalPath2); + // delete cache entry that was created by fopen + $storage2->getCache()->remove($internalPath2); } } } @@ -688,9 +698,12 @@ class View { } /** - * @param string $path1 - * @param string $path2 - * @param bool $preserveMtime + * Copy a file/folder from the source path to target path + * + * @param string $path1 source path + * @param string $path2 target path + * @param bool $preserveMtime whether to preserve mtime on the copy + * * @return bool|mixed */ public function copy($path1, $path2, $preserveMtime = false) { @@ -732,6 +745,11 @@ class View { list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->copy($internalPath1, $internalPath2); + if (!$result) { + // delete partially written target file + $storage->unlink($internalPath2); + $storage->getCache()->remove($internalPath2); + } } else { $result = false; } @@ -749,14 +767,20 @@ class View { } } } else { + list($storage2, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); - list($count, $result) = \OC_Helper::streamCopy($source, $target); - if($preserveMtime) { + list(, $result) = \OC_Helper::streamCopy($source, $target); + if($result && $preserveMtime) { $this->touch($path2, $this->filemtime($path1)); } fclose($source); fclose($target); + if (!$result) { + // delete partially written target file + $storage2->unlink($internalPath2); + $storage2->getCache()->remove($internalPath2); + } } } $this->updater->update($path2); diff --git a/lib/private/helper.php b/lib/private/helper.php index 04c063145ba..f4992744ad9 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -594,13 +594,23 @@ class OC_Helper { if (!$source or !$target) { return array(0, false); } + $bufSize = 8192; $result = true; $count = 0; while (!feof($source)) { - if (($c = fwrite($target, fread($source, 8192))) === false) { + $buf = fread($source, $bufSize); + $bytesWritten = fwrite($target, $buf); + if ($bytesWritten !== false) { + $count += $bytesWritten; + } + // note: strlen is expensive so only use it when necessary, + // on the last block + if ($bytesWritten === false + || ($bytesWritten < $bufSize && $bytesWritten < strlen($buf)) + ) { + // write error, could be disk full ? $result = false; - } else { - $count += $c; + break; } } return array($count, $result); |