diff options
author | Ryo Nakamura <upa@haeena.net> | 2024-03-14 15:14:31 +0900 |
---|---|---|
committer | Ryo Nakamura <upa@haeena.net> | 2024-03-16 00:12:14 +0900 |
commit | 07a6cbf039049d3be04c329ce6adad6d2b42744e (patch) | |
tree | f4ce3a73241011fb26857891cfcbcc3eeac7d522 | |
parent | 433f155cd3492388de11e1324be5292dcfabb24d (diff) |
chmod after truncate and setutimes on the remote side.
When the source file permission is r--r--r--, truncate and setutimes
AFTER chmod fail due to permission deined. So, do chmod after truncate
and setutimes.
-rw-r--r-- | src/fileops.c | 10 | ||||
-rw-r--r-- | test/test_e2e.py | 15 |
2 files changed, 21 insertions, 4 deletions
diff --git a/src/fileops.c b/src/fileops.c index 5db7906..2c13436 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -323,12 +323,14 @@ int mscp_setstat(const char *path, struct stat *st, bool preserve_ts, sftp_sessi ret = sftp_setstat(sftp, path, &attr); sftp_err_to_errno(sftp); } else { - if ((ret = chmod(path, st->st_mode)) < 0) - return ret; if ((ret = truncate(path, st->st_size)) < 0) return ret; - if (preserve_ts) - ret = setutimes(path, st->st_atim, st->st_mtim); + if (preserve_ts) { + if ((ret = setutimes(path, st->st_atim, st->st_mtim)) < 0) + return ret; + } + if ((ret = chmod(path, st->st_mode)) < 0) + return ret; } return ret; diff --git a/test/test_e2e.py b/test/test_e2e.py index e4dbe49..808558d 100644 --- a/test/test_e2e.py +++ b/test/test_e2e.py @@ -322,6 +322,21 @@ def test_dont_truncate_dst(mscp, src_prefix, dst_prefix): f.cleanup() @pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix) +def test_copy_readonly_file(mscp, src_prefix, dst_prefix): + """When a source file permission is r--r--r--, if chmod(r--r--r--) + runs first on the remote side, following truncate() and setutime() + fail due to permission deneid. So, run chmod() after truncate() + and setutime() + + """ + src = File("src", size = 1024 * 1024 * 128, perm = 0o444).make() + dst = File("dst") + run2ok([mscp, "-H", "-vvv", src_prefix + src.path, dst_prefix + dst.path]) + assert check_same_md5sum(src, dst) + src.cleanup() + dst.cleanup() + +@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix) def test_dont_make_conns_more_than_chunks(mscp, src_prefix, dst_prefix): # copy 100 files with -n 20 -I 1 options. if mscp creates 20 SSH # connections although all files have been copied, it is error. |