8000 [Filesystem] Use first-class callable syntax by derrabus · Pull Request #46408 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Filesystem] Use first-class callable syntax #46408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions src/Symfony/Component/Filesystem/Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
class Filesystem
{
private static $lastError;
private static ?string $lastError = null;

/**
* Copies a file.
Expand Down Expand Up @@ -50,12 +50,12 @@ public function copy(string $originFile, string $targetFile, bool $overwriteNewe

if ($doCopy) {
// https://bugs.php.net/64634
if (!$source = self::box('fopen', $originFile, 'r')) {
if (!$source = self::box(fopen(...), $originFile, 'r')) {
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);
}

// Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
if (!$target = self::box('fopen', $targetFile, 'w', false, stream_context_create(['ftp' => ['overwrite' => true]]))) {
if (!$target = self::box(fopen(...), $targetFile, 'w', false, stream_context_create(['ftp' => ['overwrite' => true]]))) {
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);
}

Expand All @@ -70,7 +70,7 @@ public function copy(string $originFile, string $targetFile, bool $overwriteNewe

if ($originIsLocal) {
// Like `cp`, preserve executable permission bits
self::box('chmod', $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
self::box(chmod(...), $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));

if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
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);
Expand All @@ -91,7 +91,7 @@ public function mkdir(string|iterable $dirs, int $mode = 0777)
continue;
}

if (!self::box('mkdir', $dir, $mode, true) && !is_dir($dir)) {
if (!self::box(mkdir(...), $dir, $mode, true) && !is_dir($dir)) {
throw new IOException(sprintf('Failed to create "%s": ', $dir).self::$lastError, 0, null, $dir);
}
}
Expand Down Expand Up @@ -128,7 +128,7 @@ public function exists(string|iterable $files): bool
public function touch(string|iterable $files, int $time = null, int $atime = null)
{
foreach ($this->toIterable($files) as $file) {
if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) {
if (!($time ? self::box(touch(...), $file, $time, $atime) : self::box(touch(...), $file))) {
throw new IOException(sprintf('Failed to touch "%s": ', $file).self::$lastError, 0, null, $file);
}
}
Expand Down Expand Up @@ -156,7 +156,7 @@ private static function doRemove(array $files, bool $isRecursive): void
foreach ($files as $file) {
if (is_link($file)) {
// See https://bugs.php.net/52176
if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
if (!(self::box(unlink(...), $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box(rmdir(...), $file)) && file_exists($file)) {
throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError);
}
} elseif (is_dir($file)) {
Expand All @@ -170,7 +170,7 @@ private static function doRemove(array $files, bool $isRecursive): void
}
}

if (!file_exists($tmpName) && self::box('rename', $file, $tmpName)) {
if (!file_exists($tmpName) && self::box(rename(...), $file, $tmpName)) {
$origFile = $file;
$file = $tmpName;
} else {
Expand All @@ -181,16 +181,16 @@ private static function doRemove(array $files, bool $isRecursive): void
$filesystemIterator = new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS);
self::doRemove(iterator_to_array($filesystemIterator, true), true);

if (!self::box('rmdir', $file) && file_exists($file) && !$isRecursive) {
if (!self::box(rmdir(...), $file) && file_exists($file) && !$isRecursive) {
$lastError = self::$lastError;

if (null !== $origFile && self::box('rename', $file, $origFile)) {
if (null !== $origFile && self::box(rename(...), $file, $origFile)) {
$file = $origFile;
}

throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError);
}
} elseif (!self::box('unlink', $file) && (str_contains(self::$lastError, 'Permission denied') || file_exists($file))) {
} elseif (!self::box(unlink(...), $file) && (str_contains(self::$lastError, 'Permission denied') || file_exists($file))) {
throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError);
}
}
Expand All @@ -208,7 +208,7 @@ private static function doRemove(array $files, bool $isRecursive): void
public function chmod(string|iterable $files, int $mode, int $umask = 0000, bool $recursive = false)
{
foreach ($this->toIterable($files) as $file) {
if (\is_int($mode) && !self::box('chmod', $file, $mode & ~$umask)) {
if (\is_int($mode) && !self::box(chmod(...), $file, $mode & ~$umask)) {
throw new IOException(sprintf('Failed to chmod file "%s": ', $file).self::$lastError, 0, null, $file);
}
if ($recursive && is_dir($file) && !is_link($file)) {
Expand All @@ -232,11 +232,11 @@ public function chown(string|iterable $files, string|int $user, bool $recursive
$this->chown(new \FilesystemIterator($file), $user, true);
}
if (is_link($file) && \function_exists('lchown')) {
if (!self::box('lchown', $file, $user)) {
if (!self::box(lchown(...), $file, $user)) {
throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
}
} else {
if (!self::box('chown', $file, $user)) {
if (!self::box(chown(...), $file, $user)) {
throw new IOException(sprintf('Failed to chown file "%s": ', $file).self::$lastError, 0, null, $file);
}
}
Expand All @@ -258,11 +258,11 @@ public function chgrp(string|iterable $files, string|int $group, bool $recursive
$this->chgrp(new \FilesystemIterator($file), $group, true);
}
if (is_link($file) && \function_exists('lchgrp')) {
if (!self::box('lchgrp', $file, $group)) {
if (!self::box(lchgrp(...), $file, $group)) {
throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
}
} else {
if (!self::box('chgrp', $file, $group)) {
if (! 10000 self::box(chgrp(...), $file, $group)) {
throw new IOException(sprintf('Failed to chgrp file "%s": ', $file).self::$lastError, 0, null, $file);
}
}
Expand All @@ -282,7 +282,7 @@ public function rename(string $origin, string $target, bool $overwrite = false)
throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
}

if (!self::box('rename', $origin, $target)) {
if (!self::box(rename(...), $origin, $target)) {
if (is_dir($origin)) {
// See https://bugs.php.net/54097 & https://php.net/rename#113943
$this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]);
Expand Down Expand Up @@ -337,7 +337,7 @@ public function symlink(string $originDir, string $targetDir, bool $copyOnWindow
$this->remove($targetDir);
}

if (!self::box('symlink', $originDir, $targetDir)) {
if (!self::box(symlink(...), $originDir, $targetDir)) {
$this->linkException($originDir, $targetDir, 'symbolic');
}
}
Expand Down Expand Up @@ -368,7 +368,7 @@ public function hardlink(string $originFile, string|iterable $targetFiles)
$this->remove($targetFile);
}

if (!self::box('link', $originFile, $targetFile)) {
if (!self::box(link(...), $originFile, $targetFile)) {
$this->linkException($originFile, $targetFile, 'hard');
}
}
Expand Down Expand Up @@ -592,7 +592,7 @@ public function tempnam(string $dir, string $prefix, string $suffix = ''): strin
// If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem
if ((null === $scheme || 'file' === $scheme || 'gs' === $scheme) && '' === $suffix) {
// If tempnam failed or no scheme return the filename otherwise prepend the scheme
if ($tmpFile = self::box('tempnam', $hierarchy, $prefix)) {
if ($tmpFile = self::box(tempnam(...), $hierarchy, $prefix)) {
if (null !== $scheme && 'gs' !== $scheme) {
return $scheme.'://'.$tmpFile;
}
Expand All @@ -610,12 +610,12 @@ public function tempnam(string $dir, string $prefix, string $suffix = ''): strin

// Use fopen instead of file_exists as some streams do not support stat
// Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability
if (!$handle = self::box('fopen', $tmpFile, 'x+')) {
if (!$handle = self::box(fopen(...), $tmpFile, 'x+')) {
continue;
}

// Close the file if it was successfully opened
self::box('fclose', $handle);
self::box(fclose(...), $handle);

return $tmpFile;
}
Expand Down Expand Up @@ -647,16 +647,16 @@ public function dumpFile(string $filename, $content)
$tmpFile = $this->tempnam($dir, basename($filename));

try {
if (false === self::box('file_put_contents', $tmpFile, $content)) {
if (false === self::box(file_put_contents(...), $tmpFile, $content)) {
throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename);
}

self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());
self::box(chmod(...), $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());

$this->rename($tmpFile, $filename, true);
} finally {
if (file_exists($tmpFile)) {
self::box('unlink', $tmpFile);
self::box(unlink(...), $tmpFile);
}
}
}
Expand All @@ -683,7 +683,7 @@ public function appendToFile(string $filename, $content/*, bool $lock = false*/)

$lock = \func_num_args() > 2 && func_get_arg(2);

if (false === self::box('file_put_contents', $filename, $content, \FILE_APPEND | ($lock ? \LOCK_EX : 0))) {
if (false === self::box(file_put_contents(...), $filename, $content, \FILE_APPEND | ($lock ? \LOCK_EX : 0))) {
throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename);
}
}
Expand All @@ -706,7 +706,7 @@ private function getSchemeAndHierarchy(string $filename): array
private static function box(callable $func, mixed ...$args): mixed
{
self::$lastError = null;
set_error_handler(__CLASS__.'::handleError');
set_error_handler(self::handleError(...));
try {
return $func(...$args);
} finally {
Expand Down
0