diff --git a/src/uu/install/locales/en-US.ftl b/src/uu/install/locales/en-US.ftl index 41dbeb335e6..ee440889993 100644 --- a/src/uu/install/locales/en-US.ftl +++ b/src/uu/install/locales/en-US.ftl @@ -39,6 +39,7 @@ install-error-invalid-user = invalid user: { $user } install-error-invalid-group = invalid group: { $group } install-error-omitting-directory = omitting directory { $path } install-error-not-a-directory = failed to access { $path }: Not a directory +install-error-existing-file-not-directory = cannot create directory { $path }: File exists install-error-override-directory-failed = cannot overwrite directory { $dir } with non-directory { $file } install-error-same-file = { $file1 } and { $file2 } are the same file install-error-extra-operand = extra operand { $operand } diff --git a/src/uu/install/locales/fr-FR.ftl b/src/uu/install/locales/fr-FR.ftl index 7edcd4a7faf..969cbdd72f1 100644 --- a/src/uu/install/locales/fr-FR.ftl +++ b/src/uu/install/locales/fr-FR.ftl @@ -39,6 +39,7 @@ install-error-invalid-user = utilisateur invalide : { $user } install-error-invalid-group = groupe invalide : { $group } install-error-omitting-directory = omission du répertoire { $path } install-error-not-a-directory = échec de l'accès à { $path } : N'est pas un répertoire +install-error-existing-file-not-directory = impossible de créer le répertoire { $path } : Le fichier existe install-error-override-directory-failed = impossible d'écraser le répertoire { $dir } avec un non-répertoire { $file } install-error-same-file = { $file1 } et { $file2 } sont le même fichier install-error-extra-operand = opérande supplémentaire { $operand } diff --git a/src/uu/install/src/install.rs b/src/uu/install/src/install.rs index c70873bdebc..ab6b6cfb49a 100644 --- a/src/uu/install/src/install.rs +++ b/src/uu/install/src/install.rs @@ -115,6 +115,9 @@ enum InstallError { #[error("{}", translate!("install-error-not-a-directory", "path" => .0.quote()))] NotADirectory(PathBuf), + #[error("{}", translate!("install-error-existing-file-not-directory", "path" => .0.quote()))] + ExistingFileNotADirectory(PathBuf), + #[error("{}", translate!("install-error-override-directory-failed", "dir" => .0.quote(), "file" => .1.quote()))] OverrideDirectoryFailed(PathBuf, PathBuf), @@ -499,8 +502,13 @@ fn directory(paths: &[OsString], b: &Behavior) -> UResult<()> { Err(InstallError::DirNeedsArg.into()) } else { for path in paths.iter().map(Path::new) { - // if the path already exist, don't try to create it again - if !path.exists() { + // if the path already exist, check if it's a file + if path.exists() { + if !path.is_dir() { + show!(InstallError::ExistingFileNotADirectory(path.to_path_buf())); + continue; + } + } else { // Special case to match GNU's behavior: // install -d foo/. should work and just create foo/ // std::fs::create_dir("foo/."); fails in pure Rust diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index eddcc36c224..4251c8a6400 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -1700,6 +1700,53 @@ fn test_install_dir_dot() { assert!(at.dir_exists("dir6")); } +#[test] +fn test_install_dir_with_existing_file() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + + let newdir1 = "newdir1"; + let existing_file = "existing_file"; + let newdir2 = "newdir2"; + at.touch(existing_file); + + scene + .ucmd() + .arg("-d") + .arg(newdir1) + .arg(existing_file) + .arg(newdir2) + .fails() + .stderr_contains("cannot create directory 'existing_file': File exists"); + + assert!(at.dir_exists(newdir1)); + assert!(!at.dir_exists(existing_file)); + assert!(at.dir_exists(newdir2)); +} + +#[test] +fn test_install_dir_with_multiple_existing_files() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let file1 = "file1"; + let file2 = "file2"; + + at.touch(file1); + at.touch(file2); + + scene + .ucmd() + .arg("-d") + .arg(file1) + .arg(file2) + .fails() + .stderr_contains("cannot create directory 'file1': File exists") + .stderr_contains("cannot create directory 'file2': File exists"); + + assert!(at.file_exists(file1)); + assert!(at.file_exists(file2)); +} + #[test] fn test_install_dir_req_verbose() { let scene = TestScenario::new(util_name!());