diff --git a/src/Support/StreamWrapper.php b/src/Support/StreamWrapper.php index b0002be..7dbe660 100644 --- a/src/Support/StreamWrapper.php +++ b/src/Support/StreamWrapper.php @@ -270,15 +270,11 @@ public function unlink(string $path): bool public function url_stat(string $path, int $flags): array|bool { return $this->withOriginalWrapper(function () use ($path, $flags): false|array { - if (is_readable($path) === false) { - return false; - } - if (($flags & STREAM_URL_STAT_LINK) !== 0) { - return lstat($path); + return is_link($path) || file_exists($path) ? lstat($path) : false; } - return stat($path); + return file_exists($path) ? stat($path) : false; }); } diff --git a/tests/Unit/Support/StreamWrapper.php b/tests/Unit/Support/StreamWrapper.php new file mode 100644 index 0000000..fc65e2e --- /dev/null +++ b/tests/Unit/Support/StreamWrapper.php @@ -0,0 +1,55 @@ +directory = sys_get_temp_dir().'/pest-mutate-stream-wrapper-'.bin2hex(random_bytes(4)); + mkdir($this->directory); + + $this->original = $this->directory.'/original.php'; + $this->override = $this->directory.'/override.php'; + + file_put_contents($this->original, "override, "directory.'/*') ?: [] as $file) { + chmod($file, 0o644); + unlink($file); + } + + rmdir($this->directory); +}); + +it('reports a file that cannot be read as existing', function (): void { + $locked = $this->directory.'/locked.log'; + + file_put_contents($locked, 'content'); + chmod($locked, 0o000); + + StreamWrapper::start($this->original, $this->override); + + clearstatcache(true, $locked); + + expect(file_exists($locked))->toBeTrue() + ->and(is_file($locked))->toBeTrue() + ->and(filesize($locked))->toBe(7); +})->skip( + fn (): bool => function_exists('posix_geteuid') && posix_geteuid() === 0, + 'The root user ignores file permissions.', +); + +it('reports a missing file as missing', function (): void { + StreamWrapper::start($this->original, $this->override); + + $missing = $this->directory.'/missing.log'; + + expect(file_exists($missing))->toBeFalse() + ->and(is_file($missing))->toBeFalse() + ->and(file_exists($missing.'/child'))->toBeFalse(); +});