From c9be787fc92d3d7ae4b97a4d326f12850c035627 Mon Sep 17 00:00:00 2001 From: Quin Gillespie Date: Mon, 12 Jan 2026 21:31:12 -0700 Subject: [PATCH 1/3] Fixed passing -0 to tail. Closes #10191 --- src/uu/tail/src/tail.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 3a16f670b63..4e570d0676e 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -403,6 +403,10 @@ fn forwards_thru_file( /// `num_delimiters` instance of `delimiter`. The `file` is left seek'd to the /// position just after that delimiter. fn backwards_thru_file(file: &mut File, num_delimiters: u64, delimiter: u8) { + if num_delimiters == 0 { + file.seek(SeekFrom::End(0)).unwrap(); + return; + } // This variable counts the number of delimiters found in the file // so far (reading from the end of the file toward the beginning). let mut counter = 0; From 1894e4364386ff816f08f4ec460d63c5b73eefdf Mon Sep 17 00:00:00 2001 From: Quin Gillespie Date: Thu, 15 Jan 2026 08:51:23 -0700 Subject: [PATCH 2/3] Added a test --- src/uu/tail/src/tail.rs | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 4e570d0676e..fdbe82ccf97 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -575,8 +575,28 @@ where #[cfg(test)] mod tests { - use crate::forwards_thru_file; - use std::io::Cursor; + use crate::{backwards_thru_file, forwards_thru_file}; + use std::{ + env, + fs::{self, File}, + io::{Cursor, Seek, SeekFrom, Write}, + process, + time::{SystemTime, UNIX_EPOCH}, + }; + + fn create_temp_file(contents: &[u8]) -> (std::path::PathBuf, File) { + let mut path = env::temp_dir(); + let unique = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos(); + path.push(format!("uutils-tail-test-{}-{unique}", process::id())); + let mut file = File::create(&path).unwrap(); + file.write_all(contents).unwrap(); + file.flush().unwrap(); + file.seek(SeekFrom::Start(0)).unwrap(); + (path, file) + } #[test] fn test_forwards_thru_file_zero() { @@ -599,4 +619,15 @@ mod tests { let i = forwards_thru_file(&mut reader, 2, b'\n').unwrap(); assert_eq!(i, 2); } + + #[test] + fn test_backwards_thru_file_zero() { + let (path, mut file) = create_temp_file(b"a\nb\nc\n"); + let len = file.metadata().unwrap().len(); + backwards_thru_file(&mut file, 0, b'\n'); + let pos = file.seek(SeekFrom::Current(0)).unwrap(); + assert_eq!(pos, len); + drop(file); + fs::remove_file(path).unwrap(); + } } From 66a1944d7edb930a9ed4e96a56a3e55b2fc7771d Mon Sep 17 00:00:00 2001 From: Quin Gillespie Date: Fri, 16 Jan 2026 22:46:43 -0700 Subject: [PATCH 3/3] Fix test --- src/uu/tail/src/tail.rs | 35 ++--------------------------------- tests/by-util/test_tail.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index fdbe82ccf97..4e570d0676e 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -575,28 +575,8 @@ where #[cfg(test)] mod tests { - use crate::{backwards_thru_file, forwards_thru_file}; - use std::{ - env, - fs::{self, File}, - io::{Cursor, Seek, SeekFrom, Write}, - process, - time::{SystemTime, UNIX_EPOCH}, - }; - - fn create_temp_file(contents: &[u8]) -> (std::path::PathBuf, File) { - let mut path = env::temp_dir(); - let unique = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_nanos(); - path.push(format!("uutils-tail-test-{}-{unique}", process::id())); - let mut file = File::create(&path).unwrap(); - file.write_all(contents).unwrap(); - file.flush().unwrap(); - file.seek(SeekFrom::Start(0)).unwrap(); - (path, file) - } + use crate::forwards_thru_file; + use std::io::Cursor; #[test] fn test_forwards_thru_file_zero() { @@ -619,15 +599,4 @@ mod tests { let i = forwards_thru_file(&mut reader, 2, b'\n').unwrap(); assert_eq!(i, 2); } - - #[test] - fn test_backwards_thru_file_zero() { - let (path, mut file) = create_temp_file(b"a\nb\nc\n"); - let len = file.metadata().unwrap().len(); - backwards_thru_file(&mut file, 0, b'\n'); - let pos = file.seek(SeekFrom::Current(0)).unwrap(); - assert_eq!(pos, len); - drop(file); - fs::remove_file(path).unwrap(); - } } diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 3dd0ee0d2d4..3def2eb08a4 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -1125,6 +1125,16 @@ fn test_obsolete_syntax_small_file() { .stdout_is("a\nb\nc\nd\ne\n"); } +/// Test for obsolete syntax `tail -0 FILE`: print nothing and exit cleanly. +#[test] +fn test_obsolete_syntax_zero_lines_file() { + new_ucmd!() + .args(&["-0", "foobar.txt"]) + .succeeds() + .no_stderr() + .no_stdout(); +} + /// Test for reading all lines, specified by `tail -n +0`. #[test] fn test_positive_zero_lines() {