From 02a9598cc2c90c34f820214d31234acc1214d63c Mon Sep 17 00:00:00 2001 From: rossilor95 Date: Fri, 17 Apr 2026 21:24:40 +0200 Subject: [PATCH 1/3] tail: fix panic on write error in bounded_tail --- src/uu/tail/src/tail.rs | 14 ++++++++------ tests/by-util/test_tail.rs | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 0b7ec01e7a8..d15aef55a07 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -175,7 +175,7 @@ fn tail_file( && file.is_seekable(if input.is_stdin() { offset } else { 0 }) && (!st.is_file() || st.len() > blksize_limit) { - bounded_tail(&mut file, settings); + bounded_tail(&mut file, settings)?; reader = BufReader::new(file); } else { reader = BufReader::new(file); @@ -466,7 +466,7 @@ fn backwards_thru_file(file: &mut File, num_delimiters: u64, delimiter: u8) { /// end of the file, and then read the file "backwards" in blocks of size /// `BLOCK_SIZE` until we find the location of the first line/byte. This ends up /// being a nice performance win for very large files. -fn bounded_tail(file: &mut File, settings: &Settings) { +fn bounded_tail(file: &mut File, settings: &Settings) -> UResult<()> { debug_assert!(!settings.presume_input_pipe); let mut limit = None; @@ -499,7 +499,8 @@ fn bounded_tail(file: &mut File, settings: &Settings) { _ => {} } - print_target_section(file, limit); + print_target_section(file, limit)?; + Ok(()) } fn unbounded_tail(reader: &mut BufReader, settings: &Settings) -> UResult<()> { @@ -580,7 +581,7 @@ fn unbounded_tail(reader: &mut BufReader, settings: &Settings) -> UR Ok(()) } -fn print_target_section(file: &mut R, limit: Option) +fn print_target_section(file: &mut R, limit: Option) -> UResult<()> where R: Read + ?Sized, { @@ -589,10 +590,11 @@ where let mut stdout = stdout.lock(); if let Some(limit) = limit { let mut reader = file.take(limit); - io::copy(&mut reader, &mut stdout).unwrap(); + io::copy(&mut reader, &mut stdout)?; } else { - io::copy(file, &mut stdout).unwrap(); + io::copy(file, &mut stdout)?; } + Ok(()) } #[cfg(test)] diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index c1b755bda78..3b8fc1d64ec 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -5086,6 +5086,21 @@ fn test_failed_write_is_reported() { .stderr_is("tail: No space left on device\n"); } +#[cfg(target_os = "linux")] +#[test] +fn test_failed_write_is_reported_on_seekable_input() { + let ts = TestScenario::new("tail"); + let at = &ts.fixtures; + + at.write("bigfile", &"x\n".repeat(100_000)); + + ts.ucmd() + .arg("bigfile") + .set_stdout(File::create("/dev/full").unwrap()) + .fails() + .stderr_is("tail: No space left on device\n"); +} + #[test] #[cfg(target_os = "linux")] fn test_dev_zero() { From 0fb2deb91b96ab91b0879261cd19e6408c50ffa7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 19:27:41 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/by-util/test_tail.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 3b8fc1d64ec..13cbfc6333c 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -5091,9 +5091,9 @@ fn test_failed_write_is_reported() { fn test_failed_write_is_reported_on_seekable_input() { let ts = TestScenario::new("tail"); let at = &ts.fixtures; - + at.write("bigfile", &"x\n".repeat(100_000)); - + ts.ucmd() .arg("bigfile") .set_stdout(File::create("/dev/full").unwrap()) From 20cc0a3c26fce21e518f300115f116eaca533b6d Mon Sep 17 00:00:00 2001 From: rossilor95 Date: Sat, 18 Apr 2026 20:56:42 +0200 Subject: [PATCH 3/3] tail: increase test file size to ensure bounded_tail path --- tests/by-util/test_tail.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 13cbfc6333c..d46ff112c4a 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -5092,7 +5092,7 @@ fn test_failed_write_is_reported_on_seekable_input() { let ts = TestScenario::new("tail"); let at = &ts.fixtures; - at.write("bigfile", &"x\n".repeat(100_000)); + at.write("bigfile", &"x\n".repeat(1_100_000)); ts.ucmd() .arg("bigfile")