2121 */
2222class Filesystem
2323{
24+ private static $ lastError ;
25+
2426 /**
2527 * Copies a file.
2628 *
@@ -95,12 +97,11 @@ public function mkdir($dirs, $mode = 0777)
9597 continue ;
9698 }
9799
98- if (true !== @mkdir ($ dir , $ mode , true )) {
99- $ error = error_get_last ();
100+ if (!self ::box ('mkdir ' , $ dir , $ mode , true )) {
100101 if (!is_dir ($ dir )) {
101102 // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
102- if ($ error ) {
103- throw new IOException (sprintf ('Failed to create "%s": %s. ' , $ dir , $ error [ ' message ' ] ), 0 , null , $ dir );
103+ if (self :: $ lastError ) {
104+ throw new IOException (sprintf ('Failed to create "%s": %s. ' , $ dir , self :: $ lastError ), 0 , null , $ dir );
104105 }
105106 throw new IOException (sprintf ('Failed to create "%s" ' , $ dir ), 0 , null , $ dir );
106107 }
@@ -169,20 +170,17 @@ public function remove($files)
169170 foreach ($ files as $ file ) {
170171 if (is_link ($ file )) {
171172 // See https://bugs.php.net/52176
172- if (!@(unlink ($ file ) || '\\' !== DIRECTORY_SEPARATOR || rmdir ($ file )) && file_exists ($ file )) {
173- $ error = error_get_last ();
174- throw new IOException (sprintf ('Failed to remove symlink "%s": %s. ' , $ file , $ error ['message ' ]));
173+ if (!(self ::box ('unlink ' , $ file ) || '\\' !== DIRECTORY_SEPARATOR || self ::box ('rmdir ' , $ file )) && file_exists ($ file )) {
174+ throw new IOException (sprintf ('Failed to remove symlink "%s": %s. ' , $ file , self ::$ lastError ));
175175 }
176176 } elseif (is_dir ($ file )) {
177177 $ this ->remove (new \FilesystemIterator ($ file , \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS ));
178178
179- if (!@rmdir ($ file ) && file_exists ($ file )) {
180- $ error = error_get_last ();
181- throw new IOException (sprintf ('Failed to remove directory "%s": %s. ' , $ file , $ error ['message ' ]));
179+ if (!self ::box ('rmdir ' , $ file ) && file_exists ($ file )) {
180+ throw new IOException (sprintf ('Failed to remove directory "%s": %s. ' , $ file , self ::$ lastError ));
182181 }
183- } elseif (!@unlink ($ file ) && file_exists ($ file )) {
184- $ error = error_get_last ();
185- throw new IOException (sprintf ('Failed to remove file "%s": %s. ' , $ file , $ error ['message ' ]));
182+ } elseif (!self ::box ('unlink ' , $ file ) && file_exists ($ file )) {
183+ throw new IOException (sprintf ('Failed to remove file "%s": %s. ' , $ file , self ::$ lastError ));
186184 }
187185 }
188186 }
@@ -336,16 +334,14 @@ public function symlink($originDir, $targetDir, $copyOnWindows = false)
336334
337335 $ this ->mkdir (dirname ($ targetDir ));
338336
339- $ ok = false ;
340337 if (is_link ($ targetDir )) {
341- if (readlink ($ targetDir ) != $ originDir ) {
342- $ this ->remove ($ targetDir );
343- } else {
344- $ ok = true ;
338+ if (readlink ($ targetDir ) === $ originDir ) {
339+ return ;
345340 }
341+ $ this ->remove ($ targetDir );
346342 }
347343
348- if (!$ ok && true !== @ symlink ( $ originDir , $ targetDir )) {
344+ if (!self :: box ( ' symlink ' , $ originDir , $ targetDir )) {
349345 $ this ->linkException ($ originDir , $ targetDir , 'symbolic ' );
350346 }
351347 }
@@ -377,7 +373,7 @@ public function hardlink($originFile, $targetFiles)
377373 $ this ->remove ($ targetFile );
378374 }
379375
380- if (true !== @ link ( $ originFile , $ targetFile )) {
376+ if (! self :: box ( ' link ' , $ originFile , $ targetFile )) {
381377 $ this ->linkException ($ originFile , $ targetFile , 'hard ' );
382378 }
383379 }
@@ -390,9 +386,8 @@ public function hardlink($originFile, $targetFiles)
390386 */
391387 private function linkException ($ origin , $ target , $ linkType )
392388 {
393- $ report = error_get_last ();
394- if (is_array ($ report )) {
395- if ('\\' === DIRECTORY_SEPARATOR && false !== strpos ($ report ['message ' ], 'error code(1314) ' )) {
389+ if (self ::$ lastError ) {
390+ if ('\\' === DIRECTORY_SEPARATOR && false !== strpos (self ::$ lastError , 'error code(1314) ' )) {
396391 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 );
397392 }
398393 }
@@ -747,4 +742,29 @@ private function getSchemeAndHierarchy($filename)
747742
748743 return 2 === count ($ components ) ? array ($ components [0 ], $ components [1 ]) : array (null , $ components [0 ]);
749744 }
745+
746+ private static function box ($ func )
747+ {
748+ self ::$ lastError = null ;
749+ \set_error_handler (__CLASS__ .'::handleError ' );
750+ try {
751+ $ result = \call_user_func_array ($ func , \array_slice (\func_get_args (), 1 ));
752+ \restore_error_handler ();
753+
754+ return $ result ;
755+ } catch (\Throwable $ e ) {
756+ } catch (\Exception $ e ) {
757+ }
758+ \restore_error_handler ();
759+
760+ throw $ e ;
761+ }
762+
763+ /**
764+ * @internal
765+ */
766+ public static function handleError ($ type , $ msg )
767+ {
768+ self ::$ lastError = $ msg ;
769+ }
750770}
0 commit comments