summaryrefslogtreecommitdiff
path: root/main/streams/streams.c
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-09-21 16:09:17 +0200
committerChristoph M. Becker <cmbecker69@gmx.de>2020-09-21 16:09:17 +0200
commit6fa2493789f8f05c7a53eca803227fcfb1bf2573 (patch)
tree92bcd4e140b9b20795d64df791ac717600a3d9d6 /main/streams/streams.c
parente95fa3eb0ce97d952598f599052a837ba90f2df2 (diff)
parent19c844594e40d79cea016b54f9ab3a367440b4c9 (diff)
downloadphp-git-6fa2493789f8f05c7a53eca803227fcfb1bf2573.tar.gz
Merge branch 'PHP-7.4' into master
* PHP-7.4: Fix mmap copying
Diffstat (limited to 'main/streams/streams.c')
-rw-r--r--main/streams/streams.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 686427bc96..b14c6fa396 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -1566,29 +1566,48 @@ PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size
if (php_stream_mmap_possible(src)) {
char *p;
- size_t mapped;
- p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
+ do {
+ size_t chunk_size = (maxlen == 0 || maxlen > PHP_STREAM_MMAP_MAX) ? PHP_STREAM_MMAP_MAX : maxlen;
+ size_t mapped;
- if (p) {
- ssize_t didwrite = php_stream_write(dest, p, mapped);
- if (didwrite < 0) {
- *len = 0;
- return FAILURE;
- }
+ p = php_stream_mmap_range(src, php_stream_tell(src), chunk_size, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
+
+ if (p) {
+ ssize_t didwrite;
+
+ if (php_stream_seek(src, mapped, SEEK_CUR) != 0) {
+ php_stream_mmap_unmap(src);
+ break;
+ }
+
+ didwrite = php_stream_write(dest, p, mapped);
+ if (didwrite < 0) {
+ *len = haveread;
+ return FAILURE;
+ }
- php_stream_mmap_unmap_ex(src, mapped);
+ php_stream_mmap_unmap(src);
- *len = didwrite;
+ *len = haveread += didwrite;
- /* we've got at least 1 byte to read
- * less than 1 is an error
- * AND read bytes match written */
- if (mapped > 0 && mapped == didwrite) {
- return SUCCESS;
+ /* we've got at least 1 byte to read
+ * less than 1 is an error
+ * AND read bytes match written */
+ if (mapped == 0 || mapped != didwrite) {
+ return FAILURE;
+ }
+ if (mapped < chunk_size) {
+ return SUCCESS;
+ }
+ if (maxlen != 0) {
+ maxlen -= mapped;
+ if (maxlen == 0) {
+ return SUCCESS;
+ }
+ }
}
- return FAILURE;
- }
+ } while (p);
}
while(1) {