unix: truncate destination in uv_fs_copyfile()

This commit adds the O_TRUNC flag to the destination file in
the sendfile() fallback. This allows smaller source files to
be properly copied into larger existing destination files.

Refs: https://github.com/libuv/libuv/pull/1551
PR-URL: https://github.com/libuv/libuv/pull/1552
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Nick Logan 2017-09-18 18:47:45 -04:00 committed by cjihrig
parent a41f8b52e1
commit b0653625e2
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
2 changed files with 11 additions and 4 deletions

View File

@ -810,7 +810,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
goto out;
}
dst_flags = O_WRONLY | O_CREAT;
dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
if (req->flags & UV_FS_COPYFILE_EXCL)
dst_flags |= O_EXCL;

View File

@ -68,7 +68,8 @@ static void touch_file(const char* name, unsigned int size) {
int r;
unsigned int i;
r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT | O_TRUNC,
S_IWUSR | S_IRUSR, NULL);
uv_fs_req_cleanup(&req);
ASSERT(r >= 0);
file = r;
@ -136,6 +137,12 @@ TEST_IMPL(fs_copyfile) {
ASSERT(r == UV_EEXIST);
uv_fs_req_cleanup(&req);
/* Truncates when an existing destination is larger than the source file. */
touch_file(src, 1);
r = uv_fs_copyfile(NULL, &req, src, dst, 0, NULL);
ASSERT(r == 0);
handle_result(&req);
/* Copies a larger file. */
unlink(dst);
touch_file(src, 4096 * 2);
@ -148,9 +155,9 @@ TEST_IMPL(fs_copyfile) {
unlink(dst);
r = uv_fs_copyfile(loop, &req, fixture, dst, 0, handle_result);
ASSERT(r == 0);
ASSERT(result_check_count == 4);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(result_check_count == 5);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(result_check_count == 6);
unlink(dst); /* Cleanup */
return 0;