From a590972e68324968b5c1f80f21e296e9bb301ace Mon Sep 17 00:00:00 2001 From: Nyholm Date: Tue, 20 Oct 2020 23:27:26 +0200 Subject: [PATCH] [Filesystem] Check if failed unlink was caused by permission denied --- Filesystem.php | 2 +- Tests/FilesystemTest.php | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Filesystem.php b/Filesystem.php index a6e8715256..96b2e96009 100644 --- a/Filesystem.php +++ b/Filesystem.php @@ -179,7 +179,7 @@ public function remove($files) if (!self::box('rmdir', $file) && file_exists($file)) { throw new IOException(sprintf('Failed to remove directory "%s": ', $file).self::$lastError); } - } elseif (!self::box('unlink', $file) && file_exists($file)) { + } elseif (!self::box('unlink', $file) && (false !== strpos(self::$lastError, 'Permission denied') || file_exists($file))) { throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError); } } diff --git a/Tests/FilesystemTest.php b/Tests/FilesystemTest.php index 14837152b3..b157cc4ed3 100644 --- a/Tests/FilesystemTest.php +++ b/Tests/FilesystemTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Filesystem\Tests; +use Symfony\Component\Filesystem\Exception\IOException; + /** * Test class for Filesystem. */ @@ -334,6 +336,28 @@ public function testRemoveIgnoresNonExistingFiles() $this->assertFileDoesNotExist($basePath.'dir'); } + public function testRemoveThrowsExceptionOnPermissionDenied() + { + $this->markAsSkippedIfChmodIsMissing(); + + $basePath = $this->workspace.\DIRECTORY_SEPARATOR.'dir_permissions'; + mkdir($basePath); + $file = $basePath.\DIRECTORY_SEPARATOR.'file'; + touch($file); + chmod($basePath, 0400); + + try { + $this->filesystem->remove($file); + $this->fail('Filesystem::remove() should throw an exception'); + } catch (IOException $e) { + $this->assertStringContainsString('Failed to remove file "'.$file.'"', $e->getMessage()); + $this->assertStringContainsString('Permission denied', $e->getMessage()); + } finally { + // Make sure we can clean up this file + chmod($basePath, 0777); + } + } + public function testRemoveCleansInvalidLinks() { $this->markAsSkippedIfSymlinkIsMissing();