From 8f6d1097f8b63395f9f866d7bcfd0e64c21598c7 Mon Sep 17 00:00:00 2001 From: David Matos Date: Thu, 19 Oct 2023 11:10:26 +0200 Subject: [PATCH 1/3] mv: moving directory itself should fail --- src/uu/mv/src/error.rs | 5 +++++ src/uu/mv/src/mv.rs | 12 ++++++++++++ tests/by-util/test_mv.rs | 13 +++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/uu/mv/src/error.rs b/src/uu/mv/src/error.rs index a6605e23234..e891fc2ec01 100644 --- a/src/uu/mv/src/error.rs +++ b/src/uu/mv/src/error.rs @@ -12,6 +12,7 @@ pub enum MvError { NoSuchFile(String), SameFile(String, String), SelfSubdirectory(String), + SelfTargetSubdirectory(String, String), DirectoryToNonDirectory(String), NonDirectoryToDirectory(String, String), NotADirectory(String), @@ -29,6 +30,10 @@ impl Display for MvError { f, "cannot move '{s}' to a subdirectory of itself, '{s}/{s}'" ), + Self::SelfTargetSubdirectory(s, t) => write!( + f, + "cannot move '{s}' to a subdirectory of itself, '{t}/{s}'" + ), Self::DirectoryToNonDirectory(t) => { write!(f, "cannot overwrite directory {t} with non-directory") } diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index 7236907da77..844e30698bd 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -326,6 +326,18 @@ fn handle_two_paths(source: &Path, target: &Path, opts: &Options) -> UResult<()> Err(MvError::DirectoryToNonDirectory(target.quote().to_string()).into()) } } else { + // Check that source & target do not contain same subdir/dir when both exist + // mkdir dir1/dir2; mv dir1 dir1/dir2 + if target + .components() + .any(|c| c.as_os_str() == source.as_os_str()) + { + return Err(MvError::SelfTargetSubdirectory( + source.display().to_string(), + target.display().to_string(), + ) + .into()); + } move_files_into_dir(&[source.to_path_buf()], target, opts) } } else if target.exists() && source.is_dir() { diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index f7f9622f52e..c3559282e41 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -1389,6 +1389,19 @@ fn test_mv_into_self_data() { assert!(at.file_exists(file2)); assert!(!at.file_exists(file1)); } + +#[test] +fn test_mv_directory_into_subdirectory_of_itself_fails() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let dir1 = "mydir"; + let dir2 = "mydir/mydir_2"; + at.mkdir(dir1); + at.mkdir(dir2); + scene.ucmd().arg(dir1).arg(dir2).fails().stderr_contains( + "mv: cannot move 'mydir' to a subdirectory of itself, 'mydir/mydir_2/mydir'", + ); +} // Todo: // $ at.touch a b From 315eaa85f15bebc59d0c5323396812afa03ad693 Mon Sep 17 00:00:00 2001 From: David Matos Date: Mon, 23 Oct 2023 22:35:55 +0200 Subject: [PATCH 2/3] mv: Check trailing slash also fails on target containing itself --- src/uu/mv/src/mv.rs | 18 ++++++++++++++---- tests/by-util/test_mv.rs | 10 ++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index 844e30698bd..47e0b864d32 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -328,10 +328,20 @@ fn handle_two_paths(source: &Path, target: &Path, opts: &Options) -> UResult<()> } else { // Check that source & target do not contain same subdir/dir when both exist // mkdir dir1/dir2; mv dir1 dir1/dir2 - if target - .components() - .any(|c| c.as_os_str() == source.as_os_str()) - { + let target_contains_itself = target + .as_os_str() + .to_str() + .ok_or("not a valid unicode string") + .and_then(|t| { + source + .as_os_str() + .to_str() + .ok_or("not a valid unicode string") + .map(|s| t.contains(s)) + }) + .unwrap(); + + if target_contains_itself { return Err(MvError::SelfTargetSubdirectory( source.display().to_string(), target.display().to_string(), diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index c3559282e41..c5bb3d7e3c2 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -1401,6 +1401,16 @@ fn test_mv_directory_into_subdirectory_of_itself_fails() { scene.ucmd().arg(dir1).arg(dir2).fails().stderr_contains( "mv: cannot move 'mydir' to a subdirectory of itself, 'mydir/mydir_2/mydir'", ); + + // check that it also errors out with / + scene + .ucmd() + .arg(format!("{}/", dir1)) + .arg(dir2) + .fails() + .stderr_contains( + "mv: cannot move 'mydir/' to a subdirectory of itself, 'mydir/mydir_2/mydir/'", + ); } // Todo: From c5bec6a8302b63fadae6f68eee29af8d72c57414 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Tue, 24 Oct 2023 09:41:30 +0200 Subject: [PATCH 3/3] mv: add "spell-checker:ignore mydir" to test --- tests/by-util/test_mv.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index c5bb3d7e3c2..e8866732014 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -2,6 +2,8 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +// +// spell-checker:ignore mydir use crate::common::util::TestScenario; use filetime::FileTime; use std::thread::sleep;