From cd5da9b3c879eac2665722cd5a4f7a2c726392e1 Mon Sep 17 00:00:00 2001 From: David Otton Date: Wed, 21 May 2014 19:12:51 +0100 Subject: [PATCH] [Filesystem] Throw Exception on copying from an unreadable file or to an unwritable file --- .../Component/Filesystem/Filesystem.php | 8 +++- .../Filesystem/Tests/FilesystemTest.php | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index ca146aa816..7e13571c9e 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -51,8 +51,12 @@ class Filesystem if ($doCopy) { // https://bugs.php.net/bug.php?id=64634 - $source = fopen($originFile, 'r'); - $target = fopen($targetFile, 'w'); + if (false === $source = @fopen($originFile, 'r')) { + throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile); + } + if (false === $target = @fopen($targetFile, 'w')) { + throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile); + } stream_copy_to_stream($source, $target); fclose($source); fclose($target); diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index aad5b99918..db9f4376e1 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -53,6 +53,27 @@ class FilesystemTest extends FilesystemTestCase $this->filesystem->copy($sourceFilePath, $targetFilePath); } + /** + * @expectedException \Symfony\Component\Filesystem\Exception\IOException + */ + public function testCopyUnreadableFileFails() + { + // skip test on Windows; PHP can't easily set file as unreadable on Windows + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { + $this->markTestSkipped('This test cannot run on Windows.');; + } + + $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file'; + $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file'; + + file_put_contents($sourceFilePath, 'SOURCE FILE'); + + // make sure target cannot be read + $this->filesystem->chmod($sourceFilePath, 0222); + + $this->filesystem->copy($sourceFilePath, $targetFilePath); + } + public function testCopyOverridesExistingFileIfModified() { $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file'; @@ -106,6 +127,33 @@ class FilesystemTest extends FilesystemTestCase $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath)); } + /** + * @expectedException \Symfony\Component\Filesystem\Exception\IOException + */ + public function testCopyWithOverrideWithReadOnlyTargetFails() + { + // skip test on Windows; PHP can't easily set file as unwritable on Windows + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { + $this->markTestSkipped('This test cannot run on Windows.');; + } + + $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file'; + $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file'; + + file_put_contents($sourceFilePath, 'SOURCE FILE'); + file_put_contents($targetFilePath, 'TARGET FILE'); + + // make sure both files have the same modification time + $modificationTime = time() - 1000; + touch($sourceFilePath, $modificationTime); + touch($targetFilePath, $modificationTime); + + // make sure target is read-only + $this->filesystem->chmod($targetFilePath, 0444); + + $this->filesystem->copy($sourceFilePath, $targetFilePath, true); + } + public function testCopyCreatesTargetDirectoryIfItDoesNotExist() { $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';