diff options
| author | Thalia Archibald <thalia@archibald.dev> | 2025-03-23 19:45:27 -0700 |
|---|---|---|
| committer | Thalia Archibald <thalia@archibald.dev> | 2025-03-27 16:49:30 -0700 |
| commit | 41b04653f3d2fd9cd6451a586354257d661385e2 (patch) | |
| tree | 7e31fa8376304695620b923eacc1c8902bc1d213 | |
| parent | 7290b04b0a46de2118968aa556bfc0970aac6661 (diff) | |
| download | rust-41b04653f3d2fd9cd6451a586354257d661385e2.tar.gz rust-41b04653f3d2fd9cd6451a586354257d661385e2.zip | |
Trusty: Implement write_vectored for stdio
Currently, `write` for stdout and stderr on Trusty is implemented with the semantics of `write_all`. Instead, call the underlying syscall only once in `write` and use the default implementation of `write_all` like other platforms. Also, implement `write_vectored` by adding support for `IoSlice`. Refactor stdin to reuse the unsupported type like #136769.
| -rw-r--r-- | library/std/src/sys/io/io_slice/iovec.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/io/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/stdio/trusty.rs | 83 |
3 files changed, 49 insertions, 38 deletions
diff --git a/library/std/src/sys/io/io_slice/iovec.rs b/library/std/src/sys/io/io_slice/iovec.rs index 072191315f7..df56358969a 100644 --- a/library/std/src/sys/io/io_slice/iovec.rs +++ b/library/std/src/sys/io/io_slice/iovec.rs @@ -1,6 +1,6 @@ #[cfg(target_os = "hermit")] use hermit_abi::iovec; -#[cfg(target_family = "unix")] +#[cfg(any(target_family = "unix", target_os = "trusty"))] use libc::iovec; use crate::ffi::c_void; diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs index e00b479109f..4d0365d42fd 100644 --- a/library/std/src/sys/io/mod.rs +++ b/library/std/src/sys/io/mod.rs @@ -2,7 +2,7 @@ mod io_slice { cfg_if::cfg_if! { - if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3"))] { + if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty"))] { mod iovec; pub use iovec::*; } else if #[cfg(target_os = "windows")] { diff --git a/library/std/src/sys/stdio/trusty.rs b/library/std/src/sys/stdio/trusty.rs index d393e95394d..e05461aa44a 100644 --- a/library/std/src/sys/stdio/trusty.rs +++ b/library/std/src/sys/stdio/trusty.rs @@ -1,21 +1,14 @@ -use crate::io; +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; -pub struct Stdin; +use crate::cmp; +use crate::io::{self, IoSlice}; + +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; pub struct Stderr; -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} - impl Stdout { pub const fn new() -> Stdout { Stdout @@ -24,7 +17,16 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - _write(libc::STDOUT_FILENO, buf) + write(libc::STDOUT_FILENO, buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + write_vectored(libc::STDOUT_FILENO, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { @@ -40,7 +42,16 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - _write(libc::STDERR_FILENO, buf) + write(libc::STDERR_FILENO, buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + write_vectored(libc::STDERR_FILENO, bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true } fn flush(&mut self) -> io::Result<()> { @@ -48,7 +59,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true @@ -58,24 +69,24 @@ pub fn panic_output() -> Option<impl io::Write> { Some(Stderr) } -fn _write(fd: i32, message: &[u8]) -> io::Result<usize> { - let mut iov = libc::iovec { iov_base: message.as_ptr() as *mut _, iov_len: message.len() }; - loop { - // SAFETY: syscall, safe arguments. - let ret = unsafe { libc::writev(fd, &iov, 1) }; - if ret < 0 { - return Err(io::Error::last_os_error()); - } - let ret = ret as usize; - if ret > iov.iov_len { - return Err(io::Error::last_os_error()); - } - if ret == iov.iov_len { - return Ok(message.len()); - } - // SAFETY: ret has been checked to be less than the length of - // the buffer - iov.iov_base = unsafe { iov.iov_base.add(ret) }; - iov.iov_len -= ret; +fn write(fd: i32, buf: &[u8]) -> io::Result<usize> { + let iov = libc::iovec { iov_base: buf.as_ptr() as *mut _, iov_len: buf.len() }; + // SAFETY: syscall, safe arguments. + let ret = unsafe { libc::writev(fd, &iov, 1) }; + // This check includes ret < 0, since the length is at most isize::MAX. + if ret as usize > iov.iov_len { + return Err(io::Error::last_os_error()); + } + Ok(ret as usize) +} + +fn write_vectored(fd: i32, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + let iov = bufs.as_ptr() as *const libc::iovec; + let len = cmp::min(bufs.len(), libc::c_int::MAX as usize) as libc::c_int; + // SAFETY: syscall, safe arguments. + let ret = unsafe { libc::writev(fd, iov, len) }; + if ret < 0 { + return Err(io::Error::last_os_error()); } + Ok(ret as usize) } |
