mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
cp: make --b=simple protective of source
When `--backup` is supplied, `cp` will take a backup of *destination* before *source* is copied. When `--backup=simple` is supplied, it is possible for the backup path for *destination* to equal the path for *source*, destroying source before the copy is made. This change prevents this by returning an error instead. This fixes https://github.com/uutils/coreutils/issues/3629
This commit is contained in:
+10
-1
@@ -1256,7 +1256,16 @@ fn handle_existing_dest(source: &Path, dest: &Path, options: &Options) -> CopyRe
|
||||
|
||||
let backup_path = backup_control::get_backup_path(options.backup, dest, &options.backup_suffix);
|
||||
if let Some(backup_path) = backup_path {
|
||||
backup_dest(dest, &backup_path)?;
|
||||
if paths_refer_to_same_file(source, &backup_path)? {
|
||||
return Err(format!(
|
||||
"backing up {} might destroy source; {} not copied",
|
||||
dest.quote(),
|
||||
source.quote()
|
||||
)
|
||||
.into());
|
||||
} else {
|
||||
backup_dest(dest, &backup_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
match options.overwrite {
|
||||
|
||||
@@ -38,6 +38,8 @@ static TEST_COPY_FROM_FOLDER: &str = "hello_dir_with_file/";
|
||||
static TEST_COPY_FROM_FOLDER_FILE: &str = "hello_dir_with_file/hello_world.txt";
|
||||
static TEST_COPY_TO_FOLDER_NEW: &str = "hello_dir_new";
|
||||
static TEST_COPY_TO_FOLDER_NEW_FILE: &str = "hello_dir_new/hello_world.txt";
|
||||
static TEST_PROTECT_BACKUP_SRC: &str = "protected.txt.bak";
|
||||
static TEST_PROTECT_BACKUP_DEST: &str = "protected.txt";
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
|
||||
static TEST_MOUNT_COPY_FROM_FOLDER: &str = "dir_with_mount";
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
|
||||
@@ -558,6 +560,25 @@ fn test_cp_backup_simple() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cp_backup_simple_protect_source() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
ucmd.arg("--backup=simple")
|
||||
.arg("--suffix")
|
||||
.arg(".bak")
|
||||
.arg(TEST_PROTECT_BACKUP_SRC)
|
||||
.arg(TEST_PROTECT_BACKUP_DEST)
|
||||
.fails()
|
||||
.stderr_only(format!(
|
||||
"cp: backing up '{}' might destroy source; '{}' not copied",
|
||||
TEST_PROTECT_BACKUP_DEST,
|
||||
TEST_PROTECT_BACKUP_SRC,
|
||||
));
|
||||
|
||||
assert_eq!(at.read(TEST_PROTECT_BACKUP_SRC), "original text\n");
|
||||
assert_eq!(at.read(TEST_PROTECT_BACKUP_DEST), "new text\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cp_backup_never() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
new text
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
original text
|
||||
Reference in New Issue
Block a user