Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/uu/cp/src/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,9 @@ fn copy_directory(
}

// if no-dereference is enabled and this is a symlink, copy it as a file
if !options.dereference && fs::symlink_metadata(root).unwrap().file_type().is_symlink() {
if !options.dereference && fs::symlink_metadata(root).unwrap().file_type().is_symlink()
// replace by is_symlink in rust>=1.58
{
return copy_file(root, target, options, symlinked_files);
}

Expand Down Expand Up @@ -1036,6 +1038,7 @@ fn copy_directory(
{
let p = or_continue!(path);
let is_symlink = fs::symlink_metadata(p.path())?.file_type().is_symlink();
// replace by is_symlink in rust >=1.58
let path = current_dir.join(&p.path());

let local_to_root_parent = match root_parent {
Expand Down Expand Up @@ -1288,7 +1291,7 @@ fn copy_file(

// Fail if dest is a dangling symlink or a symlink this program created previously
if fs::symlink_metadata(dest)
.map(|m| m.file_type().is_symlink())
.map(|m| m.file_type().is_symlink()) // replace by is_symlink in rust>=1.58
.unwrap_or(false)
{
if FileInformation::from_path(dest, false)
Expand All @@ -1301,7 +1304,7 @@ fn copy_file(
dest.display()
)));
}
if !dest.exists() {
if options.dereference && !dest.exists() {
return Err(Error::Error(format!(
"not writing through dangling symlink '{}'",
dest.display()
Expand Down Expand Up @@ -1535,7 +1538,7 @@ fn copy_link(
} else {
// we always need to remove the file to be able to create a symlink,
// even if it is writeable.
if dest.exists() {
if dest.is_file() {
fs::remove_file(dest)?;
}
dest.into()
Expand Down
12 changes: 12 additions & 0 deletions tests/by-util/test_cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,18 @@ fn test_copy_through_dangling_symlink() {
.stderr_only("cp: not writing through dangling symlink 'target'");
}

#[test]
fn test_copy_through_dangling_symlink_no_dereference() {
let (at, mut ucmd) = at_and_ucmd!();
at.symlink_file("no-such-file", "dangle");
ucmd.arg("-P")
.arg("dangle")
.arg("d2")
.succeeds()
.no_stderr()
.no_stdout();
}

#[test]
#[cfg(unix)]
fn test_cp_archive_on_nonexistent_file() {
Expand Down