diff --git a/src/uu/sort/locales/en-US.ftl b/src/uu/sort/locales/en-US.ftl index a13e932af22..21042721ab5 100644 --- a/src/uu/sort/locales/en-US.ftl +++ b/src/uu/sort/locales/en-US.ftl @@ -15,7 +15,7 @@ sort-open-failed = open failed: {$path}: {$error} sort-parse-key-error = failed to parse key {$key}: {$msg} sort-cannot-read = cannot read: {$path}: {$error} sort-open-tmp-file-failed = failed to open temporary file: {$error} -sort-compress-prog-execution-failed = couldn't execute compress program: errno {$code} +sort-compress-prog-execution-failed = could not run compress program '{$prog}': {$error} sort-compress-prog-terminated-abnormally = {$prog} terminated abnormally sort-cannot-create-tmp-file = cannot create temporary file in '{$path}': sort-file-operands-combined = extra operand '{$file}' diff --git a/src/uu/sort/locales/fr-FR.ftl b/src/uu/sort/locales/fr-FR.ftl index f434607d5d2..611613c514c 100644 --- a/src/uu/sort/locales/fr-FR.ftl +++ b/src/uu/sort/locales/fr-FR.ftl @@ -15,7 +15,7 @@ sort-open-failed = échec d'ouverture : {$path} : {$error} sort-parse-key-error = échec d'analyse de la clé {$key} : {$msg} sort-cannot-read = impossible de lire : {$path} : {$error} sort-open-tmp-file-failed = échec d'ouverture du fichier temporaire : {$error} -sort-compress-prog-execution-failed = impossible d'exécuter le programme de compression : errno {$code} +sort-compress-prog-execution-failed = impossible d'exécuter le programme de compression '{$prog}' : {$error} sort-compress-prog-terminated-abnormally = {$prog} s'est terminé anormalement sort-cannot-create-tmp-file = impossible de créer un fichier temporaire dans '{$path}' : sort-file-operands-combined = opérande supplémentaire '{$file}' diff --git a/src/uu/sort/src/ext_sort.rs b/src/uu/sort/src/ext_sort.rs index ddbc278d7e3..d61f7d2008d 100644 --- a/src/uu/sort/src/ext_sort.rs +++ b/src/uu/sort/src/ext_sort.rs @@ -20,7 +20,7 @@ use std::{ }; use itertools::Itertools; -use uucore::error::UResult; +use uucore::error::{UResult, strip_errno}; use crate::Output; use crate::chunks::RecycledChunk; @@ -52,10 +52,37 @@ pub fn ext_sort( let settings = settings.clone(); move || sorter(&recycled_receiver, &sorted_sender, &settings) }); - if settings.compress_prog.is_some() { + + // Test if compression program exists and works, disable if not + let mut effective_settings = settings.clone(); + if let Some(ref prog) = settings.compress_prog { + // Test the compression program by trying to spawn it + match std::process::Command::new(prog) + .stdin(std::process::Stdio::null()) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn() + { + Ok(mut child) => { + // Kill the test process immediately + let _ = child.kill(); + } + Err(err) => { + // Print the error and disable compression + eprintln!( + "sort: could not run compress program '{}': {}", + prog, + strip_errno(&err) + ); + effective_settings.compress_prog = None; + } + } + } + + if effective_settings.compress_prog.is_some() { reader_writer::<_, WriteableCompressedTmpFile>( files, - settings, + &effective_settings, &sorted_receiver, recycled_sender, output, @@ -64,7 +91,7 @@ pub fn ext_sort( } else { reader_writer::<_, WriteablePlainTmpFile>( files, - settings, + &effective_settings, &sorted_receiver, recycled_sender, output, diff --git a/src/uu/sort/src/merge.rs b/src/uu/sort/src/merge.rs index 1e538c6d931..ea212f62f34 100644 --- a/src/uu/sort/src/merge.rs +++ b/src/uu/sort/src/merge.rs @@ -488,7 +488,8 @@ impl WriteableTmpFile for WriteableCompressedTmpFile { let mut child = command .spawn() .map_err(|err| SortError::CompressProgExecutionFailed { - code: err.raw_os_error().unwrap(), + prog: compress_prog.to_owned(), + error: err, })?; let child_stdin = child.stdin.take().unwrap(); Ok(Self { @@ -522,7 +523,8 @@ impl ClosedTmpFile for ClosedCompressedTmpFile { let mut child = command .spawn() .map_err(|err| SortError::CompressProgExecutionFailed { - code: err.raw_os_error().unwrap(), + prog: self.compress_prog.clone(), + error: err, })?; let child_stdout = child.stdout.take().unwrap(); Ok(CompressedTmpMergeInput { diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 22c96a436ed..ec9ab5b9305 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -152,8 +152,8 @@ pub enum SortError { #[error("{}", translate!("sort-open-tmp-file-failed", "error" => strip_errno(.error)))] OpenTmpFileFailed { error: std::io::Error }, - #[error("{}", translate!("sort-compress-prog-execution-failed", "code" => .code))] - CompressProgExecutionFailed { code: i32 }, + #[error("{}", translate!("sort-compress-prog-execution-failed", "prog" => .prog, "error" => strip_errno(.error)))] + CompressProgExecutionFailed { prog: String, error: std::io::Error }, #[error("{}", translate!("sort-compress-prog-terminated-abnormally", "prog" => .prog.quote()))] CompressProgTerminatedAbnormally { prog: String }, diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index 3a4cc1a86c5..8bce9d69cb4 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -1002,8 +1002,7 @@ fn test_compress_merge() { #[test] #[cfg(not(target_os = "android"))] fn test_compress_fail() { - #[cfg(not(windows))] - new_ucmd!() + let result = new_ucmd!() .args(&[ "ext_sort.txt", "-n", @@ -1012,22 +1011,22 @@ fn test_compress_fail() { "-S", "10", ]) - .fails() - .stderr_only("sort: couldn't execute compress program: errno 2\n"); - // With coverage, it fails with a different error: - // "thread 'main' panicked at 'called `Option::unwrap()` on ... - // So, don't check the output + .succeeds(); + + #[cfg(not(windows))] + result.stderr_contains( + "sort: could not run compress program 'nonexistent-program': No such file or directory", + ); + #[cfg(windows)] - new_ucmd!() - .args(&[ - "ext_sort.txt", - "-n", - "--compress-program", - "nonexistent-program", - "-S", - "10", - ]) - .fails(); + result.stderr_contains("could not run compress program"); + + // Check that it still produces correct sorted output to stdout + let expected = new_ucmd!() + .args(&["ext_sort.txt", "-n"]) + .succeeds() + .stdout_move_str(); + assert_eq!(result.stdout_str(), expected); } #[test]