From 9fb927aa856eec92a58b6cfbf53438e4a48f71e2 Mon Sep 17 00:00:00 2001 From: Michael Debertol Date: Sat, 19 Jun 2021 17:49:04 +0200 Subject: [PATCH] cp: always delete the destination for symlinks --- src/uu/cp/src/cp.rs | 5 +++++ tests/by-util/test_cp.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index cf723e4ee..840035e4a 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -1269,6 +1269,11 @@ fn copy_link(source: &Path, dest: &Path) -> CopyResult<()> { ), } } else { + // we always need to remove the file to be able to create a symlink, + // even if it is writeable. + if dest.exists() { + fs::remove_file(dest)?; + } dest.into() }; symlink_file(&link, &dest, &*context_for(&link, &dest)) diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 4ce587e02..19f93e499 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -1325,3 +1325,16 @@ fn test_copy_dir_with_symlinks() { ucmd.args(&["-r", "dir", "copy"]).succeeds(); assert_eq!(at.resolve_link("copy/file-link"), "file"); } + +#[test] +#[cfg(not(windows))] +fn test_copy_symlink_force() { + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("file"); + at.symlink_file("file", "file-link"); + at.touch("copy"); + + ucmd.args(&["file-link", "copy", "-f", "--no-dereference"]) + .succeeds(); + assert_eq!(at.resolve_link("copy"), "file"); +}