From: Vincent Petry Date: Mon, 23 Feb 2015 11:31:22 +0000 (+0100) Subject: Properly detect streamCopy errors X-Git-Tag: v8.1.0alpha1~394^2~1 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=20738d287e456ddb05a617f6b808f152cc3028a9;p=nextcloud-server.git Properly detect streamCopy errors Now checking whether the written bytes match the number of read bytes. --- 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); diff --git a/tests/lib/files/storage/wrapper/quota.php b/tests/lib/files/storage/wrapper/quota.php index dc4de4697db..8ca8f308b71 100644 --- a/tests/lib/files/storage/wrapper/quota.php +++ b/tests/lib/files/storage/wrapper/quota.php @@ -99,6 +99,28 @@ class Quota extends \Test\Files\Storage\Storage { $this->assertEquals('foobarqwe', $instance->file_get_contents('foo')); } + public function testStreamCopyWithEnoughSpace() { + $instance = $this->getLimitedStorage(16); + $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); + $outputStream = $instance->fopen('foo', 'w+'); + list($count, $result) = \OC_Helper::streamCopy($inputStream, $outputStream); + $this->assertEquals(12, $count); + $this->assertTrue($result); + fclose($inputStream); + fclose($outputStream); + } + + public function testStreamCopyNotEnoughSpace() { + $instance = $this->getLimitedStorage(9); + $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); + $outputStream = $instance->fopen('foo', 'w+'); + list($count, $result) = \OC_Helper::streamCopy($inputStream, $outputStream); + $this->assertEquals(9, $count); + $this->assertFalse($result); + fclose($inputStream); + fclose($outputStream); + } + public function testReturnFalseWhenFopenFailed() { $failStorage = $this->getMock( '\OC\Files\Storage\Local',