From c829181e9f90142866ab2018b79dd0a73ceab5db Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Thu, 1 May 2025 22:31:26 -0700 Subject: [PATCH 1/2] Catch exceptions; return `false` --- src/StreamWrapper.php | 23 ++++++++++++++++++----- tests/StreamWrapperTest.php | 7 +++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/StreamWrapper.php b/src/StreamWrapper.php index 21159ea..1429287 100644 --- a/src/StreamWrapper.php +++ b/src/StreamWrapper.php @@ -261,11 +261,20 @@ public function stream_open( return true; } - public function stream_read(int $count): string + /** + * @param int $count + * + * @return false|string + */ + public function stream_read(int $count) { $this->log('info', __METHOD__, func_get_args()); - $this->openRead(); - return stream_get_contents($this->read, $count); + try { + $this->openRead(); + return stream_get_contents($this->read, $count); + } catch (Throwable $e) { + return false; + } } public function stream_seek(int $offset, int $whence = SEEK_SET): bool @@ -297,8 +306,12 @@ public function stream_set_option(int $option, int $arg1, ?int $arg2 = null): bo public function stream_stat() { $this->log('info', __METHOD__); - $this->openRead(); - return fstat($this->read); + try { + $this->openRead(); + return fstat($this->read); + } catch (Throwable $e) { + return false; + } } public function stream_tell(): int diff --git a/tests/StreamWrapperTest.php b/tests/StreamWrapperTest.php index 8daf8d1..2a56fe7 100644 --- a/tests/StreamWrapperTest.php +++ b/tests/StreamWrapperTest.php @@ -277,3 +277,10 @@ function dumpLogs() expect($actual)->toBe($expected); }); + +it('it returns false for file_get_contents missing file', function () { + + $actual = file_get_contents("fly://doesnotexist.txt"); + + expect($actual)->toBe(false); +}); From 30839871e443d67b4099e6ea19c57ff8bb0d4983 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sat, 10 May 2025 14:14:52 -0700 Subject: [PATCH 2/2] Update `stream_open()` to return `false` when unable to read By @elazar https://github.com/elazar/flystream/pull/17#issuecomment-2862612993 --- src/StreamWrapper.php | 17 +++++++++++++++++ tests/StreamWrapperTest.php | 9 ++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/StreamWrapper.php b/src/StreamWrapper.php index 1429287..9d54992 100644 --- a/src/StreamWrapper.php +++ b/src/StreamWrapper.php @@ -258,6 +258,17 @@ public function stream_open( $this->log('info', __METHOD__, func_get_args()); $this->path = $path; $this->mode = $mode; + + // Attempt to open for reading if mode is read or read/write + if (strpbrk($mode, 'r+') !== false) { + try { + $this->openRead(); + } catch (\Throwable $e) { + $this->log('error', __METHOD__, ['exception' => $e]); + return false; + } + } + return true; } @@ -273,6 +284,9 @@ public function stream_read(int $count) $this->openRead(); return stream_get_contents($this->read, $count); } catch (Throwable $e) { + $this->log('error', __METHOD__, func_get_args() + [ + 'exception' => $e, + ]); return false; } } @@ -310,6 +324,9 @@ public function stream_stat() $this->openRead(); return fstat($this->read); } catch (Throwable $e) { + $this->log('error', __METHOD__, func_get_args() + [ + 'exception' => $e, + ]); return false; } } diff --git a/tests/StreamWrapperTest.php b/tests/StreamWrapperTest.php index 2a56fe7..203565f 100644 --- a/tests/StreamWrapperTest.php +++ b/tests/StreamWrapperTest.php @@ -119,6 +119,8 @@ function dumpLogs() }); it('can acquire multiple shared locks', function () { + touch('fly://foo'); + $stream1 = fopen('fly://foo', 'r'); $result = flock($stream1, LOCK_SH); expect($result)->toBeTrue(); @@ -148,6 +150,8 @@ function dumpLogs() }); it('cannot acquire an exclusive lock with existing locks', function () { + touch('fly://foo'); + $stream1 = fopen('fly://foo', 'r'); $result = flock($stream1, LOCK_SH); expect($result)->toBeTrue(); @@ -278,9 +282,8 @@ function dumpLogs() expect($actual)->toBe($expected); }); -it('it returns false for file_get_contents missing file', function () { - - $actual = file_get_contents("fly://doesnotexist.txt"); +it('fails attempting to read a missing file', function () { + $actual = @file_get_contents("fly://doesnotexist.txt"); expect($actual)->toBe(false); });