1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

cp: refuse to copy symlink over itself

This commit is contained in:
Dan Hipschman 2025-04-11 12:24:52 -07:00 committed by Sylvestre Ledru
parent d957e64999
commit e92e419a93
2 changed files with 32 additions and 1 deletions

View file

@ -1802,7 +1802,13 @@ fn is_forbidden_to_copy_to_same_file(
if options.copy_mode == CopyMode::SymLink && dest_is_symlink {
return false;
}
if dest_is_symlink && source_is_symlink && !options.dereference {
// If source and dest are both the same symlink but with different names, then allow the copy.
// This can occur, for example, if source and dest are both hardlinks to the same symlink.
if dest_is_symlink
&& source_is_symlink
&& source.file_name() != dest.file_name()
&& !options.dereference
{
return false;
}
true

View file

@ -5218,6 +5218,31 @@ mod same_file {
assert_eq!(symlink1, at.resolve_link(symlink2));
}
#[test]
fn test_same_symlink_to_itself_no_dereference() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.write(FILE_NAME, CONTENTS);
at.symlink_file(FILE_NAME, SYMLINK_NAME);
scene
.ucmd()
.args(&["-P", SYMLINK_NAME, SYMLINK_NAME])
.fails()
.stderr_contains("are the same file");
}
#[test]
fn test_same_dangling_symlink_to_itself_no_dereference() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.symlink_file("nonexistent_file", SYMLINK_NAME);
scene
.ucmd()
.args(&["-P", SYMLINK_NAME, SYMLINK_NAME])
.fails()
.stderr_contains("are the same file");
}
// the following tests tries to copy file to a hardlink of the same file with
// various options
#[test]