Skip to content

Commit 252d01a

Browse files
authored
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
1 parent c5a0aa9 commit 252d01a

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/uu/cp/src/platform/macos.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,15 @@ pub(crate) fn copy_on_write(
6363
{
6464
// clonefile(2) fails if the destination exists. Remove it and try again. Do not
6565
// bother to check if removal worked because we're going to try to clone again.
66-
let _ = fs::remove_file(dest);
67-
error = pfn(src.as_ptr(), dst.as_ptr(), 0);
66+
// first lets make sure the dest file is not read only
67+
if fs::metadata(dest).map_or(false, |md| !md.permissions().readonly()) {
68+
// remove and copy again
69+
// TODO: rewrite this to better match linux behavior
70+
// linux first opens the source file and destination file then uses the file
71+
// descriptors to do the clone.
72+
let _ = fs::remove_file(dest);
73+
error = pfn(src.as_ptr(), dst.as_ptr(), 0);
74+
}
6875
}
6976
}
7077
}

tests/by-util/test_cp.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,3 +3440,19 @@ fn test_cp_only_source_no_target() {
34403440
panic!("Failure: stderr was \n{stderr_str}");
34413441
}
34423442
}
3443+
3444+
#[test]
3445+
fn test_cp_dest_no_permissions() {
3446+
let ts = TestScenario::new(util_name!());
3447+
let at = &ts.fixtures;
3448+
3449+
at.touch("valid.txt");
3450+
at.touch("invalid_perms.txt");
3451+
at.set_readonly("invalid_perms.txt");
3452+
3453+
ts.ucmd()
3454+
.args(&["valid.txt", "invalid_perms.txt"])
3455+
.fails()
3456+
.stderr_contains("invalid_perms.txt")
3457+
.stderr_contains("denied");
3458+
}

0 commit comments

Comments
 (0)