unix: handle src, dest same in uv_fs_copyfile()
This commit handles the case where the source and destination are the same. This behavior was originally addressed in #2298, but the test added in that PR doesn't validate the file size after the operation. This commit also updates the test to check for that case. Refs: https://github.com/libuv/libuv/pull/2298 Refs: https://github.com/nodejs/node/issues/34624 PR-URL: https://github.com/libuv/libuv/pull/2947 Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Jameson Nash <vtjnash@gmail.com>
This commit is contained in:
parent
b2cec846ef
commit
278cfa0183
@ -1146,7 +1146,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
|
dst_flags = O_WRONLY | O_CREAT;
|
||||||
|
|
||||||
if (req->flags & UV_FS_COPYFILE_EXCL)
|
if (req->flags & UV_FS_COPYFILE_EXCL)
|
||||||
dst_flags |= O_EXCL;
|
dst_flags |= O_EXCL;
|
||||||
@ -1165,6 +1165,9 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the file is not being opened exclusively, verify that the source and
|
||||||
|
destination are not the same file. If they are the same, bail out early. */
|
||||||
|
if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) {
|
||||||
/* Get the destination file's mode. */
|
/* Get the destination file's mode. */
|
||||||
if (fstat(dstfd, &dst_statsbuf)) {
|
if (fstat(dstfd, &dst_statsbuf)) {
|
||||||
err = UV__ERR(errno);
|
err = UV__ERR(errno);
|
||||||
@ -1177,6 +1180,13 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Truncate the file in case the destination already existed. */
|
||||||
|
if (ftruncate(dstfd, 0) != 0) {
|
||||||
|
err = UV__ERR(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
|
if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
|
||||||
err = UV__ERR(errno);
|
err = UV__ERR(errno);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|||||||
@ -125,6 +125,11 @@ TEST_IMPL(fs_copyfile) {
|
|||||||
r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL);
|
r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
uv_fs_req_cleanup(&req);
|
uv_fs_req_cleanup(&req);
|
||||||
|
/* Verify that the src file did not get truncated. */
|
||||||
|
r = uv_fs_stat(NULL, &req, src, NULL);
|
||||||
|
ASSERT_EQ(r, 0);
|
||||||
|
ASSERT_EQ(req.statbuf.st_size, 12);
|
||||||
|
uv_fs_req_cleanup(&req);
|
||||||
unlink(src);
|
unlink(src);
|
||||||
|
|
||||||
/* Copies file synchronously. Creates new file. */
|
/* Copies file synchronously. Creates new file. */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user