summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2019-12-02 16:53:35 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2019-12-02 16:53:35 +0100
commitc1a6f2b9ccd2f022b8b0a056030a287748e98eaa (patch)
tree590c447d76bda538d4fd36d24c5584310dc4b274
parent8a5601a3649734841bffff09ded6c0f3ab2e06dc (diff)
parent996f217aa5487ead468fd8edc3ef278fb0686c32 (diff)
downloadphp-git-c1a6f2b9ccd2f022b8b0a056030a287748e98eaa.tar.gz
Merge branch 'PHP-7.4'
* PHP-7.4: Fix #78883: fgets(STDIN) fails on Windows
-rw-r--r--main/streams/plain_wrapper.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
index 224753306e..dff85e966e 100644
--- a/main/streams/plain_wrapper.c
+++ b/main/streams/plain_wrapper.c
@@ -123,11 +123,12 @@ typedef struct {
FILE *file;
int fd; /* underlying file descriptor */
unsigned is_process_pipe:1; /* use pclose instead of fclose */
- unsigned is_pipe:1; /* don't try and seek */
+ unsigned is_pipe:1; /* stream is an actual pipe, currently Windows only*/
unsigned cached_fstat:1; /* sb is valid */
unsigned is_pipe_blocking:1; /* allow blocking read() on pipes, currently Windows only */
unsigned no_forced_fstat:1; /* Use fstat cache even if forced */
- unsigned _reserved:28;
+ unsigned is_seekable:1; /* don't try and seek, if not set */
+ unsigned _reserved:26;
int lock_flag; /* stores the lock state */
zend_string *temp_name; /* if non-null, this is the path to a temporary file that
@@ -171,6 +172,7 @@ static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const
self = pemalloc_rel_orig(sizeof(*self), persistent_id);
memset(self, 0, sizeof(*self));
self->file = NULL;
+ self->is_seekable = 1;
self->is_pipe = 0;
self->lock_flag = LOCK_UN;
self->is_process_pipe = 0;
@@ -190,6 +192,7 @@ static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode
self = emalloc_rel_orig(sizeof(*self));
memset(self, 0, sizeof(*self));
self->file = file;
+ self->is_seekable = 1;
self->is_pipe = 0;
self->lock_flag = LOCK_UN;
self->is_process_pipe = 0;
@@ -240,10 +243,11 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC)
return php_stream_fopen_temporary_file(NULL, "php", NULL);
}
-static void detect_is_pipe(php_stdio_stream_data *self) {
+static void detect_is_seekable(php_stdio_stream_data *self) {
#if defined(S_ISFIFO) && defined(S_ISCHR)
if (self->fd >= 0 && do_fstat(self, 0) == 0) {
- self->is_pipe = S_ISFIFO(self->sb.st_mode) || S_ISCHR(self->sb.st_mode);
+ self->is_seekable = !(S_ISFIFO(self->sb.st_mode) || S_ISCHR(self->sb.st_mode));
+ self->is_pipe = S_ISFIFO(self->sb.st_mode);
}
#elif defined(PHP_WIN32)
zend_uintptr_t handle = _get_osfhandle(self->fd);
@@ -251,7 +255,8 @@ static void detect_is_pipe(php_stdio_stream_data *self) {
if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
DWORD file_type = GetFileType((HANDLE)handle);
- self->is_pipe = file_type == FILE_TYPE_PIPE || file_type == FILE_TYPE_CHAR;
+ self->is_seekable = !(file_type == FILE_TYPE_PIPE || file_type == FILE_TYPE_CHAR);
+ self->is_pipe = file_type == FILE_TYPE_PIPE;
}
#endif
}
@@ -263,8 +268,8 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
if (stream) {
php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
- detect_is_pipe(self);
- if (self->is_pipe) {
+ detect_is_seekable(self);
+ if (!self->is_seekable) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
stream->position = -1;
} else {
@@ -273,7 +278,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
/* FIXME: Is this code still needed? */
if (stream->position == (zend_off_t)-1 && errno == ESPIPE) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
- self->is_pipe = 1;
+ self->is_seekable = 0;
}
#endif
}
@@ -289,8 +294,8 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
if (stream) {
php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
- detect_is_pipe(self);
- if (self->is_pipe) {
+ detect_is_seekable(self);
+ if (!self->is_seekable) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
stream->position = -1;
} else {
@@ -309,6 +314,7 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE
self = emalloc_rel_orig(sizeof(*self));
memset(self, 0, sizeof(*self));
self->file = file;
+ self->is_seekable = 0;
self->is_pipe = 1;
self->lock_flag = LOCK_UN;
self->is_process_pipe = 1;
@@ -353,7 +359,7 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun
} else {
#if HAVE_FLUSHIO
- if (!data->is_pipe && data->last_op == 'r') {
+ if (data->is_seekable && data->last_op == 'r') {
zend_fseek(data->file, 0, SEEK_CUR);
}
data->last_op = 'w';
@@ -428,7 +434,7 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count)
} else {
#if HAVE_FLUSHIO
- if (!data->is_pipe && data->last_op == 'w')
+ if (data->is_seekable && data->last_op == 'w')
zend_fseek(data->file, 0, SEEK_CUR);
data->last_op = 'r';
#endif
@@ -529,8 +535,8 @@ static int php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, ze
assert(data != NULL);
- if (data->is_pipe) {
- php_error_docref(NULL, E_WARNING, "cannot seek on a pipe");
+ if (!data->is_seekable) {
+ php_error_docref(NULL, E_WARNING, "cannot seek on this stream");
return -1;
}