unix: handle partial sends in uv_fs_copyfile()

uv_fs_sendfile() is used as the fallback for uv_fs_copyfile().
However, sendfile() does not necessarily send all of the bytes
in one call. This commit adds a loop to ensure all data is
sent.

Fixes: https://github.com/libuv/libuv/issues/1517
PR-URL: https://github.com/libuv/libuv/pull/1494
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Andreas Hauptmann 2017-08-20 14:42:22 +02:00 committed by cjihrig
parent 9a4468f47a
commit dff7ebe4f0
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5

View File

@ -791,6 +791,8 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
int dst_flags;
int result;
int err;
size_t bytes_to_send;
int64_t in_offset;
dstfd = -1;
@ -826,14 +828,22 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
goto out;
}
err = uv_fs_sendfile(NULL,
&fs_req,
dstfd,
srcfd,
0,
statsbuf.st_size,
NULL);
uv_fs_req_cleanup(&fs_req);
bytes_to_send = statsbuf.st_size;
in_offset = 0;
while (bytes_to_send != 0) {
err = uv_fs_sendfile(NULL,
&fs_req,
dstfd,
srcfd,
in_offset,
bytes_to_send,
NULL);
uv_fs_req_cleanup(&fs_req);
if (err < 0)
break;
bytes_to_send -= fs_req.result;
in_offset += fs_req.result;
}
out:
if (err < 0)