mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Auto merge of #87329 - sunfishcode:sunfishcode/io-safety, r=joshtriplett
I/O safety. Introduce `OwnedFd` and `BorrowedFd`, and the `AsFd` trait, and implementations of `AsFd`, `From<OwnedFd>` and `From<T> for OwnedFd` for relevant types, along with Windows counterparts for handles and sockets. Tracking issue: <https://github.com/rust-lang/rust/issues/87074> RFC: <https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md> Highlights: - The doc comments at the top of library/std/src/os/unix/io/mod.rs and library/std/src/os/windows/io/mod.rs - The new types and traits in library/std/src/os/unix/io/fd.rs and library/std/src/os/windows/io/handle.rs - The removal of the `RawHandle` struct the Windows impl, which had the same name as the `RawHandle` type alias, and its functionality is now folded into `Handle`. Managing five levels of wrapping (File wraps sys::fs::File wraps sys::fs::FileDesc wraps OwnedFd wraps RawFd, etc.) made for a fair amount of churn and verbose as/into/from sequences in some places. I've managed to simplify some of them, but I'm open to ideas here. r? `@joshtriplett`
This commit is contained in:
commit
521734787e
@ -587,6 +587,12 @@ impl File {
|
||||
}
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `File` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
||||
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
||||
|
||||
impl AsInner<fs_imp::File> for File {
|
||||
fn as_inner(&self) -> &fs_imp::File {
|
||||
&self.inner
|
||||
|
@ -546,6 +546,12 @@ impl TcpStream {
|
||||
}
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `TcpStream` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsSocket`/`From<OwnedSocket>`/`Into<OwnedSocket>` and
|
||||
// `AsRawSocket`/`IntoRawSocket`/`FromRawSocket` on Windows.
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Read for TcpStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
@ -915,6 +921,12 @@ impl TcpListener {
|
||||
}
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `TcpListener` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsSocket`/`From<OwnedSocket>`/`Into<OwnedSocket>` and
|
||||
// `AsRawSocket`/`IntoRawSocket`/`FromRawSocket` on Windows.
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a> Iterator for Incoming<'a> {
|
||||
type Item = io::Result<TcpStream>;
|
||||
|
@ -779,6 +779,12 @@ impl UdpSocket {
|
||||
}
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `UdpSocket` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsSocket`/`From<OwnedSocket>`/`Into<OwnedSocket>` and
|
||||
// `AsRawSocket`/`IntoRawSocket`/`FromRawSocket` on Windows.
|
||||
|
||||
impl AsInner<net_imp::UdpSocket> for UdpSocket {
|
||||
fn as_inner(&self) -> &net_imp::UdpSocket {
|
||||
&self.0
|
||||
|
@ -2,7 +2,6 @@ use crate::io::ErrorKind;
|
||||
use crate::net::test::{next_test_ip4, next_test_ip6};
|
||||
use crate::net::*;
|
||||
use crate::sync::mpsc::channel;
|
||||
use crate::sys_common::AsInner;
|
||||
use crate::thread;
|
||||
use crate::time::{Duration, Instant};
|
||||
|
||||
@ -173,7 +172,7 @@ fn debug() {
|
||||
let socket_addr = next_test_ip4();
|
||||
|
||||
let udpsock = t!(UdpSocket::bind(&socket_addr));
|
||||
let udpsock_inner = udpsock.0.socket().as_inner();
|
||||
let udpsock_inner = udpsock.0.socket().as_raw();
|
||||
let compare = format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", socket_addr, name, udpsock_inner);
|
||||
assert_eq!(format!("{:?}", udpsock), compare);
|
||||
}
|
||||
|
13
library/std/src/os/fd/mod.rs
Normal file
13
library/std/src/os/fd/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
//! Owned and borrowed Unix-like file descriptors.
|
||||
|
||||
#![unstable(feature = "io_safety", issue = "87074")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
// `RawFd`, `AsRawFd`, etc.
|
||||
pub mod raw;
|
||||
|
||||
// `OwnedFd`, `AsFd`, etc.
|
||||
pub mod owned;
|
||||
|
||||
// Implementations for `AsRawFd` etc. for network types.
|
||||
mod net;
|
@ -1,4 +1,5 @@
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::os::fd::owned::OwnedFd;
|
||||
use crate::os::fd::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
|
||||
use crate::{net, sys};
|
||||
|
||||
@ -8,7 +9,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()
|
||||
}
|
||||
}
|
||||
)*};
|
||||
@ -21,8 +22,10 @@ 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);
|
||||
net::$t::from_inner(sys_common::net::$t::from_inner(socket))
|
||||
unsafe {
|
||||
let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd)));
|
||||
net::$t::from_inner(sys_common::net::$t::from_inner(socket))
|
||||
}
|
||||
}
|
||||
}
|
||||
)*};
|
||||
@ -35,7 +38,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_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
)*};
|
289
library/std/src/os/fd/owned.rs
Normal file
289
library/std/src/os/fd/owned.rs
Normal file
@ -0,0 +1,289 @@
|
||||
//! Owned and borrowed Unix-like file descriptors.
|
||||
|
||||
#![unstable(feature = "io_safety", issue = "87074")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::fmt;
|
||||
use crate::fs;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::mem::forget;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
/// A borrowed file descriptor.
|
||||
///
|
||||
/// This has a lifetime parameter to tie it to the lifetime of something that
|
||||
/// owns the file descriptor.
|
||||
///
|
||||
/// This uses `repr(transparent)` and has the representation of a host file
|
||||
/// descriptor, so it can be used in FFI in places where a file descriptor is
|
||||
/// passed as an argument, it is not captured or consumed, and it never has the
|
||||
/// value `-1`.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[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)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub struct BorrowedFd<'fd> {
|
||||
fd: RawFd,
|
||||
_phantom: PhantomData<&'fd OwnedFd>,
|
||||
}
|
||||
|
||||
/// An owned 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 file descriptor is
|
||||
/// passed as a consumed argument or returned as an owned value, and it never
|
||||
/// has the value `-1`.
|
||||
#[repr(transparent)]
|
||||
#[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)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
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 `-1`.
|
||||
#[inline]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub unsafe fn borrow_raw_fd(fd: RawFd) -> Self {
|
||||
assert_ne!(fd, u32::MAX 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 } }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsRawFd for BorrowedFd<'_> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl IntoRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
let fd = self.fd;
|
||||
forget(self);
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
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, u32::MAX 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 } }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl Drop for OwnedFd {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Note that errors are ignored when closing a file descriptor. The
|
||||
// reason for this is that if an error occurs we don't actually know if
|
||||
// the file descriptor was closed or not, and if we retried (for
|
||||
// something like EINTR), we might close another valid file descriptor
|
||||
// opened after we closed ours.
|
||||
let _ = libc::close(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl fmt::Debug for BorrowedFd<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl fmt::Debug for OwnedFd {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to borrow the file descriptor from an underlying object.
|
||||
///
|
||||
/// This is only available on unix platforms and must be imported in order to
|
||||
/// call the method. Windows platforms have a corresponding `AsHandle` and
|
||||
/// `AsSocket` set of traits.
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub trait AsFd {
|
||||
/// Borrows the file descriptor.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # #![feature(io_safety)]
|
||||
/// use std::fs::File;
|
||||
/// # use std::io;
|
||||
/// # #[cfg(target_os = "wasi")]
|
||||
/// # use std::os::wasi::io::{AsFd, BorrowedFd};
|
||||
/// # #[cfg(unix)]
|
||||
/// # use std::os::unix::io::{AsFd, BorrowedFd};
|
||||
///
|
||||
/// let mut f = File::open("foo.txt")?;
|
||||
/// # #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
|
||||
/// # Ok::<(), io::Error>(())
|
||||
/// ```
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
fn as_fd(&self) -> BorrowedFd<'_>;
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for BorrowedFd<'_> {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for OwnedFd {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
// Safety: `OwnedFd` and `BorrowedFd` have the same validity
|
||||
// invariants, and the `BorrowdFd` is bounded by the lifetime
|
||||
// of `&self`.
|
||||
unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for fs::File {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<fs::File> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(file: fs::File) -> OwnedFd {
|
||||
file.into_inner().into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for fs::File {
|
||||
#[inline]
|
||||
fn from(owned_fd: OwnedFd) -> Self {
|
||||
Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned_fd)))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for crate::net::TcpStream {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().socket().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<crate::net::TcpStream> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(tcp_stream: crate::net::TcpStream) -> OwnedFd {
|
||||
tcp_stream.into_inner().into_socket().into_inner().into_inner().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for crate::net::TcpStream {
|
||||
#[inline]
|
||||
fn from(owned_fd: OwnedFd) -> Self {
|
||||
Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
|
||||
owned_fd,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for crate::net::TcpListener {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().socket().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<crate::net::TcpListener> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(tcp_listener: crate::net::TcpListener) -> OwnedFd {
|
||||
tcp_listener.into_inner().into_socket().into_inner().into_inner().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for crate::net::TcpListener {
|
||||
#[inline]
|
||||
fn from(owned_fd: OwnedFd) -> Self {
|
||||
Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
|
||||
owned_fd,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for crate::net::UdpSocket {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().socket().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<crate::net::UdpSocket> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(udp_socket: crate::net::UdpSocket) -> OwnedFd {
|
||||
udp_socket.into_inner().into_socket().into_inner().into_inner().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for crate::net::UdpSocket {
|
||||
#[inline]
|
||||
fn from(owned_fd: OwnedFd) -> Self {
|
||||
Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
|
||||
owned_fd,
|
||||
))))
|
||||
}
|
||||
}
|
@ -1,23 +1,25 @@
|
||||
//! Unix-specific extensions to general I/O primitives.
|
||||
//! Raw Unix-like file descriptors.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::fs;
|
||||
use crate::io;
|
||||
use crate::os::raw;
|
||||
use crate::sys;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
#[cfg(unix)]
|
||||
use crate::os::unix::io::OwnedFd;
|
||||
#[cfg(target_os = "wasi")]
|
||||
use crate::os::wasi::io::OwnedFd;
|
||||
use crate::sys_common::{AsInner, IntoInner};
|
||||
|
||||
/// Raw file descriptors.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub type RawFd = raw::c_int;
|
||||
|
||||
/// A trait to extract the raw unix file descriptor from an underlying
|
||||
/// object.
|
||||
/// A trait to extract the raw file descriptor from an underlying object.
|
||||
///
|
||||
/// This is only available on unix platforms and must be imported in order
|
||||
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
|
||||
/// and `AsRawSocket` set of traits.
|
||||
/// This is only available on unix and WASI platforms and must be imported in
|
||||
/// order to call the method. Windows platforms have a corresponding
|
||||
/// `AsRawHandle` and `AsRawSocket` set of traits.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRawFd {
|
||||
/// Extracts the raw file descriptor.
|
||||
@ -31,10 +33,14 @@ pub trait AsRawFd {
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// # use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::{AsRawFd, RawFd};
|
||||
/// #[cfg(target_os = "wasi")]
|
||||
/// use std::os::wasi::io::{AsRawFd, RawFd};
|
||||
///
|
||||
/// let mut f = File::open("foo.txt")?;
|
||||
/// // Note that `raw_fd` is only valid as long as `f` exists.
|
||||
/// #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// let raw_fd: RawFd = f.as_raw_fd();
|
||||
/// # Ok::<(), io::Error>(())
|
||||
/// ```
|
||||
@ -64,12 +70,17 @@ pub trait FromRawFd {
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// # use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
|
||||
/// #[cfg(target_os = "wasi")]
|
||||
/// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd};
|
||||
///
|
||||
/// let f = File::open("foo.txt")?;
|
||||
/// # #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// let raw_fd: RawFd = f.into_raw_fd();
|
||||
/// // SAFETY: no other functions should call `from_raw_fd`, so there
|
||||
/// // is only one owner for the file descriptor.
|
||||
/// # #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// let f = unsafe { File::from_raw_fd(raw_fd) };
|
||||
/// # Ok::<(), io::Error>(())
|
||||
/// ```
|
||||
@ -92,9 +103,13 @@ pub trait IntoRawFd {
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// # use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::{IntoRawFd, RawFd};
|
||||
/// #[cfg(target_os = "wasi")]
|
||||
/// use std::os::wasi::io::{IntoRawFd, RawFd};
|
||||
///
|
||||
/// let f = File::open("foo.txt")?;
|
||||
/// #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// let raw_fd: RawFd = f.into_raw_fd();
|
||||
/// # Ok::<(), io::Error>(())
|
||||
/// ```
|
||||
@ -128,21 +143,21 @@ impl FromRawFd for RawFd {
|
||||
impl AsRawFd for fs::File {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().raw()
|
||||
self.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "from_raw_os", since = "1.1.0")]
|
||||
impl FromRawFd for fs::File {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
|
||||
fs::File::from_inner(sys::fs::File::from_inner(fd))
|
||||
unsafe { fs::File::from(OwnedFd::from_raw_fd(fd)) }
|
||||
}
|
||||
}
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawFd for fs::File {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
self.into_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![unstable(feature = "linux_pidfd", issue = "82971")]
|
||||
|
||||
use crate::io::Result;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::process;
|
||||
use crate::sealed::Sealed;
|
||||
#[cfg(not(doc))]
|
||||
@ -69,19 +69,37 @@ impl IntoInner<FileDesc> for PidFd {
|
||||
|
||||
impl AsRawFd for PidFd {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().raw()
|
||||
self.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for PidFd {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
Self::from_inner(FileDesc::new(fd))
|
||||
Self::from_inner(FileDesc::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for PidFd {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_raw()
|
||||
self.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for PidFd {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for PidFd {
|
||||
fn from(fd: OwnedFd) -> Self {
|
||||
Self::from_inner(FileDesc::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PidFd> for OwnedFd {
|
||||
fn from(pid_fd: PidFd) -> Self {
|
||||
pid_fd.into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,3 +121,6 @@ mod imp {
|
||||
#[cfg(not(doc))]
|
||||
#[stable(feature = "os", since = "1.0.0")]
|
||||
pub use imp::*;
|
||||
|
||||
#[cfg(any(unix, target_os = "wasi", doc))]
|
||||
mod fd;
|
||||
|
9
library/std/src/os/unix/io/fd.rs
Normal file
9
library/std/src/os/unix/io/fd.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//! Owned and borrowed file descriptors.
|
||||
|
||||
#![unstable(feature = "io_safety", issue = "87074")]
|
||||
|
||||
// Tests for this module
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use crate::os::fd::owned::*;
|
11
library/std/src/os/unix/io/fd/tests.rs
Normal file
11
library/std/src/os/unix/io/fd/tests.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::mem::size_of;
|
||||
use crate::os::unix::io::RawFd;
|
||||
|
||||
#[test]
|
||||
fn test_raw_fd_layout() {
|
||||
// `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start`
|
||||
// and `rustc_layout_scalar_valid_range_end`, with values that depend on
|
||||
// the bit width of `RawFd`. If this ever changes, those values will need
|
||||
// to be updated.
|
||||
assert_eq!(size_of::<RawFd>(), 4);
|
||||
}
|
57
library/std/src/os/unix/io/mod.rs
Normal file
57
library/std/src/os/unix/io/mod.rs
Normal file
@ -0,0 +1,57 @@
|
||||
//! Unix-specific extensions to general I/O primitives.
|
||||
//!
|
||||
//! Just like raw pointers, raw 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 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.
|
||||
//! This list doesn't include `mmap`, since `mmap` does do a proper borrow of
|
||||
//! its file descriptor argument. That said, `mmap` is unsafe for other
|
||||
//! reasons: it operates on raw pointers, and it can have undefined behavior if
|
||||
//! the underlying storage is mutated. Mutations may come from other processes,
|
||||
//! or from the same process if the API provides `BorrowedFd` access, since as
|
||||
//! mentioned earlier, `BorrowedFd` values may be used in APIs which provide
|
||||
//! safe access to any system call. Consequently, code using `mmap` and
|
||||
//! presenting a safe API must take full responsibility for ensuring that safe
|
||||
//! Rust code cannot evoke undefined behavior through it.
|
||||
//!
|
||||
//! Like boxes, `OwnedFd` values conceptually own the resource they point to,
|
||||
//! and free (close) it when they are dropped.
|
||||
//!
|
||||
//! [`BorrowedFd<'a>`]: crate::os::unix::io::BorrowedFd
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
mod fd;
|
||||
mod raw;
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub use fd::*;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use raw::*;
|
5
library/std/src/os/unix/io/raw.rs
Normal file
5
library/std/src/os/unix/io/raw.rs
Normal file
@ -0,0 +1,5 @@
|
||||
//! Unix-specific extensions to general I/O primitives.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
pub use crate::os::fd::raw::*;
|
@ -108,7 +108,7 @@ pub mod prelude {
|
||||
pub use super::fs::{FileTypeExt, MetadataExt, OpenOptionsExt, PermissionsExt};
|
||||
#[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};
|
||||
#[doc(no_inline)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::process::{CommandExt, ExitStatusExt};
|
||||
|
@ -21,7 +21,7 @@ use super::{sockaddr_un, SocketAddr};
|
||||
))]
|
||||
use crate::io::{IoSlice, IoSliceMut};
|
||||
use crate::net::Shutdown;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::path::Path;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys::net::Socket;
|
||||
@ -106,7 +106,7 @@ impl UnixDatagram {
|
||||
let socket = UnixDatagram::unbound()?;
|
||||
let (addr, len) = sockaddr_un(path.as_ref())?;
|
||||
|
||||
cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
|
||||
cvt(libc::bind(socket.as_raw_fd(), &addr as *const _ as *const _, len as _))?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
@ -187,7 +187,7 @@ impl UnixDatagram {
|
||||
unsafe {
|
||||
let (addr, len) = sockaddr_un(path.as_ref())?;
|
||||
|
||||
cvt(libc::connect(*self.0.as_inner(), &addr as *const _ as *const _, len))?;
|
||||
cvt(libc::connect(self.as_raw_fd(), &addr as *const _ as *const _, len))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -229,7 +229,7 @@ impl UnixDatagram {
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.as_raw_fd(), addr, len) })
|
||||
}
|
||||
|
||||
/// Returns the address of this socket's peer.
|
||||
@ -253,7 +253,7 @@ impl UnixDatagram {
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getpeername(self.as_raw_fd(), addr, len) })
|
||||
}
|
||||
|
||||
fn recv_from_flags(
|
||||
@ -264,7 +264,7 @@ impl UnixDatagram {
|
||||
let mut count = 0;
|
||||
let addr = SocketAddr::new(|addr, len| unsafe {
|
||||
count = libc::recvfrom(
|
||||
*self.0.as_inner(),
|
||||
self.as_raw_fd(),
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
buf.len(),
|
||||
flags,
|
||||
@ -462,7 +462,7 @@ impl UnixDatagram {
|
||||
let (addr, len) = sockaddr_un(path.as_ref())?;
|
||||
|
||||
let count = cvt(libc::sendto(
|
||||
*self.0.as_inner(),
|
||||
self.as_raw_fd(),
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
MSG_NOSIGNAL,
|
||||
@ -881,7 +881,7 @@ impl UnixDatagram {
|
||||
impl AsRawFd for UnixDatagram {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
*self.0.as_inner()
|
||||
self.0.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -889,7 +889,7 @@ impl AsRawFd for UnixDatagram {
|
||||
impl FromRawFd for UnixDatagram {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
|
||||
UnixDatagram(Socket::from_inner(fd))
|
||||
UnixDatagram(Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,6 +897,30 @@ impl FromRawFd for UnixDatagram {
|
||||
impl IntoRawFd for UnixDatagram {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_inner()
|
||||
self.0.into_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for UnixDatagram {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_inner().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<UnixDatagram> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(unix_datagram: UnixDatagram) -> OwnedFd {
|
||||
unsafe { OwnedFd::from_raw_fd(unix_datagram.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for UnixDatagram {
|
||||
#[inline]
|
||||
fn from(owned: OwnedFd) -> Self {
|
||||
unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{sockaddr_un, SocketAddr, UnixStream};
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::path::Path;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys::net::Socket;
|
||||
@ -74,8 +74,8 @@ impl UnixListener {
|
||||
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
let (addr, len) = sockaddr_un(path.as_ref())?;
|
||||
|
||||
cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
|
||||
cvt(libc::listen(*inner.as_inner(), 128))?;
|
||||
cvt(libc::bind(inner.as_inner().as_raw_fd(), &addr as *const _ as *const _, len as _))?;
|
||||
cvt(libc::listen(inner.as_inner().as_raw_fd(), 128))?;
|
||||
|
||||
Ok(UnixListener(inner))
|
||||
}
|
||||
@ -150,7 +150,7 @@ impl UnixListener {
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.as_raw_fd(), addr, len) })
|
||||
}
|
||||
|
||||
/// Moves the socket into or out of nonblocking mode.
|
||||
@ -242,7 +242,7 @@ impl UnixListener {
|
||||
impl AsRawFd for UnixListener {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
*self.0.as_inner()
|
||||
self.0.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ impl AsRawFd for UnixListener {
|
||||
impl FromRawFd for UnixListener {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
|
||||
UnixListener(Socket::from_inner(fd))
|
||||
UnixListener(Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ impl FromRawFd for UnixListener {
|
||||
impl IntoRawFd for UnixListener {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_inner()
|
||||
self.0.into_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@ mod addr;
|
||||
mod ancillary;
|
||||
mod datagram;
|
||||
mod listener;
|
||||
mod raw_fd;
|
||||
mod stream;
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests;
|
||||
@ -48,7 +47,5 @@ pub use self::ancillary::*;
|
||||
pub use self::datagram::*;
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub use self::listener::*;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::raw_fd::*;
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub use self::stream::*;
|
||||
|
@ -13,7 +13,7 @@ use super::{sockaddr_un, SocketAddr};
|
||||
use crate::fmt;
|
||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut};
|
||||
use crate::net::Shutdown;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
@ -28,7 +28,7 @@ use crate::os::unix::ucred;
|
||||
use crate::path::Path;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys::net::Socket;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
use crate::sys_common::{AsInner, FromInner};
|
||||
use crate::time::Duration;
|
||||
|
||||
#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
|
||||
@ -101,7 +101,7 @@ impl UnixStream {
|
||||
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
let (addr, len) = sockaddr_un(path.as_ref())?;
|
||||
|
||||
cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?;
|
||||
cvt(libc::connect(inner.as_raw_fd(), &addr as *const _ as *const _, len))?;
|
||||
Ok(UnixStream(inner))
|
||||
}
|
||||
}
|
||||
@ -167,7 +167,7 @@ impl UnixStream {
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getsockname(self.as_raw_fd(), addr, len) })
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote half of this connection.
|
||||
@ -185,7 +185,7 @@ impl UnixStream {
|
||||
/// ```
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
|
||||
SocketAddr::new(|addr, len| unsafe { libc::getpeername(self.as_raw_fd(), addr, len) })
|
||||
}
|
||||
|
||||
/// Gets the peer credentials for this Unix domain socket.
|
||||
@ -659,7 +659,7 @@ impl<'a> io::Write for &'a UnixStream {
|
||||
impl AsRawFd for UnixStream {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
*self.0.as_inner()
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -667,7 +667,7 @@ impl AsRawFd for UnixStream {
|
||||
impl FromRawFd for UnixStream {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
|
||||
UnixStream(Socket::from_inner(fd))
|
||||
UnixStream(Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,6 +675,30 @@ impl FromRawFd for UnixStream {
|
||||
impl IntoRawFd for UnixStream {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_inner()
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for UnixStream {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<UnixStream> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(unix_stream: UnixStream) -> OwnedFd {
|
||||
unsafe { OwnedFd::from_raw_fd(unix_stream.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for UnixStream {
|
||||
#[inline]
|
||||
fn from(owned: OwnedFd) -> Self {
|
||||
unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use crate::ffi::OsStr;
|
||||
use crate::io;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::process;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys;
|
||||
@ -321,7 +321,17 @@ impl ExitStatusExt for process::ExitStatusError {
|
||||
impl FromRawFd for process::Stdio {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
|
||||
let fd = sys::fd::FileDesc::new(fd);
|
||||
let fd = sys::fd::FileDesc::from_raw_fd(fd);
|
||||
let io = sys::process::Stdio::Fd(fd);
|
||||
process::Stdio::from_inner(io)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedFd> for process::Stdio {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::Stdio {
|
||||
let fd = sys::fd::FileDesc::from_inner(fd);
|
||||
let io = sys::process::Stdio::Fd(fd);
|
||||
process::Stdio::from_inner(io)
|
||||
}
|
||||
@ -331,7 +341,7 @@ impl FromRawFd for process::Stdio {
|
||||
impl AsRawFd for process::ChildStdin {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().raw()
|
||||
self.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,7 +349,7 @@ impl AsRawFd for process::ChildStdin {
|
||||
impl AsRawFd for process::ChildStdout {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().raw()
|
||||
self.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,7 +357,7 @@ impl AsRawFd for process::ChildStdout {
|
||||
impl AsRawFd for process::ChildStderr {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().raw()
|
||||
self.as_inner().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,7 +365,7 @@ impl AsRawFd for process::ChildStderr {
|
||||
impl IntoRawFd for process::ChildStdin {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
self.into_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,7 +373,7 @@ impl IntoRawFd for process::ChildStdin {
|
||||
impl IntoRawFd for process::ChildStdout {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
self.into_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,7 +381,55 @@ impl IntoRawFd for process::ChildStdout {
|
||||
impl IntoRawFd for process::ChildStderr {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
self.into_inner().into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for crate::process::ChildStdin {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<crate::process::ChildStdin> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
|
||||
child_stdin.into_inner().into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for crate::process::ChildStdout {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<crate::process::ChildStdout> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
|
||||
child_stdout.into_inner().into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for crate::process::ChildStderr {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.as_inner().as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<crate::process::ChildStderr> for OwnedFd {
|
||||
#[inline]
|
||||
fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
|
||||
child_stderr.into_inner().into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,35 +228,35 @@ pub trait FileExt {
|
||||
|
||||
impl FileExt for fs::File {
|
||||
fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||
self.as_inner().fd().pread(bufs, offset)
|
||||
self.as_inner().as_inner().pread(bufs, offset)
|
||||
}
|
||||
|
||||
fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||
self.as_inner().fd().pwrite(bufs, offset)
|
||||
self.as_inner().as_inner().pwrite(bufs, offset)
|
||||
}
|
||||
|
||||
fn tell(&self) -> io::Result<u64> {
|
||||
self.as_inner().fd().tell()
|
||||
self.as_inner().as_inner().tell()
|
||||
}
|
||||
|
||||
fn fdstat_set_flags(&self, flags: u16) -> io::Result<()> {
|
||||
self.as_inner().fd().set_flags(flags)
|
||||
self.as_inner().as_inner().set_flags(flags)
|
||||
}
|
||||
|
||||
fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()> {
|
||||
self.as_inner().fd().set_rights(rights, inheriting)
|
||||
self.as_inner().as_inner().set_rights(rights, inheriting)
|
||||
}
|
||||
|
||||
fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()> {
|
||||
self.as_inner().fd().advise(offset, len, advice)
|
||||
self.as_inner().as_inner().advise(offset, len, advice)
|
||||
}
|
||||
|
||||
fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
|
||||
self.as_inner().fd().allocate(offset, len)
|
||||
self.as_inner().as_inner().allocate(offset, len)
|
||||
}
|
||||
|
||||
fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()> {
|
||||
self.as_inner().fd().create_directory(osstr2str(dir.as_ref().as_ref())?)
|
||||
self.as_inner().as_inner().create_directory(osstr2str(dir.as_ref().as_ref())?)
|
||||
}
|
||||
|
||||
fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
|
||||
@ -269,11 +269,11 @@ impl FileExt for fs::File {
|
||||
}
|
||||
|
||||
fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
self.as_inner().fd().unlink_file(osstr2str(path.as_ref().as_ref())?)
|
||||
self.as_inner().as_inner().unlink_file(osstr2str(path.as_ref().as_ref())?)
|
||||
}
|
||||
|
||||
fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
self.as_inner().fd().remove_directory(osstr2str(path.as_ref().as_ref())?)
|
||||
self.as_inner().as_inner().remove_directory(osstr2str(path.as_ref().as_ref())?)
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,10 +486,10 @@ pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
|
||||
new_fd: &File,
|
||||
new_path: U,
|
||||
) -> io::Result<()> {
|
||||
old_fd.as_inner().fd().link(
|
||||
old_fd.as_inner().as_inner().link(
|
||||
old_flags,
|
||||
osstr2str(old_path.as_ref().as_ref())?,
|
||||
new_fd.as_inner().fd(),
|
||||
new_fd.as_inner().as_inner(),
|
||||
osstr2str(new_path.as_ref().as_ref())?,
|
||||
)
|
||||
}
|
||||
@ -503,9 +503,9 @@ pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
|
||||
new_fd: &File,
|
||||
new_path: U,
|
||||
) -> io::Result<()> {
|
||||
old_fd.as_inner().fd().rename(
|
||||
old_fd.as_inner().as_inner().rename(
|
||||
osstr2str(old_path.as_ref().as_ref())?,
|
||||
new_fd.as_inner().fd(),
|
||||
new_fd.as_inner().as_inner(),
|
||||
osstr2str(new_path.as_ref().as_ref())?,
|
||||
)
|
||||
}
|
||||
@ -519,7 +519,7 @@ pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
|
||||
new_path: U,
|
||||
) -> io::Result<()> {
|
||||
fd.as_inner()
|
||||
.fd()
|
||||
.as_inner()
|
||||
.symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?)
|
||||
}
|
||||
|
||||
|
@ -1,208 +0,0 @@
|
||||
//! WASI-specific extensions to general I/O primitives
|
||||
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![unstable(feature = "wasi_ext", issue = "71213")]
|
||||
|
||||
use crate::fs;
|
||||
use crate::io;
|
||||
use crate::net;
|
||||
use crate::os::raw;
|
||||
use crate::sys;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
/// Raw file descriptors.
|
||||
///
|
||||
/// This has type `c_int` to ease compatibility with code that also compiles on
|
||||
/// Unix configurations, however unlike Unix and POSIX, in WASI negative file
|
||||
/// descriptors are valid. Only `-1` is reserved for indicating errors. Code
|
||||
/// intending to be portable across Unix platforms and WASI should avoid
|
||||
/// assuming that negative file descriptors are invalid.
|
||||
pub type RawFd = raw::c_int;
|
||||
|
||||
/// A trait to extract the raw WASI file descriptor from an underlying
|
||||
/// object.
|
||||
pub trait AsRawFd {
|
||||
/// Extracts the raw file descriptor.
|
||||
///
|
||||
/// This method does **not** pass ownership of the raw file descriptor
|
||||
/// to the caller. The descriptor is only guaranteed to be valid while
|
||||
/// the original object has not yet been destroyed.
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to construct an object from a raw file
|
||||
/// descriptor.
|
||||
pub trait FromRawFd {
|
||||
/// Constructs a new instance of `Self` from the given raw file
|
||||
/// descriptor.
|
||||
///
|
||||
/// This function **consumes ownership** of the specified file
|
||||
/// descriptor. The returned object will take responsibility for closing
|
||||
/// it when the object goes out of scope.
|
||||
///
|
||||
/// This function is also unsafe as the primitives currently returned
|
||||
/// have the contract that they are the sole owner of the file
|
||||
/// descriptor they are wrapping. Usage of this function could
|
||||
/// accidentally allow violating this contract which can cause memory
|
||||
/// unsafety in code that relies on it being true.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self;
|
||||
}
|
||||
|
||||
/// A trait to express the ability to consume an object and acquire ownership of
|
||||
/// its raw file descriptor.
|
||||
pub trait IntoRawFd {
|
||||
/// Consumes this object, returning the raw underlying file descriptor.
|
||||
///
|
||||
/// This function **transfers ownership** of the underlying file descriptor
|
||||
/// to the caller. Callers are then the unique owners of the file descriptor
|
||||
/// and must close the descriptor once it's no longer needed.
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
|
||||
#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")]
|
||||
impl AsRawFd for RawFd {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")]
|
||||
impl IntoRawFd for RawFd {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self
|
||||
}
|
||||
}
|
||||
#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")]
|
||||
impl FromRawFd for RawFd {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> RawFd {
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for net::TcpStream {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for net::TcpStream {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
|
||||
net::TcpStream::from_inner(sys::net::TcpStream::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for net::TcpStream {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for net::TcpListener {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for net::TcpListener {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
|
||||
net::TcpListener::from_inner(sys::net::TcpListener::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for net::TcpListener {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for net::UdpSocket {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for net::UdpSocket {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
|
||||
net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for net::UdpSocket {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for fs::File {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_inner().fd().as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for fs::File {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
|
||||
fs::File::from_inner(sys::fs::File::from_inner(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for fs::File {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_inner().into_fd().into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for io::Stdin {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDIN_FILENO
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for io::Stdout {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDOUT_FILENO
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for io::Stderr {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDERR_FILENO
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRawFd for io::StdinLock<'a> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDIN_FILENO
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRawFd for io::StdoutLock<'a> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDOUT_FILENO
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRawFd for io::StderrLock<'a> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDERR_FILENO
|
||||
}
|
||||
}
|
9
library/std/src/os/wasi/io/fd.rs
Normal file
9
library/std/src/os/wasi/io/fd.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//! Owned and borrowed file descriptors.
|
||||
|
||||
#![unstable(feature = "wasi_ext", issue = "71213")]
|
||||
|
||||
// Tests for this module
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use crate::os::fd::owned::*;
|
11
library/std/src/os/wasi/io/fd/tests.rs
Normal file
11
library/std/src/os/wasi/io/fd/tests.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use crate::mem::size_of;
|
||||
use crate::os::wasi::io::RawFd;
|
||||
|
||||
#[test]
|
||||
fn test_raw_fd_layout() {
|
||||
// `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start`
|
||||
// and `rustc_layout_scalar_valid_range_end`, with values that depend on
|
||||
// the bit width of `RawFd`. If this ever changes, those values will need
|
||||
// to be updated.
|
||||
assert_eq!(size_of::<RawFd>(), 4);
|
||||
}
|
12
library/std/src/os/wasi/io/mod.rs
Normal file
12
library/std/src/os/wasi/io/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//! WASI-specific extensions to general I/O primitives.
|
||||
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![unstable(feature = "wasi_ext", issue = "71213")]
|
||||
|
||||
mod fd;
|
||||
mod raw;
|
||||
|
||||
#[unstable(feature = "wasi_ext", issue = "71213")]
|
||||
pub use fd::*;
|
||||
#[unstable(feature = "wasi_ext", issue = "71213")]
|
||||
pub use raw::*;
|
5
library/std/src/os/wasi/io/raw.rs
Normal file
5
library/std/src/os/wasi/io/raw.rs
Normal file
@ -0,0 +1,5 @@
|
||||
//! WASI-specific extensions to general I/O primitives.
|
||||
|
||||
#![unstable(feature = "wasi_ext", issue = "71213")]
|
||||
|
||||
pub use crate::os::fd::raw::*;
|
@ -32,6 +32,7 @@
|
||||
pub mod ffi;
|
||||
pub mod fs;
|
||||
pub mod io;
|
||||
pub mod net;
|
||||
|
||||
/// A prelude for conveniently writing platform-specific code.
|
||||
///
|
||||
@ -49,5 +50,5 @@ pub mod prelude {
|
||||
pub use super::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt};
|
||||
#[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};
|
||||
}
|
||||
|
3
library/std/src/os/wasi/net/mod.rs
Normal file
3
library/std/src/os/wasi/net/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! WASI-specific networking functionality
|
||||
|
||||
#![unstable(feature = "wasi_ext", issue = "71213")]
|
386
library/std/src/os/windows/io/handle.rs
Normal file
386
library/std/src/os/windows/io/handle.rs
Normal file
@ -0,0 +1,386 @@
|
||||
//! Owned and borrowed OS handles.
|
||||
|
||||
#![unstable(feature = "io_safety", issue = "87074")]
|
||||
|
||||
use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
|
||||
use crate::convert::TryFrom;
|
||||
use crate::ffi::c_void;
|
||||
use crate::fmt;
|
||||
use crate::fs;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::mem::forget;
|
||||
use crate::ptr::NonNull;
|
||||
use crate::sys::c;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
/// A borrowed handle.
|
||||
///
|
||||
/// This has a lifetime parameter to tie it to the lifetime of something that
|
||||
/// owns the handle.
|
||||
///
|
||||
/// This uses `repr(transparent)` and has the representation of a host handle,
|
||||
/// so it can be used in FFI in places where a handle is passed as an argument,
|
||||
/// it is not captured or consumed, and it is never null.
|
||||
///
|
||||
/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
|
||||
/// sometimes a valid handle value. See [here] for the full story.
|
||||
///
|
||||
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub struct BorrowedHandle<'handle> {
|
||||
handle: NonNull<c_void>,
|
||||
_phantom: PhantomData<&'handle OwnedHandle>,
|
||||
}
|
||||
|
||||
/// An owned handle.
|
||||
///
|
||||
/// This closes the handle on drop.
|
||||
///
|
||||
/// This uses `repr(transparent)` and has the representation of a host handle,
|
||||
/// so it can be used in FFI in places where a handle is passed as a consumed
|
||||
/// argument or returned as an owned value, and is never null.
|
||||
///
|
||||
/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
|
||||
/// sometimes a valid handle value. See [here] for the full story. For APIs
|
||||
/// like `CreateFileW` which report errors with `INVALID_HANDLE_VALUE` instead
|
||||
/// of null, use [`HandleOrInvalid`] instead of `Option<OwnedHandle>`.
|
||||
///
|
||||
/// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
|
||||
/// it must not be used with handles to open registry keys which need to be
|
||||
/// closed with [`RegCloseKey`] instead.
|
||||
///
|
||||
/// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
|
||||
/// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
|
||||
///
|
||||
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
#[repr(transparent)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub struct OwnedHandle {
|
||||
handle: NonNull<c_void>,
|
||||
}
|
||||
|
||||
/// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
|
||||
/// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
|
||||
/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
|
||||
/// FFI declarations.
|
||||
///
|
||||
/// The only thing you can usefully do with a `HandleOrInvalid` is to convert it into an
|
||||
/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
|
||||
/// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
|
||||
/// checking for `INVALID_HANDLE_VALUE` first.
|
||||
///
|
||||
/// If this holds a valid handle, it will close the handle on drop.
|
||||
#[repr(transparent)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
#[derive(Debug)]
|
||||
pub struct HandleOrInvalid(Option<OwnedHandle>);
|
||||
|
||||
// The Windows [`HANDLE`] type may be transferred across and shared between
|
||||
// thread boundaries (despite containing a `*mut void`, which in general isn't
|
||||
// `Send` or `Sync`).
|
||||
//
|
||||
// [`HANDLE`]: std::os::windows::raw::HANDLE
|
||||
unsafe impl Send for OwnedHandle {}
|
||||
unsafe impl Send for HandleOrInvalid {}
|
||||
unsafe impl Send for BorrowedHandle<'_> {}
|
||||
unsafe impl Sync for OwnedHandle {}
|
||||
unsafe impl Sync for HandleOrInvalid {}
|
||||
unsafe impl Sync for BorrowedHandle<'_> {}
|
||||
|
||||
impl BorrowedHandle<'_> {
|
||||
/// Return a `BorrowedHandle` holding the given raw handle.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `handle` must be a valid open handle, it
|
||||
/// must remain open for the duration of the returned `BorrowedHandle`, and
|
||||
/// it must not be null.
|
||||
///
|
||||
/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
|
||||
/// sometimes a valid handle value. See [here] for the full story.
|
||||
///
|
||||
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
#[inline]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self {
|
||||
assert!(!handle.is_null());
|
||||
Self { handle: NonNull::new_unchecked(handle), _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<HandleOrInvalid> for OwnedHandle {
|
||||
type Error = ();
|
||||
|
||||
#[inline]
|
||||
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, ()> {
|
||||
// In theory, we ought to be able to assume that the pointer here is
|
||||
// never null, use `OwnedHandle` rather than `Option<OwnedHandle>`, and
|
||||
// obviate the the panic path here. Unfortunately, Win32 documentation
|
||||
// doesn't explicitly guarantee this anywhere.
|
||||
//
|
||||
// APIs like [`CreateFileW`] itself have `HANDLE` arguments where a
|
||||
// null handle indicates an absent value, which wouldn't work if null
|
||||
// were a valid handle value, so it seems very unlikely that it could
|
||||
// ever return null. But who knows?
|
||||
//
|
||||
// [`CreateFileW`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
let owned_handle = handle_or_invalid.0.expect("A `HandleOrInvalid` was null!");
|
||||
if owned_handle.handle.as_ptr() == c::INVALID_HANDLE_VALUE {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(owned_handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawHandle for BorrowedHandle<'_> {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.handle.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawHandle for OwnedHandle {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.handle.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for OwnedHandle {
|
||||
#[inline]
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
let handle = self.handle.as_ptr();
|
||||
forget(self);
|
||||
handle
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawHandle for OwnedHandle {
|
||||
/// Constructs a new instance of `Self` from the given raw handle.
|
||||
///
|
||||
/// Use `HandleOrInvalid` instead of `Option<OwnedHandle>` for APIs that
|
||||
/// use `INVALID_HANDLE_VALUE` to indicate failure.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `handle` must be open and suitable for
|
||||
/// assuming ownership. The resource must not require any cleanup other
|
||||
/// than `CloseHandle`.
|
||||
///
|
||||
/// In particular, it must not be used with handles to open registry
|
||||
/// keys which need to be closed with [`RegCloseKey`] instead.
|
||||
///
|
||||
/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
|
||||
/// sometimes a valid handle value. See [here] for the full story.
|
||||
///
|
||||
/// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
|
||||
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
#[inline]
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
|
||||
assert!(!handle.is_null());
|
||||
Self { handle: NonNull::new_unchecked(handle) }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawHandle for HandleOrInvalid {
|
||||
/// Constructs a new instance of `Self` from the given `RawHandle` returned
|
||||
/// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
|
||||
/// failure, such as `CreateFileW`.
|
||||
///
|
||||
/// Use `Option<OwnedHandle>` instead of `HandleOrInvalid` for APIs that
|
||||
/// use null to indicate failure.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `handle` must be either open and otherwise
|
||||
/// unowned, or equal to `INVALID_HANDLE_VALUE` (-1). It must not be null.
|
||||
/// Note that not all Windows APIs use `INVALID_HANDLE_VALUE` for errors;
|
||||
/// see [here] for the full story.
|
||||
///
|
||||
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
#[inline]
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
|
||||
// We require non-null here to catch errors earlier.
|
||||
Self(Some(OwnedHandle::from_raw_handle(handle)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedHandle {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = c::CloseHandle(self.handle.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BorrowedHandle<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OwnedHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to borrow the handle from an underlying object.
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub trait AsHandle {
|
||||
/// Borrows the handle.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # #![feature(io_safety)]
|
||||
/// use std::fs::File;
|
||||
/// # use std::io;
|
||||
/// use std::os::windows::io::{AsHandle, BorrowedHandle};
|
||||
///
|
||||
/// let mut f = File::open("foo.txt")?;
|
||||
/// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
|
||||
/// # Ok::<(), io::Error>(())
|
||||
/// ```
|
||||
fn as_handle(&self) -> BorrowedHandle<'_>;
|
||||
}
|
||||
|
||||
impl AsHandle for BorrowedHandle<'_> {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for OwnedHandle {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
// Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
|
||||
// invariants, and the `BorrowdHandle` is bounded by the lifetime
|
||||
// of `&self`.
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for fs::File {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.as_inner().as_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<fs::File> for OwnedHandle {
|
||||
#[inline]
|
||||
fn from(file: fs::File) -> OwnedHandle {
|
||||
file.into_inner().into_inner().into_inner().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedHandle> for fs::File {
|
||||
#[inline]
|
||||
fn from(owned: OwnedHandle) -> Self {
|
||||
Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for crate::io::Stdin {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsHandle for crate::io::StdinLock<'a> {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for crate::io::Stdout {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsHandle for crate::io::StdoutLock<'a> {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for crate::io::Stderr {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsHandle for crate::io::StderrLock<'a> {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for crate::process::ChildStdin {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::process::ChildStdin> for OwnedHandle {
|
||||
#[inline]
|
||||
fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
|
||||
unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for crate::process::ChildStdout {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::process::ChildStdout> for OwnedHandle {
|
||||
#[inline]
|
||||
fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
|
||||
unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for crate::process::ChildStderr {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::process::ChildStderr> for OwnedHandle {
|
||||
#[inline]
|
||||
fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
|
||||
unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsHandle for crate::thread::JoinHandle<T> {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
|
||||
#[inline]
|
||||
fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
|
||||
join_handle.into_inner().into_handle().into_inner()
|
||||
}
|
||||
}
|
56
library/std/src/os/windows/io/mod.rs
Normal file
56
library/std/src/os/windows/io/mod.rs
Normal file
@ -0,0 +1,56 @@
|
||||
//! Windows-specific extensions to general I/O primitives.
|
||||
//!
|
||||
//! Just like raw pointers, raw Windows handles and sockets 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 handles and sockets
|
||||
//! with different ownership properties: raw, borrowed, and owned, which are
|
||||
//! analogous to types used for representing pointers:
|
||||
//!
|
||||
//! | Type | Analogous to |
|
||||
//! | ---------------------- | ------------ |
|
||||
//! | [`RawHandle`] | `*const _` |
|
||||
//! | [`RawSocket`] | `*const _` |
|
||||
//! | | |
|
||||
//! | [`BorrowedHandle<'a>`] | `&'a _` |
|
||||
//! | [`BorrowedSocket<'a>`] | `&'a _` |
|
||||
//! | | |
|
||||
//! | [`OwnedHandle`] | `Box<_>` |
|
||||
//! | [`OwnedSocket`] | `Box<_>` |
|
||||
//!
|
||||
//! Like raw pointers, `RawHandle` and `RawSocket` 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 `RawHandle` and
|
||||
//! `RawSocket` usage as unsafe. Once the `io_safety` feature is stable,
|
||||
//! libraries will be encouraged to migrate, either by adding `unsafe` to APIs
|
||||
//! that dereference `RawHandle` and `RawSocket` values, or by using to
|
||||
//! `BorrowedHandle`, `BorrowedSocket`, `OwnedHandle`, or `OwnedSocket`.
|
||||
//!
|
||||
//! Like references, `BorrowedHandle` and `BorrowedSocket` values are tied to a
|
||||
//! lifetime, to ensure that they don't outlive the resource they point to.
|
||||
//! These are safe to use. `BorrowedHandle` and `BorrowedSocket` values may be
|
||||
//! used in APIs which provide safe access to any system call except for
|
||||
//! `CloseHandle`, `closesocket`, or any other call that would end the
|
||||
//! dynamic lifetime of the resource without ending the lifetime of the
|
||||
//! handle or socket.
|
||||
//!
|
||||
//! Like boxes, `OwnedHandle` and `OwnedSocket` values conceptually own the
|
||||
//! resource they point to, and free (close) it when they are dropped.
|
||||
//!
|
||||
//! [`BorrowedHandle<'a>`]: crate::os::windows::io::BorrowedHandle
|
||||
//! [`BorrowedSocket<'a>`]: crate::os::windows::io::BorrowedSocket
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
mod handle;
|
||||
mod raw;
|
||||
mod socket;
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub use handle::*;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use raw::*;
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub use socket::*;
|
@ -5,6 +5,7 @@
|
||||
use crate::fs;
|
||||
use crate::io;
|
||||
use crate::net;
|
||||
use crate::os::windows::io::{OwnedHandle, OwnedSocket};
|
||||
use crate::os::windows::raw;
|
||||
use crate::sys;
|
||||
use crate::sys::c;
|
||||
@ -61,7 +62,7 @@ pub trait IntoRawHandle {
|
||||
impl AsRawHandle for fs::File {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as RawHandle
|
||||
self.as_inner().as_raw_handle() as RawHandle
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +113,9 @@ impl FromRawHandle for fs::File {
|
||||
#[inline]
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
|
||||
let handle = handle as c::HANDLE;
|
||||
fs::File::from_inner(sys::fs::File::from_inner(handle))
|
||||
fs::File::from_inner(sys::fs::File::from_inner(FromInner::from_inner(
|
||||
OwnedHandle::from_raw_handle(handle),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +123,7 @@ impl FromRawHandle for fs::File {
|
||||
impl IntoRawHandle for fs::File {
|
||||
#[inline]
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
self.into_inner().into_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,21 +169,21 @@ pub trait IntoRawSocket {
|
||||
impl AsRawSocket for net::TcpStream {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
self.as_inner().socket().as_raw_socket()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::TcpListener {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
self.as_inner().socket().as_raw_socket()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRawSocket for net::UdpSocket {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
*self.as_inner().socket().as_inner()
|
||||
self.as_inner().socket().as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,7 +191,7 @@ impl AsRawSocket for net::UdpSocket {
|
||||
impl FromRawSocket for net::TcpStream {
|
||||
#[inline]
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock));
|
||||
net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock))
|
||||
}
|
||||
}
|
||||
@ -196,7 +199,7 @@ impl FromRawSocket for net::TcpStream {
|
||||
impl FromRawSocket for net::TcpListener {
|
||||
#[inline]
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock));
|
||||
net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock))
|
||||
}
|
||||
}
|
||||
@ -204,7 +207,7 @@ impl FromRawSocket for net::TcpListener {
|
||||
impl FromRawSocket for net::UdpSocket {
|
||||
#[inline]
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
|
||||
let sock = sys::net::Socket::from_inner(sock);
|
||||
let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock));
|
||||
net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock))
|
||||
}
|
||||
}
|
||||
@ -213,7 +216,7 @@ impl FromRawSocket for net::UdpSocket {
|
||||
impl IntoRawSocket for net::TcpStream {
|
||||
#[inline]
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
self.into_inner().into_socket().into_inner().into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +224,7 @@ impl IntoRawSocket for net::TcpStream {
|
||||
impl IntoRawSocket for net::TcpListener {
|
||||
#[inline]
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
self.into_inner().into_socket().into_inner().into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,6 +232,6 @@ impl IntoRawSocket for net::TcpListener {
|
||||
impl IntoRawSocket for net::UdpSocket {
|
||||
#[inline]
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.into_inner().into_socket().into_inner()
|
||||
self.into_inner().into_socket().into_inner().into_raw_socket()
|
||||
}
|
||||
}
|
216
library/std/src/os/windows/io/socket.rs
Normal file
216
library/std/src/os/windows/io/socket.rs
Normal file
@ -0,0 +1,216 @@
|
||||
//! Owned and borrowed OS sockets.
|
||||
|
||||
#![unstable(feature = "io_safety", issue = "87074")]
|
||||
|
||||
use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
use crate::fmt;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::mem::forget;
|
||||
use crate::sys::c;
|
||||
|
||||
/// A borrowed socket.
|
||||
///
|
||||
/// 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 socket,
|
||||
/// 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
|
||||
/// `INVALID_SOCKET`.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
|
||||
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
|
||||
#[cfg_attr(
|
||||
target_pointer_width = "64",
|
||||
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
|
||||
)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub struct BorrowedSocket<'socket> {
|
||||
socket: RawSocket,
|
||||
_phantom: PhantomData<&'socket OwnedSocket>,
|
||||
}
|
||||
|
||||
/// An owned socket.
|
||||
///
|
||||
/// This closes the socket on drop.
|
||||
///
|
||||
/// This uses `repr(transparent)` and has the representation of a host socket,
|
||||
/// so it can be used in FFI in places where a socket is passed as a consumed
|
||||
/// argument or returned as an owned value, and it never has the value
|
||||
/// `INVALID_SOCKET`.
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
|
||||
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
|
||||
#[cfg_attr(
|
||||
target_pointer_width = "64",
|
||||
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
|
||||
)]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub struct OwnedSocket {
|
||||
socket: RawSocket,
|
||||
}
|
||||
|
||||
impl BorrowedSocket<'_> {
|
||||
/// Return a `BorrowedSocket` holding the given raw socket.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `raw` must remain open for the duration of
|
||||
/// the returned `BorrowedSocket`, and it must not have the value
|
||||
/// `INVALID_SOCKET`.
|
||||
#[inline]
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub unsafe fn borrow_raw_socket(socket: RawSocket) -> Self {
|
||||
debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
|
||||
Self { socket, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawSocket for BorrowedSocket<'_> {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.socket
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawSocket for OwnedSocket {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.socket
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawSocket for OwnedSocket {
|
||||
#[inline]
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
let socket = self.socket;
|
||||
forget(self);
|
||||
socket
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawSocket for OwnedSocket {
|
||||
/// Constructs a new instance of `Self` from the given raw socket.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The resource pointed to by `socket` must be open and suitable for
|
||||
/// assuming ownership. The resource must not require cleanup other than
|
||||
/// `closesocket`.
|
||||
#[inline]
|
||||
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
|
||||
debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
|
||||
Self { socket }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedSocket {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = c::closesocket(self.socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BorrowedSocket<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BorrowedSocket").field("socket", &self.socket).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OwnedSocket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("OwnedSocket").field("socket", &self.socket).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to borrow the socket from an underlying object.
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
pub trait AsSocket {
|
||||
/// Borrows the socket.
|
||||
fn as_socket(&self) -> BorrowedSocket<'_>;
|
||||
}
|
||||
|
||||
impl AsSocket for BorrowedSocket<'_> {
|
||||
#[inline]
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSocket for OwnedSocket {
|
||||
#[inline]
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
// Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
|
||||
// invariants, and the `BorrowdSocket` is bounded by the lifetime
|
||||
// of `&self`.
|
||||
unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSocket for crate::net::TcpStream {
|
||||
#[inline]
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::net::TcpStream> for OwnedSocket {
|
||||
#[inline]
|
||||
fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
|
||||
unsafe { OwnedSocket::from_raw_socket(tcp_stream.into_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedSocket> for crate::net::TcpStream {
|
||||
#[inline]
|
||||
fn from(owned: OwnedSocket) -> Self {
|
||||
unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSocket for crate::net::TcpListener {
|
||||
#[inline]
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::net::TcpListener> for OwnedSocket {
|
||||
#[inline]
|
||||
fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
|
||||
unsafe { OwnedSocket::from_raw_socket(tcp_listener.into_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedSocket> for crate::net::TcpListener {
|
||||
#[inline]
|
||||
fn from(owned: OwnedSocket) -> Self {
|
||||
unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSocket for crate::net::UdpSocket {
|
||||
#[inline]
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::net::UdpSocket> for OwnedSocket {
|
||||
#[inline]
|
||||
fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
|
||||
unsafe { OwnedSocket::from_raw_socket(udp_socket.into_raw_socket()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedSocket> for crate::net::UdpSocket {
|
||||
#[inline]
|
||||
fn from(owned: OwnedSocket) -> Self {
|
||||
unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
|
||||
}
|
||||
}
|
@ -32,8 +32,11 @@ pub mod prelude {
|
||||
pub use super::fs::{MetadataExt, OpenOptionsExt};
|
||||
#[doc(no_inline)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::io::{AsRawHandle, AsRawSocket, RawHandle, RawSocket};
|
||||
pub use super::io::{
|
||||
AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, FromRawHandle, FromRawSocket,
|
||||
HandleOrInvalid, IntoRawHandle, IntoRawSocket, OwnedHandle, OwnedSocket,
|
||||
};
|
||||
#[doc(no_inline)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use super::io::{FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket};
|
||||
pub use super::io::{AsRawHandle, AsRawSocket, RawHandle, RawSocket};
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
#![stable(feature = "process_extensions", since = "1.2.0")]
|
||||
|
||||
use crate::ffi::OsStr;
|
||||
use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
|
||||
use crate::os::windows::io::{
|
||||
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
|
||||
};
|
||||
use crate::process;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys;
|
||||
@ -12,7 +14,16 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||
impl FromRawHandle for process::Stdio {
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
|
||||
let handle = sys::handle::Handle::new(handle as *mut _);
|
||||
let handle = sys::handle::Handle::from_raw_handle(handle as *mut _);
|
||||
let io = sys::process::Stdio::Handle(handle);
|
||||
process::Stdio::from_inner(io)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<OwnedHandle> for process::Stdio {
|
||||
fn from(handle: OwnedHandle) -> process::Stdio {
|
||||
let handle = sys::handle::Handle::from_inner(handle);
|
||||
let io = sys::process::Stdio::Handle(handle);
|
||||
process::Stdio::from_inner(io)
|
||||
}
|
||||
@ -22,14 +33,29 @@ impl FromRawHandle for process::Stdio {
|
||||
impl AsRawHandle for process::Child {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as *mut _
|
||||
self.as_inner().handle().as_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsHandle for process::Child {
|
||||
#[inline]
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.as_inner().handle().as_handle()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawHandle for process::Child {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
self.into_inner().into_handle().into_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl From<process::Child> for OwnedHandle {
|
||||
fn from(child: process::Child) -> OwnedHandle {
|
||||
child.into_inner().into_handle().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +63,7 @@ impl IntoRawHandle for process::Child {
|
||||
impl AsRawHandle for process::ChildStdin {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as *mut _
|
||||
self.as_inner().handle().as_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +71,7 @@ impl AsRawHandle for process::ChildStdin {
|
||||
impl AsRawHandle for process::ChildStdout {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as *mut _
|
||||
self.as_inner().handle().as_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,28 +79,28 @@ impl AsRawHandle for process::ChildStdout {
|
||||
impl AsRawHandle for process::ChildStderr {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as *mut _
|
||||
self.as_inner().handle().as_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawHandle for process::ChildStdin {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
self.into_inner().into_handle().into_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawHandle for process::ChildStdout {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
self.into_inner().into_handle().into_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||
impl IntoRawHandle for process::ChildStderr {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
self.into_inner().into_handle().into_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ use crate::thread;
|
||||
impl<T> AsRawHandle for thread::JoinHandle<T> {
|
||||
#[inline]
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().handle().raw() as *mut _
|
||||
self.as_inner().handle().as_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,6 @@ impl<T> AsRawHandle for thread::JoinHandle<T> {
|
||||
impl<T> IntoRawHandle for thread::JoinHandle<T> {
|
||||
#[inline]
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_handle().into_raw() as *mut _
|
||||
self.into_inner().into_handle().into_raw_handle() as *mut _
|
||||
}
|
||||
}
|
||||
|
@ -258,6 +258,12 @@ pub struct ChildStdin {
|
||||
inner: AnonPipe,
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `ChildStdin` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
||||
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
||||
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
impl Write for ChildStdin {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
@ -335,6 +341,12 @@ pub struct ChildStdout {
|
||||
inner: AnonPipe,
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `ChildStdout` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
||||
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
||||
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
impl Read for ChildStdout {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
@ -396,6 +408,12 @@ pub struct ChildStderr {
|
||||
inner: AnonPipe,
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `ChildStderr` also has `impl`s for
|
||||
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
||||
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
||||
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
||||
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
||||
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
impl Read for ChildStderr {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
|
@ -5,21 +5,14 @@ mod tests;
|
||||
|
||||
use crate::cmp;
|
||||
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
|
||||
use crate::mem;
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::sys::cvt;
|
||||
use crate::sys_common::AsInner;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
use libc::{c_int, c_void};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[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)]
|
||||
pub struct FileDesc {
|
||||
fd: c_int,
|
||||
}
|
||||
pub struct FileDesc(OwnedFd);
|
||||
|
||||
// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
|
||||
// with the man page quoting that if the count of bytes to read is
|
||||
@ -67,26 +60,13 @@ const fn max_iov() -> usize {
|
||||
}
|
||||
|
||||
impl FileDesc {
|
||||
pub 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 } }
|
||||
}
|
||||
|
||||
pub fn raw(&self) -> c_int {
|
||||
self.fd
|
||||
}
|
||||
|
||||
/// Extracts the actual file descriptor without closing it.
|
||||
pub fn into_raw(self) -> c_int {
|
||||
let fd = self.fd;
|
||||
mem::forget(self);
|
||||
fd
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
|
||||
libc::read(
|
||||
self.as_raw_fd(),
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
cmp::min(buf.len(), READ_LIMIT),
|
||||
)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
@ -95,7 +75,7 @@ impl FileDesc {
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
libc::readv(
|
||||
self.fd,
|
||||
self.as_raw_fd(),
|
||||
bufs.as_ptr() as *const libc::iovec,
|
||||
cmp::min(bufs.len(), max_iov()) as c_int,
|
||||
)
|
||||
@ -138,7 +118,7 @@ impl FileDesc {
|
||||
|
||||
unsafe {
|
||||
cvt_pread64(
|
||||
self.fd,
|
||||
self.as_raw_fd(),
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
cmp::min(buf.len(), READ_LIMIT),
|
||||
offset as i64,
|
||||
@ -149,7 +129,11 @@ impl FileDesc {
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
|
||||
libc::write(
|
||||
self.as_raw_fd(),
|
||||
buf.as_ptr() as *const c_void,
|
||||
cmp::min(buf.len(), READ_LIMIT),
|
||||
)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
@ -158,7 +142,7 @@ impl FileDesc {
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
libc::writev(
|
||||
self.fd,
|
||||
self.as_raw_fd(),
|
||||
bufs.as_ptr() as *const libc::iovec,
|
||||
cmp::min(bufs.len(), max_iov()) as c_int,
|
||||
)
|
||||
@ -196,7 +180,7 @@ impl FileDesc {
|
||||
|
||||
unsafe {
|
||||
cvt_pwrite64(
|
||||
self.fd,
|
||||
self.as_raw_fd(),
|
||||
buf.as_ptr() as *const c_void,
|
||||
cmp::min(buf.len(), READ_LIMIT),
|
||||
offset as i64,
|
||||
@ -207,7 +191,7 @@ impl FileDesc {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_cloexec(&self) -> io::Result<bool> {
|
||||
unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
|
||||
unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
@ -224,7 +208,7 @@ impl FileDesc {
|
||||
)))]
|
||||
pub fn set_cloexec(&self) -> io::Result<()> {
|
||||
unsafe {
|
||||
cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
|
||||
cvt(libc::ioctl(self.as_raw_fd(), libc::FIOCLEX))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -242,10 +226,10 @@ impl FileDesc {
|
||||
))]
|
||||
pub fn set_cloexec(&self) -> io::Result<()> {
|
||||
unsafe {
|
||||
let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
|
||||
let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))?;
|
||||
let new = previous | libc::FD_CLOEXEC;
|
||||
if new != previous {
|
||||
cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
|
||||
cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFD, new))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -261,7 +245,7 @@ impl FileDesc {
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
unsafe {
|
||||
let v = nonblocking as c_int;
|
||||
cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
|
||||
cvt(libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &v))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -269,14 +253,14 @@ impl FileDesc {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
unsafe {
|
||||
let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
|
||||
let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL))?;
|
||||
let new = if nonblocking {
|
||||
previous | libc::O_NONBLOCK
|
||||
} else {
|
||||
previous & !libc::O_NONBLOCK
|
||||
};
|
||||
if new != previous {
|
||||
cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
|
||||
cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -296,8 +280,8 @@ impl FileDesc {
|
||||
#[cfg(target_os = "espidf")]
|
||||
let cmd = libc::F_DUPFD;
|
||||
|
||||
let fd = cvt(unsafe { libc::fcntl(self.raw(), cmd, 0) })?;
|
||||
Ok(FileDesc::new(fd))
|
||||
let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?;
|
||||
Ok(unsafe { FileDesc::from_raw_fd(fd) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,19 +296,44 @@ impl<'a> Read for &'a FileDesc {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<c_int> for FileDesc {
|
||||
fn as_inner(&self) -> &c_int {
|
||||
&self.fd
|
||||
impl AsInner<OwnedFd> for FileDesc {
|
||||
fn as_inner(&self) -> &OwnedFd {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FileDesc {
|
||||
fn drop(&mut self) {
|
||||
// Note that errors are ignored when closing a file descriptor. The
|
||||
// reason for this is that if an error occurs we don't actually know if
|
||||
// the file descriptor was closed or not, and if we retried (for
|
||||
// something like EINTR), we might close another valid file descriptor
|
||||
// opened after we closed ours.
|
||||
let _ = unsafe { libc::close(self.fd) };
|
||||
impl IntoInner<OwnedFd> for FileDesc {
|
||||
fn into_inner(self) -> OwnedFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<OwnedFd> for FileDesc {
|
||||
fn from_inner(owned_fd: OwnedFd) -> Self {
|
||||
Self(owned_fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for FileDesc {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for FileDesc {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for FileDesc {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for FileDesc {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FromRawFd::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use super::{FileDesc, IoSlice};
|
||||
use crate::os::unix::io::FromRawFd;
|
||||
use core::mem::ManuallyDrop;
|
||||
|
||||
#[test]
|
||||
fn limit_vector_count() {
|
||||
let stdout = ManuallyDrop::new(unsafe { FileDesc { fd: 1 } });
|
||||
let stdout = ManuallyDrop::new(unsafe { FileDesc::from_raw_fd(1) });
|
||||
let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();
|
||||
assert!(stdout.write_vectored(&bufs).is_ok());
|
||||
}
|
||||
|
@ -4,13 +4,14 @@ use crate::ffi::{CStr, CString, OsStr, OsString};
|
||||
use crate::fmt;
|
||||
use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::mem;
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::ptr;
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::{cvt, cvt_r};
|
||||
use crate::sys_common::{AsInner, FromInner};
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "linux", target_env = "gnu"),
|
||||
@ -764,11 +765,11 @@ impl File {
|
||||
// However, since this is a variadic function, C integer promotion rules mean that on
|
||||
// the ABI level, this still gets passed as `c_int` (aka `u32` on Unix platforms).
|
||||
let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode as c_int) })?;
|
||||
Ok(File(FileDesc::new(fd)))
|
||||
Ok(File(unsafe { FileDesc::from_raw_fd(fd) }))
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
let fd = self.0.raw();
|
||||
let fd = self.as_raw_fd();
|
||||
|
||||
cfg_has_statx! {
|
||||
if let Some(ret) = unsafe { try_statx(
|
||||
@ -787,7 +788,7 @@ impl File {
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
cvt_r(|| unsafe { os_fsync(self.0.raw()) })?;
|
||||
cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?;
|
||||
return Ok(());
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
@ -801,7 +802,7 @@ impl File {
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
cvt_r(|| unsafe { os_datasync(self.0.raw()) })?;
|
||||
cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?;
|
||||
return Ok(());
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
@ -834,14 +835,14 @@ impl File {
|
||||
|
||||
pub fn truncate(&self, size: u64) -> io::Result<()> {
|
||||
#[cfg(target_os = "android")]
|
||||
return crate::sys::android::ftruncate64(self.0.raw(), size);
|
||||
return crate::sys::android::ftruncate64(self.as_raw_fd(), size);
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
{
|
||||
use crate::convert::TryInto;
|
||||
let size: off64_t =
|
||||
size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
|
||||
cvt_r(|| unsafe { ftruncate64(self.0.raw(), size) }).map(drop)
|
||||
cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
@ -891,7 +892,7 @@ impl File {
|
||||
SeekFrom::End(off) => (libc::SEEK_END, off),
|
||||
SeekFrom::Current(off) => (libc::SEEK_CUR, off),
|
||||
};
|
||||
let n = cvt(unsafe { lseek64(self.0.raw(), pos, whence) })?;
|
||||
let n = cvt(unsafe { lseek64(self.as_raw_fd(), pos, whence) })?;
|
||||
Ok(n as u64)
|
||||
}
|
||||
|
||||
@ -899,16 +900,8 @@ impl File {
|
||||
self.0.duplicate().map(File)
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn into_fd(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
|
||||
cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
|
||||
cvt_r(|| unsafe { libc::fchmod(self.as_raw_fd(), perm.mode) })?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -933,9 +926,51 @@ fn cstr(path: &Path) -> io::Result<CString> {
|
||||
Ok(CString::new(path.as_os_str().as_bytes())?)
|
||||
}
|
||||
|
||||
impl FromInner<c_int> for File {
|
||||
fn from_inner(fd: c_int) -> File {
|
||||
File(FileDesc::new(fd))
|
||||
impl AsInner<FileDesc> for File {
|
||||
fn as_inner(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerMut<FileDesc> for File {
|
||||
fn as_inner_mut(&mut self) -> &mut FileDesc {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<FileDesc> for File {
|
||||
fn into_inner(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<FileDesc> for File {
|
||||
fn from_inner(file_desc: FileDesc) -> Self {
|
||||
Self(file_desc)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for File {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for File {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for File {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FromRawFd::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1009,7 +1044,7 @@ impl fmt::Debug for File {
|
||||
None
|
||||
}
|
||||
|
||||
let fd = self.0.raw();
|
||||
let fd = self.as_raw_fd();
|
||||
let mut b = f.debug_struct("File");
|
||||
b.field("fd", &fd);
|
||||
if let Some(path) = get_path(fd) {
|
||||
|
@ -3,6 +3,7 @@ use crate::ffi::CStr;
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::mem;
|
||||
use crate::net::{Shutdown, SocketAddr};
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::str;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
|
||||
@ -74,10 +75,10 @@ impl Socket {
|
||||
// flag to atomically create the socket and set it as
|
||||
// CLOEXEC. On Linux this was added in 2.6.27.
|
||||
let fd = cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0))?;
|
||||
Ok(Socket(FileDesc::new(fd)))
|
||||
Ok(Socket(FileDesc::from_raw_fd(fd)))
|
||||
} else {
|
||||
let fd = cvt(libc::socket(fam, ty, 0))?;
|
||||
let fd = FileDesc::new(fd);
|
||||
let fd = FileDesc::from_raw_fd(fd);
|
||||
fd.set_cloexec()?;
|
||||
let socket = Socket(fd);
|
||||
|
||||
@ -109,11 +110,11 @@ impl Socket {
|
||||
))] {
|
||||
// Like above, set cloexec atomically
|
||||
cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?;
|
||||
Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1]))))
|
||||
Ok((Socket(FileDesc::from_raw_fd(fds[0])), Socket(FileDesc::from_raw_fd(fds[1]))))
|
||||
} else {
|
||||
cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?;
|
||||
let a = FileDesc::new(fds[0]);
|
||||
let b = FileDesc::new(fds[1]);
|
||||
let a = FileDesc::from_raw_fd(fds[0]);
|
||||
let b = FileDesc::from_raw_fd(fds[1]);
|
||||
a.set_cloexec()?;
|
||||
b.set_cloexec()?;
|
||||
Ok((Socket(a), Socket(b)))
|
||||
@ -131,7 +132,7 @@ impl Socket {
|
||||
self.set_nonblocking(true)?;
|
||||
let r = unsafe {
|
||||
let (addrp, len) = addr.into_inner();
|
||||
cvt(libc::connect(self.0.raw(), addrp, len))
|
||||
cvt(libc::connect(self.as_raw_fd(), addrp, len))
|
||||
};
|
||||
self.set_nonblocking(false)?;
|
||||
|
||||
@ -142,7 +143,7 @@ impl Socket {
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
let mut pollfd = libc::pollfd { fd: self.0.raw(), events: libc::POLLOUT, revents: 0 };
|
||||
let mut pollfd = libc::pollfd { fd: self.as_raw_fd(), events: libc::POLLOUT, revents: 0 };
|
||||
|
||||
if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
|
||||
return Err(io::Error::new_const(
|
||||
@ -212,15 +213,17 @@ impl Socket {
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))] {
|
||||
let fd = cvt_r(|| unsafe {
|
||||
libc::accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC)
|
||||
})?;
|
||||
Ok(Socket(FileDesc::new(fd)))
|
||||
unsafe {
|
||||
let fd = cvt_r(|| libc::accept4(self.as_raw_fd(), storage, len, libc::SOCK_CLOEXEC))?;
|
||||
Ok(Socket(FileDesc::from_raw_fd(fd)))
|
||||
}
|
||||
} else {
|
||||
let fd = cvt_r(|| unsafe { libc::accept(self.0.raw(), storage, len) })?;
|
||||
let fd = FileDesc::new(fd);
|
||||
fd.set_cloexec()?;
|
||||
Ok(Socket(fd))
|
||||
unsafe {
|
||||
let fd = cvt_r(|| libc::accept(self.as_raw_fd(), storage, len))?;
|
||||
let fd = FileDesc::from_raw_fd(fd);
|
||||
fd.set_cloexec()?;
|
||||
Ok(Socket(fd))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,7 +234,7 @@ impl Socket {
|
||||
|
||||
fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
libc::recv(self.0.raw(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags)
|
||||
libc::recv(self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
@ -263,7 +266,7 @@ impl Socket {
|
||||
|
||||
let n = cvt(unsafe {
|
||||
libc::recvfrom(
|
||||
self.0.raw(),
|
||||
self.as_raw_fd(),
|
||||
buf.as_mut_ptr() as *mut c_void,
|
||||
buf.len(),
|
||||
flags,
|
||||
@ -288,7 +291,7 @@ impl Socket {
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
pub fn recv_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
|
||||
let n = cvt(unsafe { libc::recvmsg(self.0.raw(), msg, libc::MSG_CMSG_CLOEXEC) })?;
|
||||
let n = cvt(unsafe { libc::recvmsg(self.as_raw_fd(), msg, libc::MSG_CMSG_CLOEXEC) })?;
|
||||
Ok(n as usize)
|
||||
}
|
||||
|
||||
@ -319,7 +322,7 @@ impl Socket {
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
pub fn send_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
|
||||
let n = cvt(unsafe { libc::sendmsg(self.0.raw(), msg, 0) })?;
|
||||
let n = cvt(unsafe { libc::sendmsg(self.as_raw_fd(), msg, 0) })?;
|
||||
Ok(n as usize)
|
||||
}
|
||||
|
||||
@ -369,7 +372,7 @@ impl Socket {
|
||||
Shutdown::Read => libc::SHUT_RD,
|
||||
Shutdown::Both => libc::SHUT_RDWR,
|
||||
};
|
||||
cvt(unsafe { libc::shutdown(self.0.raw(), how) })?;
|
||||
cvt(unsafe { libc::shutdown(self.as_raw_fd(), how) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -396,7 +399,7 @@ impl Socket {
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
let mut nonblocking = nonblocking as libc::c_int;
|
||||
cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(drop)
|
||||
cvt(unsafe { libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &mut nonblocking) }).map(drop)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||
@ -410,23 +413,52 @@ impl Socket {
|
||||
let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?;
|
||||
if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<c_int> for Socket {
|
||||
fn as_inner(&self) -> &c_int {
|
||||
self.0.as_inner()
|
||||
// This is used by sys_common code to abstract over Windows and Unix.
|
||||
pub fn as_raw(&self) -> RawFd {
|
||||
self.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c_int> for Socket {
|
||||
fn from_inner(fd: c_int) -> Socket {
|
||||
Socket(FileDesc::new(fd))
|
||||
impl AsInner<FileDesc> for Socket {
|
||||
fn as_inner(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<c_int> for Socket {
|
||||
fn into_inner(self) -> c_int {
|
||||
self.0.into_raw()
|
||||
impl IntoInner<FileDesc> for Socket {
|
||||
fn into_inner(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<FileDesc> for Socket {
|
||||
fn from_inner(file_desc: FileDesc) -> Self {
|
||||
Self(file_desc)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for Socket {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Socket {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for Socket {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for Socket {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FromRawFd::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::mem;
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::{cvt, cvt_r};
|
||||
use crate::sys_common::IntoInner;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Anonymous pipes
|
||||
@ -24,16 +26,20 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
target_os = "openbsd",
|
||||
target_os = "redox"
|
||||
))] {
|
||||
cvt(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
|
||||
Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1]))))
|
||||
unsafe {
|
||||
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?;
|
||||
Ok((AnonPipe(FileDesc::from_raw_fd(fds[0])), AnonPipe(FileDesc::from_raw_fd(fds[1]))))
|
||||
}
|
||||
} else {
|
||||
cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
|
||||
unsafe {
|
||||
cvt(libc::pipe(fds.as_mut_ptr()))?;
|
||||
|
||||
let fd0 = FileDesc::new(fds[0]);
|
||||
let fd1 = FileDesc::new(fds[1]);
|
||||
fd0.set_cloexec()?;
|
||||
fd1.set_cloexec()?;
|
||||
Ok((AnonPipe(fd0), AnonPipe(fd1)))
|
||||
let fd0 = FileDesc::from_raw_fd(fds[0]);
|
||||
let fd1 = FileDesc::from_raw_fd(fds[1]);
|
||||
fd0.set_cloexec()?;
|
||||
fd1.set_cloexec()?;
|
||||
Ok((AnonPipe(fd0), AnonPipe(fd1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,11 +70,10 @@ impl AnonPipe {
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
pub fn into_fd(self) -> FileDesc {
|
||||
impl IntoInner<FileDesc> for AnonPipe {
|
||||
fn into_inner(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@ -76,15 +81,15 @@ impl AnonPipe {
|
||||
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
// Set both pipes into nonblocking mode as we're gonna be reading from both
|
||||
// in the `select` loop below, and we wouldn't want one to block the other!
|
||||
let p1 = p1.into_fd();
|
||||
let p2 = p2.into_fd();
|
||||
let p1 = p1.into_inner();
|
||||
let p2 = p2.into_inner();
|
||||
p1.set_nonblocking(true)?;
|
||||
p2.set_nonblocking(true)?;
|
||||
|
||||
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
|
||||
fds[0].fd = p1.raw();
|
||||
fds[0].fd = p1.as_raw_fd();
|
||||
fds[0].events = libc::POLLIN;
|
||||
fds[1].fd = p2.raw();
|
||||
fds[1].fd = p2.as_raw_fd();
|
||||
fds[1].events = libc::POLLIN;
|
||||
loop {
|
||||
// wait for either pipe to become readable using `poll`
|
||||
@ -120,3 +125,27 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) ->
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for AnonPipe {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for AnonPipe {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for AnonPipe {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for AnonPipe {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FromRawFd::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ use crate::sys::fd::FileDesc;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::pipe::{self, AnonPipe};
|
||||
use crate::sys_common::process::{CommandEnv, CommandEnvs};
|
||||
use crate::sys_common::IntoInner;
|
||||
|
||||
#[cfg(not(target_os = "fuchsia"))]
|
||||
use crate::sys::fs::OpenOptions;
|
||||
@ -388,17 +389,17 @@ impl Stdio {
|
||||
// stderr. No matter which we dup first, the second will get
|
||||
// overwritten prematurely.
|
||||
Stdio::Fd(ref fd) => {
|
||||
if fd.raw() >= 0 && fd.raw() <= libc::STDERR_FILENO {
|
||||
if fd.as_raw_fd() >= 0 && fd.as_raw_fd() <= libc::STDERR_FILENO {
|
||||
Ok((ChildStdio::Owned(fd.duplicate()?), None))
|
||||
} else {
|
||||
Ok((ChildStdio::Explicit(fd.raw()), None))
|
||||
Ok((ChildStdio::Explicit(fd.as_raw_fd()), None))
|
||||
}
|
||||
}
|
||||
|
||||
Stdio::MakePipe => {
|
||||
let (reader, writer) = pipe::anon_pipe()?;
|
||||
let (ours, theirs) = if readable { (writer, reader) } else { (reader, writer) };
|
||||
Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours)))
|
||||
Ok((ChildStdio::Owned(theirs.into_inner()), Some(ours)))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "fuchsia"))]
|
||||
@ -408,7 +409,7 @@ impl Stdio {
|
||||
opts.write(!readable);
|
||||
let path = unsafe { CStr::from_ptr(DEV_NULL.as_ptr() as *const _) };
|
||||
let fd = File::open_c(&path, &opts)?;
|
||||
Ok((ChildStdio::Owned(fd.into_fd()), None))
|
||||
Ok((ChildStdio::Owned(fd.into_inner()), None))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
@ -419,13 +420,13 @@ impl Stdio {
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
Stdio::Fd(pipe.into_fd())
|
||||
Stdio::Fd(pipe.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(file: File) -> Stdio {
|
||||
Stdio::Fd(file.into_fd())
|
||||
Stdio::Fd(file.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,7 +435,7 @@ impl ChildStdio {
|
||||
match *self {
|
||||
ChildStdio::Inherit => None,
|
||||
ChildStdio::Explicit(fd) => Some(fd),
|
||||
ChildStdio::Owned(ref fd) => Some(fd.raw()),
|
||||
ChildStdio::Owned(ref fd) => Some(fd.as_raw_fd()),
|
||||
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
ChildStdio::Null => None,
|
||||
|
@ -97,7 +97,9 @@ impl Command {
|
||||
drop(env_lock);
|
||||
drop(output);
|
||||
|
||||
let mut p = Process::new(pid, pidfd);
|
||||
// Safety: We obtained the pidfd from calling `clone3` with
|
||||
// `CLONE_PIDFD` so it's valid an otherwise unowned.
|
||||
let mut p = unsafe { Process::new(pid, pidfd) };
|
||||
let mut bytes = [0; 8];
|
||||
|
||||
// loop to handle EINTR
|
||||
@ -446,7 +448,8 @@ impl Command {
|
||||
None => None,
|
||||
};
|
||||
|
||||
let mut p = Process::new(0, -1);
|
||||
// Safety: -1 indicates we don't have a pidfd.
|
||||
let mut p = unsafe { Process::new(0, -1) };
|
||||
|
||||
struct PosixSpawnFileActions<'a>(&'a mut MaybeUninit<libc::posix_spawn_file_actions_t>);
|
||||
|
||||
@ -545,14 +548,17 @@ pub struct Process {
|
||||
|
||||
impl Process {
|
||||
#[cfg(target_os = "linux")]
|
||||
fn new(pid: pid_t, pidfd: pid_t) -> Self {
|
||||
unsafe fn new(pid: pid_t, pidfd: pid_t) -> Self {
|
||||
use crate::os::unix::io::FromRawFd;
|
||||
use crate::sys_common::FromInner;
|
||||
let pidfd = (pidfd >= 0).then(|| PidFd::from_inner(sys::fd::FileDesc::new(pidfd)));
|
||||
// Safety: If `pidfd` is nonnegative, we assume it's valid and otherwise unowned.
|
||||
let pidfd = (pidfd >= 0)
|
||||
.then(|| PidFd::from_inner(unsafe { sys::fd::FileDesc::from_raw_fd(pidfd) }));
|
||||
Process { pid, status: None, pidfd }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn new(pid: pid_t, _pidfd: pid_t) -> Self {
|
||||
unsafe fn new(pid: pid_t, _pidfd: pid_t) -> Self {
|
||||
Process { pid, status: None }
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::os::unix::io::{AsFd, BorrowedFd, FromRawFd};
|
||||
use crate::sys::fd::FileDesc;
|
||||
|
||||
pub struct Stdin(());
|
||||
@ -14,11 +15,11 @@ impl Stdin {
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read(buf)
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read(buf) }
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(FileDesc::new(libc::STDIN_FILENO)).read_vectored(bufs)
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDIN_FILENO)).read_vectored(bufs) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -35,11 +36,13 @@ impl Stdout {
|
||||
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write(buf)
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDOUT_FILENO)).write(buf) }
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(FileDesc::new(libc::STDOUT_FILENO)).write_vectored(bufs)
|
||||
unsafe {
|
||||
ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDOUT_FILENO)).write_vectored(bufs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -60,11 +63,13 @@ impl Stderr {
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write(buf)
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDERR_FILENO)).write(buf) }
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(FileDesc::new(libc::STDERR_FILENO)).write_vectored(bufs)
|
||||
unsafe {
|
||||
ManuallyDrop::new(FileDesc::from_raw_fd(libc::STDERR_FILENO)).write_vectored(bufs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -86,3 +91,51 @@ pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
|
||||
pub fn panic_output() -> Option<impl io::Write> {
|
||||
Some(Stderr::new())
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for io::Stdin {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl<'a> AsFd for io::StdinLock<'a> {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for io::Stdout {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl<'a> AsFd for io::StdoutLock<'a> {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl AsFd for io::Stderr {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "io_safety", issue = "87074")]
|
||||
impl<'a> AsFd for io::StderrLock<'a> {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) }
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,12 @@ use super::err2io;
|
||||
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::mem;
|
||||
use crate::net::Shutdown;
|
||||
use crate::os::raw::c_int;
|
||||
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WasiFd {
|
||||
fd: c_int,
|
||||
fd: OwnedFd,
|
||||
}
|
||||
|
||||
fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
|
||||
@ -27,38 +28,26 @@ fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
|
||||
}
|
||||
|
||||
impl WasiFd {
|
||||
pub unsafe fn from_raw(fd: c_int) -> WasiFd {
|
||||
WasiFd { fd }
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> c_int {
|
||||
let ret = self.fd;
|
||||
mem::forget(self);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.fd
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
unsafe { wasi::fd_datasync(self.fd as wasi::Fd).map_err(err2io) }
|
||||
unsafe { wasi::fd_datasync(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||
unsafe { wasi::fd_pread(self.fd as wasi::Fd, iovec(bufs), offset).map_err(err2io) }
|
||||
unsafe { wasi::fd_pread(self.as_raw_fd() as wasi::Fd, iovec(bufs), offset).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||
unsafe { wasi::fd_pwrite(self.fd as wasi::Fd, ciovec(bufs), offset).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::fd_pwrite(self.as_raw_fd() as wasi::Fd, ciovec(bufs), offset).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
unsafe { wasi::fd_read(self.fd as wasi::Fd, iovec(bufs)).map_err(err2io) }
|
||||
unsafe { wasi::fd_read(self.as_raw_fd() as wasi::Fd, iovec(bufs)).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
unsafe { wasi::fd_write(self.fd as wasi::Fd, ciovec(bufs)).map_err(err2io) }
|
||||
unsafe { wasi::fd_write(self.as_raw_fd() as wasi::Fd, ciovec(bufs)).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
|
||||
@ -67,37 +56,42 @@ impl WasiFd {
|
||||
SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
|
||||
SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
|
||||
};
|
||||
unsafe { wasi::fd_seek(self.fd as wasi::Fd, offset, whence).map_err(err2io) }
|
||||
unsafe { wasi::fd_seek(self.as_raw_fd() as wasi::Fd, offset, whence).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn tell(&self) -> io::Result<u64> {
|
||||
unsafe { wasi::fd_tell(self.fd as wasi::Fd).map_err(err2io) }
|
||||
unsafe { wasi::fd_tell(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
|
||||
}
|
||||
|
||||
// FIXME: __wasi_fd_fdstat_get
|
||||
|
||||
pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
|
||||
unsafe { wasi::fd_fdstat_set_flags(self.fd as wasi::Fd, flags).map_err(err2io) }
|
||||
unsafe { wasi::fd_fdstat_set_flags(self.as_raw_fd() as wasi::Fd, flags).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
|
||||
unsafe { wasi::fd_fdstat_set_rights(self.fd as wasi::Fd, base, inheriting).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::fd_fdstat_set_rights(self.as_raw_fd() as wasi::Fd, base, inheriting)
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sync(&self) -> io::Result<()> {
|
||||
unsafe { wasi::fd_sync(self.fd as wasi::Fd).map_err(err2io) }
|
||||
unsafe { wasi::fd_sync(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
|
||||
unsafe { wasi::fd_advise(self.fd as wasi::Fd, offset, len, advice).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::fd_advise(self.as_raw_fd() as wasi::Fd, offset, len, advice).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
|
||||
unsafe { wasi::fd_allocate(self.fd as wasi::Fd, offset, len).map_err(err2io) }
|
||||
unsafe { wasi::fd_allocate(self.as_raw_fd() as wasi::Fd, offset, len).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn create_directory(&self, path: &str) -> io::Result<()> {
|
||||
unsafe { wasi::path_create_directory(self.fd as wasi::Fd, path).map_err(err2io) }
|
||||
unsafe { wasi::path_create_directory(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn link(
|
||||
@ -109,10 +103,10 @@ impl WasiFd {
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
wasi::path_link(
|
||||
self.fd as wasi::Fd,
|
||||
self.as_raw_fd() as wasi::Fd,
|
||||
old_flags,
|
||||
old_path,
|
||||
new_fd.fd as wasi::Fd,
|
||||
new_fd.as_raw_fd() as wasi::Fd,
|
||||
new_path,
|
||||
)
|
||||
.map_err(err2io)
|
||||
@ -130,7 +124,7 @@ impl WasiFd {
|
||||
) -> io::Result<WasiFd> {
|
||||
unsafe {
|
||||
wasi::path_open(
|
||||
self.fd as wasi::Fd,
|
||||
self.as_raw_fd() as wasi::Fd,
|
||||
dirflags,
|
||||
path,
|
||||
oflags,
|
||||
@ -138,34 +132,39 @@ impl WasiFd {
|
||||
fs_rights_inheriting,
|
||||
fs_flags,
|
||||
)
|
||||
.map(|fd| WasiFd::from_raw(fd as c_int))
|
||||
.map(|fd| WasiFd::from_raw_fd(fd as RawFd))
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
|
||||
unsafe {
|
||||
wasi::fd_readdir(self.fd as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie)
|
||||
wasi::fd_readdir(self.as_raw_fd() as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie)
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
wasi::path_readlink(self.fd as wasi::Fd, path, buf.as_mut_ptr(), buf.len())
|
||||
wasi::path_readlink(self.as_raw_fd() as wasi::Fd, path, buf.as_mut_ptr(), buf.len())
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
|
||||
unsafe {
|
||||
wasi::path_rename(self.fd as wasi::Fd, old_path, new_fd.fd as wasi::Fd, new_path)
|
||||
.map_err(err2io)
|
||||
wasi::path_rename(
|
||||
self.as_raw_fd() as wasi::Fd,
|
||||
old_path,
|
||||
new_fd.as_raw_fd() as wasi::Fd,
|
||||
new_path,
|
||||
)
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
|
||||
unsafe { wasi::fd_filestat_get(self.fd as wasi::Fd).map_err(err2io) }
|
||||
unsafe { wasi::fd_filestat_get(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn filestat_set_times(
|
||||
@ -175,12 +174,13 @@ impl WasiFd {
|
||||
fstflags: wasi::Fstflags,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
wasi::fd_filestat_set_times(self.fd as wasi::Fd, atim, mtim, fstflags).map_err(err2io)
|
||||
wasi::fd_filestat_set_times(self.as_raw_fd() as wasi::Fd, atim, mtim, fstflags)
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
|
||||
unsafe { wasi::fd_filestat_set_size(self.fd as wasi::Fd, size).map_err(err2io) }
|
||||
unsafe { wasi::fd_filestat_set_size(self.as_raw_fd() as wasi::Fd, size).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn path_filestat_get(
|
||||
@ -188,7 +188,9 @@ impl WasiFd {
|
||||
flags: wasi::Lookupflags,
|
||||
path: &str,
|
||||
) -> io::Result<wasi::Filestat> {
|
||||
unsafe { wasi::path_filestat_get(self.fd as wasi::Fd, flags, path).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::path_filestat_get(self.as_raw_fd() as wasi::Fd, flags, path).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_filestat_set_times(
|
||||
@ -200,21 +202,30 @@ impl WasiFd {
|
||||
fstflags: wasi::Fstflags,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
wasi::path_filestat_set_times(self.fd as wasi::Fd, flags, path, atim, mtim, fstflags)
|
||||
.map_err(err2io)
|
||||
wasi::path_filestat_set_times(
|
||||
self.as_raw_fd() as wasi::Fd,
|
||||
flags,
|
||||
path,
|
||||
atim,
|
||||
mtim,
|
||||
fstflags,
|
||||
)
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
|
||||
unsafe { wasi::path_symlink(old_path, self.fd as wasi::Fd, new_path).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::path_symlink(old_path, self.as_raw_fd() as wasi::Fd, new_path).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unlink_file(&self, path: &str) -> io::Result<()> {
|
||||
unsafe { wasi::path_unlink_file(self.fd as wasi::Fd, path).map_err(err2io) }
|
||||
unsafe { wasi::path_unlink_file(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn remove_directory(&self, path: &str) -> io::Result<()> {
|
||||
unsafe { wasi::path_remove_directory(self.fd as wasi::Fd, path).map_err(err2io) }
|
||||
unsafe { wasi::path_remove_directory(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn sock_recv(
|
||||
@ -222,11 +233,15 @@ impl WasiFd {
|
||||
ri_data: &mut [IoSliceMut<'_>],
|
||||
ri_flags: wasi::Riflags,
|
||||
) -> io::Result<(usize, wasi::Roflags)> {
|
||||
unsafe { wasi::sock_recv(self.fd as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::sock_recv(self.as_raw_fd() as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
|
||||
unsafe { wasi::sock_send(self.fd as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io) }
|
||||
unsafe {
|
||||
wasi::sock_send(self.as_raw_fd() as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
@ -235,14 +250,54 @@ impl WasiFd {
|
||||
Shutdown::Write => wasi::SDFLAGS_WR,
|
||||
Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
|
||||
};
|
||||
unsafe { wasi::sock_shutdown(self.fd as wasi::Fd, how).map_err(err2io) }
|
||||
unsafe { wasi::sock_shutdown(self.as_raw_fd() as wasi::Fd, how).map_err(err2io) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WasiFd {
|
||||
fn drop(&mut self) {
|
||||
// FIXME: can we handle the return code here even though we can't on
|
||||
// unix?
|
||||
let _ = unsafe { wasi::fd_close(self.fd as wasi::Fd) };
|
||||
impl AsInner<OwnedFd> for WasiFd {
|
||||
fn as_inner(&self) -> &OwnedFd {
|
||||
&self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerMut<OwnedFd> for WasiFd {
|
||||
fn as_inner_mut(&mut self) -> &mut OwnedFd {
|
||||
&mut self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<OwnedFd> for WasiFd {
|
||||
fn into_inner(self) -> OwnedFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<OwnedFd> for WasiFd {
|
||||
fn from_inner(owned_fd: OwnedFd) -> Self {
|
||||
Self { fd: owned_fd }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for WasiFd {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.fd.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for WasiFd {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for WasiFd {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.fd.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for WasiFd {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
unsafe { Self { fd: FromRawFd::from_raw_fd(raw_fd) } }
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,13 @@ use crate::iter;
|
||||
use crate::mem::{self, ManuallyDrop};
|
||||
use crate::os::raw::c_int;
|
||||
use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
|
||||
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::ptr;
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::unsupported;
|
||||
use crate::sys_common::FromInner;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
pub use crate::sys_common::fs::{remove_dir_all, try_exists};
|
||||
|
||||
@ -442,22 +443,50 @@ impl File {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &WasiFd {
|
||||
&self.fd
|
||||
}
|
||||
|
||||
pub fn into_fd(self) -> WasiFd {
|
||||
self.fd
|
||||
}
|
||||
|
||||
pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> {
|
||||
read_link(&self.fd, file)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c_int> for File {
|
||||
fn from_inner(fd: c_int) -> File {
|
||||
unsafe { File { fd: WasiFd::from_raw(fd) } }
|
||||
impl AsInner<WasiFd> for File {
|
||||
fn as_inner(&self) -> &WasiFd {
|
||||
&self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<WasiFd> for File {
|
||||
fn into_inner(self) -> WasiFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<WasiFd> for File {
|
||||
fn from_inner(fd: WasiFd) -> File {
|
||||
File { fd }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for File {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.fd.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for File {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.fd.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for File {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
unsafe { Self { fd: FromRawFd::from_raw_fd(raw_fd) } }
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,7 +503,7 @@ impl DirBuilder {
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("File").field("fd", &self.fd.as_raw()).finish()
|
||||
f.debug_struct("File").field("fd", &self.as_raw_fd()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -654,7 +683,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
|
||||
let relative = CStr::from_ptr(relative_path).to_bytes().to_vec();
|
||||
|
||||
return Ok((
|
||||
ManuallyDrop::new(WasiFd::from_raw(fd as c_int)),
|
||||
ManuallyDrop::new(WasiFd::from_raw_fd(fd as c_int)),
|
||||
PathBuf::from(OsString::from_vec(relative)),
|
||||
));
|
||||
}
|
||||
|
@ -5,13 +5,57 @@ use crate::convert::TryFrom;
|
||||
use crate::fmt;
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
||||
use crate::os::raw::c_int;
|
||||
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::sys::unsupported;
|
||||
use crate::sys_common::FromInner;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct Socket(WasiFd);
|
||||
|
||||
pub struct TcpStream {
|
||||
fd: WasiFd,
|
||||
inner: Socket,
|
||||
}
|
||||
|
||||
impl AsInner<WasiFd> for Socket {
|
||||
fn as_inner(&self) -> &WasiFd {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<WasiFd> for Socket {
|
||||
fn into_inner(self) -> WasiFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<WasiFd> for Socket {
|
||||
fn from_inner(inner: WasiFd) -> Socket {
|
||||
Socket(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for Socket {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Socket {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for Socket {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for Socket {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl TcpStream {
|
||||
@ -107,29 +151,29 @@ impl TcpStream {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &WasiFd {
|
||||
&self.fd
|
||||
pub fn socket(&self) -> &Socket {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn into_fd(self) -> WasiFd {
|
||||
self.fd
|
||||
pub fn into_socket(self) -> Socket {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c_int> for TcpStream {
|
||||
fn from_inner(fd: c_int) -> TcpStream {
|
||||
unsafe { TcpStream { fd: WasiFd::from_raw(fd) } }
|
||||
impl FromInner<Socket> for TcpStream {
|
||||
fn from_inner(socket: Socket) -> TcpStream {
|
||||
TcpStream { inner: socket }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("TcpStream").field("fd", &self.fd.as_raw()).finish()
|
||||
f.debug_struct("TcpStream").field("fd", &self.inner.as_raw_fd()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TcpListener {
|
||||
fd: WasiFd,
|
||||
inner: Socket,
|
||||
}
|
||||
|
||||
impl TcpListener {
|
||||
@ -173,29 +217,41 @@ impl TcpListener {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &WasiFd {
|
||||
&self.fd
|
||||
pub fn socket(&self) -> &Socket {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn into_fd(self) -> WasiFd {
|
||||
self.fd
|
||||
pub fn into_socket(self) -> Socket {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c_int> for TcpListener {
|
||||
fn from_inner(fd: c_int) -> TcpListener {
|
||||
unsafe { TcpListener { fd: WasiFd::from_raw(fd) } }
|
||||
impl AsInner<Socket> for TcpListener {
|
||||
fn as_inner(&self) -> &Socket {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<Socket> for TcpListener {
|
||||
fn into_inner(self) -> Socket {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<Socket> for TcpListener {
|
||||
fn from_inner(inner: Socket) -> TcpListener {
|
||||
TcpListener { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpListener {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("TcpListener").field("fd", &self.fd.as_raw()).finish()
|
||||
f.debug_struct("TcpListener").field("fd", &self.inner.as_raw_fd()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UdpSocket {
|
||||
fd: WasiFd,
|
||||
inner: Socket,
|
||||
}
|
||||
|
||||
impl UdpSocket {
|
||||
@ -323,24 +379,36 @@ impl UdpSocket {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> &WasiFd {
|
||||
&self.fd
|
||||
pub fn socket(&self) -> &Socket {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn into_fd(self) -> WasiFd {
|
||||
self.fd
|
||||
pub fn into_socket(self) -> Socket {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c_int> for UdpSocket {
|
||||
fn from_inner(fd: c_int) -> UdpSocket {
|
||||
unsafe { UdpSocket { fd: WasiFd::from_raw(fd) } }
|
||||
impl AsInner<Socket> for UdpSocket {
|
||||
fn as_inner(&self) -> &Socket {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<Socket> for UdpSocket {
|
||||
fn into_inner(self) -> Socket {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<Socket> for UdpSocket {
|
||||
fn from_inner(inner: Socket) -> UdpSocket {
|
||||
UdpSocket { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for UdpSocket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("UdpSocket").field("fd", &self.fd.as_raw()).finish()
|
||||
f.debug_struct("UdpSocket").field("fd", &self.inner.as_raw_fd()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use super::fd::WasiFd;
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::os::raw;
|
||||
use crate::os::wasi::io::{AsRawFd, FromRawFd};
|
||||
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
@ -13,9 +14,11 @@ impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Stdin {
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> raw::c_int {
|
||||
fn as_raw_fd(&self) -> raw::c_int {
|
||||
0
|
||||
}
|
||||
}
|
||||
@ -26,7 +29,7 @@ impl io::Read for Stdin {
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw_fd(self.as_raw_fd()) }).read(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -39,9 +42,11 @@ impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
Stdout
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Stdout {
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> raw::c_int {
|
||||
fn as_raw_fd(&self) -> raw::c_int {
|
||||
1
|
||||
}
|
||||
}
|
||||
@ -52,7 +57,7 @@ impl io::Write for Stdout {
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw_fd(self.as_raw_fd()) }).write(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -68,9 +73,11 @@ impl Stderr {
|
||||
pub const fn new() -> Stderr {
|
||||
Stderr
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Stderr {
|
||||
#[inline]
|
||||
pub fn as_raw_fd(&self) -> raw::c_int {
|
||||
fn as_raw_fd(&self) -> raw::c_int {
|
||||
2
|
||||
}
|
||||
}
|
||||
@ -81,7 +88,7 @@ impl io::Write for Stderr {
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
||||
ManuallyDrop::new(unsafe { WasiFd::from_raw_fd(self.as_raw_fd()) }).write(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -4,6 +4,7 @@ use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::mem;
|
||||
use crate::os::windows::io::{AsHandle, BorrowedHandle};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::ptr;
|
||||
use crate::slice;
|
||||
@ -11,7 +12,7 @@ use crate::sync::Arc;
|
||||
use crate::sys::handle::Handle;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::{c, cvt};
|
||||
use crate::sys_common::FromInner;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
use super::to_u16s;
|
||||
|
||||
@ -295,12 +296,12 @@ impl File {
|
||||
if handle == c::INVALID_HANDLE_VALUE {
|
||||
Err(Error::last_os_error())
|
||||
} else {
|
||||
Ok(File { handle: Handle::new(handle) })
|
||||
unsafe { Ok(File { handle: Handle::from_raw_handle(handle) }) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
cvt(unsafe { c::FlushFileBuffers(self.handle.raw()) })?;
|
||||
cvt(unsafe { c::FlushFileBuffers(self.handle.as_raw_handle()) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -313,7 +314,7 @@ impl File {
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
c::SetFileInformationByHandle(
|
||||
self.handle.raw(),
|
||||
self.handle.as_raw_handle(),
|
||||
c::FileEndOfFileInfo,
|
||||
&mut info as *mut _ as *mut _,
|
||||
size as c::DWORD,
|
||||
@ -326,7 +327,7 @@ impl File {
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
unsafe {
|
||||
let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed();
|
||||
cvt(c::GetFileInformationByHandle(self.handle.raw(), &mut info))?;
|
||||
cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
|
||||
let mut reparse_tag = 0;
|
||||
if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
|
||||
let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
@ -449,7 +450,7 @@ impl File {
|
||||
};
|
||||
let pos = pos as c::LARGE_INTEGER;
|
||||
let mut newpos = 0;
|
||||
cvt(unsafe { c::SetFilePointerEx(self.handle.raw(), pos, &mut newpos, whence) })?;
|
||||
cvt(unsafe { c::SetFilePointerEx(self.handle.as_raw_handle(), pos, &mut newpos, whence) })?;
|
||||
Ok(newpos as u64)
|
||||
}
|
||||
|
||||
@ -457,14 +458,6 @@ impl File {
|
||||
Ok(File { handle: self.handle.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)? })
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&self.handle
|
||||
}
|
||||
|
||||
pub fn into_handle(self) -> Handle {
|
||||
self.handle
|
||||
}
|
||||
|
||||
fn reparse_point<'a>(
|
||||
&self,
|
||||
space: &'a mut [u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE],
|
||||
@ -473,7 +466,7 @@ impl File {
|
||||
let mut bytes = 0;
|
||||
cvt({
|
||||
c::DeviceIoControl(
|
||||
self.handle.raw(),
|
||||
self.handle.as_raw_handle(),
|
||||
c::FSCTL_GET_REPARSE_POINT,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
@ -541,7 +534,7 @@ impl File {
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
c::SetFileInformationByHandle(
|
||||
self.handle.raw(),
|
||||
self.handle.as_raw_handle(),
|
||||
c::FileBasicInfo,
|
||||
&mut info as *mut _ as *mut _,
|
||||
size as c::DWORD,
|
||||
@ -551,9 +544,45 @@ impl File {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c::HANDLE> for File {
|
||||
fn from_inner(handle: c::HANDLE) -> File {
|
||||
File { handle: Handle::new(handle) }
|
||||
impl AsInner<Handle> for File {
|
||||
fn as_inner(&self) -> &Handle {
|
||||
&self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<Handle> for File {
|
||||
fn into_inner(self) -> Handle {
|
||||
self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<Handle> for File {
|
||||
fn from_inner(handle: Handle) -> File {
|
||||
File { handle: handle }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsHandle for File {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.as_inner().as_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawHandle for File {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.as_inner().as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for File {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.into_inner().into_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawHandle for File {
|
||||
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
|
||||
Self { handle: FromInner::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,7 +590,7 @@ impl fmt::Debug for File {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// FIXME(#24570): add more info here (e.g., mode)
|
||||
let mut b = f.debug_struct("File");
|
||||
b.field("handle", &self.handle.raw());
|
||||
b.field("handle", &self.handle.as_raw_handle());
|
||||
if let Ok(path) = get_path(&self) {
|
||||
b.field("path", &path);
|
||||
}
|
||||
@ -838,7 +867,7 @@ pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
fn get_path(f: &File) -> io::Result<PathBuf> {
|
||||
super::fill_utf16_buf(
|
||||
|buf, sz| unsafe {
|
||||
c::GetFinalPathNameByHandleW(f.handle.raw(), buf, sz, c::VOLUME_NAME_DOS)
|
||||
c::GetFinalPathNameByHandleW(f.handle.as_raw_handle(), buf, sz, c::VOLUME_NAME_DOS)
|
||||
},
|
||||
|buf| PathBuf::from(OsString::from_wide(buf)),
|
||||
)
|
||||
@ -909,7 +938,7 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
|
||||
opts.write(true);
|
||||
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
|
||||
let f = File::open(junction, &opts)?;
|
||||
let h = f.handle().raw();
|
||||
let h = f.as_inner().as_raw_handle();
|
||||
|
||||
unsafe {
|
||||
let mut data = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
|
@ -3,76 +3,87 @@
|
||||
use crate::cmp;
|
||||
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read};
|
||||
use crate::mem;
|
||||
use crate::ops::Deref;
|
||||
use crate::os::windows::io::{
|
||||
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
|
||||
};
|
||||
use crate::ptr;
|
||||
use crate::sys::c;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
/// An owned container for `HANDLE` object, closing them on Drop.
|
||||
///
|
||||
/// All methods are inherited through a `Deref` impl to `RawHandle`
|
||||
pub struct Handle(RawHandle);
|
||||
|
||||
/// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
|
||||
/// as well as Rust-y methods.
|
||||
///
|
||||
/// This does **not** drop the handle when it goes out of scope, use `Handle`
|
||||
/// instead for that.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct RawHandle(c::HANDLE);
|
||||
|
||||
unsafe impl Send for RawHandle {}
|
||||
unsafe impl Sync for RawHandle {}
|
||||
pub struct Handle(OwnedHandle);
|
||||
|
||||
impl Handle {
|
||||
pub fn new(handle: c::HANDLE) -> Handle {
|
||||
Handle(RawHandle::new(handle))
|
||||
}
|
||||
|
||||
pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
|
||||
unsafe {
|
||||
let event =
|
||||
c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, ptr::null());
|
||||
if event.is_null() { Err(io::Error::last_os_error()) } else { Ok(Handle::new(event)) }
|
||||
if event.is_null() {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Handle::from_raw_handle(event))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> c::HANDLE {
|
||||
let ret = self.raw();
|
||||
mem::forget(self);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Handle {
|
||||
type Target = RawHandle;
|
||||
fn deref(&self) -> &RawHandle {
|
||||
impl AsInner<OwnedHandle> for Handle {
|
||||
fn as_inner(&self) -> &OwnedHandle {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Handle {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = c::CloseHandle(self.raw());
|
||||
}
|
||||
impl IntoInner<OwnedHandle> for Handle {
|
||||
fn into_inner(self) -> OwnedHandle {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl RawHandle {
|
||||
pub fn new(handle: c::HANDLE) -> RawHandle {
|
||||
RawHandle(handle)
|
||||
impl FromInner<OwnedHandle> for Handle {
|
||||
fn from_inner(file_desc: OwnedHandle) -> Self {
|
||||
Self(file_desc)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn raw(&self) -> c::HANDLE {
|
||||
self.0
|
||||
impl AsHandle for Handle {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.0.as_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawHandle for Handle {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.0.as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawHandle for Handle {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.0.into_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawHandle for Handle {
|
||||
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
|
||||
Self(FromRawHandle::from_raw_handle(raw_handle))
|
||||
}
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let mut read = 0;
|
||||
let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
|
||||
let res = cvt(unsafe {
|
||||
c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, ptr::null_mut())
|
||||
c::ReadFile(
|
||||
self.as_raw_handle(),
|
||||
buf.as_mut_ptr() as c::LPVOID,
|
||||
len,
|
||||
&mut read,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
});
|
||||
|
||||
match res {
|
||||
@ -104,7 +115,13 @@ impl RawHandle {
|
||||
let mut overlapped: c::OVERLAPPED = mem::zeroed();
|
||||
overlapped.Offset = offset as u32;
|
||||
overlapped.OffsetHigh = (offset >> 32) as u32;
|
||||
cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, &mut overlapped))
|
||||
cvt(c::ReadFile(
|
||||
self.as_raw_handle(),
|
||||
buf.as_mut_ptr() as c::LPVOID,
|
||||
len,
|
||||
&mut read,
|
||||
&mut overlapped,
|
||||
))
|
||||
};
|
||||
match res {
|
||||
Ok(_) => Ok(read as usize),
|
||||
@ -120,7 +137,13 @@ impl RawHandle {
|
||||
) -> io::Result<Option<usize>> {
|
||||
let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
|
||||
let mut amt = 0;
|
||||
let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped));
|
||||
let res = cvt(c::ReadFile(
|
||||
self.as_raw_handle(),
|
||||
buf.as_ptr() as c::LPVOID,
|
||||
len,
|
||||
&mut amt,
|
||||
overlapped,
|
||||
));
|
||||
match res {
|
||||
Ok(_) => Ok(Some(amt as usize)),
|
||||
Err(e) => {
|
||||
@ -143,7 +166,8 @@ impl RawHandle {
|
||||
unsafe {
|
||||
let mut bytes = 0;
|
||||
let wait = if wait { c::TRUE } else { c::FALSE };
|
||||
let res = cvt(c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait));
|
||||
let res =
|
||||
cvt(c::GetOverlappedResult(self.as_raw_handle(), overlapped, &mut bytes, wait));
|
||||
match res {
|
||||
Ok(_) => Ok(bytes as usize),
|
||||
Err(e) => {
|
||||
@ -160,14 +184,20 @@ impl RawHandle {
|
||||
}
|
||||
|
||||
pub fn cancel_io(&self) -> io::Result<()> {
|
||||
unsafe { cvt(c::CancelIo(self.raw())).map(drop) }
|
||||
unsafe { cvt(c::CancelIo(self.as_raw_handle())).map(drop) }
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let mut amt = 0;
|
||||
let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
|
||||
cvt(unsafe {
|
||||
c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut())
|
||||
c::WriteFile(
|
||||
self.as_raw_handle(),
|
||||
buf.as_ptr() as c::LPVOID,
|
||||
len,
|
||||
&mut amt,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
})?;
|
||||
Ok(amt as usize)
|
||||
}
|
||||
@ -189,7 +219,7 @@ impl RawHandle {
|
||||
overlapped.Offset = offset as u32;
|
||||
overlapped.OffsetHigh = (offset >> 32) as u32;
|
||||
cvt(c::WriteFile(
|
||||
self.0,
|
||||
self.as_raw_handle(),
|
||||
buf.as_ptr() as c::LPVOID,
|
||||
len,
|
||||
&mut written,
|
||||
@ -210,7 +240,7 @@ impl RawHandle {
|
||||
let cur_proc = c::GetCurrentProcess();
|
||||
c::DuplicateHandle(
|
||||
cur_proc,
|
||||
self.0,
|
||||
self.as_raw_handle(),
|
||||
cur_proc,
|
||||
&mut ret,
|
||||
access,
|
||||
@ -218,11 +248,11 @@ impl RawHandle {
|
||||
options,
|
||||
)
|
||||
})?;
|
||||
Ok(Handle::new(ret))
|
||||
unsafe { Ok(Handle::from_raw_handle(ret)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for &'a RawHandle {
|
||||
impl<'a> Read for &'a Handle {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
(**self).read(buf)
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ use crate::cmp;
|
||||
use crate::io::{self, IoSlice, IoSliceMut, Read};
|
||||
use crate::mem;
|
||||
use crate::net::{Shutdown, SocketAddr};
|
||||
use crate::os::windows::io::{
|
||||
AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
|
||||
};
|
||||
use crate::ptr;
|
||||
use crate::sync::Once;
|
||||
use crate::sys;
|
||||
@ -24,7 +27,7 @@ pub mod netc {
|
||||
pub use crate::sys::c::*;
|
||||
}
|
||||
|
||||
pub struct Socket(c::SOCKET);
|
||||
pub struct Socket(OwnedSocket);
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
@ -109,7 +112,7 @@ impl Socket {
|
||||
};
|
||||
|
||||
if socket != c::INVALID_SOCKET {
|
||||
Ok(Self(socket))
|
||||
unsafe { Ok(Self::from_raw_socket(socket)) }
|
||||
} else {
|
||||
let error = unsafe { c::WSAGetLastError() };
|
||||
|
||||
@ -124,9 +127,11 @@ impl Socket {
|
||||
return Err(last_error());
|
||||
}
|
||||
|
||||
let socket = Self(socket);
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
unsafe {
|
||||
let socket = Self::from_raw_socket(socket);
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +139,7 @@ impl Socket {
|
||||
self.set_nonblocking(true)?;
|
||||
let result = {
|
||||
let (addrp, len) = addr.into_inner();
|
||||
let result = unsafe { c::connect(self.0, addrp, len) };
|
||||
let result = unsafe { c::connect(self.as_raw_socket(), addrp, len) };
|
||||
cvt(result).map(drop)
|
||||
};
|
||||
self.set_nonblocking(false)?;
|
||||
@ -160,7 +165,7 @@ impl Socket {
|
||||
let fds = {
|
||||
let mut fds = unsafe { mem::zeroed::<c::fd_set>() };
|
||||
fds.fd_count = 1;
|
||||
fds.fd_array[0] = self.0;
|
||||
fds.fd_array[0] = self.as_raw_socket();
|
||||
fds
|
||||
};
|
||||
|
||||
@ -194,17 +199,19 @@ impl Socket {
|
||||
}
|
||||
|
||||
pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result<Socket> {
|
||||
let socket = unsafe { c::accept(self.0, storage, len) };
|
||||
let socket = unsafe { c::accept(self.as_raw_socket(), storage, len) };
|
||||
|
||||
match socket {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
_ => Ok(Self(socket)),
|
||||
_ => unsafe { Ok(Self::from_raw_socket(socket)) },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<Socket> {
|
||||
let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
|
||||
let result = unsafe { c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info) };
|
||||
let result = unsafe {
|
||||
c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info)
|
||||
};
|
||||
cvt(result)?;
|
||||
let socket = unsafe {
|
||||
c::WSASocketW(
|
||||
@ -218,7 +225,7 @@ impl Socket {
|
||||
};
|
||||
|
||||
if socket != c::INVALID_SOCKET {
|
||||
Ok(Self(socket))
|
||||
unsafe { Ok(Self::from_inner(OwnedSocket::from_raw_socket(socket))) }
|
||||
} else {
|
||||
let error = unsafe { c::WSAGetLastError() };
|
||||
|
||||
@ -241,9 +248,11 @@ impl Socket {
|
||||
return Err(last_error());
|
||||
}
|
||||
|
||||
let socket = Self(socket);
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
unsafe {
|
||||
let socket = Self::from_inner(OwnedSocket::from_raw_socket(socket));
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +260,8 @@ impl Socket {
|
||||
// On unix when a socket is shut down all further reads return 0, so we
|
||||
// do the same on windows to map a shut down socket to returning EOF.
|
||||
let length = cmp::min(buf.len(), i32::MAX as usize) as i32;
|
||||
let result = unsafe { c::recv(self.0, buf.as_mut_ptr() as *mut _, length, flags) };
|
||||
let result =
|
||||
unsafe { c::recv(self.as_raw_socket(), buf.as_mut_ptr() as *mut _, length, flags) };
|
||||
|
||||
match result {
|
||||
c::SOCKET_ERROR => {
|
||||
@ -279,7 +289,7 @@ impl Socket {
|
||||
let mut flags = 0;
|
||||
let result = unsafe {
|
||||
c::WSARecv(
|
||||
self.0,
|
||||
self.as_raw_socket(),
|
||||
bufs.as_mut_ptr() as *mut c::WSABUF,
|
||||
length,
|
||||
&mut nread,
|
||||
@ -325,7 +335,7 @@ impl Socket {
|
||||
// do the same on windows to map a shut down socket to returning EOF.
|
||||
let result = unsafe {
|
||||
c::recvfrom(
|
||||
self.0,
|
||||
self.as_raw_socket(),
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
length,
|
||||
flags,
|
||||
@ -361,7 +371,7 @@ impl Socket {
|
||||
let mut nwritten = 0;
|
||||
let result = unsafe {
|
||||
c::WSASend(
|
||||
self.0,
|
||||
self.as_raw_socket(),
|
||||
bufs.as_ptr() as *const c::WSABUF as *mut _,
|
||||
length,
|
||||
&mut nwritten,
|
||||
@ -408,8 +418,10 @@ impl Socket {
|
||||
|
||||
#[cfg(not(target_vendor = "uwp"))]
|
||||
fn set_no_inherit(&self) -> io::Result<()> {
|
||||
sys::cvt(unsafe { c::SetHandleInformation(self.0 as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0) })
|
||||
.map(drop)
|
||||
sys::cvt(unsafe {
|
||||
c::SetHandleInformation(self.as_raw_socket() as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0)
|
||||
})
|
||||
.map(drop)
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "uwp")]
|
||||
@ -423,13 +435,14 @@ impl Socket {
|
||||
Shutdown::Read => c::SD_RECEIVE,
|
||||
Shutdown::Both => c::SD_BOTH,
|
||||
};
|
||||
let result = unsafe { c::shutdown(self.0, how) };
|
||||
let result = unsafe { c::shutdown(self.as_raw_socket(), how) };
|
||||
cvt(result).map(drop)
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
let mut nonblocking = nonblocking as c_ulong;
|
||||
let result = unsafe { c::ioctlsocket(self.0, c::FIONBIO as c_int, &mut nonblocking) };
|
||||
let result =
|
||||
unsafe { c::ioctlsocket(self.as_raw_socket(), c::FIONBIO as c_int, &mut nonblocking) };
|
||||
cvt(result).map(drop)
|
||||
}
|
||||
|
||||
@ -446,6 +459,11 @@ impl Socket {
|
||||
let raw: c_int = net::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?;
|
||||
if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
|
||||
}
|
||||
|
||||
// This is used by sys_common code to abstract over Windows and Unix.
|
||||
pub fn as_raw(&self) -> RawSocket {
|
||||
self.as_inner().as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(reason = "not public", issue = "none", feature = "fd_read")]
|
||||
@ -455,28 +473,44 @@ impl<'a> Read for &'a Socket {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Socket {
|
||||
fn drop(&mut self) {
|
||||
let _ = unsafe { c::closesocket(self.0) };
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<c::SOCKET> for Socket {
|
||||
fn as_inner(&self) -> &c::SOCKET {
|
||||
impl AsInner<OwnedSocket> for Socket {
|
||||
fn as_inner(&self) -> &OwnedSocket {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c::SOCKET> for Socket {
|
||||
fn from_inner(sock: c::SOCKET) -> Socket {
|
||||
impl FromInner<OwnedSocket> for Socket {
|
||||
fn from_inner(sock: OwnedSocket) -> Socket {
|
||||
Socket(sock)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<c::SOCKET> for Socket {
|
||||
fn into_inner(self) -> c::SOCKET {
|
||||
let ret = self.0;
|
||||
mem::forget(self);
|
||||
ret
|
||||
impl IntoInner<OwnedSocket> for Socket {
|
||||
fn into_inner(self) -> OwnedSocket {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsSocket for Socket {
|
||||
fn as_socket(&self) -> BorrowedSocket<'_> {
|
||||
self.0.as_socket()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawSocket for Socket {
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.0.as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawSocket for Socket {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
self.0.into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawSocket for Socket {
|
||||
unsafe fn from_raw_socket(raw_socket: RawSocket) -> Self {
|
||||
Self(FromRawSocket::from_raw_socket(raw_socket))
|
||||
}
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ fn home_dir_crt() -> Option<PathBuf> {
|
||||
if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
|
||||
return None;
|
||||
}
|
||||
let _handle = Handle::new(token);
|
||||
let _handle = Handle::from_raw_handle(token);
|
||||
super::fill_utf16_buf(
|
||||
|buf, mut sz| {
|
||||
match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
|
||||
|
@ -12,6 +12,7 @@ use crate::sys::c;
|
||||
use crate::sys::fs::{File, OpenOptions};
|
||||
use crate::sys::handle::Handle;
|
||||
use crate::sys::hashmap_random_keys;
|
||||
use crate::sys_common::IntoInner;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Anonymous pipes
|
||||
@ -21,6 +22,12 @@ pub struct AnonPipe {
|
||||
inner: Handle,
|
||||
}
|
||||
|
||||
impl IntoInner<Handle> for AnonPipe {
|
||||
fn into_inner(self) -> Handle {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pipes {
|
||||
pub ours: AnonPipe,
|
||||
pub theirs: AnonPipe,
|
||||
@ -123,7 +130,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
ours = Handle::new(handle);
|
||||
ours = Handle::from_raw_handle(handle);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -146,11 +153,11 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
|
||||
};
|
||||
opts.security_attributes(&mut sa);
|
||||
let theirs = File::open(Path::new(&name), &opts)?;
|
||||
let theirs = AnonPipe { inner: theirs.into_handle() };
|
||||
let theirs = AnonPipe { inner: theirs.into_inner() };
|
||||
|
||||
Ok(Pipes {
|
||||
ours: AnonPipe { inner: ours },
|
||||
theirs: AnonPipe { inner: theirs.into_handle() },
|
||||
theirs: AnonPipe { inner: theirs.into_inner() },
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -207,7 +214,7 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) ->
|
||||
|
||||
let mut p1 = AsyncPipe::new(p1, v1)?;
|
||||
let mut p2 = AsyncPipe::new(p2, v2)?;
|
||||
let objs = [p1.event.raw(), p2.event.raw()];
|
||||
let objs = [p1.event.as_raw_handle(), p2.event.as_raw_handle()];
|
||||
|
||||
// In a loop we wait for either pipe's scheduled read operation to complete.
|
||||
// If the operation completes with 0 bytes, that means EOF was reached, in
|
||||
@ -262,7 +269,7 @@ impl<'a> AsyncPipe<'a> {
|
||||
// I/O operation is successfully scheduled (what we want).
|
||||
let event = Handle::new_event(true, true)?;
|
||||
let mut overlapped: Box<c::OVERLAPPED> = unsafe { Box::new(mem::zeroed()) };
|
||||
overlapped.hEvent = event.raw();
|
||||
overlapped.hEvent = event.as_raw_handle();
|
||||
Ok(AsyncPipe { pipe, overlapped, event, dst, state: State::NotReading })
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ use crate::io::{self, Error, ErrorKind};
|
||||
use crate::mem;
|
||||
use crate::num::NonZeroI32;
|
||||
use crate::os::windows::ffi::OsStrExt;
|
||||
use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle};
|
||||
use crate::path::Path;
|
||||
use crate::ptr;
|
||||
use crate::sys::c;
|
||||
@ -26,7 +27,7 @@ use crate::sys::pipe::{self, AnonPipe};
|
||||
use crate::sys::stdio;
|
||||
use crate::sys_common::mutex::StaticMutex;
|
||||
use crate::sys_common::process::{CommandEnv, CommandEnvs};
|
||||
use crate::sys_common::AsInner;
|
||||
use crate::sys_common::{AsInner, IntoInner};
|
||||
|
||||
use libc::{c_void, EXIT_FAILURE, EXIT_SUCCESS};
|
||||
|
||||
@ -316,9 +317,9 @@ impl Command {
|
||||
let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?;
|
||||
let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?;
|
||||
let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?;
|
||||
si.hStdInput = stdin.raw();
|
||||
si.hStdOutput = stdout.raw();
|
||||
si.hStdError = stderr.raw();
|
||||
si.hStdInput = stdin.as_raw_handle();
|
||||
si.hStdOutput = stdout.as_raw_handle();
|
||||
si.hStdError = stderr.as_raw_handle();
|
||||
|
||||
unsafe {
|
||||
cvt(c::CreateProcessW(
|
||||
@ -338,9 +339,11 @@ impl Command {
|
||||
// We close the thread handle because we don't care about keeping
|
||||
// the thread id valid, and we aren't keeping the thread handle
|
||||
// around to be able to close it later.
|
||||
drop(Handle::new(pi.hThread));
|
||||
unsafe {
|
||||
drop(Handle::from_raw_handle(pi.hThread));
|
||||
|
||||
Ok((Process { handle: Handle::new(pi.hProcess) }, pipes))
|
||||
Ok((Process { handle: Handle::from_raw_handle(pi.hProcess) }, pipes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,13 +368,13 @@ impl Stdio {
|
||||
// should still be unavailable so propagate the
|
||||
// INVALID_HANDLE_VALUE.
|
||||
Stdio::Inherit => match stdio::get_handle(stdio_id) {
|
||||
Ok(io) => {
|
||||
let io = Handle::new(io);
|
||||
Ok(io) => unsafe {
|
||||
let io = Handle::from_raw_handle(io);
|
||||
let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS);
|
||||
io.into_raw();
|
||||
io.into_raw_handle();
|
||||
ret
|
||||
}
|
||||
Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)),
|
||||
},
|
||||
Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) },
|
||||
},
|
||||
|
||||
Stdio::MakePipe => {
|
||||
@ -397,7 +400,7 @@ impl Stdio {
|
||||
opts.read(stdio_id == c::STD_INPUT_HANDLE);
|
||||
opts.write(stdio_id != c::STD_INPUT_HANDLE);
|
||||
opts.security_attributes(&mut sa);
|
||||
File::open(Path::new("NUL"), &opts).map(|file| file.into_handle())
|
||||
File::open(Path::new("NUL"), &opts).map(|file| file.into_inner())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -411,7 +414,7 @@ impl From<AnonPipe> for Stdio {
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(file: File) -> Stdio {
|
||||
Stdio::Handle(file.into_handle())
|
||||
Stdio::Handle(file.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,29 +433,29 @@ pub struct Process {
|
||||
|
||||
impl Process {
|
||||
pub fn kill(&mut self) -> io::Result<()> {
|
||||
cvt(unsafe { c::TerminateProcess(self.handle.raw(), 1) })?;
|
||||
cvt(unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u32 {
|
||||
unsafe { c::GetProcessId(self.handle.raw()) as u32 }
|
||||
unsafe { c::GetProcessId(self.handle.as_raw_handle()) as u32 }
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
unsafe {
|
||||
let res = c::WaitForSingleObject(self.handle.raw(), c::INFINITE);
|
||||
let res = c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE);
|
||||
if res != c::WAIT_OBJECT_0 {
|
||||
return Err(Error::last_os_error());
|
||||
}
|
||||
let mut status = 0;
|
||||
cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))?;
|
||||
cvt(c::GetExitCodeProcess(self.handle.as_raw_handle(), &mut status))?;
|
||||
Ok(ExitStatus(status))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
||||
unsafe {
|
||||
match c::WaitForSingleObject(self.handle.raw(), 0) {
|
||||
match c::WaitForSingleObject(self.handle.as_raw_handle(), 0) {
|
||||
c::WAIT_OBJECT_0 => {}
|
||||
c::WAIT_TIMEOUT => {
|
||||
return Ok(None);
|
||||
@ -460,7 +463,7 @@ impl Process {
|
||||
_ => return Err(io::Error::last_os_error()),
|
||||
}
|
||||
let mut status = 0;
|
||||
cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))?;
|
||||
cvt(c::GetExitCodeProcess(self.handle.as_raw_handle(), &mut status))?;
|
||||
Ok(Some(ExitStatus(status)))
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
use crate::char::decode_utf16;
|
||||
use crate::cmp;
|
||||
use crate::io;
|
||||
use crate::os::windows::io::{FromRawHandle, IntoRawHandle};
|
||||
use crate::ptr;
|
||||
use crate::str;
|
||||
use crate::sys::c;
|
||||
@ -53,10 +54,12 @@ fn is_console(handle: c::HANDLE) -> bool {
|
||||
fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
|
||||
let handle = get_handle(handle_id)?;
|
||||
if !is_console(handle) {
|
||||
let handle = Handle::new(handle);
|
||||
let ret = handle.write(data);
|
||||
handle.into_raw(); // Don't close the handle
|
||||
return ret;
|
||||
unsafe {
|
||||
let handle = Handle::from_raw_handle(handle);
|
||||
let ret = handle.write(data);
|
||||
handle.into_raw_handle(); // Don't close the handle
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// As the console is meant for presenting text, we assume bytes of `data` come from a string
|
||||
@ -140,10 +143,12 @@ impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let handle = get_handle(c::STD_INPUT_HANDLE)?;
|
||||
if !is_console(handle) {
|
||||
let handle = Handle::new(handle);
|
||||
let ret = handle.read(buf);
|
||||
handle.into_raw(); // Don't close the handle
|
||||
return ret;
|
||||
unsafe {
|
||||
let handle = Handle::from_raw_handle(handle);
|
||||
let ret = handle.read(buf);
|
||||
handle.into_raw_handle(); // Don't close the handle
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if buf.len() == 0 {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::os::windows::io::{AsRawHandle, FromRawHandle};
|
||||
use crate::ptr;
|
||||
use crate::sys::c;
|
||||
use crate::sys::handle::Handle;
|
||||
@ -45,7 +46,7 @@ impl Thread {
|
||||
drop(Box::from_raw(p));
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Thread { handle: Handle::new(ret) })
|
||||
Ok(Thread { handle: Handle::from_raw_handle(ret) })
|
||||
};
|
||||
|
||||
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
|
||||
@ -71,7 +72,7 @@ impl Thread {
|
||||
}
|
||||
|
||||
pub fn join(self) {
|
||||
let rc = unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE) };
|
||||
let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
|
||||
if rc == c::WAIT_FAILED {
|
||||
panic!("failed to join on thread: {}", io::Error::last_os_error());
|
||||
}
|
||||
|
@ -61,13 +61,7 @@ cfg_if::cfg_if! {
|
||||
pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> {
|
||||
unsafe {
|
||||
let payload = &payload as *const T as *const c_void;
|
||||
cvt(c::setsockopt(
|
||||
*sock.as_inner(),
|
||||
opt,
|
||||
val,
|
||||
payload,
|
||||
mem::size_of::<T>() as c::socklen_t,
|
||||
))?;
|
||||
cvt(c::setsockopt(sock.as_raw(), opt, val, payload, mem::size_of::<T>() as c::socklen_t))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -76,7 +70,7 @@ pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<
|
||||
unsafe {
|
||||
let mut slot: T = mem::zeroed();
|
||||
let mut len = mem::size_of::<T>() as c::socklen_t;
|
||||
cvt(c::getsockopt(*sock.as_inner(), opt, val, &mut slot as *mut _ as *mut _, &mut len))?;
|
||||
cvt(c::getsockopt(sock.as_raw(), opt, val, &mut slot as *mut _ as *mut _, &mut len))?;
|
||||
assert_eq!(len as usize, mem::size_of::<T>());
|
||||
Ok(slot)
|
||||
}
|
||||
@ -217,7 +211,7 @@ impl TcpStream {
|
||||
let sock = Socket::new(addr, c::SOCK_STREAM)?;
|
||||
|
||||
let (addrp, len) = addr.into_inner();
|
||||
cvt_r(|| unsafe { c::connect(*sock.as_inner(), addrp, len) })?;
|
||||
cvt_r(|| unsafe { c::connect(sock.as_raw(), addrp, len) })?;
|
||||
Ok(TcpStream { inner: sock })
|
||||
}
|
||||
|
||||
@ -273,7 +267,7 @@ impl TcpStream {
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
|
||||
let ret = cvt(unsafe {
|
||||
c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
|
||||
c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
@ -288,11 +282,11 @@ impl TcpStream {
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
|
||||
sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
|
||||
sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
@ -348,7 +342,7 @@ impl fmt::Debug for TcpStream {
|
||||
}
|
||||
|
||||
let name = if cfg!(windows) { "socket" } else { "fd" };
|
||||
res.field(name, &self.inner.as_inner()).finish()
|
||||
res.field(name, &self.inner.as_raw()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,10 +374,10 @@ impl TcpListener {
|
||||
|
||||
// Bind our new socket
|
||||
let (addrp, len) = addr.into_inner();
|
||||
cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
|
||||
cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?;
|
||||
|
||||
// Start listening
|
||||
cvt(unsafe { c::listen(*sock.as_inner(), 128) })?;
|
||||
cvt(unsafe { c::listen(sock.as_raw(), 128) })?;
|
||||
Ok(TcpListener { inner: sock })
|
||||
}
|
||||
|
||||
@ -396,7 +390,7 @@ impl TcpListener {
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
|
||||
sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
|
||||
}
|
||||
|
||||
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
|
||||
@ -453,7 +447,7 @@ impl fmt::Debug for TcpListener {
|
||||
}
|
||||
|
||||
let name = if cfg!(windows) { "socket" } else { "fd" };
|
||||
res.field(name, &self.inner.as_inner()).finish()
|
||||
res.field(name, &self.inner.as_raw()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,7 +467,7 @@ impl UdpSocket {
|
||||
|
||||
let sock = Socket::new(addr, c::SOCK_DGRAM)?;
|
||||
let (addrp, len) = addr.into_inner();
|
||||
cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
|
||||
cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?;
|
||||
Ok(UdpSocket { inner: sock })
|
||||
}
|
||||
|
||||
@ -486,11 +480,11 @@ impl UdpSocket {
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe { c::getpeername(*self.inner.as_inner(), buf, len) })
|
||||
sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) })
|
||||
sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
|
||||
}
|
||||
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
@ -506,7 +500,7 @@ impl UdpSocket {
|
||||
let (dstp, dstlen) = dst.into_inner();
|
||||
let ret = cvt(unsafe {
|
||||
c::sendto(
|
||||
*self.inner.as_inner(),
|
||||
self.inner.as_raw(),
|
||||
buf.as_ptr() as *const c_void,
|
||||
len,
|
||||
MSG_NOSIGNAL,
|
||||
@ -643,14 +637,14 @@ impl UdpSocket {
|
||||
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
|
||||
let ret = cvt(unsafe {
|
||||
c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
|
||||
c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
let (addrp, len) = addr?.into_inner();
|
||||
cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(drop)
|
||||
cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addrp, len) }).map(drop)
|
||||
}
|
||||
}
|
||||
|
||||
@ -669,6 +663,6 @@ impl fmt::Debug for UdpSocket {
|
||||
}
|
||||
|
||||
let name = if cfg!(windows) { "socket" } else { "fd" };
|
||||
res.field(name, &self.inner.as_inner()).finish()
|
||||
res.field(name, &self.inner.as_raw()).finish()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user