8000 feature #40143 [Filesystem] improve messages on failure (nicolas-grekas) · symfony/symfony@f2f880a · GitHub
[go: up one dir, main page]

Skip to content

Commit f2f880a

Browse files
committed
feature #40143 [Filesystem] improve messages on failure (nicolas-grekas)
This PR was merged into the 5.3-dev branch. Discussion ---------- [Filesystem] improve messages on failure | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Commits ------- f5ddfad [Filesystem] improve messages on failure
2 parents 1f067bc + f5ddfad commit f2f880a

File tree

1 file changed

+33
-45
lines changed

1 file changed

+33
-45
lines changed

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ public function copy(string $originFile, string $targetFile, bool $overwriteNewe
5050

5151
if ($doCopy) {
5252
// https://bugs.php.net/64634
53-
if (false === $source = @fopen($originFile, 'r')) {
54-
throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
53+
if (!$source = self::box('fopen', $originFile, 'r')) {
54+
throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile);
5555
}
5656

5757
// Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
58-
if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(['ftp' => ['overwrite' => true]]))) {
59-
throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
58+
if (!$target = self::box('fopen', $targetFile, 'w', null, stream_context_create(['ftp' => ['overwrite' => true]]))) {
59+
throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing: ', $originFile, $targetFile).self::$lastError, 0, null, $originFile);
6060
}
6161

6262
$bytesCopied = stream_copy_to_stream($source, $target);
@@ -70,7 +70,7 @@ public function copy(string $originFile, string $targetFile, bool $overwriteNewe
7070

7171
if ($originIsLocal) {
7272
// Like `cp`, preserve executable permission bits
73-
@chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
73+
self::box('chmod', $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
7474

7575
if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
7676
throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
@@ -93,14 +93,8 @@ public function mkdir($dirs, int $mode = 0777)
9393
continue;
9494
}
9595

96-
if (!self::box('mkdir', $dir, $mode, true)) {
97-
if (!is_dir($dir)) {
98-
// The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
99-
if (self::$lastError) {
100-
throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir);
101-
}
102-
throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir);
103-
}
96+
if (!self::box('mkdir', $dir, $mode, true) && !is_dir($dir)) {
97+
throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir);
10498
}
10599
}
106100
}
@@ -141,9 +135,8 @@ public function exists($files)
141135
public function touch($files, int $time = null, int $atime = null)
142136
{
143137
foreach ($this->toIterable($files) as $file) {
144-
$touch = $time ? @touch($file, $time, $atime) : @touch($file);
145-
if (true !== $touch) {
146-
throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
138+
if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) {
139+
throw new IOException(sprintf('Failed to touch "%s": ', $file).self::$lastError, 0, null, $file);
147140
}
148141
}
149142
}
@@ -225,8 +218,8 @@ private static function doRemove(array $files, bool $isRecursive): void
225218
public function chmod($files, int $mode, int $umask = 0000, bool $recursive = false)
226219
{
227220
foreach ($this->toIterable($files) as $file) {
228-
if ((\PHP_VERSION_ID < 80000 || \is_int($mode)) && true !== @chmod($file, $mode & ~$umask)) {
229-
throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
221+
if ((\PHP_VERSION_ID < 80000 || \is_int($mode)) && !self::box('chmod', $file, $mode & ~$umask)) {
222+
throw new IOException(sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file);
230223
}
231224
if ($recursive && is_dir($file) && !is_link($file)) {
232225
$this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
@@ -250,12 +243,12 @@ public function chown($files, $user, bool $recursive = false)
250243
$this->chown(new \FilesystemIterator($file), $user, true);
251244
}
252245
if (is_link($file) && \function_exists('lchown')) {
253-
if (true !== @lchown($file, $user)) {
254-
throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
246+
if (!self::box('lchown', $file, $user)) {
247+
throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
255248
}
256249
} else {
257-
if (true !== @chown($file, $user)) {
258-
throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
250+
if (!self::box('chown', $file, $user)) {
251+
throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
259252
}
260253
}
261254
}
@@ -277,12 +270,12 @@ public function chgrp($files, $group, bool $recursive = false)
277270
$this->chgrp(new \FilesystemIterator($file), $group, true);
278271
}
279272
if (is_link($file) && \function_exists('lchgrp')) {
280-
if (true !== @lchgrp($file, $group)) {
281-
throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
273+
if (!self::box('lchgrp', $file, $group)) {
274+
throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
282275
}
283276
} else {
284-
if (true !== @chgrp($file, $group)) {
285-
throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
277+
if (!self::box('chgrp', $file, $group)) {
278+
throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
286279
}
287280
}
288281
}
@@ -301,15 +294,15 @@ public function rename(string $origin, string $target, bool $overwrite = false)
301294
throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
302295
}
303296

304-
if (true !== @rename($origin, $target)) {
297+
if (!self::box('rename', $origin, $target)) {
305298
if (is_dir($origin)) {
306299
// See https://bugs.php.net/54097 & https://php.net/rename#113943
307300
$this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]);
308301
$this->remove($origin);
309302

310303
return;
311304
}
312-
throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
< 10000 code>305+
throw new IOException(sprintf('Cannot rename "%s" to "%s": ', $origin, $target).self::$lastError, 0, null, $target);
313306
}
314307
}
315308

@@ -403,7 +396,7 @@ private function linkException(string $origin, string $target, string $linkType)
403396
throw new IOException(sprintf('Unable to create "%s" link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target);
404397
}
405398
}
406-
throw new IOException(sprintf('Failed to create "%s" link from "%s" to "%s".', $linkType, $origin, $target), 0, null, $target);
399+
throw new IOException(sprintf('Failed to create "%s" link from "%s" to "%s": ', $linkType, $origin, $target).self::$lastError, 0, null, $target);
407400
}
408401

409402
/**
@@ -625,18 +618,16 @@ public function tempnam(string $dir, string $prefix/*, string $suffix = ''*/)
625618

626619
// If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem
627620
if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) {
628-
$tmpFile = @tempnam($hierarchy, $prefix);
629-
630621
// If tempnam failed or no scheme return the filename otherwise prepend the scheme
631-
if (false !== $tmpFile) {
622+
if ($tmpFile = self::box('tempnam', $hierarchy, $prefix)) {
632623
if (null !== $scheme && 'gs' !== $scheme) {
633624
return $scheme.'://'.$tmpFile;
634625
}
635626

636627
return $tmpFile;
637628
}
638629

639-
throw new IOException('A temporary file could not be created.');
630+
throw new IOException('A temporary file could not be created: '.self::$lastError);
640631
}
641632

642633
// Loop until we create a valid temp file or have reached 10 attempts
@@ -646,20 +637,17 @@ public function tempnam(string $dir, string $prefix/*, string $suffix = ''*/)
646637

647638
// Use fopen instead of file_exists as some streams do not support stat
648639
// Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability
649-
$handle = @fopen($tmpFile, 'x+');
650-
651-
// If unsuccessful restart the loop
652-
if (false === $handle) {
640+
if (!$handle = self::box('fopen', $tmpFile, 'x+')) {
653641
continue;
654642
}
655643

656644
// Close the file if it was successfully opened
657-
@fclose($handle);
645+
self::box('fclose', $handle);
658646

659647
return $tmpFile;
660648
}
661649

662-
throw new IOException('A temporary file could not be created.');
650+
throw new IOException('A temporary file could not be created: '.self::$lastError);
663651
}
664652

665653
/**
@@ -690,16 +678,16 @@ public function dumpFile(string $filename, $content)
690678
$tmpFile = $this->tempnam($dir, basename($filename));
691679

692680
try {
693-
if (false === @file_put_contents($tmpFile, $content)) {
694-
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
681+
if (false === self::box('file_put_contents', $tmpFile, $content)) {
682+
throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename);
695683
}
696684

697-
@chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());
685+
self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());
698686

699687
$this->rename($tmpFile, $filename, true);
700688
} finally {
701689
if (file_exists($tmpFile)) {
702-
@unlink($tmpFile);
690+
self::box('unlink', $tmpFile);
703691
}
704692
}
705693
}
@@ -727,8 +715,8 @@ public function appendToFile(string $filename, $content)
727715
throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
728716
}
729717

730-
if (false === @file_put_contents($filename, $content, \FILE_APPEND)) {
731-
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
718+
if (false === self::box('file_put_contents', $filename, $content, \FILE_APPEND)) {
719+
throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename);
732720
}
733721
}
734722

0 commit comments

Comments
 (0)
0