Skip to content

Commit 7143379

Browse files
committed
add support of RustyHermit's BSD socket layer
RustHermit publishs a new kernel interface and supports a common BSD socket layer. By supporting this interface, the implementation can be harmonized to other operating systems. To realize this socket layer, the handling of file descriptors is also harmonized to other operating systems.
1 parent 07c993e commit 7143379

File tree

11 files changed

+812
-459
lines changed

11 files changed

+812
-459
lines changed

Cargo.lock

+10-2
Original file line numberDiff line numberDiff line change
@@ -1927,8 +1927,16 @@ version = "0.2.6"
19271927
source = "registry+https://github.com/rust-lang/crates.io-index"
19281928
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
19291929
dependencies = [
1930-
"compiler_builtins",
19311930
"libc",
1931+
]
1932+
1933+
[[package]]
1934+
name = "hermit-abi"
1935+
version = "0.3.0"
1936+
source = "registry+https://github.com/rust-lang/crates.io-index"
1937+
checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
1938+
dependencies = [
1939+
"compiler_builtins",
19321940
"rustc-std-workspace-alloc",
19331941
"rustc-std-workspace-core",
19341942
]
@@ -5294,7 +5302,7 @@ dependencies = [
52945302
"dlmalloc",
52955303
"fortanix-sgx-abi",
52965304
"hashbrown 0.12.3",
5297-
"hermit-abi 0.2.6",
5305+
"hermit-abi 0.3.0",
52985306
"libc",
52995307
"miniz_oxide",
53005308
"object 0.29.0",

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] }
4343
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] }
4444

4545
[target.'cfg(target_os = "hermit")'.dependencies]
46-
hermit-abi = { version = "0.2.6", features = ['rustc-dep-of-std'] }
46+
hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] }
4747

4848
[target.wasm32-wasi.dependencies]
4949
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }

library/std/src/os/hermit/io.rs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![stable(feature = "rust1", since = "1.0.0")]
2+
3+
use hermit_abi as abi;
4+
5+
#[stable(feature = "rust1", since = "1.0.0")]
6+
pub type RawFd = abi::FileDescriptor;
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,26 @@
11
#![unstable(reason = "not public", issue = "none", feature = "fd")]
22

3+
mod owned;
4+
mod raw;
5+
36
use crate::io::{self, Read};
4-
use crate::mem;
57
use crate::sys::cvt;
68
use crate::sys::hermit::abi;
79
use crate::sys::unsupported;
8-
use crate::sys_common::AsInner;
10+
use crate::sys_common::{AsInner, FromInner, IntoInner};
11+
12+
pub use self::owned::*;
13+
pub use self::raw::*;
914

1015
#[derive(Debug)]
1116
pub struct FileDesc {
12-
fd: i32,
17+
fd: OwnedFd,
1318
}
1419

1520
impl FileDesc {
16-
pub fn new(fd: i32) -> FileDesc {
17-
FileDesc { fd }
18-
}
19-
20-
pub fn raw(&self) -> i32 {
21-
self.fd
22-
}
23-
24-
/// Extracts the actual file descriptor without closing it.
25-
pub fn into_raw(self) -> i32 {
26-
let fd = self.fd;
27-
mem::forget(self);
28-
fd
29-
}
30-
3121
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
32-
let result = unsafe { abi::read(self.fd, buf.as_mut_ptr(), buf.len()) };
33-
cvt(result as i32)
22+
let result = cvt(unsafe { abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?;
23+
Ok(result as usize)
3424
}
3525

3626
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@@ -39,8 +29,8 @@ impl FileDesc {
3929
}
4030

4131
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
42-
let result = unsafe { abi::write(self.fd, buf.as_ptr(), buf.len()) };
43-
cvt(result as i32)
32+
let result = cvt(unsafe { abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
33+
Ok(result as usize)
4434
}
4535

4636
pub fn duplicate(&self) -> io::Result<FileDesc> {
@@ -69,19 +59,39 @@ impl<'a> Read for &'a FileDesc {
6959
}
7060
}
7161

72-
impl AsInner<i32> for FileDesc {
73-
fn as_inner(&self) -> &i32 {
62+
impl IntoInner<OwnedFd> for FileDesc {
63+
fn into_inner(self) -> OwnedFd {
64+
self.fd
65+
}
66+
}
67+
68+
impl FromInner<OwnedFd> for FileDesc {
69+
fn from_inner(owned_fd: OwnedFd) -> Self {
70+
Self { fd: owned_fd }
71+
}
72+
}
73+
74+
impl FromRawFd for FileDesc {
75+
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
76+
Self { fd: FromRawFd::from_raw_fd(raw_fd) }
77+
}
78+
}
79+
80+
impl AsInner<OwnedFd> for FileDesc {
81+
fn as_inner(&self) -> &OwnedFd {
7482
&self.fd
7583
}
7684
}
7785

78-
impl Drop for FileDesc {
79-
fn drop(&mut self) {
80-
// Note that errors are ignored when closing a file descriptor. The
81-
// reason for this is that if an error occurs we don't actually know if
82-
// the file descriptor was closed or not, and if we retried (for
83-
// something like EINTR), we might close another valid file descriptor
84-
// (opened after we closed ours.
85-
let _ = unsafe { abi::close(self.fd) };
86+
impl AsFd for FileDesc {
87+
fn as_fd(&self) -> BorrowedFd<'_> {
88+
self.fd.as_fd()
89+
}
90+
}
91+
92+
impl AsRawFd for FileDesc {
93+
#[inline]
94+
fn as_raw_fd(&self) -> RawFd {
95+
self.fd.as_raw_fd()
8696
}
8797
}
+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
use super::raw::RawFd;
2+
3+
use crate::marker::PhantomData;
4+
use crate::mem::forget;
5+
use crate::sys::fd::{AsRawFd, FromRawFd, IntoRawFd};
6+
use crate::sys::hermit::abi;
7+
use crate::sys_common::{AsInner, FromInner, IntoInner};
8+
9+
/// A borrowed file descriptor.
10+
///
11+
/// This has a lifetime parameter to tie it to the lifetime of something that
12+
/// owns the file descriptor.
13+
///
14+
/// This uses `repr(transparent)` and has the representation of a host file
15+
/// descriptor, so it can be used in FFI in places where a file descriptor is
16+
/// passed as an argument, it is not captured or consumed, and it never has the
17+
/// value `-1`.
18+
///
19+
/// This type's `.to_owned()` implementation returns another `BorrowedFd`
20+
/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
21+
/// descriptor, which is then borrowed under the same lifetime.
22+
#[derive(Copy, Clone)]
23+
#[repr(transparent)]
24+
#[rustc_layout_scalar_valid_range_start(0)]
25+
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
26+
// 32-bit c_int. Below is -2, in two's complement, but that only works out
27+
// because c_int is 32 bits.
28+
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
29+
#[rustc_nonnull_optimization_guaranteed]
30+
#[stable(feature = "io_safety", since = "1.63.0")]
31+
pub struct BorrowedFd<'fd> {
32+
fd: RawFd,
33+
_phantom: PhantomData<&'fd OwnedFd>,
34+
}
35+
36+
/// An owned file descriptor.
37+
///
38+
/// This closes the file descriptor on drop.
39+
///
40+
/// This uses `repr(transparent)` and has the representation of a host file
41+
/// descriptor, so it can be used in FFI in places where a file descriptor is
42+
/// passed as a consumed argument or returned as an owned value, and it never
43+
/// has the value `-1`.
44+
#[repr(transparent)]
45+
#[rustc_layout_scalar_valid_range_start(0)]
46+
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
47+
// 32-bit c_int. Below is -2, in two's complement, but that only works out
48+
// because c_int is 32 bits.
49+
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
50+
#[rustc_nonnull_optimization_guaranteed]
51+
#[stable(feature = "io_safety", since = "1.63.0")]
52+
#[derive(Debug)]
53+
pub struct OwnedFd {
54+
fd: RawFd,
55+
}
56+
57+
impl BorrowedFd<'_> {
58+
/// Return a `BorrowedFd` holding the given raw file descriptor.
59+
///
60+
/// # Safety
61+
///
62+
/// The resource pointed to by `fd` must remain open for the duration of
63+
/// the returned `BorrowedFd`, and it must not have the value `-1`.
64+
#[inline]
65+
#[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
66+
#[stable(feature = "io_safety", since = "1.63.0")]
67+
pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
68+
assert!(fd != u32::MAX as RawFd);
69+
// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
70+
unsafe { Self { fd, _phantom: PhantomData } }
71+
}
72+
}
73+
74+
#[stable(feature = "io_safety", since = "1.63.0")]
75+
impl AsRawFd for BorrowedFd<'_> {
76+
#[inline]
77+
fn as_raw_fd(&self) -> RawFd {
78+
self.fd
79+
}
80+
}
81+
82+
#[stable(feature = "io_safety", since = "1.63.0")]
83+
impl AsRawFd for OwnedFd {
84+
#[inline]
85+
fn as_raw_fd(&self) -> RawFd {
86+
self.fd
87+
}
88+
}
89+
90+
#[stable(feature = "io_safety", since = "1.63.0")]
91+
impl IntoRawFd for OwnedFd {
92+
#[inline]
93+
fn into_raw_fd(self) -> RawFd {
94+
let fd = self.fd;
95+
forget(self);
96+
fd
97+
}
98+
}
99+
100+
#[stable(feature = "io_safety", since = "1.63.0")]
101+
impl FromRawFd for OwnedFd {
102+
/// Constructs a new instance of `Self` from the given raw file descriptor.
103+
///
104+
/// # Safety
105+
///
106+
/// The resource pointed to by `fd` must be open and suitable for assuming
107+
/// ownership. The resource must not require any cleanup other than `close`.
108+
#[inline]
109+
unsafe fn from_raw_fd(fd: RawFd) -> Self {
110+
assert_ne!(fd, u32::MAX as RawFd);
111+
// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
112+
unsafe { Self { fd } }
113+
}
114+
}
115+
116+
#[stable(feature = "io_safety", since = "1.63.0")]
117+
impl AsFd for crate::net::TcpStream {
118+
#[inline]
119+
fn as_fd(&self) -> BorrowedFd<'_> {
120+
self.as_inner().socket().as_fd()
121+
}
122+
}
123+
124+
#[stable(feature = "io_safety", since = "1.63.0")]
125+
impl From<crate::net::TcpStream> for OwnedFd {
126+
#[inline]
127+
fn from(tcp_stream: crate::net::TcpStream) -> OwnedFd {
128+
tcp_stream.into_inner().into_socket().into_inner().into_inner().into()
129+
}
130+
}
131+
132+
#[stable(feature = "io_safety", since = "1.63.0")]
133+
impl From<OwnedFd> for crate::net::TcpStream {
134+
#[inline]
135+
fn from(owned_fd: OwnedFd) -> Self {
136+
Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
137+
owned_fd,
138+
))))
139+
}
140+
}
141+
142+
#[stable(feature = "io_safety", since = "1.63.0")]
143+
impl AsFd for crate::net::TcpListener {
144+
#[inline]
145+
fn as_fd(&self) -> BorrowedFd<'_> {
146+
self.as_inner().socket().as_fd()
147+
}
148+
}
149+
150+
#[stable(feature = "io_safety", since = "1.63.0")]
151+
impl From<crate::net::TcpListener> for OwnedFd {
152+
#[inline]
153+
fn from(tcp_listener: crate::net::TcpListener) -> OwnedFd {
154+
tcp_listener.into_inner().into_socket().into_inner().into_inner().into()
155+
}
156+
}
157+
158+
#[stable(feature = "io_safety", since = "1.63.0")]
159+
impl From<OwnedFd> for crate::net::TcpListener {
160+
#[inline]
161+
fn from(owned_fd: OwnedFd) -> Self {
162+
Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
163+
owned_fd,
164+
))))
165+
}
166+
}
167+
168+
#[stable(feature = "io_safety", since = "1.63.0")]
169+
impl AsFd for crate::net::UdpSocket {
170+
#[inline]
171+
fn as_fd(&self) -> BorrowedFd<'_> {
172+
self.as_inner().socket().as_fd()
173+
}
174+
}
175+
176+
#[stable(feature = "io_safety", since = "1.63.0")]
177+
impl From<crate::net::UdpSocket> for OwnedFd {
178+
#[inline]
179+
fn from(udp_socket: crate::net::UdpSocket) -> OwnedFd {
180+
udp_socket.into_inner().into_socket().into_inner().into_inner().into()
181+
}
182+
}
183+
184+
#[stable(feature = "io_safety", since = "1.63.0")]
185+
impl From<OwnedFd> for crate::net::UdpSocket {
186+
#[inline]
187+
fn from(owned_fd: OwnedFd) -> Self {
188+
Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
189+
owned_fd,
190+
))))
191+
}
192+
}
193+
194+
#[stable(feature = "io_safety", since = "1.63.0")]
195+
impl Drop for OwnedFd {
196+
#[inline]
197+
fn drop(&mut self) {
198+
unsafe {
199+
// Note that errors are ignored when closing a file descriptor. The
200+
// reason for this is that if an error occurs we don't actually know if
201+
// the file descriptor was closed or not, and if we retried (for
202+
// something like EINTR), we might close another valid file descriptor
203+
// opened after we closed ours.
204+
let _ = abi::close(self.fd);
205+
}
206+
}
207+
}
208+
209+
pub trait AsFd {
210+
/// Borrows the file descriptor.
211+
///
212+
/// # Example
213+
///
214+
/// ```rust,no_run
215+
/// use std::fs::File;
216+
/// # use std::io;
217+
/// # #[cfg(any(unix, target_os = "wasi"))]
218+
/// # use std::os::fd::{AsFd, BorrowedFd};
219+
///
220+
/// let mut f = File::open("foo.txt")?;
221+
/// # #[cfg(any(unix, target_os = "wasi"))]
222+
/// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
223+
/// # Ok::<(), io::Error>(())
224+
/// ```
225+
#[stable(feature = "io_safety", since = "1.63.0")]
226+
fn as_fd(&self) -> BorrowedFd<'_>;
227+
}
228+
229+
#[stable(feature = "io_safety", since = "1.63.0")]
230+
impl AsFd for OwnedFd {
231+
#[inline]
232+
fn as_fd(&self) -> BorrowedFd<'_> {
233+
// Safety: `OwnedFd` and `BorrowedFd` have the same validity
234+
// invariants, and the `BorrowdFd` is bounded by the lifetime
235+
// of `&self`.
236+
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
237+
}
238+
}

0 commit comments

Comments
 (0)