From a5a39b6ba81c922a58bffe11a033031d0bfd1dfc Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 6 May 2023 00:24:42 +0200 Subject: [PATCH] mv: 'mv source hardlink' should fail fixes: tests/mv/force.sh --- src/uu/mv/Cargo.toml | 2 +- src/uu/mv/src/mv.rs | 3 ++- tests/by-util/test_mv.rs | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/uu/mv/Cargo.toml b/src/uu/mv/Cargo.toml index d1f82bf88..5bc660d08 100644 --- a/src/uu/mv/Cargo.toml +++ b/src/uu/mv/Cargo.toml @@ -18,7 +18,7 @@ path = "src/mv.rs" clap = { workspace=true } fs_extra = { workspace=true } indicatif = { workspace=true } -uucore = { workspace=true } +uucore = { workspace=true, features=["fs"] } [[bin]] name = "mv" diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index ed6481863..dfc1129cb 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -25,6 +25,7 @@ use std::path::{Path, PathBuf}; use uucore::backup_control::{self, BackupMode}; use uucore::display::Quotable; use uucore::error::{set_exit_code, FromIo, UError, UResult, USimpleError, UUsageError}; +use uucore::fs::are_hardlinks_to_same_file; use uucore::update_control::{self, UpdateMode}; use uucore::{format_usage, help_about, help_section, help_usage, prompt_yes, show}; @@ -268,7 +269,7 @@ fn exec(files: &[OsString], b: &Behavior) -> UResult<()> { } // GNU semantics are: if the source and target are the same, no move occurs and we print an error - if source.eq(target) { + if source.eq(target) || are_hardlinks_to_same_file(source, target) { // Done to match GNU semantics for the dot file if source.eq(Path::new(".")) || source.ends_with("/.") || source.is_file() { return Err(MvError::SameFile( diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index edeb47a96..93955711d 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -400,6 +400,23 @@ fn test_mv_same_file() { .stderr_is(format!("mv: '{file_a}' and '{file_a}' are the same file\n",)); } +#[test] +#[cfg(unix)] +fn test_mv_same_hardlink() { + let (at, mut ucmd) = at_and_ucmd!(); + let file_a = "test_mv_same_file_a"; + let file_b = "test_mv_same_file_b"; + at.touch(file_a); + + at.hard_link(file_a, file_b); + + at.touch(file_a); + ucmd.arg(file_a) + .arg(file_b) + .fails() + .stderr_is(format!("mv: '{file_a}' and '{file_b}' are the same file\n",)); +} + #[test] fn test_mv_same_file_not_dot_dir() { let (at, mut ucmd) = at_and_ucmd!();