Skip to content

Commit 2fb77e8

Browse files
limadog9RenjiSann
authored andcommitted
mv: diagnose directory overwrites of symlink destinations
Check the destination entry without following its symlink target so missing or inaccessible referents do not fall through to a raw rename error. Extend the regression to cover existing and dangling symlinks. Closes #15358
1 parent 0982bd1 commit 2fb77e8

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

‎src/uu/mv/src/mv.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ fn handle_two_paths(source: &Path, target: &Path, opts: &Options) -> UResult<()>
462462
} else {
463463
move_files_into_dir(&[source.to_path_buf()], target, opts)
464464
}
465-
} else if source_is_dir && target.exists() {
465+
} else if source_is_dir && target.symlink_metadata().is_ok() {
466466
match opts.overwrite {
467467
OverwriteMode::NoClobber => return Ok(()),
468468
OverwriteMode::Interactive => prompt_overwrite(target, None)?,

‎tests/by-util/test_mv.rs‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,16 @@ fn test_mv_replace_symlink_with_symlink() {
425425
assert!(!at.symlink_exists("symlink_b"));
426426
}
427427

428-
#[test]
428+
#[rstest]
429+
#[case::existing_target(true)]
430+
#[case::dangling_target(false)]
429431
#[cfg(all(unix, not(target_os = "android")))]
430-
fn test_mv_replace_symlink_with_directory() {
432+
fn test_mv_replace_symlink_with_directory(#[case] target_exists: bool) {
431433
let (at, mut ucmd) = at_and_ucmd!();
432434

433-
at.touch("a");
435+
if target_exists {
436+
at.touch("a");
437+
}
434438
at.mkdir("b");
435439
at.touch("b/empty_file_b");
436440

@@ -439,9 +443,13 @@ fn test_mv_replace_symlink_with_directory() {
439443
ucmd.arg("-T")
440444
.arg("b")
441445
.arg("symlink")
442-
.fails()
443-
.stderr_contains("cannot overwrite non-directory")
444-
.stderr_contains("with directory");
446+
.fails_with_code(1)
447+
.no_stdout()
448+
.stderr_is("mv: cannot overwrite non-directory 'symlink' with directory 'b'\n");
449+
450+
assert!(at.dir_exists("b"));
451+
assert!(at.is_symlink("symlink"));
452+
assert_eq!(at.read("b/empty_file_b"), "");
445453
}
446454

447455
#[test]

0 commit comments

Comments
 (0)