From 072331e88cab8e85c2ea2ec84e0f454ae32a97e2 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:56:14 +0100 Subject: [PATCH] Revert "tail: stop reading past the original end of file" This reverts commit 781ddfc58cd5a283c5e53b3d5c8743d046afd366. --- src/uu/tail/src/tail.rs | 13 ++----------- tests/by-util/test_tail.rs | 28 ---------------------------- 2 files changed, 2 insertions(+), 39 deletions(-) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 3c097f8f3..9db1ceadf 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -178,7 +178,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, st.is_file().then_some(st.len()))?; + bounded_tail(&mut file, settings)?; reader = BufReader::new(file); } else { reader = BufReader::new(file); @@ -452,7 +452,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, file_size: Option) -> UResult<()> { +fn bounded_tail(file: &mut File, settings: &Settings) -> UResult<()> { debug_assert!(!settings.presume_input_pipe); let mut limit = None; @@ -460,15 +460,6 @@ fn bounded_tail(file: &mut File, settings: &Settings, file_size: Option) -> match &settings.mode { FilterMode::Lines(Signum::Negative(count), delimiter) => { backwards_thru_file(file, *count, *delimiter); - // Print only up to the end the file had when it was opened. - // Otherwise, if the output is appended back to the input file - // (e.g. `tail -n1 f >> f`), reading until EOF never terminates - // because our own output keeps extending it. - if let Some(size) = file_size - && let Ok(pos) = file.stream_position() - { - limit = Some(size.saturating_sub(pos)); - } } FilterMode::Lines(Signum::Positive(count), delimiter) if count > &1 => { let i = forwards_thru_file(file, *count - 1, *delimiter).unwrap(); diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 7c229fd35..9758f5cf7 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -263,34 +263,6 @@ fn test_n0_with_follow() { child.kill(); } -#[test] -#[cfg(unix)] -#[cfg_attr(wasi_runner, ignore = "WASI: no rlimit support")] -fn test_output_appended_to_input_file_terminates() { - // $ tail -n1 f >> f - // Appends the last line once and exits; it must not read back its - // own output forever. The file size limit makes a broken - // implementation fail instead of filling the disk. - use rustix::process::Resource; - - let (at, mut ucmd) = at_and_ucmd!(); - - // Larger than the filesystem block size so `tail` reads from the end. - let content = "x".repeat(256 * 1024) + "\n"; - at.write("f", &content); - let out = std::fs::OpenOptions::new() - .append(true) - .open(at.plus("f")) - .unwrap(); - - ucmd.args(&["-n1", "f"]) - .set_stdout(Stdio::from(out)) - .limit(Resource::Fsize, 4 * 1024 * 1024, 4 * 1024 * 1024) - .succeeds(); - - assert_eq!(at.read("f"), content.repeat(2)); -} - // TODO: Add similar test for windows #[test] #[cfg(unix)]