1010
1111namespace AdrianSuter \Autoload \Override ;
1212
13+ use RuntimeException ;
14+
1315use function chgrp ;
1416use function chmod ;
1517use function chown ;
4749class FileStreamWrapper
4850{
4951 /**
50- * @var resource
52+ * @var resource|null
5153 */
5254 public $ context ;
5355
5456 /**
55- * @var resource|null
57+ * @var resource|null|false
5658 */
5759 private $ resource ;
5860
@@ -65,7 +67,9 @@ public function dir_closedir(): bool
6567 {
6668 stream_wrapper_restore ('file ' );
6769
68- closedir ($ this ->resource );
70+ if (is_resource ($ this ->resource )) {
71+ closedir ($ this ->resource );
72+ }
6973
7074 stream_wrapper_unregister ('file ' );
7175 stream_wrapper_register ('file ' , self ::class);
@@ -108,7 +112,10 @@ public function dir_readdir()
108112 {
109113 stream_wrapper_restore ('file ' );
110114
111- $ r = readdir ($ this ->resource );
115+ $ r = false ;
116+ if (is_resource ($ this ->resource )) {
117+ $ r = readdir ($ this ->resource );
118+ }
112119
113120 stream_wrapper_unregister ('file ' );
114121 stream_wrapper_register ('file ' , self ::class);
@@ -126,7 +133,9 @@ public function dir_rewinddir(): bool
126133 {
127134 stream_wrapper_restore ('file ' );
128135
129- rewinddir ($ this ->resource );
136+ if (is_resource ($ this ->resource )) {
137+ rewinddir ($ this ->resource );
138+ }
130139
131140 stream_wrapper_unregister ('file ' );
132141 stream_wrapper_register ('file ' , self ::class);
@@ -234,7 +243,9 @@ public function stream_close(): void
234243 {
235244 stream_wrapper_restore ('file ' );
236245
237- fclose ($ this ->resource );
246+ if (is_resource ($ this ->resource )) {
247+ fclose ($ this ->resource );
248+ }
238249
239250 stream_wrapper_unregister ('file ' );
240251 stream_wrapper_register ('file ' , self ::class);
@@ -250,7 +261,10 @@ public function stream_eof(): bool
250261 {
251262 stream_wrapper_restore ('file ' );
252263
253- $ r = feof ($ this ->resource );
264+ $ r = false ;
265+ if (is_resource ($ this ->resource )) {
266+ $ r = feof ($ this ->resource );
267+ }
254268
255269 stream_wrapper_unregister ('file ' );
256270 stream_wrapper_register ('file ' , self ::class);
@@ -268,7 +282,10 @@ public function stream_flush(): bool
268282 {
269283 stream_wrapper_restore ('file ' );
270284
271- $ r = fflush ($ this ->resource );
285+ $ r = false ;
286+ if (is_resource ($ this ->resource )) {
287+ $ r = fflush ($ this ->resource );
288+ }
272289
273290 stream_wrapper_unregister ('file ' );
274291 stream_wrapper_register ('file ' , self ::class);
@@ -307,7 +324,7 @@ public function stream_metadata(string $path, int $option, $value): bool
307324 $ r = false ;
308325 switch ($ option ) {
309326 case STREAM_META_TOUCH :
310- if (!isset ($ value [0 ]) || $ value [0 ] === null ) {
327+ if (!isset ($ value [0 ]) || is_null ( $ value [0 ]) ) {
311328 $ r = touch ($ path );
312329 } else {
313330 $ r = touch ($ path , $ value [0 ], $ value [1 ]);
@@ -361,11 +378,16 @@ public function stream_open(string $path, string $mode, int $options, ?string &$
361378 // Replace the global function calls into local function calls.
362379 if (!empty ($ functionCallMap )) {
363380 $ source = file_get_contents ($ path , $ usePath );
381+ if (!is_string ($ source )) {
382+ throw new RuntimeException (sprintf ("File `%s` could not be loaded. " , $ path ));
383+ }
364384 $ source = Override::convert ($ source , $ functionCallMap );
365385
366386 $ this ->resource = fopen ('php://temp ' , 'w+ ' );
367- fwrite ($ this ->resource , $ source );
368- fseek ($ this ->resource , 0 );
387+ if (is_resource ($ this ->resource )) {
388+ fwrite ($ this ->resource , $ source );
389+ fseek ($ this ->resource , 0 );
390+ }
369391 } elseif (is_resource ($ this ->context )) {
370392 $ this ->resource = fopen ($ path , $ mode , $ usePath , $ this ->context );
371393 } else {
@@ -390,7 +412,10 @@ public function stream_read(int $count): string
390412 {
391413 stream_wrapper_restore ('file ' );
392414
393- $ r = fgets ($ this ->resource , $ count );
415+ $ r = false ;
416+ if (is_resource ($ this ->resource )) {
417+ $ r = fgets ($ this ->resource , $ count );
418+ }
394419
395420 stream_wrapper_unregister ('file ' );
396421 stream_wrapper_register ('file ' , self ::class);
@@ -415,7 +440,10 @@ public function stream_seek(int $offset, int $whence = SEEK_SET): bool
415440 {
416441 stream_wrapper_restore ('file ' );
417442
418- $ r = fseek ($ this ->resource , $ offset , $ whence );
443+ $ r = -1 ;
444+ if (is_resource ($ this ->resource )) {
445+ $ r = fseek ($ this ->resource , $ offset , $ whence );
446+ }
419447
420448 stream_wrapper_unregister ('file ' );
421449 stream_wrapper_register ('file ' , self ::class);
@@ -440,21 +468,29 @@ public function stream_set_option(int $option, int $arg1, ?int $arg2)
440468 $ r = false ;
441469 switch ($ option ) {
442470 case STREAM_OPTION_BLOCKING :
443- $ r = stream_set_blocking ($ this ->resource , $ arg1 ? true : false );
471+ if (is_resource ($ this ->resource )) {
472+ $ r = stream_set_blocking ($ this ->resource , $ arg1 ? true : false );
473+ }
444474 break ;
445475
446476 case STREAM_OPTION_READ_TIMEOUT :
447- $ r = stream_set_timeout ($ this ->resource , $ arg1 , $ arg2 );
477+ if (is_resource ($ this ->resource )) {
478+ $ r = stream_set_timeout ($ this ->resource , $ arg1 , $ arg2 );
479+ }
448480 break ;
449481
450482 case STREAM_OPTION_WRITE_BUFFER :
451483 switch ($ arg1 ) {
452484 case STREAM_BUFFER_NONE :
453- $ r = stream_set_write_buffer ($ this ->resource , 0 );
485+ if (is_resource ($ this ->resource )) {
486+ $ r = stream_set_write_buffer ($ this ->resource , 0 );
487+ }
454488 break ;
455489
456490 case STREAM_BUFFER_FULL :
457- $ r = stream_set_write_buffer ($ this ->resource , $ arg2 );
491+ if (is_resource ($ this ->resource ) && is_int ($ arg2 )) {
492+ $ r = stream_set_write_buffer ($ this ->resource , $ arg2 );
493+ }
458494 break ;
459495 }
460496 break ;
@@ -469,14 +505,20 @@ public function stream_set_option(int $option, int $arg1, ?int $arg2)
469505 /**
470506 * Retrieve information about a file resource.
471507 *
472- * @return array
508+ * @return array<int|string, int>
473509 * @noinspection PhpUnused
474510 */
475511 public function stream_stat (): array
476512 {
477513 stream_wrapper_restore ('file ' );
478514
479- $ r = fstat ($ this ->resource );
515+ $ r = [];
516+ if (is_resource ($ this ->resource )) {
517+ $ r = fstat ($ this ->resource );
518+ if (!is_array ($ r )) {
519+ $ r = [];
520+ }
521+ }
480522
481523 stream_wrapper_unregister ('file ' );
482524 stream_wrapper_register ('file ' , self ::class);
@@ -494,7 +536,10 @@ public function stream_tell(): int
494536 {
495537 stream_wrapper_restore ('file ' );
496538
497- $ r = fseek ($ this ->resource , 0 , SEEK_CUR );
539+ $ r = -1 ;
540+ if (is_resource ($ this ->resource )) {
541+ $ r = fseek ($ this ->resource , 0 , SEEK_CUR );
542+ }
498543
499544 stream_wrapper_unregister ('file ' );
500545 stream_wrapper_register ('file ' , self ::class);
@@ -514,7 +559,10 @@ public function stream_truncate(int $new_size): bool
514559 {
515560 stream_wrapper_restore ('file ' );
516561
517- $ r = ftruncate ($ this ->resource , $ new_size );
562+ $ r = false ;
563+ if (is_resource ($ this ->resource )) {
564+ $ r = ftruncate ($ this ->resource , $ new_size );
565+ }
518566
519567 stream_wrapper_unregister ('file ' );
520568 stream_wrapper_register ('file ' , self ::class);
@@ -534,7 +582,10 @@ public function stream_write(string $data)
534582 {
535583 stream_wrapper_restore ('file ' );
536584
537- $ r = fwrite ($ this ->resource , $ data );
585+ $ r = false ;
586+ if (is_resource ($ this ->resource )) {
587+ $ r = fwrite ($ this ->resource , $ data );
588+ }
538589
539590 stream_wrapper_unregister ('file ' );
540591 stream_wrapper_register ('file ' , self ::class);
@@ -567,7 +618,7 @@ public function unlink(string $path): bool
567618 * @param string $path
568619 * @param int $flags
569620 *
570- * @return array|false
621+ * @return array<int|string, int> |false
571622 * @noinspection PhpUnused
572623 */
573624 public function url_stat (string $ path , int $ flags )
0 commit comments