@@ -125,11 +125,12 @@ typedef struct {
125125 FILE * file ;
126126 int fd ; /* underlying file descriptor */
127127 unsigned is_process_pipe :1 ; /* use pclose instead of fclose */
128- unsigned is_pipe :1 ; /* don't try and seek */
128+ unsigned is_pipe :1 ; /* stream is an actual pipe, currently Windows only */
129129 unsigned cached_fstat :1 ; /* sb is valid */
130130 unsigned is_pipe_blocking :1 ; /* allow blocking read() on pipes, currently Windows only */
131131 unsigned no_forced_fstat :1 ; /* Use fstat cache even if forced */
132- unsigned _reserved :28 ;
132+ unsigned is_seekable :1 ; /* don't try and seek, if not set */
133+ unsigned _reserved :26 ;
133134
134135 int lock_flag ; /* stores the lock state */
135136 zend_string * temp_name ; /* if non-null, this is the path to a temporary file that
@@ -173,6 +174,7 @@ static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const
173174 self = pemalloc_rel_orig (sizeof (* self ), persistent_id );
174175 memset (self , 0 , sizeof (* self ));
175176 self -> file = NULL ;
177+ self -> is_seekable = 1 ;
176178 self -> is_pipe = 0 ;
177179 self -> lock_flag = LOCK_UN ;
178180 self -> is_process_pipe = 0 ;
@@ -192,6 +194,7 @@ static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode
192194 self = emalloc_rel_orig (sizeof (* self ));
193195 memset (self , 0 , sizeof (* self ));
194196 self -> file = file ;
197+ self -> is_seekable = 1 ;
195198 self -> is_pipe = 0 ;
196199 self -> lock_flag = LOCK_UN ;
197200 self -> is_process_pipe = 0 ;
@@ -242,18 +245,20 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC)
242245 return php_stream_fopen_temporary_file (NULL , "php" , NULL );
243246}
244247
245- static void detect_is_pipe (php_stdio_stream_data * self ) {
248+ static void detect_is_seekable (php_stdio_stream_data * self ) {
246249#if defined(S_ISFIFO ) && defined(S_ISCHR )
247250 if (self -> fd >= 0 && do_fstat (self , 0 ) == 0 ) {
248- self -> is_pipe = S_ISFIFO (self -> sb .st_mode ) || S_ISCHR (self -> sb .st_mode );
251+ self -> is_seekable = !(S_ISFIFO (self -> sb .st_mode ) || S_ISCHR (self -> sb .st_mode ));
252+ self -> is_pipe = S_ISFIFO (self -> sb .st_mode );
249253 }
250254#elif defined(PHP_WIN32 )
251255 zend_uintptr_t handle = _get_osfhandle (self -> fd );
252256
253257 if (handle != (zend_uintptr_t )INVALID_HANDLE_VALUE ) {
254258 DWORD file_type = GetFileType ((HANDLE )handle );
255259
256- self -> is_pipe = file_type == FILE_TYPE_PIPE || file_type == FILE_TYPE_CHAR ;
260+ self -> is_seekable = !(file_type == FILE_TYPE_PIPE || file_type == FILE_TYPE_CHAR );
261+ self -> is_pipe = file_type == FILE_TYPE_PIPE ;
257262 }
258263#endif
259264}
@@ -265,8 +270,8 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
265270 if (stream ) {
266271 php_stdio_stream_data * self = (php_stdio_stream_data * )stream -> abstract ;
267272
268- detect_is_pipe (self );
269- if (self -> is_pipe ) {
273+ detect_is_seekable (self );
274+ if (! self -> is_seekable ) {
270275 stream -> flags |= PHP_STREAM_FLAG_NO_SEEK ;
271276 stream -> position = -1 ;
272277 } else {
@@ -275,7 +280,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
275280 /* FIXME: Is this code still needed? */
276281 if (stream -> position == (zend_off_t )- 1 && errno == ESPIPE ) {
277282 stream -> flags |= PHP_STREAM_FLAG_NO_SEEK ;
278- self -> is_pipe = 1 ;
283+ self -> is_seekable = 0 ;
279284 }
280285#endif
281286 }
@@ -291,8 +296,8 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
291296 if (stream ) {
292297 php_stdio_stream_data * self = (php_stdio_stream_data * )stream -> abstract ;
293298
294- detect_is_pipe (self );
295- if (self -> is_pipe ) {
299+ detect_is_seekable (self );
300+ if (! self -> is_seekable ) {
296301 stream -> flags |= PHP_STREAM_FLAG_NO_SEEK ;
297302 stream -> position = -1 ;
298303 } else {
@@ -311,6 +316,7 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE
311316 self = emalloc_rel_orig (sizeof (* self ));
312317 memset (self , 0 , sizeof (* self ));
313318 self -> file = file ;
319+ self -> is_seekable = 0 ;
314320 self -> is_pipe = 1 ;
315321 self -> lock_flag = LOCK_UN ;
316322 self -> is_process_pipe = 1 ;
@@ -355,7 +361,7 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
355361 } else {
356362
357363#if HAVE_FLUSHIO
358- if (! data -> is_pipe && data -> last_op == 'r' ) {
364+ if (data -> is_seekable && data -> last_op == 'r' ) {
359365 zend_fseek (data -> file , 0 , SEEK_CUR );
360366 }
361367 data -> last_op = 'w' ;
@@ -430,7 +436,7 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
430436
431437 } else {
432438#if HAVE_FLUSHIO
433- if (! data -> is_pipe && data -> last_op == 'w' )
439+ if (data -> is_seekable && data -> last_op == 'w' )
434440 zend_fseek (data -> file , 0 , SEEK_CUR );
435441 data -> last_op = 'r' ;
436442#endif
@@ -531,8 +537,8 @@ static int php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, ze
531537
532538 assert (data != NULL );
533539
534- if (data -> is_pipe ) {
535- php_error_docref (NULL , E_WARNING , "cannot seek on a pipe " );
540+ if (! data -> is_seekable ) {
541+ php_error_docref (NULL , E_WARNING , "cannot seek on this stream " );
536542 return -1 ;
537543 }
538544
0 commit comments