From 5d3aefe58d2148d277a1b28e29caed0e48858a9f Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 14:46:28 +0900 Subject: [PATCH 1/9] kmc-solid: Add `std::os::solid::io::{BorrowedFd,OwnedFd,AsFd}` It's mostly based on `std::os::fd::owned`. --- library/std/src/os/solid/io.rs | 191 +++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index f82034663d4e6..ab17a01e4112b 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -3,6 +3,9 @@ #![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "solid_ext", issue = "none")] +use crate::fmt; +use crate::marker::PhantomData; +use crate::mem::forget; use crate::net; use crate::sys; use crate::sys_common::{self, AsInner, FromInner, IntoInner}; @@ -10,6 +13,194 @@ use crate::sys_common::{self, AsInner, FromInner, IntoInner}; /// Raw file descriptors. pub type RawFd = i32; +/// A borrowed SOLID Sockets file descriptor. +/// +/// This has a lifetime parameter to tie it to the lifetime of something that +/// owns the socket. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a socket is passed as +/// an argument, it is not captured or consumed, and it never has the value +/// `SOLID_NET_INVALID_FD`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedFd` +/// rather than an `OwnedFd`. It just makes a trivial copy of the raw +/// socket, which is then borrowed under the same lifetime. +#[derive(Copy, Clone)] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +#[rustc_nonnull_optimization_guaranteed] +pub struct BorrowedFd<'socket> { + fd: RawFd, + _phantom: PhantomData<&'socket OwnedFd>, +} + +/// An owned SOLID Sockets file descriptor. +/// +/// This closes the file descriptor on drop. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a socket is passed as +/// an argument, it is not captured or consumed, and it never has the value +/// `SOLID_NET_INVALID_FD`. +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(0)] +// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`. +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +#[rustc_nonnull_optimization_guaranteed] +pub struct OwnedFd { + fd: RawFd, +} + +impl BorrowedFd<'_> { + /// Return a `BorrowedFd` holding the given raw file descriptor. + /// + /// # Safety + /// + /// The resource pointed to by `fd` must remain open for the duration of + /// the returned `BorrowedFd`, and it must not have the value + /// `SOLID_NET_INVALID_FD`. + #[inline] + pub const unsafe fn borrow_raw(fd: RawFd) -> Self { + assert!(fd != -1 as RawFd); + // 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) + unsafe { Self { fd, _phantom: PhantomData } } + } +} + +impl OwnedFd { + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// description as the existing `OwnedFd` instance. + pub fn try_clone(&self) -> crate::io::Result { + self.as_fd().try_clone_to_owned() + } +} + +impl BorrowedFd<'_> { + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// description as the existing `BorrowedFd` instance. + pub fn try_clone_to_owned(&self) -> crate::io::Result { + let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd) }) + } +} + +impl AsRawFd for BorrowedFd<'_> { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +impl AsRawFd for OwnedFd { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +impl IntoRawFd for OwnedFd { + #[inline] + fn into_raw_fd(self) -> RawFd { + let fd = self.fd; + forget(self); + fd + } +} + +impl FromRawFd for OwnedFd { + /// Constructs a new instance of `Self` from the given raw file descriptor. + /// + /// # Safety + /// + /// The resource pointed to by `fd` must be open and suitable for assuming + /// ownership. The resource must not require any cleanup other than `close`. + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> Self { + assert_ne!(fd, -1 as RawFd); + // 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) + unsafe { Self { fd } } + } +} + +impl Drop for OwnedFd { + #[inline] + fn drop(&mut self) { + unsafe { sys::net::netc::close(self.fd) }; + } +} + +impl fmt::Debug for BorrowedFd<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BorrowedFd").field("fd", &self.fd).finish() + } +} + +impl fmt::Debug for OwnedFd { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OwnedFd").field("fd", &self.fd).finish() + } +} + +macro_rules! impl_is_terminal { + ($($t:ty),*$(,)?) => {$( + #[unstable(feature = "sealed", issue = "none")] + impl crate::sealed::Sealed for $t {} + + #[stable(feature = "is_terminal", since = "1.70.0")] + impl crate::io::IsTerminal for $t { + #[inline] + fn is_terminal(&self) -> bool { + crate::sys::io::is_terminal(self) + } + } + )*} +} + +impl_is_terminal!(BorrowedFd<'_>, OwnedFd); + +/// A trait to borrow the SOLID Sockets file descriptor from an underlying +/// object. +pub trait AsFd { + /// Borrows the file descriptor. + fn as_fd(&self) -> BorrowedFd<'_>; +} + +impl AsFd for &T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +impl AsFd for &mut T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +impl AsFd for BorrowedFd<'_> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + *self + } +} + +impl AsFd for OwnedFd { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // Safety: `OwnedFd` and `BorrowedFd` have the same validity + // invariants, and the `BorrowedFd` is bounded by the lifetime + // of `&self`. + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + /// A trait to extract the raw SOLID Sockets file descriptor from an underlying /// object. pub trait AsRawFd { From ddfe168e6c6e6c3f8fe8c35568c84cbe11506cb9 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 14:48:50 +0900 Subject: [PATCH 2/9] kmc-solid: Document I/O safety in `std::os::solid::io` Mostly copied from `std::os::unix::io`, except quantifying file descriptors with SOLID Sockets and removing the paragraph mentioning `mmap`. --- library/std/src/os/solid/io.rs | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index ab17a01e4112b..6bddfc779fb44 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -1,4 +1,48 @@ //! SOLID-specific extensions to general I/O primitives +//! +//! Just like raw pointers, raw SOLID Sockets file descriptors point to +//! resources with dynamic lifetimes, and they can dangle if they outlive their +//! resources or be forged if they're created from invalid values. +//! +//! This module provides three types for representing raw file descriptors +//! with different ownership properties: raw, borrowed, and owned, which are +//! analogous to types used for representing pointers: +//! +//! | Type | Analogous to | +//! | ------------------ | ------------ | +//! | [`RawFd`] | `*const _` | +//! | [`BorrowedFd<'a>`] | `&'a _` | +//! | [`OwnedFd`] | `Box<_>` | +//! +//! Like raw pointers, `RawFd` values are primitive values. And in new code, +//! they should be considered unsafe to do I/O on (analogous to dereferencing +//! them). Rust did not always provide this guidance, so existing code in the +//! Rust ecosystem often doesn't mark `RawFd` usage as unsafe. Once the +//! `io_safety` feature is stable, libraries will be encouraged to migrate, +//! either by adding `unsafe` to APIs that dereference `RawFd` values, or by +//! using to `BorrowedFd` or `OwnedFd` instead. +//! +//! Like references, `BorrowedFd` values are tied to a lifetime, to ensure +//! that they don't outlive the resource they point to. These are safe to +//! use. `BorrowedFd` values may be used in APIs which provide safe access to +//! any system call except for: +//! +//! - `close`, because that would end the dynamic lifetime of the resource +//! without ending the lifetime of the file descriptor. +//! +//! - `dup2`/`dup3`, in the second argument, because this argument is +//! closed and assigned a new resource, which may break the assumptions +//! other code using that file descriptor. +//! +//! `BorrowedFd` values may be used in APIs which provide safe access to `dup` +//! system calls, so types implementing `AsFd` or `From` should not +//! assume they always have exclusive access to the underlying file +//! description. +//! +//! Like boxes, `OwnedFd` values conceptually own the resource they point to, +//! and free (close) it when they are dropped. +//! +//! [`BorrowedFd<'a>`]: crate::os::solid::io::BorrowedFd #![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "solid_ext", issue = "none")] From cf9c4a32f3293dc3acd2149248880d15d922c7a6 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 16:19:58 +0900 Subject: [PATCH 3/9] kmc-solid: Implement `AsFd` and conversion to/from `OwnedFd` for `{TcpStream,TcpListener,UdpSocket}` --- library/std/src/os/solid/io.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 6bddfc779fb44..67fc94830d07f 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -245,6 +245,32 @@ impl AsFd for OwnedFd { } } +macro_rules! impl_owned_fd_traits { + ($($t:ident)*) => {$( + impl AsFd for net::$t { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } + } + + impl From for OwnedFd { + #[inline] + fn from(socket: net::$t) -> OwnedFd { + unsafe { Self::from_raw_fd(socket.into_raw_fd()) } + } + } + + impl From for net::$t { + #[inline] + fn from(owned_fd: OwnedFd) -> Self { + unsafe { Self::from_raw_fd(owned_fd.into_raw_fd()) } + } + } + )*}; +} +impl_owned_fd_traits! { TcpStream TcpListener UdpSocket } + /// A trait to extract the raw SOLID Sockets file descriptor from an underlying /// object. pub trait AsRawFd { From 0dd3b25e2d96f953e5087d9405893ca777ebeaec Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 16:46:26 +0900 Subject: [PATCH 4/9] kmc-solid: Implement `AsFd` for `{Arc,Rc,Box}` --- library/std/src/os/solid/io.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 67fc94830d07f..683edc1ca8557 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -271,6 +271,39 @@ macro_rules! impl_owned_fd_traits { } impl_owned_fd_traits! { TcpStream TcpListener UdpSocket } +/// This impl allows implementing traits that require `AsFd` on Arc. +/// ``` +/// # #[cfg(target_os = "solid_asp3")] mod group_cfg { +/// # use std::os::solid::io::AsFd; +/// use std::net::UdpSocket; +/// use std::sync::Arc; +/// +/// trait MyTrait: AsFd {} +/// impl MyTrait for Arc {} +/// impl MyTrait for Box {} +/// # } +/// ``` +impl AsFd for crate::sync::Arc { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + +impl AsFd for crate::rc::Rc { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + +impl AsFd for Box { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + (**self).as_fd() + } +} + /// A trait to extract the raw SOLID Sockets file descriptor from an underlying /// object. pub trait AsRawFd { From cbfab81f3d3fe678c20ed8861fcddda98198db68 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 19:07:18 +0900 Subject: [PATCH 5/9] kmc-solid: Replace `{From,Into}Inner` impls with `*RawFd` for `Socket` Follows how other targets are implemented. --- library/std/src/os/solid/io.rs | 6 +++--- library/std/src/sys/solid/net.rs | 30 +++++++++++++----------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 683edc1ca8557..54583c73af138 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -378,7 +378,7 @@ macro_rules! impl_as_raw_fd { impl AsRawFd for net::$t { #[inline] fn as_raw_fd(&self) -> RawFd { - *self.as_inner().socket().as_inner() + self.as_inner().socket().as_raw_fd() } } )*}; @@ -391,7 +391,7 @@ macro_rules! impl_from_raw_fd { impl FromRawFd for net::$t { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::$t { - let socket = sys::net::Socket::from_inner(fd); + let socket = unsafe { sys::net::Socket::from_raw_fd(fd) }; net::$t::from_inner(sys_common::net::$t::from_inner(socket)) } } @@ -405,7 +405,7 @@ macro_rules! impl_into_raw_fd { impl IntoRawFd for net::$t { #[inline] fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() + self.into_inner().into_socket().into_raw_fd() } } )*}; diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 1eae0fc0642b4..4b25ca3028040 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -5,9 +5,10 @@ use crate::{ io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}, mem, net::{Shutdown, SocketAddr}, + os::solid::io::{AsRawFd, FromRawFd, IntoRawFd}, ptr, str, sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}, - sys_common::{AsInner, FromInner, IntoInner}, + sys_common::IntoInner, time::Duration, }; @@ -111,13 +112,6 @@ impl FileDesc { } } -impl AsInner for FileDesc { - #[inline] - fn as_inner(&self) -> &c_int { - &self.fd - } -} - impl Drop for FileDesc { fn drop(&mut self) { unsafe { netc::close(self.fd) }; @@ -454,7 +448,7 @@ impl Socket { pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_int; cvt(unsafe { - netc::ioctl(*self.as_inner(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) + netc::ioctl(self.0.raw(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) }) .map(drop) } @@ -466,25 +460,27 @@ impl Socket { // This method is used by sys_common code to abstract over targets. pub fn as_raw(&self) -> c_int { - *self.as_inner() + self.0.raw() } } -impl AsInner for Socket { +impl AsRawFd for Socket { #[inline] - fn as_inner(&self) -> &c_int { - self.0.as_inner() + fn as_raw_fd(&self) -> c_int { + self.0.fd } } -impl FromInner for Socket { - fn from_inner(fd: c_int) -> Socket { +impl FromRawFd for Socket { + #[inline] + unsafe fn from_raw_fd(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) } } -impl IntoInner for Socket { - fn into_inner(self) -> c_int { +impl IntoRawFd for Socket { + #[inline] + fn into_raw_fd(self) -> c_int { self.0.into_raw() } } From 6d1e4ddf0354e51e3520abfbd32a394f497d3f3b Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 8 Nov 2023 10:51:57 +0900 Subject: [PATCH 6/9] kmc-solid: Remove `FileDesc` Removes the private type `std::sys::solid::net::FileDesc`, replacing its only usage in `std::sys::solid::net::Socket` with `std::os::solid::io:: OwnedFd`. --- library/std/src/sys/solid/net.rs | 158 +++++++++---------------------- 1 file changed, 43 insertions(+), 115 deletions(-) diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 4b25ca3028040..1a7f9e347d06f 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -5,7 +5,7 @@ use crate::{ io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}, mem, net::{Shutdown, SocketAddr}, - os::solid::io::{AsRawFd, FromRawFd, IntoRawFd}, + os::solid::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd}, ptr, str, sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}, sys_common::IntoInner, @@ -29,95 +29,6 @@ const fn max_iov() -> usize { 1024 } -/// A file descriptor. -#[rustc_layout_scalar_valid_range_start(0)] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] -struct FileDesc { - fd: c_int, -} - -impl FileDesc { - #[inline] - fn new(fd: c_int) -> FileDesc { - assert_ne!(fd, -1i32); - // 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) - unsafe { FileDesc { fd } } - } - - #[inline] - fn raw(&self) -> c_int { - self.fd - } - - /// Extracts the actual file descriptor without closing it. - #[inline] - fn into_raw(self) -> c_int { - let fd = self.fd; - mem::forget(self); - fd - } - - fn read(&self, buf: &mut [u8]) -> io::Result { - let ret = cvt(unsafe { - netc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT)) - })?; - Ok(ret as usize) - } - - fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - let ret = cvt(unsafe { - netc::readv( - self.fd, - bufs.as_ptr() as *const netc::iovec, - cmp::min(bufs.len(), max_iov()) as c_int, - ) - })?; - Ok(ret as usize) - } - - #[inline] - fn is_read_vectored(&self) -> bool { - true - } - - fn write(&self, buf: &[u8]) -> io::Result { - let ret = cvt(unsafe { - netc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT)) - })?; - Ok(ret as usize) - } - - fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - let ret = cvt(unsafe { - netc::writev( - self.fd, - bufs.as_ptr() as *const netc::iovec, - cmp::min(bufs.len(), max_iov()) as c_int, - ) - })?; - Ok(ret as usize) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - true - } - - fn duplicate(&self) -> io::Result { - cvt(unsafe { netc::dup(self.fd) }).map(Self::new) - } -} - -impl Drop for FileDesc { - fn drop(&mut self) { - unsafe { netc::close(self.fd) }; - } -} - #[doc(hidden)] pub trait IsMinusOne { fn is_minus_one(&self) -> bool; @@ -206,7 +117,7 @@ pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { pub fn init() {} -pub struct Socket(FileDesc); +pub struct Socket(OwnedFd); impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { @@ -220,16 +131,13 @@ impl Socket { pub fn new_raw(fam: c_int, ty: c_int) -> io::Result { unsafe { let fd = cvt(netc::socket(fam, ty, 0))?; - let fd = FileDesc::new(fd); - let socket = Socket(fd); - - Ok(socket) + Ok(Self::from_raw_fd(fd)) } } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { let (addr, len) = addr.into_inner(); - cvt(unsafe { netc::connect(self.0.raw(), addr.as_ptr(), len) })?; + cvt(unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; Ok(()) } @@ -258,14 +166,14 @@ impl Socket { timeout.tv_usec = 1; } - let fds = netc::fd_set { num_fds: 1, fds: [self.0.raw()] }; + let fds = netc::fd_set { num_fds: 1, fds: [self.as_raw_fd()] }; let mut writefds = fds; let mut errorfds = fds; let n = unsafe { cvt(netc::select( - self.0.raw() + 1, + self.as_raw_fd() + 1, ptr::null_mut(), &mut writefds, &mut errorfds, @@ -288,18 +196,17 @@ impl Socket { } pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { - let fd = cvt_r(|| unsafe { netc::accept(self.0.raw(), storage, len) })?; - let fd = FileDesc::new(fd); - Ok(Socket(fd)) + let fd = cvt_r(|| unsafe { netc::accept(self.as_raw_fd(), storage, len) })?; + unsafe { Ok(Self::from_raw_fd(fd)) } } pub fn duplicate(&self) -> io::Result { - self.0.duplicate().map(Socket) + Ok(Self(self.0.try_clone()?)) } fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { let ret = cvt(unsafe { - netc::recv(self.0.raw(), buf.as_mut().as_mut_ptr().cast(), buf.capacity(), flags) + netc::recv(self.as_raw_fd(), buf.as_mut().as_mut_ptr().cast(), buf.capacity(), flags) })?; unsafe { buf.advance(ret as usize); @@ -324,12 +231,19 @@ impl Socket { } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - self.0.read_vectored(bufs) + let ret = cvt(unsafe { + netc::readv( + self.as_raw_fd(), + bufs.as_ptr() as *const netc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + ) + })?; + Ok(ret as usize) } #[inline] pub fn is_read_vectored(&self) -> bool { - self.0.is_read_vectored() + true } fn recv_from_with_flags( @@ -342,7 +256,7 @@ impl Socket { let n = cvt(unsafe { netc::recvfrom( - self.0.raw(), + self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags, @@ -362,16 +276,30 @@ impl Socket { } pub fn write(&self, buf: &[u8]) -> io::Result { - self.0.write(buf) + let ret = cvt(unsafe { + netc::write( + self.as_raw_fd(), + buf.as_ptr() as *const c_void, + cmp::min(buf.len(), READ_LIMIT), + ) + })?; + Ok(ret as usize) } pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { - self.0.write_vectored(bufs) + let ret = cvt(unsafe { + netc::writev( + self.as_raw_fd(), + bufs.as_ptr() as *const netc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + ) + })?; + Ok(ret as usize) } #[inline] pub fn is_write_vectored(&self) -> bool { - self.0.is_write_vectored() + true } pub fn set_timeout(&self, dur: Option, kind: c_int) -> io::Result<()> { @@ -417,7 +345,7 @@ impl Socket { Shutdown::Read => netc::SHUT_RD, Shutdown::Both => netc::SHUT_RDWR, }; - cvt(unsafe { netc::shutdown(self.0.raw(), how) })?; + cvt(unsafe { netc::shutdown(self.as_raw_fd(), how) })?; Ok(()) } @@ -448,7 +376,7 @@ impl Socket { pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_int; cvt(unsafe { - netc::ioctl(self.0.raw(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) + netc::ioctl(self.as_raw_fd(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) }) .map(drop) } @@ -460,27 +388,27 @@ impl Socket { // This method is used by sys_common code to abstract over targets. pub fn as_raw(&self) -> c_int { - self.0.raw() + self.as_raw_fd() } } impl AsRawFd for Socket { #[inline] fn as_raw_fd(&self) -> c_int { - self.0.fd + self.0.as_raw_fd() } } impl FromRawFd for Socket { #[inline] unsafe fn from_raw_fd(fd: c_int) -> Socket { - Socket(FileDesc::new(fd)) + unsafe { Self(FromRawFd::from_raw_fd(fd)) } } } impl IntoRawFd for Socket { #[inline] fn into_raw_fd(self) -> c_int { - self.0.into_raw() + self.0.into_raw_fd() } } From 46bc247bd145f3357acb07b7f146ec9514e0a193 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 19:06:43 +0900 Subject: [PATCH 7/9] kmc-solid: Implement `{From,Into}Inner` for `Socket` --- library/std/src/sys/solid/net.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 1a7f9e347d06f..a768e2406c8a8 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -5,10 +5,10 @@ use crate::{ io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}, mem, net::{Shutdown, SocketAddr}, - os::solid::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd}, + os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd}, ptr, str, sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}, - sys_common::IntoInner, + sys_common::{FromInner, IntoInner}, time::Duration, }; @@ -392,6 +392,27 @@ impl Socket { } } +impl FromInner for Socket { + #[inline] + fn from_inner(sock: OwnedFd) -> Socket { + Socket(sock) + } +} + +impl IntoInner for Socket { + #[inline] + fn into_inner(self) -> OwnedFd { + self.0 + } +} + +impl AsFd for Socket { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + impl AsRawFd for Socket { #[inline] fn as_raw_fd(&self) -> c_int { From c8c3339133fb25b0e059e076fb499708df39c669 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Wed, 23 Aug 2023 18:41:26 +0900 Subject: [PATCH 8/9] kmc-solid: Reimplement `AsFd` etc for `{TcpStream,TcpListener,UdpSocket}` by delegating to inner `Socket` Removes some `unsafe` blocks. --- library/std/src/os/solid/io.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 54583c73af138..19b4fe22093c3 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -250,21 +250,21 @@ macro_rules! impl_owned_fd_traits { impl AsFd for net::$t { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + self.as_inner().socket().as_fd() } } impl From for OwnedFd { #[inline] fn from(socket: net::$t) -> OwnedFd { - unsafe { Self::from_raw_fd(socket.into_raw_fd()) } + socket.into_inner().into_socket().into_inner() } } impl From for net::$t { #[inline] fn from(owned_fd: OwnedFd) -> Self { - unsafe { Self::from_raw_fd(owned_fd.into_raw_fd()) } + Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned_fd))) } } )*}; From 52eb92de37353737b6b9269922b7bc4c9ddddf73 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Thu, 24 Aug 2023 11:33:08 +0900 Subject: [PATCH 9/9] kmc-solid: Re-export `{As,Borrowed,Owned}Fd` in `std::os::solid::prelude` --- library/std/src/os/solid/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/solid/mod.rs b/library/std/src/os/solid/mod.rs index 4328ba7c34022..0bb83c73ddf7c 100644 --- a/library/std/src/os/solid/mod.rs +++ b/library/std/src/os/solid/mod.rs @@ -13,5 +13,5 @@ pub mod prelude { pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + pub use super::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; }