summaryrefslogtreecommitdiff
path: root/main/streams/plain_wrapper.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-09-05 16:35:40 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-09-05 18:29:15 +0200
commit9ec61e43d453aadab9539f6814e8694295aa1ed1 (patch)
tree66e1bcfce505809c0263be1431ef55527ab1462e /main/streams/plain_wrapper.c
parent4ecdff2da829a60ddb01ecb260d688acca7339d4 (diff)
downloadphp-git-9ec61e43d453aadab9539f6814e8694295aa1ed1.tar.gz
Fix pipe detection and stream position handling
There are two related changes here: 1. Also check for S_ISCHR/FILE_TYPE_CHAR when checking for pipes, so that we detect ttys as well, which are also not seekable. 2. Always set position=-1 (i.e. ftell will return false) when a pipe is detected. Previously position=0 was sometimes used, depending on whether we're on Windows/Linux and whether the FD or FILE codepath was used.
Diffstat (limited to 'main/streams/plain_wrapper.c')
-rw-r--r--main/streams/plain_wrapper.c52
1 files changed, 21 insertions, 31 deletions
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
index bce58f7df2..61b19e48ad 100644
--- a/main/streams/plain_wrapper.c
+++ b/main/streams/plain_wrapper.c
@@ -242,6 +242,22 @@ 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) {
+#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);
+ }
+#elif defined(PHP_WIN32)
+ zend_uintptr_t handle = _get_osfhandle(self->fd);
+
+ 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;
+ }
+#endif
+}
+
PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC)
{
php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
@@ -249,28 +265,15 @@ 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;
-#ifdef S_ISFIFO
- /* detect if this is a pipe */
- if (self->fd >= 0) {
- self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
- }
-#elif defined(PHP_WIN32)
- {
- zend_uintptr_t handle = _get_osfhandle(self->fd);
-
- if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
- self->is_pipe = GetFileType((HANDLE)handle) == FILE_TYPE_PIPE;
- }
- }
-#endif
-
+ detect_is_pipe(self);
if (self->is_pipe) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
+ stream->position = -1;
} else {
stream->position = zend_lseek(self->fd, 0, SEEK_CUR);
#ifdef ESPIPE
+ /* FIXME: Is this code still needed? */
if (stream->position == (zend_off_t)-1 && errno == ESPIPE) {
- stream->position = 0;
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
self->is_pipe = 1;
}
@@ -288,23 +291,10 @@ 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;
-#ifdef S_ISFIFO
- /* detect if this is a pipe */
- if (self->fd >= 0) {
- self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
- }
-#elif defined(PHP_WIN32)
- {
- zend_uintptr_t handle = _get_osfhandle(self->fd);
-
- if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
- self->is_pipe = GetFileType((HANDLE)handle) == FILE_TYPE_PIPE;
- }
- }
-#endif
-
+ detect_is_pipe(self);
if (self->is_pipe) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
+ stream->position = -1;
} else {
stream->position = zend_ftell(file);
}