diff --git a/src/uu/truncate/src/truncate.rs b/src/uu/truncate/src/truncate.rs index 6f460cfd708..b0b8c8a2984 100644 --- a/src/uu/truncate/src/truncate.rs +++ b/src/uu/truncate/src/truncate.rs @@ -7,7 +7,7 @@ use clap::{Arg, ArgAction, Command}; use std::ffi::OsString; use std::fs::{OpenOptions, metadata}; -use std::io::ErrorKind; +use std::io::{ErrorKind, Seek, SeekFrom}; #[cfg(unix)] use std::os::unix::fs::FileTypeExt; use std::path::Path; @@ -255,7 +255,13 @@ fn truncate( _ => error.map_err_context(String::new), })?; - Some(reference_metadata.len()) + // For normal files and symbolic links, the size returned by `stat` is correct. + if reference_metadata.is_file() || reference_metadata.is_symlink() { + Some(reference_metadata.len()) + } else { + let mut reference_file = OpenOptions::new().read(true).open(reference_path)?; + Some(reference_file.seek(SeekFrom::End(0))?) + } } None => None, }; diff --git a/tests/by-util/test_truncate.rs b/tests/by-util/test_truncate.rs index a875d158bd1..7e8748da2b6 100644 --- a/tests/by-util/test_truncate.rs +++ b/tests/by-util/test_truncate.rs @@ -484,3 +484,14 @@ fn test_truncate_non_utf8_paths() { // Test that truncate can handle non-UTF-8 filenames ts.ucmd().arg("-s").arg("10").arg(file_name).succeeds(); } + +#[test] +#[cfg(all(unix, not(target_os = "openbsd")))] +fn test_truncate_stdin_reference() { + let ts = TestScenario::new(util_name!()); + ts.ucmd() + .args(&["-r", "/dev/stdin", "dst"]) + .terminal_simulation(true) + .fails() + .stderr_contains("Illegal seek"); +}