Skip to content

Commit

Permalink
linux,darwin: make uv_fs_copyfile behaves like cp -r (libuv#4396)
Browse files Browse the repository at this point in the history
This commit changes the timestamps in the file, the ownership and the
group.

Fixes: libuv#3125

Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com>
  • Loading branch information
juanarbol committed May 8, 2024
1 parent 520eb62 commit bf61390
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/unix/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
uv_file dstfd;
struct stat src_statsbuf;
struct stat dst_statsbuf;
struct timespec times[2];
int dst_flags;
int result;
int err;
Expand Down Expand Up @@ -1310,6 +1311,29 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
}
}

/**
* Change the timestamps of the destination file to match the source file.
*/
#if defined(__APPLE__)
times[0] = src_statsbuf.st_atimespec;
times[1] = src_statsbuf.st_mtimespec;
#else
times[0] = src_statsbuf.st_atim;
times[1] = src_statsbuf.st_mtim;
#endif

if (futimens(dstfd, times) == -1) {
err = UV__ERR(errno);
goto out;
}

/*
* Change the ownership and permissions of the destination file to match the
* source file.
* `cp -p` does not care about errors here, so we don't either.
*/
fchown(dstfd, src_statsbuf.st_uid, src_statsbuf.st_gid);

if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
err = UV__ERR(errno);
#ifdef __linux__
Expand Down
6 changes: 6 additions & 0 deletions test/test-fs-copyfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ static void handle_result(uv_fs_t* req) {
uv_fs_t stat_req;
uint64_t size;
uint64_t mode;
uint64_t uid;
uint64_t gid;
int r;

ASSERT_EQ(req->fs_type, UV_FS_COPYFILE);
Expand All @@ -56,11 +58,15 @@ static void handle_result(uv_fs_t* req) {
ASSERT_OK(r);
size = stat_req.statbuf.st_size;
mode = stat_req.statbuf.st_mode;
uid = stat_req.statbuf.st_uid;
gid = stat_req.statbuf.st_gid;
uv_fs_req_cleanup(&stat_req);
r = uv_fs_stat(NULL, &stat_req, dst, NULL);
ASSERT_OK(r);
ASSERT_EQ(stat_req.statbuf.st_size, size);
ASSERT_EQ(stat_req.statbuf.st_mode, mode);
ASSERT_EQ(stat_req.statbuf.st_uid, uid);
ASSERT_EQ(stat_req.statbuf.st_gid, gid);
uv_fs_req_cleanup(&stat_req);
uv_fs_req_cleanup(req);
result_check_count++;
Expand Down

0 comments on commit bf61390

Please sign in to comment.