From a313fd515f5f99be825cb4894890a75d497f6869 Mon Sep 17 00:00:00 2001 From: Kanishk Sachan Date: Thu, 1 Oct 2026 15:52:56 +0100 Subject: [PATCH 1/2] install: print the OS error, not its Debug form, when removing the destination fails --- src/uu/install/src/install.rs | 4 ++-- tests/by-util/test_install.rs | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/uu/install/src/install.rs b/src/uu/install/src/install.rs index f67c8b3ead9..9e8812e5017 100644 --- a/src/uu/install/src/install.rs +++ b/src/uu/install/src/install.rs @@ -802,7 +802,7 @@ fn standard(mut paths: Vec, b: &Behavior) -> UResult<()> { { show_error!( "{}", - translate!("install-error-failed-to-remove", "path" => target.quote(), "error" => format!("{e:?}")) + translate!("install-error-failed-to-remove", "path" => target.quote(), "error" => strip_errno(&e)) ); } @@ -1032,7 +1032,7 @@ fn copy_file(from: &Path, to: &Path) -> UResult<()> { } _ => show_error!( "{}", - translate!("install-error-failed-to-remove", "path" => to.quote(), "error" => format!("{e:?}")) + translate!("install-error-failed-to-remove", "path" => to.quote(), "error" => strip_errno(&e)) ), } } diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index bfb1a4f78c6..314c1d55a82 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -2719,6 +2719,26 @@ fn test_install_non_utf8_paths() { ucmd.arg("-D").arg(source_file).arg(&target_path).succeeds(); } +/// The error for a failed removal of the existing destination must be the +/// plain OS message, not the `Debug` form of the Rust error. +#[test] +fn test_install_failed_remove_existing_error_is_plain() { + // Root can always remove the file. + if geteuid().is_root() { + return; + } + + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("f"); + at.mkdir("r--"); + at.set_mode("r--", 0o400); + + ucmd.args(&["-D", "f", "r--/f"]) + .fails() + .stderr_contains("Error: Permission denied") + .stderr_does_not_contain("Os {"); +} + /// A failed ownership change must not leave the setuid/setgid mode applied. #[test] fn test_install_failed_chown_does_not_leave_setuid() { From 6df30fd88a116af129cf20f39478c7b24b2a3d2c Mon Sep 17 00:00:00 2001 From: Kanishk Sachan Date: Sun, 4 Oct 2026 13:29:32 +0100 Subject: [PATCH 2/2] install: drop the redundant 'Error:' prefix from the failed-removal message --- src/uu/install/locales/en-US.ftl | 2 +- src/uu/install/locales/fr-FR.ftl | 2 +- tests/by-util/test_install.rs | 20 -------------------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/uu/install/locales/en-US.ftl b/src/uu/install/locales/en-US.ftl index 0a4037ecc4e..903054ac43c 100644 --- a/src/uu/install/locales/en-US.ftl +++ b/src/uu/install/locales/en-US.ftl @@ -51,7 +51,7 @@ install-error-mutually-exclusive-target = Options --target-directory and --no-ta install-error-mutually-exclusive-compare-strip = Options --compare and --strip are mutually exclusive install-error-missing-file-operand = missing file operand install-error-missing-destination-operand = missing destination file operand after { $path } -install-error-failed-to-remove = Failed to remove existing file { $path }. Error: { $error } +install-error-failed-to-remove = Failed to remove existing file { $path }. { $error } install-error-will-not-overwrite-just-created = will not overwrite just-created { $dest } with { $source } # Warning messages diff --git a/src/uu/install/locales/fr-FR.ftl b/src/uu/install/locales/fr-FR.ftl index 70ae931697b..b2e1bc02ff9 100644 --- a/src/uu/install/locales/fr-FR.ftl +++ b/src/uu/install/locales/fr-FR.ftl @@ -50,7 +50,7 @@ install-error-mutually-exclusive-target = Les options --target-directory et --no install-error-mutually-exclusive-compare-strip = Les options --compare et --strip sont mutuellement exclusives install-error-missing-file-operand = opérande de fichier manquant install-error-missing-destination-operand = opérande de fichier de destination manquant après { $path } -install-error-failed-to-remove = Échec de la suppression du fichier existant { $path }. Erreur : { $error } +install-error-failed-to-remove = Échec de la suppression du fichier existant { $path }. { $error } install-error-will-not-overwrite-just-created = n'écrasera pas le fichier tout juste créé { $dest } avec { $source } # Messages d'avertissement diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index 314c1d55a82..bfb1a4f78c6 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -2719,26 +2719,6 @@ fn test_install_non_utf8_paths() { ucmd.arg("-D").arg(source_file).arg(&target_path).succeeds(); } -/// The error for a failed removal of the existing destination must be the -/// plain OS message, not the `Debug` form of the Rust error. -#[test] -fn test_install_failed_remove_existing_error_is_plain() { - // Root can always remove the file. - if geteuid().is_root() { - return; - } - - let (at, mut ucmd) = at_and_ucmd!(); - at.touch("f"); - at.mkdir("r--"); - at.set_mode("r--", 0o400); - - ucmd.args(&["-D", "f", "r--/f"]) - .fails() - .stderr_contains("Error: Permission denied") - .stderr_does_not_contain("Os {"); -} - /// A failed ownership change must not leave the setuid/setgid mode applied. #[test] fn test_install_failed_chown_does_not_leave_setuid() {