@@ -125,11 +125,12 @@ typedef struct {
125
125
FILE * file ;
126
126
int fd ; /* underlying file descriptor */
127
127
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 */
129
129
unsigned cached_fstat :1 ; /* sb is valid */
130
130
unsigned is_pipe_blocking :1 ; /* allow blocking read() on pipes, currently Windows only */
131
131
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 ;
133
134
134
135
int lock_flag ; /* stores the lock state */
135
136
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
173
174
self = pemalloc_rel_orig (sizeof (* self ), persistent_id );
174
175
memset (self , 0 , sizeof (* self ));
175
176
self -> file = NULL ;
177
+ self -> is_seekable = 1 ;
176
178
self -> is_pipe = 0 ;
177
179
self -> lock_flag = LOCK_UN ;
178
180
self -> is_process_pipe = 0 ;
@@ -192,6 +194,7 @@ static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode
192
194
self = emalloc_rel_orig (sizeof (* self ));
193
195
memset (self , 0 , sizeof (* self ));
194
196
self -> file = file ;
197
+ self -> is_seekable = 1 ;
195
198
self -> is_pipe = 0 ;
196
199
self -> lock_flag = LOCK_UN ;
197
200
self -> is_process_pipe = 0 ;
@@ -242,18 +245,20 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC)
242
245
return php_stream_fopen_temporary_file (NULL , "php" , NULL );
243
246
}
244
247
245
- static void detect_is_pipe (php_stdio_stream_data * self ) {
248
+ static void detect_is_seekable (php_stdio_stream_data * self ) {
246
249
#if defined(S_ISFIFO ) && defined(S_ISCHR )
247
250
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 );
249
253
}
250
254
#elif defined(PHP_WIN32 )
251
255
zend_uintptr_t handle = _get_osfhandle (self -> fd );
252
256
253
257
if (handle != (zend_uintptr_t )INVALID_HANDLE_VALUE ) {
254
258
DWORD file_type = GetFileType ((HANDLE )handle );
255
259
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 ;
257
262
}
258
263
#endif
259
264
}
@@ -265,8 +270,8 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
265
270
if (stream ) {
266
271
php_stdio_stream_data * self = (php_stdio_stream_data * )stream -> abstract ;
267
272
268
- detect_is_pipe (self );
269
- if (self -> is_pipe ) {
273
+ detect_is_seekable (self );
274
+ if (! self -> is_seekable ) {
270
275
stream -> flags |= PHP_STREAM_FLAG_NO_SEEK ;
271
276
stream -> position = -1 ;
272
277
} else {
@@ -275,7 +280,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
275
280
/* FIXME: Is this code still needed? */
276
281
if (stream -> position == (zend_off_t )- 1 && errno == ESPIPE ) {
277
282
stream -> flags |= PHP_STREAM_FLAG_NO_SEEK ;
278
- self -> is_pipe = 1 ;
283
+ self -> is_seekable = 0 ;
279
284
}
280
285
#endif
281
286
}
@@ -291,8 +296,8 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
291
296
if (stream ) {
292
297
php_stdio_stream_data * self = (php_stdio_stream_data * )stream -> abstract ;
293
298
294
- detect_is_pipe (self );
295
- if (self -> is_pipe ) {
299
+ detect_is_seekable (self );
300
+ if (! self -> is_seekable ) {
296
301
stream -> flags |= PHP_STREAM_FLAG_NO_SEEK ;
297
302
stream -> position = -1 ;
298
303
} else {
@@ -311,6 +316,7 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE
311
316
self = emalloc_rel_orig (sizeof (* self ));
312
317
memset (self , 0 , sizeof (* self ));
313
318
self -> file = file ;
319
+ self -> is_seekable = 0 ;
314
320
self -> is_pipe = 1 ;
315
321
self -> lock_flag = LOCK_UN ;
316
322
self -> is_process_pipe = 1 ;
@@ -355,7 +361,7 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
355
361
} else {
356
362
357
363
#if HAVE_FLUSHIO
358
- if (! data -> is_pipe && data -> last_op == 'r' ) {
364
+ if (data -> is_seekable && data -> last_op == 'r' ) {
359
365
zend_fseek (data -> file , 0 , SEEK_CUR );
360
366
}
361
367
data -> last_op = 'w' ;
@@ -430,7 +436,7 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
430
436
431
437
} else {
432
438
#if HAVE_FLUSHIO
433
- if (! data -> is_pipe && data -> last_op == 'w' )
439
+ if (data -> is_seekable && data -> last_op == 'w' )
434
440
zend_fseek (data -> file , 0 , SEEK_CUR );
435
441
data -> last_op = 'r' ;
436
442
#endif
@@ -531,8 +537,8 @@ static int php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, ze
531
537
532
538
assert (data != NULL );
533
539
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 " );
536
542
return -1 ;
537
543
}
538
544
0 commit comments