summaryrefslogtreecommitdiff
path: root/main/streams/plain_wrapper.c
diff options
context:
space:
mode:
authorStanley Sufficool <ssufficool@php.net>2014-10-20 21:33:32 -0700
committerStanley Sufficool <ssufficool@php.net>2014-10-20 21:33:32 -0700
commit8defcb855ab01d9c8ab4759cb793d80149b55a8c (patch)
treeed51eb30a2cbc92b102557498fb3e4113da1bb07 /main/streams/plain_wrapper.c
parent9c7dbb0487f5991fde03873ea8f5e66d6688415f (diff)
parentbaddb1c73a170ef1d2c31bd54cddbc6e1ab596b9 (diff)
downloadphp-git-8defcb855ab01d9c8ab4759cb793d80149b55a8c.tar.gz
Merge branch 'master' of https://git.php.net/push/php-src
* 'master' of https://git.php.net/push/php-src: (6215 commits) Extra comma Moved proxy object support in ASSIGN_ADD (and family) from VM to slow paths of corresponding operators Simplification zend_get_property_info_quick() cleanup and optimization initialize lineno before calling compile file file in phar Use ADDREF instead of DUP, it must be enough. Removed old irrelevant comment fixed compilation error Fix bug #68262: Broken reference across cloned objects export functions needed for phpdbg Fixed compilation Optimized property access handlers. Removed EG(std_property_info). Fixed bug #68199 (PDO::pgsqlGetNotify doesn't support NOTIFY payloads) Don't make difference between undefined and unaccessible properies when call __get() and family Don't make useless CSE array_pop/array_shift optimization check for zlib headers as well as lib for mysqlnd a realpath cache key can be int or float, catching this News entry for new curl constants News entry for new curl constants ...
Diffstat (limited to 'main/streams/plain_wrapper.c')
-rw-r--r--main/streams/plain_wrapper.c134
1 files changed, 82 insertions, 52 deletions
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
index 949b827679..28328c3cd5 100644
--- a/main/streams/plain_wrapper.c
+++ b/main/streams/plain_wrapper.c
@@ -1,8 +1,8 @@
/*
+----------------------------------------------------------------------+
- | PHP Version 5 |
+ | PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2013 The PHP Group |
+ | Copyright (c) 1997-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -53,6 +53,12 @@ extern int php_get_uid_by_name(const char *name, uid_t *uid TSRMLS_DC);
extern int php_get_gid_by_name(const char *name, gid_t *gid TSRMLS_DC);
#endif
+#if defined(PHP_WIN32)
+# define PLAIN_WRAP_BUF_SIZE(st) (((st) > UINT_MAX) ? UINT_MAX : (unsigned int)(st))
+#else
+# define PLAIN_WRAP_BUF_SIZE(st) (st)
+#endif
+
/* parse standard "fopen" modes into open() flags */
PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
{
@@ -78,11 +84,7 @@ PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
/* unknown mode */
return FAILURE;
}
-#if defined(O_NONBLOCK)
- if (strchr(mode, 'n')) {
- flags |= O_NONBLOCK;
- }
-#endif
+
if (strchr(mode, '+')) {
flags |= O_RDWR;
} else if (flags) {
@@ -91,6 +93,12 @@ PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
flags |= O_RDONLY;
}
+#if defined(O_NONBLOCK)
+ if (strchr(mode, 'n')) {
+ flags |= O_NONBLOCK;
+ }
+#endif
+
#if defined(_O_TEXT) && defined(O_BINARY)
if (strchr(mode, 't')) {
flags |= _O_TEXT;
@@ -130,7 +138,7 @@ typedef struct {
HANDLE file_mapping;
#endif
- struct stat sb;
+ zend_stat_t sb;
} php_stdio_stream_data;
#define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd
@@ -141,7 +149,7 @@ static int do_fstat(php_stdio_stream_data *d, int force)
int r;
PHP_STDIOP_GET_FD(fd, d);
- r = fstat(fd, &d->sb);
+ r = zend_fstat(fd, &d->sb);
d->cached_fstat = r == 0;
return r;
@@ -181,31 +189,20 @@ static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode
return php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
}
-PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC)
+PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path_ptr STREAMS_DC TSRMLS_DC)
{
- int fd = php_open_temporary_fd(dir, pfx, opened_path TSRMLS_CC);
+ char *opened_path = NULL;
+ int fd;
+ fd = php_open_temporary_fd(dir, pfx, &opened_path TSRMLS_CC);
if (fd != -1) {
- php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, "r+b", NULL);
- if (stream) {
- return stream;
- }
- close(fd);
-
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate stream");
-
- return NULL;
- }
- return NULL;
-}
+ php_stream *stream;
-PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC)
-{
- char *opened_path = NULL;
- int fd = php_open_temporary_fd(NULL, "php", &opened_path TSRMLS_CC);
+ if (opened_path_ptr) {
+ *opened_path_ptr = opened_path;
+ }
- if (fd != -1) {
- php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, "r+b", NULL);
+ stream = php_stream_fopen_from_fd_int_rel(fd, "r+b", NULL);
if (stream) {
php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
stream->wrapper = &php_plain_files_wrapper;
@@ -225,6 +222,11 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC)
return NULL;
}
+PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC)
+{
+ return php_stream_fopen_temporary_file(NULL, "php", NULL);
+}
+
PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC)
{
php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
@@ -250,9 +252,9 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const cha
if (self->is_pipe) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
} else {
- stream->position = lseek(self->fd, 0, SEEK_CUR);
+ stream->position = zend_lseek(self->fd, 0, SEEK_CUR);
#ifdef ESPIPE
- if (stream->position == (off_t)-1 && errno == ESPIPE) {
+ if (stream->position == (zend_off_t)-1 && errno == ESPIPE) {
stream->position = 0;
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
self->is_pipe = 1;
@@ -289,7 +291,7 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
if (self->is_pipe) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
} else {
- stream->position = ftell(file);
+ stream->position = zend_ftell(file);
}
}
@@ -346,13 +348,41 @@ static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count TSRMLS
assert(data != NULL);
if (data->fd >= 0) {
- ret = read(data->fd, buf, count);
+#ifdef PHP_WIN32
+ php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
+
+ if (self->is_pipe || self->is_process_pipe) {
+ HANDLE ph = (HANDLE)_get_osfhandle(data->fd);
+ int retry = 0;
+ DWORD avail_read = 0;
+
+ do {
+ /* Look ahead to get the available data amount to read. Do the same
+ as read() does, however not blocking forever. In case it failed,
+ no data will be read (better than block). */
+ if (!PeekNamedPipe(ph, NULL, 0, NULL, &avail_read, NULL)) {
+ break;
+ }
+ /* If there's nothing to read, wait in 100ms periods. */
+ if (0 == avail_read) {
+ usleep(100000);
+ }
+ } while (0 == avail_read && retry++ < 320);
+
+ /* Reduce the required data amount to what is available, otherwise read()
+ will block.*/
+ if (avail_read < count) {
+ count = avail_read;
+ }
+ }
+#endif
+ ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count));
if (ret == (size_t)-1 && errno == EINTR) {
/* Read was interrupted, retry once,
If read still fails, giveup with feof==0
so script can retry if desired */
- ret = read(data->fd, buf, count);
+ ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count));
}
stream->eof = (ret == 0 || (ret == (size_t)-1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF));
@@ -360,7 +390,7 @@ static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count TSRMLS
} else {
#if HAVE_FLUSHIO
if (!data->is_pipe && data->last_op == 'w')
- fseek(data->file, 0, SEEK_CUR);
+ zend_fseek(data->file, 0, SEEK_CUR);
data->last_op = 'r';
#endif
@@ -449,7 +479,7 @@ static int php_stdiop_flush(php_stream *stream TSRMLS_DC)
return 0;
}
-static int php_stdiop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC)
+static int php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset TSRMLS_DC)
{
php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
int ret;
@@ -462,25 +492,25 @@ static int php_stdiop_seek(php_stream *stream, off_t offset, int whence, off_t *
}
if (data->fd >= 0) {
- off_t result;
+ zend_off_t result;
- result = lseek(data->fd, offset, whence);
- if (result == (off_t)-1)
+ result = zend_lseek(data->fd, offset, whence);
+ if (result == (zend_off_t)-1)
return -1;
*newoffset = result;
return 0;
} else {
- ret = fseek(data->file, offset, whence);
- *newoffset = ftell(data->file);
+ ret = zend_fseek(data->file, offset, whence);
+ *newoffset = zend_ftell(data->file);
return ret;
}
}
static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
{
- int fd;
+ php_socket_t fd;
php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
assert(data != NULL);
@@ -504,31 +534,31 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
}
*(FILE**)ret = data->file;
- data->fd = -1;
+ data->fd = SOCK_ERR;
}
return SUCCESS;
case PHP_STREAM_AS_FD_FOR_SELECT:
PHP_STDIOP_GET_FD(fd, data);
- if (fd < 0) {
+ if (SOCK_ERR == fd) {
return FAILURE;
}
if (ret) {
- *(int*)ret = fd;
+ *(php_socket_t *)ret = fd;
}
return SUCCESS;
case PHP_STREAM_AS_FD:
PHP_STDIOP_GET_FD(fd, data);
- if (fd < 0) {
+ if (SOCK_ERR == fd) {
return FAILURE;
}
if (data->file) {
fflush(data->file);
}
if (ret) {
- *(int*)ret = fd;
+ *(php_socket_t *)ret = fd;
}
return SUCCESS;
default:
@@ -835,7 +865,7 @@ static int php_plain_files_dirstream_close(php_stream *stream, int close_handle
return closedir((DIR *)stream->abstract);
}
-static int php_plain_files_dirstream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
+static int php_plain_files_dirstream_rewind(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs TSRMLS_DC)
{
rewinddir((DIR *)stream->abstract);
return 0;
@@ -1100,7 +1130,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f
#ifndef PHP_WIN32
# ifdef EXDEV
if (errno == EXDEV) {
- struct stat sb;
+ zend_stat_t sb;
if (php_copy_file(url_from, url_to TSRMLS_CC) == SUCCESS) {
if (VCWD_STAT(url_from, &sb) == 0) {
# if !defined(TSRM_WIN32) && !defined(NETWARE)
@@ -1163,7 +1193,7 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i
} else {
/* we look for directory separator from the end of string, thus hopefuly reducing our work load */
char *e;
- struct stat sb;
+ zend_stat_t sb;
int dir_len = strlen(dir);
int offset = 0;
char buf[MAXPATHLEN];
@@ -1334,7 +1364,7 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url
break;
#endif
case PHP_STREAM_META_ACCESS:
- mode = (mode_t)*(long *)value;
+ mode = (mode_t)*(zend_long *)value;
ret = VCWD_CHMOD(url, mode);
break;
default:
@@ -1436,7 +1466,7 @@ not_relative_path:
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", cwd, filename, MAXPATHLEN);
}
- free(cwd);
+ efree(cwd);
if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(trypath TSRMLS_CC)) {
return NULL;