mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00: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:
parent
fa51f8b986
commit
c49d8e6113
4 changed files with 33 additions and 1 deletions
|
@ -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);
|
let backup_path = backup_control::get_backup_path(options.backup, dest, &options.backup_suffix);
|
||||||
if let Some(backup_path) = backup_path {
|
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 {
|
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_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: &str = "hello_dir_new";
|
||||||
static TEST_COPY_TO_FOLDER_NEW_FILE: &str = "hello_dir_new/hello_world.txt";
|
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"))]
|
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
|
||||||
static TEST_MOUNT_COPY_FROM_FOLDER: &str = "dir_with_mount";
|
static TEST_MOUNT_COPY_FROM_FOLDER: &str = "dir_with_mount";
|
||||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
|
#[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]
|
#[test]
|
||||||
fn test_cp_backup_never() {
|
fn test_cp_backup_never() {
|
||||||
let (at, mut ucmd) = at_and_ucmd!();
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
1
tests/fixtures/cp/protected.txt
vendored
Normal file
1
tests/fixtures/cp/protected.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
new text
|
1
tests/fixtures/cp/protected.txt.bak
vendored
Normal file
1
tests/fixtures/cp/protected.txt.bak
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
original text
|
Loading…
Add table
Add a link
Reference in a new issue