Merge pull request #8314 from bvinc/tail_zero
Some checks are pending
CICD / Style/cargo-deny (push) Waiting to run
CICD / MinRustV (push) Waiting to run
CICD / Dependencies (push) Waiting to run
CICD / Tests/BusyBox test suite (push) Blocked by required conditions
CICD / Tests/Toybox test suite (push) Blocked by required conditions
CICD / Code Coverage (push) Waiting to run
CICD / Separate Builds (push) Waiting to run
CICD / Test all features separately (push) Blocked by required conditions
CICD / Build/SELinux (push) Blocked by required conditions
CICD / Build (push) Blocked by required conditions
CICD / Style/deps (push) Waiting to run
CICD / Documentation/warnings (push) Waiting to run
CICD / Build/Makefile (push) Blocked by required conditions
CICD / Build/stable (push) Blocked by required conditions
CICD / Build/nightly (push) Blocked by required conditions
CICD / Binary sizes (push) Blocked by required conditions
GnuTests / Run GNU tests (push) Waiting to run
Android / Test builds (push) Waiting to run
Code Quality / Style/format (push) Waiting to run
Code Quality / Style/lint (push) Waiting to run
Code Quality / Style/spelling (push) Waiting to run
Code Quality / Style/toml (push) Waiting to run
Code Quality / Style/Python (push) Waiting to run
Code Quality / Pre-commit hooks (push) Waiting to run
FreeBSD / Style and Lint (push) Waiting to run
FreeBSD / Tests (push) Waiting to run

tail: fix tailing /dev/zero
This commit is contained in:
Daniel Hofstetter 2025-07-07 10:30:34 +02:00 committed by GitHub
commit b9a790b476
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 23 deletions

View file

@ -23,7 +23,7 @@ clap = { workspace = true }
libc = { workspace = true }
memchr = { workspace = true }
notify = { workspace = true }
uucore = { workspace = true, features = ["parser"] }
uucore = { workspace = true, features = ["fs", "parser"] }
same-file = { workspace = true }
[target.'cfg(windows)'.dependencies]

View file

@ -158,7 +158,6 @@ impl FileExtTail for File {
pub trait MetadataExtTail {
fn is_tailable(&self) -> bool;
fn got_truncated(&self, other: &Metadata) -> UResult<bool>;
fn get_block_size(&self) -> u64;
fn file_id_eq(&self, other: &Metadata) -> bool;
}
@ -180,17 +179,6 @@ impl MetadataExtTail for Metadata {
Ok(other.len() < self.len() && other.modified()? != self.modified()?)
}
fn get_block_size(&self) -> u64 {
#[cfg(unix)]
{
self.blocks()
}
#[cfg(not(unix))]
{
self.len()
}
}
fn file_id_eq(&self, _other: &Metadata) -> bool {
#[cfg(unix)]
{

View file

@ -26,7 +26,7 @@ use args::{FilterMode, Settings, Signum, parse_args};
use chunks::ReverseChunks;
use follow::Observer;
use memchr::{memchr_iter, memrchr_iter};
use paths::{FileExtTail, HeaderPrinter, Input, InputKind, MetadataExtTail};
use paths::{FileExtTail, HeaderPrinter, Input, InputKind};
use same_file::Handle;
use std::cmp::Ordering;
use std::collections::HashMap;
@ -169,14 +169,15 @@ fn tail_file(
}
observer.add_bad_path(path, input.display_name.as_str(), false)?;
} else if input.is_tailable() {
let metadata = path.metadata().ok();
match File::open(path) {
Ok(mut file) => {
let st = file.metadata()?;
let blksize_limit = uucore::fs::sane_blksize::sane_blksize_from_metadata(&st);
header_printer.print_input(input);
let mut reader;
if !settings.presume_input_pipe
&& file.is_seekable(if input.is_stdin() { offset } else { 0 })
&& metadata.as_ref().unwrap().get_block_size() > 0
&& (!st.is_file() || st.len() > blksize_limit)
{
bounded_tail(&mut file, settings);
reader = BufReader::new(file);
@ -448,6 +449,7 @@ fn backwards_thru_file(file: &mut File, num_delimiters: u64, delimiter: u8) {
/// being a nice performance win for very large files.
fn bounded_tail(file: &mut File, settings: &Settings) {
debug_assert!(!settings.presume_input_pipe);
let mut limit = None;
// Find the position in the file to start printing from.
match &settings.mode {
@ -462,9 +464,8 @@ fn bounded_tail(file: &mut File, settings: &Settings) {
return;
}
FilterMode::Bytes(Signum::Negative(count)) => {
let len = file.seek(SeekFrom::End(0)).unwrap();
file.seek(SeekFrom::End(-((*count).min(len) as i64)))
.unwrap();
file.seek(SeekFrom::End(-(*count as i64))).unwrap();
limit = Some(*count);
}
FilterMode::Bytes(Signum::Positive(count)) if count > &1 => {
// GNU `tail` seems to index bytes and lines starting at 1, not
@ -477,10 +478,7 @@ fn bounded_tail(file: &mut File, settings: &Settings) {
_ => {}
}
// Print the target section of the file.
let stdout = stdout();
let mut stdout = stdout.lock();
io::copy(file, &mut stdout).unwrap();
print_target_section(file, limit);
}
fn unbounded_tail<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UResult<()> {
@ -547,6 +545,21 @@ fn unbounded_tail<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> UR
Ok(())
}
fn print_target_section<R>(file: &mut R, limit: Option<u64>)
where
R: Read + ?Sized,
{
// Print the target section of the file.
let stdout = stdout();
let mut stdout = stdout.lock();
if let Some(limit) = limit {
let mut reader = file.take(limit);
io::copy(&mut reader, &mut stdout).unwrap();
} else {
io::copy(file, &mut stdout).unwrap();
}
}
#[cfg(test)]
mod tests {

View file

@ -4923,3 +4923,12 @@ fn test_failed_write_is_reported() {
.fails()
.stderr_is("tail: No space left on device\n");
}
#[test]
#[cfg(target_os = "linux")]
fn test_dev_zero() {
new_ucmd!()
.args(&["-c", "1", "/dev/zero"])
.succeeds()
.stdout_only("\0");
}