From 2c42623b6e3bf4e53d3aae3034d75351d63b6712 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Thu, 28 Dec 2023 10:59:33 +0100 Subject: [PATCH 1/2] cp: backup dest symlink linking to source --- src/uu/cp/src/cp.rs | 1 + tests/by-util/test_cp.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index 30cb3f59f..a5fb66d29 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -1521,6 +1521,7 @@ fn is_forbidden_copy_to_same_file( options.dereference(source_in_command_line) || !source.is_symlink(); paths_refer_to_same_file(source, dest, dereference_to_compare) && !(options.force() && options.backup != BackupMode::NoBackup) + && !(dest.is_symlink() && options.backup != BackupMode::NoBackup) } /// Back up, remove, or leave intact the destination file, depending on the options. diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index a1638584b..63cfa2155 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -701,6 +701,25 @@ fn test_cp_arg_backup_with_dest_a_symlink() { assert_eq!(original, at.resolve_link(backup)); } +#[test] +fn test_cp_arg_backup_with_dest_a_symlink_to_source() { + let (at, mut ucmd) = at_and_ucmd!(); + let source = "source"; + let source_content = "content"; + let symlink = "symlink"; + let backup = "symlink~"; + + at.write(source, source_content); + at.symlink_file(source, symlink); + + ucmd.arg("-b").arg(source).arg(symlink).succeeds(); + + assert!(!at.symlink_exists(symlink)); + assert_eq!(source_content, at.read(symlink)); + assert!(at.symlink_exists(backup)); + assert_eq!(source, at.resolve_link(backup)); +} + #[test] fn test_cp_arg_backup_with_other_args() { let (at, mut ucmd) = at_and_ucmd!(); From 902a128ea8a3cce5b520afef3c7c357728b93a97 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Sun, 31 Dec 2023 14:17:16 +0100 Subject: [PATCH 2/2] cp: rename function is_forbidden_copy_to_same_file -> is_forbidden_to_copy_to_same_file --- src/uu/cp/src/cp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index a5fb66d29..91507f319 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -1509,7 +1509,7 @@ fn backup_dest(dest: &Path, backup_path: &Path) -> CopyResult { /// /// Copying to the same file is only allowed if both `--backup` and /// `--force` are specified and the file is a regular file. -fn is_forbidden_copy_to_same_file( +fn is_forbidden_to_copy_to_same_file( source: &Path, dest: &Path, options: &Options, @@ -1533,7 +1533,7 @@ fn handle_existing_dest( ) -> CopyResult<()> { // Disallow copying a file to itself, unless `--force` and // `--backup` are both specified. - if is_forbidden_copy_to_same_file(source, dest, options, source_in_command_line) { + if is_forbidden_to_copy_to_same_file(source, dest, options, source_in_command_line) { return Err(format!("{} and {} are the same file", source.quote(), dest.quote()).into()); }