Skip to content

[Filesystem] Fix usages of error_get_last() #27236

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

Merged
merged 1 commit into from
May 14, 2018
Merged
Show file tree
Hide file tree
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
5 changes: 2 additions & 3 deletions src/Symfony/Component/Console/Command/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,11 @@ public function run(InputInterface $input, OutputInterface $output)

if (null !== $this->processTitle) {
if (function_exists('cli_set_process_title')) {
if (false === @cli_set_process_title($this->processTitle)) {
if (!@cli_set_process_title($this->processTitle)) {
if ('Darwin' === PHP_OS) {
$output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
} else {
$error = error_get_last();
trigger_error($error['message'], E_USER_WARNING);
cli_set_process_title($this->processTitle);
}
}
} elseif (function_exists('setproctitle')) {
Expand Down
64 changes: 42 additions & 22 deletions src/Symfony/Component/Filesystem/Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
*/
class Filesystem
{
private static $lastError;

/**
* Copies a file.
*
Expand Down Expand Up @@ -95,12 +97,11 @@ public function mkdir($dirs, $mode = 0777)
continue;
}

if (true !== @mkdir($dir, $mode, true)) {
$error = error_get_last();
if (!self::box('mkdir', $dir, $mode, true)) {
if (!is_dir($dir)) {
// The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
if ($error) {
throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
if (self::$lastError) {
throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
}
throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
}
Expand Down Expand Up @@ -169,20 +170,17 @@ public function remove($files)
foreach ($files as $file) {
if (is_link($file)) {
// See https://bugs.php.net/52176
if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
$error = error_get_last();
throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
if (!(self::box('unlink', $file) || '\\' !== DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
}
} elseif (is_dir($file)) {
$this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));

if (!@rmdir($file) && file_exists($file)) {
$error = error_get_last();
throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
if (!self::box('rmdir', $file) && file_exists($file)) {
throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
}
} elseif (!@unlink($file) && file_exists($file)) {
$error = error_get_last();
throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
} elseif (!self::box('unlink', $file) && file_exists($file)) {
throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
}
}
}
Expand Down Expand Up @@ -336,19 +334,16 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false)

$this->mkdir(dirname($targetDir));

$ok = false;
if (is_link($targetDir)) {
if (readlink($targetDir) != $originDir) {
$this->remove($targetDir);
} else {
$ok = true;
if (readlink($targetDir) === $originDir) {
return;
}
$this->remove($targetDir);
}

if (!$ok && true !== @symlink($originDir, $targetDir)) {
$report = error_get_last();
if (is_array($report)) {
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
if (!self::box('symlink', $originDir, $targetDir)) {
if (null !== self::$lastError) {
if ('\\' === DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', 0, null, $targetDir);
}
}
Expand Down Expand Up @@ -580,4 +575,29 @@ private function toIterator($files)

return $files;
}

private static function box($func)
{
self::$lastError = null;
\set_error_handler(__CLASS__.'::handleError');
try {
$result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
\restore_error_handler();

return $result;
} catch (\Throwable $e) {
} catch (\Exception $e) {
}
\restore_error_handler();

throw $e;
}

/**
* @internal
*/
public static function handleError($type, $msg)
{
self::$lastError = $msg;
}
}
7 changes: 3 additions & 4 deletions src/Symfony/Component/Finder/SplFileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,11 @@ public function getRelativePathname()
*/
public function getContents()
{
$level = error_reporting(0);
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
$content = file_get_contents($this->getPathname());
error_reporting($level);
restore_error_handler();
if (false === $content) {
$error = error_get_last();
throw new \RuntimeException($error['message']);
throw new \RuntimeException($error);
}

return $content;
Expand Down
8 changes: 5 additions & 3 deletions src/Symfony/Component/HttpFoundation/File/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@ public function move($directory, $name = null)
{
$target = $this->getTargetFile($directory, $name);

if (!@rename($this->getPathname(), $target)) {
$error = error_get_last();
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
$renamed = rename($this->getPathname(), $target);
restore_error_handler();
if (!$renamed) {
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}

@chmod($target, 0666 & ~umask());
Expand Down
8 changes: 5 additions & 3 deletions src/Symfony/Component/HttpFoundation/File/UploadedFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,11 @@ public function move($directory, $name = null)

$target = $this->getTargetFile($directory, $name);

if (!@move_uploaded_file($this->getPathname(), $target)) {
$error = error_get_last();
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
$moved = move_uploaded_file($this->getPathname(), $target);
restore_error_handler();
if (!$moved) {
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}

@chmod($target, 0666 & ~umask());
Expand Down
14 changes: 12 additions & 2 deletions src/Symfony/Component/Process/Pipes/AbstractPipes.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ abstract class AbstractPipes implements PipesInterface
private $inputBuffer = '';
private $input;
private $blocked = true;
private $lastError;

/**
* @param resource|null $input
Expand Down Expand Up @@ -56,10 +57,11 @@ public function close()
*/
protected function hasSystemCallBeenInterrupted()
{
$lastError = error_get_last();
$lastError = $this->lastError;
$this->lastError = null;

// stream_select returns false when the `select` system call is interrupted by an incoming signal
return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
}

/**
Expand Down Expand Up @@ -137,4 +139,12 @@ protected function write()
return array($this->pipes[0]);
}
}

/**
* @internal
*/
public function handleError($type, $msg)
{
$this->lastError = $msg;
}
}
5 changes: 4 additions & 1 deletion src/Symfony/Component/Process/Pipes/UnixPipes.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ public function readAndWrite($blocking, $close = false)
unset($r[0]);

// let's have a look if something changed in streams
if (($r || $w) && false === @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
set_error_handler(array($this, 'handleError'));
if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
restore_error_handler();
// if a system call has been interrupted, forget about it, let's try again
// otherwise, an error occurred, let's reset pipes
if (!$this->hasSystemCallBeenInterrupted()) {
Expand All @@ -108,6 +110,7 @@ public function readAndWrite($blocking, $close = false)

return $read;
}
restore_error_handler();

foreach ($r as $pipe) {
// prior PHP 5.4 the array passed to stream_select is modified and
Expand Down