Skip to content

Commit a43a2ff

Browse files
committed
cp: refuse to copy symlink over itself
1 parent da61ebf commit a43a2ff

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/uu/cp/src/cp.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,11 @@ fn is_forbidden_to_copy_to_same_file(
18081808
if options.copy_mode == CopyMode::SymLink && dest_is_symlink {
18091809
return false;
18101810
}
1811-
if dest_is_symlink && source_is_symlink && !options.dereference {
1811+
if dest_is_symlink
1812+
&& source_is_symlink
1813+
&& source.file_name() != dest.file_name()
1814+
&& !options.dereference
1815+
{
18121816
return false;
18131817
}
18141818
true

tests/by-util/test_cp.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5217,6 +5217,31 @@ mod same_file {
52175217
assert_eq!(symlink1, at.resolve_link(symlink2));
52185218
}
52195219

5220+
#[test]
5221+
fn test_same_symlink_to_itself_no_dereference() {
5222+
let scene = TestScenario::new(util_name!());
5223+
let at = &scene.fixtures;
5224+
at.write(FILE_NAME, CONTENTS);
5225+
at.symlink_file(FILE_NAME, SYMLINK_NAME);
5226+
scene
5227+
.ucmd()
5228+
.args(&["-P", SYMLINK_NAME, SYMLINK_NAME])
5229+
.fails()
5230+
.stderr_contains("are the same file");
5231+
}
5232+
5233+
#[test]
5234+
fn test_same_dangling_symlink_to_itself_no_dereference() {
5235+
let scene = TestScenario::new(util_name!());
5236+
let at = &scene.fixtures;
5237+
at.symlink_file("nonexistent_file", SYMLINK_NAME);
5238+
scene
5239+
.ucmd()
5240+
.args(&["-P", SYMLINK_NAME, SYMLINK_NAME])
5241+
.fails()
5242+
.stderr_contains("are the same file");
5243+
}
5244+
52205245
// the following tests tries to copy file to a hardlink of the same file with
52215246
// various options
52225247
#[test]

0 commit comments

Comments
 (0)