summaryrefslogtreecommitdiff
path: root/ext/spl/spl_directory.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-07-18 15:25:59 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-07-22 17:17:28 +0200
commitd59aac58b3e7da7ad01a194fe9840d89725ea229 (patch)
tree5cfc4509f8aa6f9cb0c49df3530fb82c5b0456df /ext/spl/spl_directory.c
parentc817b8020c8a835946681ca94b9257e78e64dad3 (diff)
downloadphp-git-d59aac58b3e7da7ad01a194fe9840d89725ea229.tar.gz
Report errors from stream read and write operations
The php_stream_read() and php_stream_write() functions now return an ssize_t value, with negative results indicating failure. Functions like fread() and fwrite() will return false in that case. As a special case, EWOULDBLOCK and EAGAIN on non-blocking streams should not be regarded as error conditions, and be reported as successful zero-length reads/writes instead. The handling of EINTR remains unclear and is internally inconsistent (e.g. some code-paths will automatically retry on EINTR, while some won't). I'm landing this now to make sure the stream wrapper ops API changes make it into 7.4 -- however, if the user-facing changes turn out to be problematic we have the option of clamping negative returns to zero in php_stream_read() and php_stream_write() to restore the old behavior in a relatively non-intrusive manner.
Diffstat (limited to 'ext/spl/spl_directory.c')
-rw-r--r--ext/spl/spl_directory.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 1fdaacb588..9f70a2c867 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -2896,7 +2896,7 @@ SPL_METHOD(SplFileObject, fscanf)
}
/* }}} */
-/* {{{ proto mixed SplFileObject::fwrite(string str [, int length])
+/* {{{ proto int|false SplFileObject::fwrite(string str [, int length])
Binary-safe file write */
SPL_METHOD(SplFileObject, fwrite)
{
@@ -2904,6 +2904,7 @@ SPL_METHOD(SplFileObject, fwrite)
char *str;
size_t str_len;
zend_long length = 0;
+ ssize_t written;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &length) == FAILURE) {
return;
@@ -2926,13 +2927,18 @@ SPL_METHOD(SplFileObject, fwrite)
RETURN_LONG(0);
}
- RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len));
+ written = php_stream_write(intern->u.file.stream, str, str_len);
+ if (written < 0) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(written);
} /* }}} */
SPL_METHOD(SplFileObject, fread)
{
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
zend_long length = 0;
+ zend_string *str;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &length) == FAILURE) {
return;
@@ -2948,11 +2954,11 @@ SPL_METHOD(SplFileObject, fread)
RETURN_FALSE;
}
- ZVAL_NEW_STR(return_value, zend_string_alloc(length, 0));
- Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length);
-
- /* needed because recv/read/gzread doesn't put a null at the end*/
- Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
+ str = php_stream_read_to_str(intern->u.file.stream, length);
+ if (!str) {
+ RETURN_FALSE;
+ }
+ RETURN_STR(str);
}
/* {{{ proto bool SplFileObject::fstat()