Skip to content

Commit 41b0465

Browse files
committed
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.
1 parent 7290b04 commit 41b0465

File tree

3 files changed

+49
-38
lines changed

3 files changed

+49
-38
lines changed

library/std/src/sys/io/io_slice/iovec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#[cfg(target_os = "hermit")]
22
use hermit_abi::iovec;
3-
#[cfg(target_family = "unix")]
3+
#[cfg(any(target_family = "unix", target_os = "trusty"))]
44
use libc::iovec;
55

66
use crate::ffi::c_void;

library/std/src/sys/io/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
mod io_slice {
44
cfg_if::cfg_if! {
5-
if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3"))] {
5+
if #[cfg(any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty"))] {
66
mod iovec;
77
pub use iovec::*;
88
} else if #[cfg(target_os = "windows")] {

library/std/src/sys/stdio/trusty.rs

+47-36
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
1-
use crate::io;
1+
#[expect(dead_code)]
2+
#[path = "unsupported.rs"]
3+
mod unsupported_stdio;
24

3-
pub struct Stdin;
5+
use crate::cmp;
6+
use crate::io::{self, IoSlice};
7+
8+
pub type Stdin = unsupported_stdio::Stdin;
49
pub struct Stdout;
510
pub struct Stderr;
611

7-
impl Stdin {
8-
pub const fn new() -> Stdin {
9-
Stdin
10-
}
11-
}
12-
13-
impl io::Read for Stdin {
14-
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
15-
Ok(0)
16-
}
17-
}
18-
1912
impl Stdout {
2013
pub const fn new() -> Stdout {
2114
Stdout
@@ -24,7 +17,16 @@ impl Stdout {
2417

2518
impl io::Write for Stdout {
2619
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
27-
_write(libc::STDOUT_FILENO, buf)
20+
write(libc::STDOUT_FILENO, buf)
21+
}
22+
23+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
24+
write_vectored(libc::STDOUT_FILENO, bufs)
25+
}
26+
27+
#[inline]
28+
fn is_write_vectored(&self) -> bool {
29+
true
2830
}
2931

3032
fn flush(&mut self) -> io::Result<()> {
@@ -40,15 +42,24 @@ impl Stderr {
4042

4143
impl io::Write for Stderr {
4244
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
43-
_write(libc::STDERR_FILENO, buf)
45+
write(libc::STDERR_FILENO, buf)
46+
}
47+
48+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
49+
write_vectored(libc::STDERR_FILENO, bufs)
50+
}
51+
52+
#[inline]
53+
fn is_write_vectored(&self) -> bool {
54+
true
4455
}
4556

4657
fn flush(&mut self) -> io::Result<()> {
4758
Ok(())
4859
}
4960
}
5061

51-
pub const STDIN_BUF_SIZE: usize = 0;
62+
pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
5263

5364
pub fn is_ebadf(_err: &io::Error) -> bool {
5465
true
@@ -58,24 +69,24 @@ pub fn panic_output() -> Option<impl io::Write> {
5869
Some(Stderr)
5970
}
6071

61-
fn _write(fd: i32, message: &[u8]) -> io::Result<usize> {
62-
let mut iov = libc::iovec { iov_base: message.as_ptr() as *mut _, iov_len: message.len() };
63-
loop {
64-
// SAFETY: syscall, safe arguments.
65-
let ret = unsafe { libc::writev(fd, &iov, 1) };
66-
if ret < 0 {
67-
return Err(io::Error::last_os_error());
68-
}
69-
let ret = ret as usize;
70-
if ret > iov.iov_len {
71-
return Err(io::Error::last_os_error());
72-
}
73-
if ret == iov.iov_len {
74-
return Ok(message.len());
75-
}
76-
// SAFETY: ret has been checked to be less than the length of
77-
// the buffer
78-
iov.iov_base = unsafe { iov.iov_base.add(ret) };
79-
iov.iov_len -= ret;
72+
fn write(fd: i32, buf: &[u8]) -> io::Result<usize> {
73+
let iov = libc::iovec { iov_base: buf.as_ptr() as *mut _, iov_len: buf.len() };
74+
// SAFETY: syscall, safe arguments.
75+
let ret = unsafe { libc::writev(fd, &iov, 1) };
76+
// This check includes ret < 0, since the length is at most isize::MAX.
77+
if ret as usize > iov.iov_len {
78+
return Err(io::Error::last_os_error());
79+
}
80+
Ok(ret as usize)
81+
}
82+
83+
fn write_vectored(fd: i32, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
84+
let iov = bufs.as_ptr() as *const libc::iovec;
85+
let len = cmp::min(bufs.len(), libc::c_int::MAX as usize) as libc::c_int;
86+
// SAFETY: syscall, safe arguments.
87+
let ret = unsafe { libc::writev(fd, iov, len) };
88+
if ret < 0 {
89+
return Err(io::Error::last_os_error());
8090
}
91+
Ok(ret as usize)
8192
}

0 commit comments

Comments
 (0)