summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Le Blanc <lbarnaud@php.net>2009-04-19 13:46:47 +0000
committerArnaud Le Blanc <lbarnaud@php.net>2009-04-19 13:46:47 +0000
commit14c717f449934f1fd611451c20a95344635fc83b (patch)
treeb26ac7e9e868e09527519aa20b58b66a7cbcd0e8
parent0c6cf02985c4d4b847a0228344ad1358b3676cbe (diff)
downloadphp-git-14c717f449934f1fd611451c20a95344635fc83b.tar.gz
Fixed bug #47997 (stream_copy_to_stream returns 1 on empty streams)
-rw-r--r--NEWS1
-rw-r--r--ext/standard/file.c7
-rw-r--r--ext/standard/streamsfuncs.c8
-rwxr-xr-xmain/php_streams.h5
-rw-r--r--main/streams/cast.c6
-rwxr-xr-xmain/streams/streams.c40
6 files changed, 53 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index c1c41e6014..996485ddf2 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ PHP NEWS
disable this behaviour using "http"=>array("auto_decode"=>0) in stream
context. (Dmitry)
+- Fixed bug #47997 (stream_copy_to_stream returns 1 on empty streams). (Arnaud)
- Fixed bug #47880 (crashes in call_user_func_array()). (Dmitry)
- Fixed bug #47856 (stristr() converts needle to lower-case). (Ilia)
- Fixed bug #47851 (is_callable throws fatal error). (Dmitry)
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 192d7f1cc2..a3b96b3b1b 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -627,7 +627,10 @@ PHP_FUNCTION(file_put_contents)
switch (Z_TYPE_P(data)) {
case IS_RESOURCE:
- numbytes = php_stream_copy_to_stream(srcstream, stream, PHP_STREAM_COPY_ALL);
+ numbytes = (int) php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL);
+ if ((size_t)numbytes == PHP_STREAM_FAILURE) {
+ numbytes = -1;
+ }
break;
case IS_NULL:
case IS_LONG:
@@ -1783,7 +1786,7 @@ safe_to_copy:
deststream = php_stream_open_wrapper(dest, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
if (srcstream && deststream) {
- ret = php_stream_copy_to_stream(srcstream, deststream, PHP_STREAM_COPY_ALL) == 0 ? FAILURE : SUCCESS;
+ ret = php_stream_copy_to_stream_ex(srcstream, deststream, PHP_STREAM_COPY_ALL) == PHP_STREAM_FAILURE ? FAILURE : SUCCESS;
}
if (srcstream) {
php_stream_close(srcstream);
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index cdb420c0f7..426849e81e 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -443,6 +443,7 @@ PHP_FUNCTION(stream_copy_to_stream)
php_stream *src, *dest;
zval *zsrc, *zdest;
long maxlen = PHP_STREAM_COPY_ALL, pos = 0;
+ size_t ret;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|ll", &zsrc, &zdest, &maxlen, &pos) == FAILURE) {
RETURN_FALSE;
@@ -456,7 +457,12 @@ PHP_FUNCTION(stream_copy_to_stream)
RETURN_FALSE;
}
- RETURN_LONG(php_stream_copy_to_stream(src, dest, maxlen));
+ ret = php_stream_copy_to_stream_ex(src, dest, maxlen);
+
+ if (ret == PHP_STREAM_FAILURE) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(ret);
}
/* }}} */
diff --git a/main/php_streams.h b/main/php_streams.h
index 5c699f2e97..fab62c19af 100755
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -420,9 +420,14 @@ END_EXTERN_C()
* Uses mmap if the src is a plain file and at offset 0 */
#define PHP_STREAM_COPY_ALL ((size_t)-1)
+#define PHP_STREAM_FAILURE ((size_t)-1)
+
BEGIN_EXTERN_C()
+ZEND_ATTRIBUTE_DEPRECATED
PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC);
#define php_stream_copy_to_stream(src, dest, maxlen) _php_stream_copy_to_stream((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC)
+PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC);
+#define php_stream_copy_to_stream_ex(src, dest, maxlen) _php_stream_copy_to_stream_ex((src), (dest), (maxlen) STREAMS_CC TSRMLS_CC)
/* read all data from stream and put into a buffer. Caller must free buffer when done.
diff --git a/main/streams/cast.c b/main/streams/cast.c
index dea72da53d..06805c709c 100644
--- a/main/streams/cast.c
+++ b/main/streams/cast.c
@@ -214,9 +214,9 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
newstream = php_stream_fopen_tmpfile();
if (newstream) {
- size_t copied = php_stream_copy_to_stream(stream, newstream, PHP_STREAM_COPY_ALL);
+ size_t copied = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL);
- if (copied == 0) {
+ if (copied == PHP_STREAM_FAILURE) {
php_stream_close(newstream);
} else {
int retcode = php_stream_cast(newstream, castas | flags, ret, show_err);
@@ -332,7 +332,7 @@ PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstr
(*newstream)->open_lineno = origstream->open_lineno;
#endif
- if (php_stream_copy_to_stream(origstream, *newstream, PHP_STREAM_COPY_ALL) == 0) {
+ if (php_stream_copy_to_stream_ex(origstream, *newstream, PHP_STREAM_COPY_ALL) == PHP_STREAM_FAILURE) {
php_stream_close(*newstream);
*newstream = NULL;
return PHP_STREAM_CRITICAL;
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 6d9d2ecd0e..c5aebe7812 100755
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -1297,7 +1297,8 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen
return len;
}
-PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC)
+/* Returns the number of bytes moved, or PHP_STREAM_FAILURE on failure. */
+PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC)
{
char buf[CHUNK_SIZE];
size_t readchunk;
@@ -1314,8 +1315,6 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
}
if (php_stream_stat(src, &ssbuf) == 0) {
- /* in the event that the source file is 0 bytes, return 1 to indicate success
- * because opening the file to write had already created a copy */
if (ssbuf.sb.st_size == 0
#ifdef S_ISFIFO
&& !S_ISFIFO(ssbuf.sb.st_mode)
@@ -1324,7 +1323,7 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
&& !S_ISCHR(ssbuf.sb.st_mode)
#endif
) {
- return 1;
+ return 0;
}
}
@@ -1338,8 +1337,14 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
mapped = php_stream_write(dest, p, mapped);
php_stream_mmap_unmap(src);
+
+ /* we've got at least 1 byte to read.
+ * less than 1 is an error */
- return mapped;
+ if (mapped > 0) {
+ return mapped;
+ }
+ return PHP_STREAM_FAILURE;
}
}
@@ -1364,14 +1369,14 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
while(towrite) {
didwrite = php_stream_write(dest, writeptr, towrite);
if (didwrite == 0) {
- return 0; /* error */
+ return PHP_STREAM_FAILURE;
}
towrite -= didwrite;
writeptr += didwrite;
}
} else {
- return haveread;
+ break;
}
if (maxlen - haveread == 0) {
@@ -1379,7 +1384,26 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
}
}
- return haveread;
+ /* we've got at least 1 byte to read.
+ * less than 1 is an error */
+
+ if (haveread > 0) {
+ return haveread;
+ }
+ return PHP_STREAM_FAILURE;
+}
+
+/* Returns the number of bytes moved.
+ * Returns 1 when source len is 0.
+ * Deprecated in favor of php_stream_copy_to_stream_ex() */
+ZEND_ATTRIBUTE_DEPRECATED
+PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC)
+{
+ size_t ret = _php_stream_copy_to_stream_ex(src, dest, maxlen STREAMS_REL_CC TSRMLS_CC);
+ if (ret == 0 && maxlen != 0) {
+ return 1;
+ }
+ return ret;
}
/* }}} */