Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 5 additions & 22 deletions src/uu/cat/src/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,31 +497,13 @@ fn print_fast<R: FdReadable>(handle: &mut InputHandle<R>) -> 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<R: FdReadable>(
handle: &mut InputHandle<R>,
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::<u8>::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<R: FdReadable>(
handle: &mut InputHandle<R>,
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 {
Expand All @@ -531,8 +513,9 @@ fn print_unbuffered<R: FdReadable>(
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 <https://github.com/uutils/coreutils/issues/12188>
#[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()),
Expand Down
15 changes: 14 additions & 1 deletion src/uucore/src/lib/mods/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<usize> {
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<()> {
Expand Down
Loading