From ff93b402bb0fcc86e59a892da6e2ad48c2615b83 Mon Sep 17 00:00:00 2001 From: oech3 <79379754+oech3@users.noreply.github.com> Date: Sun, 10 May 2026 16:43:29 +0900 Subject: [PATCH] cat: dedup print_unbuffered --- src/uu/cat/src/cat.rs | 27 +++++---------------------- src/uucore/src/lib/mods/io.rs | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index 7d643bbed1a..66bd69dfc85 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -497,31 +497,13 @@ fn print_fast(handle: &mut InputHandle) -> CatResult<()> { } #[cfg_attr(any(target_os = "linux", target_os = "android"), inline(never))] // splice fast-path does not require this allocation -#[cfg(any(unix, target_os = "wasi"))] -fn print_unbuffered( - handle: &mut InputHandle, - stdout: io::Stdout, -) -> CatResult<()> { - // todo: since there is no cost by 0-fill, we could use larger heap buffer for throughput - let mut buf = [std::mem::MaybeUninit::::uninit(); 1024 * 64]; - // use raw syscall to remove buffering - loop { - match rustix::io::read(&handle.reader, &mut buf) { - Ok(([], _)) => return Ok(()), - Ok((filled, _)) => { - uucore::io::write_all_raw(&stdout, filled).inspect_err(handle_broken_pipe)?; - } - Err(e) if e.kind() != ErrorKind::Interrupted => return Err(e.into()), - _ => {} - } - } -} - -#[cfg(not(any(unix, target_os = "wasi")))] fn print_unbuffered( handle: &mut InputHandle, stdout: io::Stdout, ) -> CatResult<()> { + #[cfg(any(unix, target_os = "wasi"))] + let mut stdout = uucore::io::RawWriter(stdout); // use raw syscall to remove buffering + #[cfg(not(any(unix, target_os = "wasi")))] let mut stdout = stdout.lock(); let mut buf = [0; 1024 * 64]; loop { @@ -531,8 +513,9 @@ fn print_unbuffered( stdout .write_all(&buf[..n]) .inspect_err(handle_broken_pipe)?; - // we cannot use rustix::io on Windows + // cannot use rustix::io on Windows // really bad workaround for unbuffered write + #[cfg(not(any(unix, target_os = "wasi")))] stdout.flush().inspect_err(handle_broken_pipe)?; } Err(e) if e.kind() != ErrorKind::Interrupted => return Err(e.into()), diff --git a/src/uucore/src/lib/mods/io.rs b/src/uucore/src/lib/mods/io.rs index b3fcb938956..9d7fe889a3f 100644 --- a/src/uucore/src/lib/mods/io.rs +++ b/src/uucore/src/lib/mods/io.rs @@ -30,7 +30,20 @@ type NativeType = OwnedHandle; #[cfg(not(windows))] type NativeType = OwnedFd; -// io::write_all but no buffering +// create stdout without buffering +#[cfg(any(unix, target_os = "wasi"))] +pub struct RawWriter(pub io::Stdout); +#[cfg(any(unix, target_os = "wasi"))] +impl io::Write for RawWriter { + fn write(&mut self, b: &[u8]) -> io::Result { + rustix::io::write(&self.0, b).map_err(Into::into) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +// io::write_all but no buffering (deprecated?) #[inline] #[cfg(any(unix, target_os = "wasi"))] pub fn write_all_raw(output: impl AsFd, buf: &[u8]) -> io::Result<()> {