From 73a83009c8b9dedcadf609b56293075ee4ce9d58 Mon Sep 17 00:00:00 2001 From: Zhang Wen Date: Sun, 20 Apr 2025 19:38:15 +0800 Subject: [PATCH 1/2] friently message install file to directory containing directory with same name --- src/uu/install/src/install.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/uu/install/src/install.rs b/src/uu/install/src/install.rs index 6fd04bc14b5..8c4a8d808f0 100644 --- a/src/uu/install/src/install.rs +++ b/src/uu/install/src/install.rs @@ -98,6 +98,9 @@ enum InstallError { #[error("failed to access {}: Not a directory", .0.quote())] NotADirectory(PathBuf), + + #[error("cannot overwrite directory {} with non-directory {}", .0.quote(), .1.quote())] + OverrideDirectoryFailed(PathBuf, PathBuf), } impl UError for InstallError { @@ -748,6 +751,13 @@ fn copy_normal_file(from: &Path, to: &Path) -> UResult<()> { /// Returns an empty Result or an error in case of failure. /// fn copy_file(from: &Path, to: &Path) -> UResult<()> { + if to.is_dir() && !from.is_dir() { + return Err(InstallError::OverrideDirectoryFailed( + to.to_path_buf().clone(), + from.to_path_buf().clone(), + ) + .into()); + } // fs::copy fails if destination is a invalid symlink. // so lets just remove all existing files at destination before copy. if let Err(e) = fs::remove_file(to) { From d30e2d7a6e5b9e7045ded5ce580b7159268e8e1e Mon Sep 17 00:00:00 2001 From: Zhang Wen Date: Sun, 20 Apr 2025 19:54:10 +0800 Subject: [PATCH 2/2] install: test install file to directory containing directory with same name --- tests/by-util/test_install.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index 2b3ad8a8c04..1270460d853 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -1764,3 +1764,17 @@ fn test_install_from_stdin() { assert!(at.file_exists(target)); assert_eq!(at.read(target), test_string); } + +#[test] +fn test_install_failing_copy_file_to_target_contain_subdir_with_same_name() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "file"; + let dir1 = "dir1"; + + at.touch(file); + at.mkdir_all(&format!("{dir1}/{file}")); + ucmd.arg(file) + .arg(dir1) + .fails() + .stderr_contains("cannot overwrite directory"); +}