Skip to content

Commit 9f4c0ea

Browse files
committed
solaris fix attempt
1 parent af43ee2 commit 9f4c0ea

1 file changed

Lines changed: 17 additions & 5 deletions

File tree

main/io/php_io_copy_solaris.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "php_io_internal.h"
1818
#include <sys/types.h>
19+
#include <sys/stat.h>
1920
#include <sys/sendfile.h>
2021
#include <unistd.h>
2122
#include <errno.h>
@@ -31,22 +32,33 @@ static zend_result php_io_solaris_sendfile(int src_fd, int dest_fd, size_t maxle
3132
return php_io_generic_copy_fallback(src_fd, dest_fd, maxlen, copied);
3233
}
3334

35+
/* Unlike Linux, Solaris sendfile() returns -1/EINVAL (rather than 0) when
36+
* called with an offset at or past EOF, so a trailing call issued after the
37+
* source has been fully consumed would spuriously fail an otherwise complete
38+
* copy. Bound the loop to the bytes actually available in the source file so
39+
* we stop exactly at EOF and never call sendfile() past it. */
40+
struct stat st;
41+
if (fstat(src_fd, &st) != 0 || !S_ISREG(st.st_mode)) {
42+
return php_io_generic_copy_fallback(src_fd, dest_fd, maxlen, copied);
43+
}
44+
45+
size_t available = (st.st_size > start_offset) ? (size_t) (st.st_size - start_offset) : 0;
46+
size_t target = (maxlen == PHP_IO_COPY_ALL || maxlen > available) ? available : maxlen;
47+
3448
off_t offset = start_offset;
3549
size_t total_copied = 0;
36-
size_t remaining = (maxlen == PHP_IO_COPY_ALL) ? SIZE_MAX : maxlen;
3750
zend_result result = SUCCESS;
3851

39-
while (remaining > 0) {
52+
while (total_copied < target) {
53+
size_t remaining = target - total_copied;
4054
size_t to_send = (remaining < SSIZE_MAX) ? remaining : SSIZE_MAX;
4155
/* offset is updated in place by sendfile() */
4256
ssize_t sent = sendfile(dest_fd, src_fd, &offset, to_send);
4357

4458
if (sent > 0) {
4559
total_copied += (size_t) sent;
46-
if (maxlen != PHP_IO_COPY_ALL) {
47-
remaining -= (size_t) sent;
48-
}
4960
} else if (sent == 0) {
61+
/* Source shrank under us; stop with what we have. */
5062
break;
5163
} else {
5264
if (errno == EINTR) {

0 commit comments

Comments
 (0)