fix(shred): stop immediately on write errors (fixes #7947)

Replace show_if_err!() with ? operator in wipe_file() to properly
propagate errors and stop pass loop on first write failure.

This matches GNU shred behavior where any write error (disk quota,
I/O error, etc.) stops execution immediately instead of continuing
with remaining passes.

Changes:
- src/uu/shred/src/shred.rs: Use ? operator for error propagation
- tests/by-util/test_shred.rs: Enable previously ignored test
This commit is contained in:
naoNao89
2025-12-26 23:55:40 +01:00
committed by Sylvestre Ledru
parent 18a50ff513
commit 31b5cc10dc
2 changed files with 11 additions and 10 deletions
+3 -6
View File
@@ -713,12 +713,9 @@ fn wipe_file(
);
}
// size is an optional argument for exactly how many bytes we want to shred
// Ignore failed writes; just keep trying
show_if_err!(
do_pass(&mut file, &pass_type, exact, random_source, size).map_err_context(|| {
translate!("shred-file-write-pass-failed", "file" => path.maybe_quote())
})
);
do_pass(&mut file, &pass_type, exact, random_source, size).map_err_context(
|| translate!("shred-file-write-pass-failed", "file" => path.maybe_quote()),
)?;
}
if remove_method != RemoveMethod::None {
+8 -4
View File
@@ -279,7 +279,6 @@ fn test_random_source_regular_file() {
}
#[test]
#[ignore = "known issue #7947"]
fn test_random_source_dir() {
let (at, mut ucmd) = at_and_ucmd!();
@@ -287,12 +286,17 @@ fn test_random_source_dir() {
let file = "foo.txt";
at.write(file, "a");
ucmd
.arg("-v")
// The test verifies that shred stops immediately on error instead of continuing
// Platform differences:
// - Unix: Error during write ("File write pass failed: Is a directory")
// - Windows: Error during open ("cannot open random source")
// Both are correct - key is NOT seeing "pass 2/3" (which proves it stopped)
ucmd.arg("-v")
.arg("--random-source=source")
.arg(file)
.fails()
.stderr_only("shred: foo.txt: pass 1/3 (random)...\nshred: foo.txt: File write pass failed: Is a directory\n");
.stderr_does_not_contain("pass 2/3")
.stderr_does_not_contain("pass 3/3");
}
#[test]