From 252d01ac33b2eb4fdd0640a07840d0ef3318f886 Mon Sep 17 00:00:00 2001 From: PGIII Date: Mon, 2 Oct 2023 18:48:22 -0400 Subject: [PATCH] cp: fail when trying to copy to read only file on mac (#5261) * cp: fail when trying to copy to read only file * fix spelling error in macos.rs * simplify permissions check * add comment * fix typo --- src/uu/cp/src/platform/macos.rs | 11 +++++++++-- tests/by-util/test_cp.rs | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/uu/cp/src/platform/macos.rs b/src/uu/cp/src/platform/macos.rs index 8c62c78d95d..77bdbbbdb83 100644 --- a/src/uu/cp/src/platform/macos.rs +++ b/src/uu/cp/src/platform/macos.rs @@ -63,8 +63,15 @@ pub(crate) fn copy_on_write( { // clonefile(2) fails if the destination exists. Remove it and try again. Do not // bother to check if removal worked because we're going to try to clone again. - let _ = fs::remove_file(dest); - error = pfn(src.as_ptr(), dst.as_ptr(), 0); + // first lets make sure the dest file is not read only + if fs::metadata(dest).map_or(false, |md| !md.permissions().readonly()) { + // remove and copy again + // TODO: rewrite this to better match linux behavior + // linux first opens the source file and destination file then uses the file + // descriptors to do the clone. + let _ = fs::remove_file(dest); + error = pfn(src.as_ptr(), dst.as_ptr(), 0); + } } } } diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 1ce74572d5d..fe56d11601e 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -3440,3 +3440,19 @@ fn test_cp_only_source_no_target() { panic!("Failure: stderr was \n{stderr_str}"); } } + +#[test] +fn test_cp_dest_no_permissions() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + at.touch("valid.txt"); + at.touch("invalid_perms.txt"); + at.set_readonly("invalid_perms.txt"); + + ts.ucmd() + .args(&["valid.txt", "invalid_perms.txt"]) + .fails() + .stderr_contains("invalid_perms.txt") + .stderr_contains("denied"); +}