diff options
Diffstat (limited to 'library/std/src/sys')
40 files changed, 14 insertions, 7702 deletions
diff --git a/library/std/src/sys/hermit/ext/ffi.rs b/library/std/src/sys/hermit/ext/ffi.rs deleted file mode 100644 index 07b59a02556..00000000000 --- a/library/std/src/sys/hermit/ext/ffi.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! HermitCore-specific extension to the primitives in the `std::ffi` module -//! -//! # Examples -//! -//! ``` -//! use std::ffi::OsString; -//! use std::os::hermit::ffi::OsStringExt; -//! -//! let bytes = b"foo".to_vec(); -//! -//! // OsStringExt::from_vec -//! let os_string = OsString::from_vec(bytes); -//! assert_eq!(os_string.to_str(), Some("foo")); -//! -//! // OsStringExt::into_vec -//! let bytes = os_string.into_vec(); -//! assert_eq!(bytes, b"foo"); -//! ``` -//! -//! ``` -//! use std::ffi::OsStr; -//! use std::os::hermit::ffi::OsStrExt; -//! -//! let bytes = b"foo"; -//! -//! // OsStrExt::from_bytes -//! let os_str = OsStr::from_bytes(bytes); -//! assert_eq!(os_str.to_str(), Some("foo")); -//! -//! // OsStrExt::as_bytes -//! let bytes = os_str.as_bytes(); -//! assert_eq!(bytes, b"foo"); -//! ``` - -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::os_str_bytes::*; diff --git a/library/std/src/sys/hermit/ext/mod.rs b/library/std/src/sys/hermit/ext/mod.rs deleted file mode 100644 index ea87d0ad2c9..00000000000 --- a/library/std/src/sys/hermit/ext/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![stable(feature = "rust1", since = "1.0.0")] -#![allow(missing_docs)] - -pub mod ffi; - -/// A prelude for conveniently writing platform-specific code. -/// -/// Includes all extension traits, and some important type definitions. -#[stable(feature = "rust1", since = "1.0.0")] -pub mod prelude { - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::ffi::{OsStrExt, OsStringExt}; -} diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 0c49a6fb6de..15a76bbd2c9 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -24,7 +24,6 @@ pub mod args; pub mod cmath; pub mod condvar; pub mod env; -pub mod ext; pub mod fd; pub mod fs; #[path = "../unsupported/io.rs"] diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 2450a7aac5e..f813587b1b3 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -49,80 +49,27 @@ cfg_if::cfg_if! { } } -// Import essential modules from both platforms when documenting. These are -// then later used in the `std::os` module when documenting, for example, -// Windows when we're compiling for Linux. +// Import essential modules from platforms used in `std::os` when documenting. +// +// Note that on some platforms those modules don't compile +// (missing things in `libc` which is empty), so they are not included in `std::os` and can be +// omitted here as well. #[cfg(doc)] +#[cfg(not(any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") +)))] cfg_if::cfg_if! { - if #[cfg(unix)] { - // On unix we'll document what's already available - #[stable(feature = "rust1", since = "1.0.0")] - pub use self::ext as unix_ext; - } else if #[cfg(any(target_os = "hermit", - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx")))] { - // On non-WASI wasm right now the module below doesn't compile - // (missing things in `libc` which is empty) so just omit everything - // with an empty module - #[unstable(issue = "none", feature = "std_internals")] - #[allow(missing_docs)] - pub mod unix_ext {} - } else { - #[path = "unix/ext/mod.rs"] - pub mod unix_ext; - } -} - -#[cfg(doc)] -cfg_if::cfg_if! { - if #[cfg(windows)] { - // On windows we'll just be documenting what's already available - #[allow(missing_docs)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use self::ext as windows_ext; - } else if #[cfg(any(target_os = "hermit", - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx")))] { - // On non-WASI wasm right now the shim below doesn't compile, so - // just omit it - #[unstable(issue = "none", feature = "std_internals")] - #[allow(missing_docs)] - pub mod windows_ext {} - } else { - // On all other platforms (aka linux/osx/etc) then pull in a "minimal" + if #[cfg(not(windows))] { + // On non-Windows platforms (aka linux/osx/etc) pull in a "minimal" // amount of windows goop which ends up compiling + #[macro_use] #[path = "windows/compat.rs"] - mod compat; + pub mod compat; #[path = "windows/c.rs"] - mod c; - - #[path = "windows/ext/mod.rs"] - pub mod windows_ext; - } -} - -#[cfg(doc)] -cfg_if::cfg_if! { - if #[cfg(target_os = "wasi")] { - // On WASI we'll document what's already available - #[stable(feature = "wasi_ext_doc", since = "1.35.0")] - pub use self::ext as wasi_ext; - } else if #[cfg(any(target_os = "hermit", - target_arch = "wasm32", - all(target_vendor = "fortanix", target_env = "sgx")))] { - // On non-WASI wasm right now the module below doesn't compile - // (missing things in `libc` which is empty) so just omit everything - // with an empty module - #[unstable(issue = "none", feature = "std_internals")] - #[allow(missing_docs)] - pub mod wasi_ext {} - } else { - // On other platforms like Windows document the bare bones of WASI - #[path = "wasi/ext/mod.rs"] - #[stable(feature = "wasi_ext_doc", since = "1.35.0")] - pub mod wasi_ext; + pub mod c; } } diff --git a/library/std/src/sys/sgx/ext/arch.rs b/library/std/src/sys/sgx/ext/arch.rs deleted file mode 100644 index b0170e67446..00000000000 --- a/library/std/src/sys/sgx/ext/arch.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! SGX-specific access to architectural features. -//! -//! The functionality in this module is further documented in the Intel -//! Software Developer's Manual, Volume 3, Chapter 40. -#![unstable(feature = "sgx_platform", issue = "56975")] - -use crate::mem::MaybeUninit; - -/// Wrapper struct to force 16-byte alignment. -#[repr(align(16))] -#[unstable(feature = "sgx_platform", issue = "56975")] -pub struct Align16<T>(pub T); - -/// Wrapper struct to force 128-byte alignment. -#[repr(align(128))] -#[unstable(feature = "sgx_platform", issue = "56975")] -pub struct Align128<T>(pub T); - -/// Wrapper struct to force 512-byte alignment. -#[repr(align(512))] -#[unstable(feature = "sgx_platform", issue = "56975")] -pub struct Align512<T>(pub T); - -const ENCLU_EREPORT: u32 = 0; -const ENCLU_EGETKEY: u32 = 1; - -/// Call the `EGETKEY` instruction to obtain a 128-bit secret key. -#[unstable(feature = "sgx_platform", issue = "56975")] -pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> { - unsafe { - let mut out = MaybeUninit::uninit(); - let error; - - asm!( - // rbx is reserved by LLVM - "xchg {0}, rbx", - "enclu", - "mov rbx, {0}", - inout(reg) request => _, - inlateout("eax") ENCLU_EGETKEY => error, - in("rcx") out.as_mut_ptr(), - options(nostack), - ); - - match error { - 0 => Ok(out.assume_init()), - err => Err(err), - } - } -} - -/// Call the `EREPORT` instruction. -/// -/// This creates a cryptographic report describing the contents of the current -/// enclave. The report may be verified by the enclave described in -/// `targetinfo`. -#[unstable(feature = "sgx_platform", issue = "56975")] -pub fn ereport( - targetinfo: &Align512<[u8; 512]>, - reportdata: &Align128<[u8; 64]>, -) -> Align512<[u8; 432]> { - unsafe { - let mut report = MaybeUninit::uninit(); - - asm!( - // rbx is reserved by LLVM - "xchg {0}, rbx", - "enclu", - "mov rbx, {0}", - inout(reg) targetinfo => _, - in("eax") ENCLU_EREPORT, - in("rcx") reportdata, - in("rdx") report.as_mut_ptr(), - options(preserves_flags, nostack), - ); - - report.assume_init() - } -} diff --git a/library/std/src/sys/sgx/ext/ffi.rs b/library/std/src/sys/sgx/ext/ffi.rs deleted file mode 100644 index 63fc5ff2866..00000000000 --- a/library/std/src/sys/sgx/ext/ffi.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! SGX-specific extension to the primitives in the `std::ffi` module -//! -//! # Examples -//! -//! ``` -//! use std::ffi::OsString; -//! use std::os::fortanix_sgx::ffi::OsStringExt; -//! -//! let bytes = b"foo".to_vec(); -//! -//! // OsStringExt::from_vec -//! let os_string = OsString::from_vec(bytes); -//! assert_eq!(os_string.to_str(), Some("foo")); -//! -//! // OsStringExt::into_vec -//! let bytes = os_string.into_vec(); -//! assert_eq!(bytes, b"foo"); -//! ``` -//! -//! ``` -//! use std::ffi::OsStr; -//! use std::os::fortanix_sgx::ffi::OsStrExt; -//! -//! let bytes = b"foo"; -//! -//! // OsStrExt::from_bytes -//! let os_str = OsStr::from_bytes(bytes); -//! assert_eq!(os_str.to_str(), Some("foo")); -//! -//! // OsStrExt::as_bytes -//! let bytes = os_str.as_bytes(); -//! assert_eq!(bytes, b"foo"); -//! ``` - -#![unstable(feature = "sgx_platform", issue = "56975")] - -#[unstable(feature = "sgx_platform", issue = "56975")] -pub use crate::sys_common::os_str_bytes::*; diff --git a/library/std/src/sys/sgx/ext/io.rs b/library/std/src/sys/sgx/ext/io.rs deleted file mode 100644 index 7223ade6815..00000000000 --- a/library/std/src/sys/sgx/ext/io.rs +++ /dev/null @@ -1,144 +0,0 @@ -//! SGX-specific extensions to general I/O primitives -//! -//! SGX file descriptors behave differently from Unix file descriptors. See the -//! description of [`TryIntoRawFd`] for more details. -#![unstable(feature = "sgx_platform", issue = "56975")] - -use crate::net; -pub use crate::sys::abi::usercalls::raw::Fd as RawFd; -use crate::sys::{self, AsInner, FromInner, IntoInner, TryIntoInner}; - -/// A trait to extract the raw SGX file descriptor from an underlying -/// object. -#[unstable(feature = "sgx_platform", issue = "56975")] -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. - #[unstable(feature = "sgx_platform", issue = "56975")] - fn as_raw_fd(&self) -> RawFd; -} - -/// A trait to express the ability to construct an object from a raw file -/// descriptor. -#[unstable(feature = "sgx_platform", issue = "56975")] -pub trait FromRawFd { - /// An associated type that contains relevant metadata for `Self`. - type Metadata: Default; - - /// Constructs a new instance of `Self` from the given raw file - /// descriptor and metadata. - /// - /// 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. - #[unstable(feature = "sgx_platform", issue = "56975")] - unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> Self; -} - -/// A trait to express the ability to consume an object and acquire ownership of -/// its raw file descriptor. -#[unstable(feature = "sgx_platform", issue = "56975")] -pub trait TryIntoRawFd: Sized { - /// Consumes this object, returning the raw underlying file descriptor, if - /// this object is not cloned. - /// - /// 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. - /// - /// Unlike other platforms, on SGX, the file descriptor is shared between - /// all clones of an object. To avoid race conditions, this function will - /// only return `Ok` when called on the final clone. - #[unstable(feature = "sgx_platform", issue = "56975")] - fn try_into_raw_fd(self) -> Result<RawFd, Self>; -} - -impl AsRawFd for net::TcpStream { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self.as_inner().as_inner().as_inner().as_inner() - } -} - -impl AsRawFd for net::TcpListener { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self.as_inner().as_inner().as_inner().as_inner() - } -} - -/// Metadata for `TcpStream`. -#[derive(Debug, Clone, Default)] -#[unstable(feature = "sgx_platform", issue = "56975")] -pub struct TcpStreamMetadata { - /// Local address of the TCP stream - pub local_addr: Option<String>, - /// Peer address of the TCP stream - pub peer_addr: Option<String>, -} - -impl FromRawFd for net::TcpStream { - type Metadata = TcpStreamMetadata; - - #[inline] - unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpStream { - let fd = sys::fd::FileDesc::from_inner(fd); - let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); - net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, metadata.peer_addr))) - } -} - -/// Metadata for `TcpListener`. -#[derive(Debug, Clone, Default)] -#[unstable(feature = "sgx_platform", issue = "56975")] -pub struct TcpListenerMetadata { - /// Local address of the TCP listener - pub local_addr: Option<String>, -} - -impl FromRawFd for net::TcpListener { - type Metadata = TcpListenerMetadata; - - #[inline] - unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpListener { - let fd = sys::fd::FileDesc::from_inner(fd); - let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); - net::TcpListener::from_inner(sys::net::TcpListener::from_inner(socket)) - } -} - -impl TryIntoRawFd for net::TcpStream { - #[inline] - fn try_into_raw_fd(self) -> Result<RawFd, Self> { - let (socket, peer_addr) = self.into_inner().into_inner(); - match socket.try_into_inner() { - Ok(fd) => Ok(fd.into_inner()), - Err(socket) => { - let sys = sys::net::TcpStream::from_inner((socket, peer_addr)); - Err(net::TcpStream::from_inner(sys)) - } - } - } -} - -impl TryIntoRawFd for net::TcpListener { - #[inline] - fn try_into_raw_fd(self) -> Result<RawFd, Self> { - match self.into_inner().into_inner().try_into_inner() { - Ok(fd) => Ok(fd.into_inner()), - Err(socket) => { - let sys = sys::net::TcpListener::from_inner(socket); - Err(net::TcpListener::from_inner(sys)) - } - } - } -} diff --git a/library/std/src/sys/sgx/ext/mod.rs b/library/std/src/sys/sgx/ext/mod.rs deleted file mode 100644 index 258ad3cd218..00000000000 --- a/library/std/src/sys/sgx/ext/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![unstable(feature = "sgx_platform", issue = "56975")] - -pub mod arch; -pub mod ffi; -pub mod io; diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index bf3bd57e982..cdfceca19fc 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -17,7 +17,6 @@ pub mod args; pub mod cmath; pub mod condvar; pub mod env; -pub mod ext; pub mod fd; #[path = "../unsupported/fs.rs"] pub mod fs; diff --git a/library/std/src/sys/unix/ext/ffi.rs b/library/std/src/sys/unix/ext/ffi.rs deleted file mode 100644 index 123f85deaf9..00000000000 --- a/library/std/src/sys/unix/ext/ffi.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Unix-specific extension to the primitives in the `std::ffi` module. -//! -//! # Examples -//! -//! ``` -//! use std::ffi::OsString; -//! use std::os::unix::ffi::OsStringExt; -//! -//! let bytes = b"foo".to_vec(); -//! -//! // OsStringExt::from_vec -//! let os_string = OsString::from_vec(bytes); -//! assert_eq!(os_string.to_str(), Some("foo")); -//! -//! // OsStringExt::into_vec -//! let bytes = os_string.into_vec(); -//! assert_eq!(bytes, b"foo"); -//! ``` -//! -//! ``` -//! use std::ffi::OsStr; -//! use std::os::unix::ffi::OsStrExt; -//! -//! let bytes = b"foo"; -//! -//! // OsStrExt::from_bytes -//! let os_str = OsStr::from_bytes(bytes); -//! assert_eq!(os_str.to_str(), Some("foo")); -//! -//! // OsStrExt::as_bytes -//! let bytes = os_str.as_bytes(); -//! assert_eq!(bytes, b"foo"); -//! ``` - -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::os_str_bytes::*; diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs deleted file mode 100644 index 9cf51be2836..00000000000 --- a/library/std/src/sys/unix/ext/fs.rs +++ /dev/null @@ -1,912 +0,0 @@ -//! Unix-specific extensions to primitives in the `std::fs` module. - -#![stable(feature = "rust1", since = "1.0.0")] - -use super::platform::fs::MetadataExt as _; -use crate::fs::{self, OpenOptions, Permissions}; -use crate::io; -use crate::path::Path; -use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut, FromInner}; -// Used for `File::read` on intra-doc links -#[allow(unused_imports)] -use io::{Read, Write}; - -/// Unix-specific extensions to [`fs::File`]. -#[stable(feature = "file_offset", since = "1.15.0")] -pub trait FileExt { - /// Reads a number of bytes starting from a given offset. - /// - /// Returns the number of bytes read. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// Note that similar to [`File::read`], it is not an error to return with a - /// short read. - /// - /// [`File::read`]: fs::File::read - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs::File; - /// use std::os::unix::prelude::FileExt; - /// - /// fn main() -> io::Result<()> { - /// let mut buf = [0u8; 8]; - /// let file = File::open("foo.txt")?; - /// - /// // We now read 8 bytes from the offset 10. - /// let num_bytes_read = file.read_at(&mut buf, 10)?; - /// println!("read {} bytes: {:?}", num_bytes_read, buf); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_offset", since = "1.15.0")] - fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>; - - /// Reads the exact number of byte required to fill `buf` from the given offset. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// Similar to [`io::Read::read_exact`] but uses [`read_at`] instead of `read`. - /// - /// [`read_at`]: FileExt::read_at - /// - /// # Errors - /// - /// If this function encounters an error of the kind - /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation - /// will continue. - /// - /// If this function encounters an "end of file" before completely filling - /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`]. - /// The contents of `buf` are unspecified in this case. - /// - /// If any other read error is encountered then this function immediately - /// returns. The contents of `buf` are unspecified in this case. - /// - /// If this function returns an error, it is unspecified how many bytes it - /// has read, but it will never read more than would be necessary to - /// completely fill the buffer. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs::File; - /// use std::os::unix::prelude::FileExt; - /// - /// fn main() -> io::Result<()> { - /// let mut buf = [0u8; 8]; - /// let file = File::open("foo.txt")?; - /// - /// // We now read exactly 8 bytes from the offset 10. - /// file.read_exact_at(&mut buf, 10)?; - /// println!("read {} bytes: {:?}", buf.len(), buf); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "rw_exact_all_at", since = "1.33.0")] - fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { - while !buf.is_empty() { - match self.read_at(buf, offset) { - Ok(0) => break, - Ok(n) => { - let tmp = buf; - buf = &mut tmp[n..]; - offset += n as u64; - } - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(e) => return Err(e), - } - } - if !buf.is_empty() { - Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) - } else { - Ok(()) - } - } - - /// Writes a number of bytes starting from a given offset. - /// - /// Returns the number of bytes written. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// When writing beyond the end of the file, the file is appropriately - /// extended and the intermediate bytes are initialized with the value 0. - /// - /// Note that similar to [`File::write`], it is not an error to return a - /// short write. - /// - /// [`File::write`]: fs::File::write - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::io; - /// use std::os::unix::prelude::FileExt; - /// - /// fn main() -> io::Result<()> { - /// let file = File::open("foo.txt")?; - /// - /// // We now write at the offset 10. - /// file.write_at(b"sushi", 10)?; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_offset", since = "1.15.0")] - fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>; - - /// Attempts to write an entire buffer starting from a given offset. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// This method will continuously call [`write_at`] until there is no more data - /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is - /// returned. This method will not return until the entire buffer has been - /// successfully written or such an error occurs. The first error that is - /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be - /// returned. - /// - /// # Errors - /// - /// This function will return the first error of - /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns. - /// - /// [`write_at`]: FileExt::write_at - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::io; - /// use std::os::unix::prelude::FileExt; - /// - /// fn main() -> io::Result<()> { - /// let file = File::open("foo.txt")?; - /// - /// // We now write at the offset 10. - /// file.write_all_at(b"sushi", 10)?; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "rw_exact_all_at", since = "1.33.0")] - fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { - while !buf.is_empty() { - match self.write_at(buf, offset) { - Ok(0) => { - return Err(io::Error::new_const( - io::ErrorKind::WriteZero, - &"failed to write whole buffer", - )); - } - Ok(n) => { - buf = &buf[n..]; - offset += n as u64 - } - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(e) => return Err(e), - } - } - Ok(()) - } -} - -#[stable(feature = "file_offset", since = "1.15.0")] -impl FileExt for fs::File { - fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { - self.as_inner().read_at(buf, offset) - } - fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { - self.as_inner().write_at(buf, offset) - } -} - -/// Unix-specific extensions to [`fs::Permissions`]. -#[stable(feature = "fs_ext", since = "1.1.0")] -pub trait PermissionsExt { - /// Returns the underlying raw `st_mode` bits that contain the standard - /// Unix permissions for this file. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; - /// - /// fn main() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let permissions = metadata.permissions(); - /// - /// println!("permissions: {:o}", permissions.mode()); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "fs_ext", since = "1.1.0")] - fn mode(&self) -> u32; - - /// Sets the underlying raw bits for this set of permissions. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::os::unix::fs::PermissionsExt; - /// - /// fn main() -> std::io::Result<()> { - /// let f = File::create("foo.txt")?; - /// let metadata = f.metadata()?; - /// let mut permissions = metadata.permissions(); - /// - /// permissions.set_mode(0o644); // Read/write for owner and read for others. - /// assert_eq!(permissions.mode(), 0o644); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "fs_ext", since = "1.1.0")] - fn set_mode(&mut self, mode: u32); - - /// Creates a new instance of `Permissions` from the given set of Unix - /// permission bits. - /// - /// # Examples - /// - /// ``` - /// use std::fs::Permissions; - /// use std::os::unix::fs::PermissionsExt; - /// - /// // Read/write for owner and read for others. - /// let permissions = Permissions::from_mode(0o644); - /// assert_eq!(permissions.mode(), 0o644); - /// ``` - #[stable(feature = "fs_ext", since = "1.1.0")] - fn from_mode(mode: u32) -> Self; -} - -#[stable(feature = "fs_ext", since = "1.1.0")] -impl PermissionsExt for Permissions { - fn mode(&self) -> u32 { - self.as_inner().mode() - } - - fn set_mode(&mut self, mode: u32) { - *self = Permissions::from_inner(FromInner::from_inner(mode)); - } - - fn from_mode(mode: u32) -> Permissions { - Permissions::from_inner(FromInner::from_inner(mode)) - } -} - -/// Unix-specific extensions to [`fs::OpenOptions`]. -#[stable(feature = "fs_ext", since = "1.1.0")] -pub trait OpenOptionsExt { - /// Sets the mode bits that a new file will be created with. - /// - /// If a new file is created as part of an `OpenOptions::open` call then this - /// specified `mode` will be used as the permission bits for the new file. - /// If no `mode` is set, the default of `0o666` will be used. - /// The operating system masks out bits with the system's `umask`, to produce - /// the final permissions. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::OpenOptions; - /// use std::os::unix::fs::OpenOptionsExt; - /// - /// # fn main() { - /// let mut options = OpenOptions::new(); - /// options.mode(0o644); // Give read/write for owner and read for others. - /// let file = options.open("foo.txt"); - /// # } - /// ``` - #[stable(feature = "fs_ext", since = "1.1.0")] - fn mode(&mut self, mode: u32) -> &mut Self; - - /// Pass custom flags to the `flags` argument of `open`. - /// - /// The bits that define the access mode are masked out with `O_ACCMODE`, to - /// ensure they do not interfere with the access mode set by Rusts options. - /// - /// Custom flags can only set flags, not remove flags set by Rusts options. - /// This options overwrites any previously set custom flags. - /// - /// # Examples - /// - /// ```no_run - /// # #![feature(rustc_private)] - /// extern crate libc; - /// use std::fs::OpenOptions; - /// use std::os::unix::fs::OpenOptionsExt; - /// - /// # fn main() { - /// let mut options = OpenOptions::new(); - /// options.write(true); - /// if cfg!(unix) { - /// options.custom_flags(libc::O_NOFOLLOW); - /// } - /// let file = options.open("foo.txt"); - /// # } - /// ``` - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn custom_flags(&mut self, flags: i32) -> &mut Self; -} - -#[stable(feature = "fs_ext", since = "1.1.0")] -impl OpenOptionsExt for OpenOptions { - fn mode(&mut self, mode: u32) -> &mut OpenOptions { - self.as_inner_mut().mode(mode); - self - } - - fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions { - self.as_inner_mut().custom_flags(flags); - self - } -} - -/// Unix-specific extensions to [`fs::Metadata`]. -#[stable(feature = "metadata_ext", since = "1.1.0")] -pub trait MetadataExt { - /// Returns the ID of the device containing the file. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let dev_id = meta.dev(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn dev(&self) -> u64; - /// Returns the inode number. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let inode = meta.ino(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn ino(&self) -> u64; - /// Returns the rights applied to this file. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let mode = meta.mode(); - /// let user_has_write_access = mode & 0o200; - /// let user_has_read_write_access = mode & 0o600; - /// let group_has_read_access = mode & 0o040; - /// let others_have_exec_access = mode & 0o001; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn mode(&self) -> u32; - /// Returns the number of hard links pointing to this file. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nb_hard_links = meta.nlink(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn nlink(&self) -> u64; - /// Returns the user ID of the owner of this file. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let user_id = meta.uid(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn uid(&self) -> u32; - /// Returns the group ID of the owner of this file. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let group_id = meta.gid(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn gid(&self) -> u32; - /// Returns the device ID of this file (if it is a special one). - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let device_id = meta.rdev(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn rdev(&self) -> u64; - /// Returns the total size of this file in bytes. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let file_size = meta.size(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn size(&self) -> u64; - /// Returns the last access time of the file, in seconds since Unix Epoch. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_access_time = meta.atime(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn atime(&self) -> i64; - /// Returns the last access time of the file, in nanoseconds since [`atime`]. - /// - /// [`atime`]: MetadataExt::atime - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_access_time = meta.atime_nsec(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn atime_nsec(&self) -> i64; - /// Returns the last modification time of the file, in seconds since Unix Epoch. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_modification_time = meta.mtime(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn mtime(&self) -> i64; - /// Returns the last modification time of the file, in nanoseconds since [`mtime`]. - /// - /// [`mtime`]: MetadataExt::mtime - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_modification_time = meta.mtime_nsec(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn mtime_nsec(&self) -> i64; - /// Returns the last status change time of the file, in seconds since Unix Epoch. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let last_status_change_time = meta.ctime(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn ctime(&self) -> i64; - /// Returns the last status change time of the file, in nanoseconds since [`ctime`]. - /// - /// [`ctime`]: MetadataExt::ctime - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let nano_last_status_change_time = meta.ctime_nsec(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn ctime_nsec(&self) -> i64; - /// Returns the block size for filesystem I/O. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let block_size = meta.blksize(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn blksize(&self) -> u64; - /// Returns the number of blocks allocated to the file, in 512-byte units. - /// - /// Please note that this may be smaller than `st_size / 512` when the file has holes. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::MetadataExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("some_file")?; - /// let blocks = meta.blocks(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn blocks(&self) -> u64; - #[cfg(target_os = "vxworks")] - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn attrib(&self) -> u8; -} - -#[stable(feature = "metadata_ext", since = "1.1.0")] -impl MetadataExt for fs::Metadata { - fn dev(&self) -> u64 { - self.st_dev() - } - fn ino(&self) -> u64 { - self.st_ino() - } - fn mode(&self) -> u32 { - self.st_mode() - } - fn nlink(&self) -> u64 { - self.st_nlink() - } - fn uid(&self) -> u32 { - self.st_uid() - } - fn gid(&self) -> u32 { - self.st_gid() - } - fn rdev(&self) -> u64 { - self.st_rdev() - } - fn size(&self) -> u64 { - self.st_size() - } - fn atime(&self) -> i64 { - self.st_atime() - } - fn atime_nsec(&self) -> i64 { - self.st_atime_nsec() - } - fn mtime(&self) -> i64 { - self.st_mtime() - } - fn mtime_nsec(&self) -> i64 { - self.st_mtime_nsec() - } - fn ctime(&self) -> i64 { - self.st_ctime() - } - fn ctime_nsec(&self) -> i64 { - self.st_ctime_nsec() - } - fn blksize(&self) -> u64 { - self.st_blksize() - } - fn blocks(&self) -> u64 { - self.st_blocks() - } - #[cfg(target_os = "vxworks")] - fn attrib(&self) -> u8 { - self.st_attrib() - } -} - -/// Unix-specific extensions for [`fs::FileType`]. -/// -/// Adds support for special Unix file types such as block/character devices, -/// pipes, and sockets. -#[stable(feature = "file_type_ext", since = "1.5.0")] -pub trait FileTypeExt { - /// Returns `true` if this file type is a block device. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::FileTypeExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("block_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_block_device()); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_type_ext", since = "1.5.0")] - fn is_block_device(&self) -> bool; - /// Returns `true` if this file type is a char device. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::FileTypeExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("char_device_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_char_device()); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_type_ext", since = "1.5.0")] - fn is_char_device(&self) -> bool; - /// Returns `true` if this file type is a fifo. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::FileTypeExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("fifo_file")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_fifo()); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_type_ext", since = "1.5.0")] - fn is_fifo(&self) -> bool; - /// Returns `true` if this file type is a socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs; - /// use std::os::unix::fs::FileTypeExt; - /// use std::io; - /// - /// fn main() -> io::Result<()> { - /// let meta = fs::metadata("unix.socket")?; - /// let file_type = meta.file_type(); - /// assert!(file_type.is_socket()); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_type_ext", since = "1.5.0")] - fn is_socket(&self) -> bool; -} - -#[stable(feature = "file_type_ext", since = "1.5.0")] -impl FileTypeExt for fs::FileType { - fn is_block_device(&self) -> bool { - self.as_inner().is(libc::S_IFBLK) - } - fn is_char_device(&self) -> bool { - self.as_inner().is(libc::S_IFCHR) - } - fn is_fifo(&self) -> bool { - self.as_inner().is(libc::S_IFIFO) - } - fn is_socket(&self) -> bool { - self.as_inner().is(libc::S_IFSOCK) - } -} - -/// Unix-specific extension methods for [`fs::DirEntry`]. -#[stable(feature = "dir_entry_ext", since = "1.1.0")] -pub trait DirEntryExt { - /// Returns the underlying `d_ino` field in the contained `dirent` - /// structure. - /// - /// # Examples - /// - /// ``` - /// use std::fs; - /// use std::os::unix::fs::DirEntryExt; - /// - /// if let Ok(entries) = fs::read_dir(".") { - /// for entry in entries { - /// if let Ok(entry) = entry { - /// // Here, `entry` is a `DirEntry`. - /// println!("{:?}: {}", entry.file_name(), entry.ino()); - /// } - /// } - /// } - /// ``` - #[stable(feature = "dir_entry_ext", since = "1.1.0")] - fn ino(&self) -> u64; -} - -#[stable(feature = "dir_entry_ext", since = "1.1.0")] -impl DirEntryExt for fs::DirEntry { - fn ino(&self) -> u64 { - self.as_inner().ino() - } -} - -/// Creates a new symbolic link on the filesystem. -/// -/// The `link` path will be a symbolic link pointing to the `original` path. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::fs; -/// -/// fn main() -> std::io::Result<()> { -/// fs::symlink("a.txt", "b.txt")?; -/// Ok(()) -/// } -/// ``` -#[stable(feature = "symlink", since = "1.1.0")] -pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> { - sys::fs::symlink(original.as_ref(), link.as_ref()) -} - -/// Unix-specific extensions to [`fs::DirBuilder`]. -#[stable(feature = "dir_builder", since = "1.6.0")] -pub trait DirBuilderExt { - /// Sets the mode to create new directories with. This option defaults to - /// 0o777. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::DirBuilder; - /// use std::os::unix::fs::DirBuilderExt; - /// - /// let mut builder = DirBuilder::new(); - /// builder.mode(0o755); - /// ``` - #[stable(feature = "dir_builder", since = "1.6.0")] - fn mode(&mut self, mode: u32) -> &mut Self; -} - -#[stable(feature = "dir_builder", since = "1.6.0")] -impl DirBuilderExt for fs::DirBuilder { - fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder { - self.as_inner_mut().set_mode(mode); - self - } -} - -/// Change the root directory of the current process to the specified path. -/// -/// This typically requires privileges, such as root or a specific capability. -/// -/// This does not change the current working directory; you should call -/// [`std::env::set_current_dir`][`crate::env::set_current_dir`] afterwards. -/// -/// # Examples -/// -/// ```no_run -/// #![feature(unix_chroot)] -/// use std::os::unix::fs; -/// -/// fn main() -> std::io::Result<()> { -/// fs::chroot("/sandbox")?; -/// std::env::set_current_dir("/")?; -/// // continue working in sandbox -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "unix_chroot", issue = "84715")] -#[cfg(not(target_os = "fuchsia"))] -pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> { - sys::fs::chroot(dir.as_ref()) -} diff --git a/library/std/src/sys/unix/ext/io.rs b/library/std/src/sys/unix/ext/io.rs deleted file mode 100644 index 07c30bfa9ed..00000000000 --- a/library/std/src/sys/unix/ext/io.rs +++ /dev/null @@ -1,195 +0,0 @@ -//! Unix-specific extensions to general I/O primitives. - -#![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}; - -/// 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. -/// -/// 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. -#[stable(feature = "rust1", since = "1.0.0")] -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. - /// - /// # Example - /// - /// ```no_run - /// use std::fs::File; - /// # use std::io; - /// use std::os::unix::io::{AsRawFd, RawFd}; - /// - /// let mut f = File::open("foo.txt")?; - /// // Note that `raw_fd` is only valid as long as `f` exists. - /// let raw_fd: RawFd = f.as_raw_fd(); - /// # Ok::<(), io::Error>(()) - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn as_raw_fd(&self) -> RawFd; -} - -/// A trait to express the ability to construct an object from a raw file -/// descriptor. -#[stable(feature = "from_raw_os", since = "1.1.0")] -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. - /// - /// # Example - /// - /// ```no_run - /// use std::fs::File; - /// # use std::io; - /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; - /// - /// let f = File::open("foo.txt")?; - /// 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. - /// let f = unsafe { File::from_raw_fd(raw_fd) }; - /// # Ok::<(), io::Error>(()) - /// ``` - #[stable(feature = "from_raw_os", since = "1.1.0")] - 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. -#[stable(feature = "into_raw_os", since = "1.4.0")] -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. - /// - /// # Example - /// - /// ```no_run - /// use std::fs::File; - /// # use std::io; - /// use std::os::unix::io::{IntoRawFd, RawFd}; - /// - /// let f = File::open("foo.txt")?; - /// let raw_fd: RawFd = f.into_raw_fd(); - /// # Ok::<(), io::Error>(()) - /// ``` - #[stable(feature = "into_raw_os", since = "1.4.0")] - 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 - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for fs::File { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.as_inner().fd().raw() - } -} -#[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)) - } -} -#[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() - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawFd for io::Stdin { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawFd for io::Stdout { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawFd for io::Stderr { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawFd for io::StdinLock<'a> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawFd for io::StdoutLock<'a> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawFd for io::StderrLock<'a> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO - } -} diff --git a/library/std/src/sys/unix/ext/mod.rs b/library/std/src/sys/unix/ext/mod.rs deleted file mode 100644 index 735bf35a3ce..00000000000 --- a/library/std/src/sys/unix/ext/mod.rs +++ /dev/null @@ -1,116 +0,0 @@ -//! Platform-specific extensions to `std` for Unix platforms. -//! -//! Provides access to platform-level information on Unix platforms, and -//! exposes Unix-specific functions that would otherwise be inappropriate as -//! part of the core `std` library. -//! -//! It exposes more ways to deal with platform-specific strings (`OsStr`, -//! `OsString`), allows to set permissions more granularly, extract low-level -//! file descriptors from files and sockets, and has platform-specific helpers -//! for spawning processes. -//! -//! # Examples -//! -//! ```no_run -//! use std::fs::File; -//! use std::os::unix::prelude::*; -//! -//! fn main() -> std::io::Result<()> { -//! let f = File::create("foo.txt")?; -//! let fd = f.as_raw_fd(); -//! -//! // use fd with native unix bindings -//! -//! Ok(()) -//! } -//! ``` - -#![stable(feature = "rust1", since = "1.0.0")] -#![doc(cfg(unix))] -#![allow(missing_docs)] - -cfg_if::cfg_if! { - if #[cfg(doc)] { - // Use linux as the default platform when documenting on other platforms like Windows - use crate::os::linux as platform; - } else { - #[cfg(target_os = "android")] - use crate::os::android as platform; - #[cfg(target_os = "dragonfly")] - use crate::os::dragonfly as platform; - #[cfg(target_os = "emscripten")] - use crate::os::emscripten as platform; - #[cfg(target_os = "freebsd")] - use crate::os::freebsd as platform; - #[cfg(target_os = "fuchsia")] - use crate::os::fuchsia as platform; - #[cfg(target_os = "haiku")] - use crate::os::haiku as platform; - #[cfg(target_os = "illumos")] - use crate::os::illumos as platform; - #[cfg(target_os = "ios")] - use crate::os::ios as platform; - #[cfg(any(target_os = "linux", target_os = "l4re"))] - use crate::os::linux as platform; - #[cfg(target_os = "macos")] - use crate::os::macos as platform; - #[cfg(target_os = "netbsd")] - use crate::os::netbsd as platform; - #[cfg(target_os = "openbsd")] - use crate::os::openbsd as platform; - #[cfg(target_os = "redox")] - use crate::os::redox as platform; - #[cfg(target_os = "solaris")] - use crate::os::solaris as platform; - #[cfg(target_os = "vxworks")] - use crate::os::vxworks as platform; - } -} - -pub mod ffi; -pub mod fs; -pub mod io; -pub mod net; -pub mod process; -pub mod raw; -pub mod thread; - -#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" -))] -pub mod ucred; - -/// A prelude for conveniently writing platform-specific code. -/// -/// Includes all extension traits, and some important type definitions. -#[stable(feature = "rust1", since = "1.0.0")] -pub mod prelude { - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::ffi::{OsStrExt, OsStringExt}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::fs::DirEntryExt; - #[doc(no_inline)] - #[stable(feature = "file_offset", since = "1.15.0")] - pub use super::fs::FileExt; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - 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}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::process::{CommandExt, ExitStatusExt}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::thread::JoinHandleExt; -} diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs deleted file mode 100644 index 459f3590e64..00000000000 --- a/library/std/src/sys/unix/ext/net/addr.rs +++ /dev/null @@ -1,226 +0,0 @@ -use crate::ffi::OsStr; -use crate::os::unix::ffi::OsStrExt; -use crate::path::Path; -use crate::sys::cvt; -use crate::{ascii, fmt, io, iter, mem}; - -// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(not(unix))] -#[allow(non_camel_case_types)] -mod libc { - pub use libc::c_int; - pub type socklen_t = u32; - pub struct sockaddr; - #[derive(Clone)] - pub struct sockaddr_un; -} - -fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { - // Work with an actual instance of the type since using a null pointer is UB - let base = addr as *const _ as usize; - let path = &addr.sun_path as *const _ as usize; - path - base -} - -pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { - let mut addr: libc::sockaddr_un = mem::zeroed(); - addr.sun_family = libc::AF_UNIX as libc::sa_family_t; - - let bytes = path.as_os_str().as_bytes(); - - if bytes.contains(&0) { - return Err(io::Error::new_const( - io::ErrorKind::InvalidInput, - &"paths may not contain interior null bytes", - )); - } - - if bytes.len() >= addr.sun_path.len() { - return Err(io::Error::new_const( - io::ErrorKind::InvalidInput, - &"path must be shorter than SUN_LEN", - )); - } - for (dst, src) in iter::zip(&mut addr.sun_path, bytes) { - *dst = *src as libc::c_char; - } - // null byte for pathname addresses is already there because we zeroed the - // struct - - let mut len = sun_path_offset(&addr) + bytes.len(); - match bytes.get(0) { - Some(&0) | None => {} - Some(_) => len += 1, - } - Ok((addr, len as libc::socklen_t)) -} - -enum AddressKind<'a> { - Unnamed, - Pathname(&'a Path), - Abstract(&'a [u8]), -} - -struct AsciiEscaped<'a>(&'a [u8]); - -impl<'a> fmt::Display for AsciiEscaped<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "\"")?; - for byte in self.0.iter().cloned().flat_map(ascii::escape_default) { - write!(fmt, "{}", byte as char)?; - } - write!(fmt, "\"") - } -} - -/// An address associated with a Unix socket. -/// -/// # Examples -/// -/// ``` -/// use std::os::unix::net::UnixListener; -/// -/// let socket = match UnixListener::bind("/tmp/sock") { -/// Ok(sock) => sock, -/// Err(e) => { -/// println!("Couldn't bind: {:?}", e); -/// return -/// } -/// }; -/// let addr = socket.local_addr().expect("Couldn't get local address"); -/// ``` -#[derive(Clone)] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct SocketAddr { - addr: libc::sockaddr_un, - len: libc::socklen_t, -} - -impl SocketAddr { - pub(super) fn new<F>(f: F) -> io::Result<SocketAddr> - where - F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int, - { - unsafe { - let mut addr: libc::sockaddr_un = mem::zeroed(); - let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t; - cvt(f(&mut addr as *mut _ as *mut _, &mut len))?; - SocketAddr::from_parts(addr, len) - } - } - - pub(super) fn from_parts( - addr: libc::sockaddr_un, - mut len: libc::socklen_t, - ) -> io::Result<SocketAddr> { - if len == 0 { - // When there is a datagram from unnamed unix socket - // linux returns zero bytes of address - len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address - } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new_const( - io::ErrorKind::InvalidInput, - &"file descriptor did not correspond to a Unix socket", - )); - } - - Ok(SocketAddr { addr, len }) - } - - /// Returns `true` if the address is unnamed. - /// - /// # Examples - /// - /// A named address: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixListener::bind("/tmp/sock")?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), false); - /// Ok(()) - /// } - /// ``` - /// - /// An unnamed address: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixDatagram::unbound()?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.is_unnamed(), true); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn is_unnamed(&self) -> bool { - if let AddressKind::Unnamed = self.address() { true } else { false } - } - - /// Returns the contents of this address if it is a `pathname` address. - /// - /// # Examples - /// - /// With a pathname: - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// use std::path::Path; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixListener::bind("/tmp/sock")?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); - /// Ok(()) - /// } - /// ``` - /// - /// Without a pathname: - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixDatagram::unbound()?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(addr.as_pathname(), None); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn as_pathname(&self) -> Option<&Path> { - if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } - } - - fn address(&self) -> AddressKind<'_> { - let len = self.len as usize - sun_path_offset(&self.addr); - let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - - // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 - || (cfg!(not(any(target_os = "linux", target_os = "android"))) - && self.addr.sun_path[0] == 0) - { - AddressKind::Unnamed - } else if self.addr.sun_path[0] == 0 { - AddressKind::Abstract(&path[1..len]) - } else { - AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) - } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for SocketAddr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.address() { - AddressKind::Unnamed => write!(fmt, "(unnamed)"), - AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)), - AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path), - } - } -} diff --git a/library/std/src/sys/unix/ext/net/ancillary.rs b/library/std/src/sys/unix/ext/net/ancillary.rs deleted file mode 100644 index 15ce7056fea..00000000000 --- a/library/std/src/sys/unix/ext/net/ancillary.rs +++ /dev/null @@ -1,675 +0,0 @@ -use super::{sockaddr_un, SocketAddr}; -use crate::convert::TryFrom; -use crate::io::{self, IoSlice, IoSliceMut}; -use crate::marker::PhantomData; -use crate::mem::{size_of, zeroed}; -use crate::os::unix::io::RawFd; -use crate::path::Path; -use crate::ptr::{eq, read_unaligned}; -use crate::slice::from_raw_parts; -use crate::sys::net::Socket; - -// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(all(doc, not(target_os = "linux"), not(target_os = "android")))] -#[allow(non_camel_case_types)] -mod libc { - pub use libc::c_int; - pub struct ucred; - pub struct cmsghdr; - pub type pid_t = i32; - pub type gid_t = u32; - pub type uid_t = u32; -} - -pub(super) fn recv_vectored_with_ancillary_from( - socket: &Socket, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, -) -> io::Result<(usize, bool, io::Result<SocketAddr>)> { - unsafe { - let mut msg_name: libc::sockaddr_un = zeroed(); - let mut msg: libc::msghdr = zeroed(); - msg.msg_name = &mut msg_name as *mut _ as *mut _; - msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t; - msg.msg_iov = bufs.as_mut_ptr().cast(); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_iovlen = bufs.len() as libc::size_t; - msg.msg_controllen = ancillary.buffer.len() as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_iovlen = bufs.len() as libc::c_int; - msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t; - } - } - // macos requires that the control pointer is null when the len is 0. - if msg.msg_controllen > 0 { - msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); - } - - let count = socket.recv_msg(&mut msg)?; - - ancillary.length = msg.msg_controllen as usize; - ancillary.truncated = msg.msg_flags & libc::MSG_CTRUNC == libc::MSG_CTRUNC; - - let truncated = msg.msg_flags & libc::MSG_TRUNC == libc::MSG_TRUNC; - let addr = SocketAddr::from_parts(msg_name, msg.msg_namelen); - - Ok((count, truncated, addr)) - } -} - -pub(super) fn send_vectored_with_ancillary_to( - socket: &Socket, - path: Option<&Path>, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, -) -> io::Result<usize> { - unsafe { - let (mut msg_name, msg_namelen) = - if let Some(path) = path { sockaddr_un(path)? } else { (zeroed(), 0) }; - - let mut msg: libc::msghdr = zeroed(); - msg.msg_name = &mut msg_name as *mut _ as *mut _; - msg.msg_namelen = msg_namelen; - msg.msg_iov = bufs.as_ptr() as *mut _; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_iovlen = bufs.len() as libc::size_t; - msg.msg_controllen = ancillary.length as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_iovlen = bufs.len() as libc::c_int; - msg.msg_controllen = ancillary.length as libc::socklen_t; - } - } - // macos requires that the control pointer is null when the len is 0. - if msg.msg_controllen > 0 { - msg.msg_control = ancillary.buffer.as_mut_ptr().cast(); - } - - ancillary.truncated = false; - - socket.send_msg(&mut msg) - } -} - -fn add_to_ancillary_data<T>( - buffer: &mut [u8], - length: &mut usize, - source: &[T], - cmsg_level: libc::c_int, - cmsg_type: libc::c_int, -) -> bool { - let source_len = if let Some(source_len) = source.len().checked_mul(size_of::<T>()) { - if let Ok(source_len) = u32::try_from(source_len) { - source_len - } else { - return false; - } - } else { - return false; - }; - - unsafe { - let additional_space = libc::CMSG_SPACE(source_len) as usize; - - let new_length = if let Some(new_length) = additional_space.checked_add(*length) { - new_length - } else { - return false; - }; - - if new_length > buffer.len() { - return false; - } - - buffer[*length..new_length].fill(0); - - *length = new_length; - - let mut msg: libc::msghdr = zeroed(); - msg.msg_control = buffer.as_mut_ptr().cast(); - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_controllen = *length as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_controllen = *length as libc::socklen_t; - } - } - - let mut cmsg = libc::CMSG_FIRSTHDR(&msg); - let mut previous_cmsg = cmsg; - while !cmsg.is_null() { - previous_cmsg = cmsg; - cmsg = libc::CMSG_NXTHDR(&msg, cmsg); - - // Most operating systems, but not Linux or emscripten, return the previous pointer - // when its length is zero. Therefore, check if the previous pointer is the same as - // the current one. - if eq(cmsg, previous_cmsg) { - break; - } - } - - if previous_cmsg.is_null() { - return false; - } - - (*previous_cmsg).cmsg_level = cmsg_level; - (*previous_cmsg).cmsg_type = cmsg_type; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::socklen_t; - } - } - - let data = libc::CMSG_DATA(previous_cmsg).cast(); - - libc::memcpy(data, source.as_ptr().cast(), source_len as usize); - } - true -} - -struct AncillaryDataIter<'a, T> { - data: &'a [u8], - phantom: PhantomData<T>, -} - -impl<'a, T> AncillaryDataIter<'a, T> { - /// Create `AncillaryDataIter` struct to iterate through the data unit in the control message. - /// - /// # Safety - /// - /// `data` must contain a valid control message. - unsafe fn new(data: &'a [u8]) -> AncillaryDataIter<'a, T> { - AncillaryDataIter { data, phantom: PhantomData } - } -} - -impl<'a, T> Iterator for AncillaryDataIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option<T> { - if size_of::<T>() <= self.data.len() { - unsafe { - let unit = read_unaligned(self.data.as_ptr().cast()); - self.data = &self.data[size_of::<T>()..]; - Some(unit) - } - } else { - None - } - } -} - -/// Unix credential. -#[cfg(any(doc, target_os = "android", target_os = "linux",))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[derive(Clone)] -pub struct SocketCred(libc::ucred); - -#[cfg(any(doc, target_os = "android", target_os = "linux",))] -impl SocketCred { - /// Create a Unix credential struct. - /// - /// PID, UID and GID is set to 0. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn new() -> SocketCred { - SocketCred(libc::ucred { pid: 0, uid: 0, gid: 0 }) - } - - /// Set the PID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_pid(&mut self, pid: libc::pid_t) { - self.0.pid = pid; - } - - /// Get the current PID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_pid(&self) -> libc::pid_t { - self.0.pid - } - - /// Set the UID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_uid(&mut self, uid: libc::uid_t) { - self.0.uid = uid; - } - - /// Get the current UID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_uid(&self) -> libc::uid_t { - self.0.uid - } - - /// Set the GID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_gid(&mut self, gid: libc::gid_t) { - self.0.gid = gid; - } - - /// Get the current GID. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn get_gid(&self) -> libc::gid_t { - self.0.gid - } -} - -/// This control message contains file descriptors. -/// -/// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`. -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmRights<'a>(AncillaryDataIter<'a, RawFd>); - -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -impl<'a> Iterator for ScmRights<'a> { - type Item = RawFd; - - fn next(&mut self) -> Option<RawFd> { - self.0.next() - } -} - -/// This control message contains unix credentials. -/// -/// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_CREDENTIALS` or `SCM_CREDS`. -#[cfg(any(doc, target_os = "android", target_os = "linux",))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>); - -#[cfg(any(doc, target_os = "android", target_os = "linux",))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -impl<'a> Iterator for ScmCredentials<'a> { - type Item = SocketCred; - - fn next(&mut self) -> Option<SocketCred> { - Some(SocketCred(self.0.next()?)) - } -} - -/// The error type which is returned from parsing the type a control message. -#[non_exhaustive] -#[derive(Debug)] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub enum AncillaryError { - Unknown { cmsg_level: i32, cmsg_type: i32 }, -} - -/// This enum represent one control message of variable type. -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub enum AncillaryData<'a> { - ScmRights(ScmRights<'a>), - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - ScmCredentials(ScmCredentials<'a>), -} - -impl<'a> AncillaryData<'a> { - /// Create a `AncillaryData::ScmRights` variant. - /// - /// # Safety - /// - /// `data` must contain a valid control message and the control message must be type of - /// `SOL_SOCKET` and level of `SCM_RIGHTS`. - unsafe fn as_rights(data: &'a [u8]) -> Self { - let ancillary_data_iter = AncillaryDataIter::new(data); - let scm_rights = ScmRights(ancillary_data_iter); - AncillaryData::ScmRights(scm_rights) - } - - /// Create a `AncillaryData::ScmCredentials` variant. - /// - /// # Safety - /// - /// `data` must contain a valid control message and the control message must be type of - /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDENTIALS`. - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - unsafe fn as_credentials(data: &'a [u8]) -> Self { - let ancillary_data_iter = AncillaryDataIter::new(data); - let scm_credentials = ScmCredentials(ancillary_data_iter); - AncillaryData::ScmCredentials(scm_credentials) - } - - fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> { - unsafe { - cfg_if::cfg_if! { - if #[cfg(any( - target_os = "android", - all(target_os = "linux", target_env = "gnu"), - all(target_os = "linux", target_env = "uclibc"), - ))] { - let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t; - } - } - let data_len = (*cmsg).cmsg_len - cmsg_len_zero; - let data = libc::CMSG_DATA(cmsg).cast(); - let data = from_raw_parts(data, data_len as usize); - - match (*cmsg).cmsg_level { - libc::SOL_SOCKET => match (*cmsg).cmsg_type { - libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)), - #[cfg(any(target_os = "android", target_os = "linux",))] - libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)), - cmsg_type => { - Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type }) - } - }, - cmsg_level => { - Err(AncillaryError::Unknown { cmsg_level, cmsg_type: (*cmsg).cmsg_type }) - } - } - } - } -} - -/// This struct is used to iterate through the control messages. -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub struct Messages<'a> { - buffer: &'a [u8], - current: Option<&'a libc::cmsghdr>, -} - -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -impl<'a> Iterator for Messages<'a> { - type Item = Result<AncillaryData<'a>, AncillaryError>; - - fn next(&mut self) -> Option<Self::Item> { - unsafe { - let mut msg: libc::msghdr = zeroed(); - msg.msg_control = self.buffer.as_ptr() as *mut _; - cfg_if::cfg_if! { - if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] { - msg.msg_controllen = self.buffer.len() as libc::size_t; - } else if #[cfg(any( - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - all(target_os = "linux", target_env = "musl",), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] { - msg.msg_controllen = self.buffer.len() as libc::socklen_t; - } - } - - let cmsg = if let Some(current) = self.current { - libc::CMSG_NXTHDR(&msg, current) - } else { - libc::CMSG_FIRSTHDR(&msg) - }; - - let cmsg = cmsg.as_ref()?; - - // Most operating systems, but not Linux or emscripten, return the previous pointer - // when its length is zero. Therefore, check if the previous pointer is the same as - // the current one. - if let Some(current) = self.current { - if eq(current, cmsg) { - return None; - } - } - - self.current = Some(cmsg); - let ancillary_result = AncillaryData::try_from_cmsghdr(cmsg); - Some(ancillary_result) - } - } -} - -/// A Unix socket Ancillary data struct. -/// -/// # Example -/// ```no_run -/// #![feature(unix_socket_ancillary_data)] -/// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData}; -/// use std::io::IoSliceMut; -/// -/// fn main() -> std::io::Result<()> { -/// let sock = UnixStream::connect("/tmp/sock")?; -/// -/// let mut fds = [0; 8]; -/// let mut ancillary_buffer = [0; 128]; -/// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); -/// -/// let mut buf = [1; 8]; -/// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..]; -/// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; -/// -/// for ancillary_result in ancillary.messages() { -/// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { -/// for fd in scm_rights { -/// println!("receive file descriptor: {}", fd); -/// } -/// } -/// } -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -#[derive(Debug)] -pub struct SocketAncillary<'a> { - buffer: &'a mut [u8], - length: usize, - truncated: bool, -} - -impl<'a> SocketAncillary<'a> { - /// Create an ancillary data with the given buffer. - /// - /// # Example - /// - /// ```no_run - /// # #![allow(unused_mut)] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::SocketAncillary; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ``` - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn new(buffer: &'a mut [u8]) -> Self { - SocketAncillary { buffer, length: 0, truncated: false } - } - - /// Returns the capacity of the buffer. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn capacity(&self) -> usize { - self.buffer.len() - } - - /// Returns `true` if the ancillary data is empty. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn is_empty(&self) -> bool { - self.length == 0 - } - - /// Returns the number of used bytes. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn len(&self) -> usize { - self.length - } - - /// Returns the iterator of the control messages. - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn messages(&self) -> Messages<'_> { - Messages { buffer: &self.buffer[..self.length], current: None } - } - - /// Is `true` if during a recv operation the ancillary was truncated. - /// - /// # Example - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixStream::connect("/tmp/sock")?; - /// - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// - /// let mut buf = [1; 8]; - /// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..]; - /// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// - /// println!("Is truncated: {}", ancillary.truncated()); - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn truncated(&self) -> bool { - self.truncated - } - - /// Add file descriptors to the ancillary data. - /// - /// The function returns `true` if there was enough space in the buffer. - /// If there was not enough space then no file descriptors was appended. - /// Technically, that means this operation adds a control message with the level `SOL_SOCKET` - /// and type `SCM_RIGHTS`. - /// - /// # Example - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary}; - /// use std::os::unix::io::AsRawFd; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixStream::connect("/tmp/sock")?; - /// - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&[sock.as_raw_fd()][..]); - /// - /// let mut buf = [1; 8]; - /// let mut bufs = &mut [IoSlice::new(&mut buf[..])][..]; - /// sock.send_vectored_with_ancillary(bufs, &mut ancillary)?; - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn add_fds(&mut self, fds: &[RawFd]) -> bool { - self.truncated = false; - add_to_ancillary_data( - &mut self.buffer, - &mut self.length, - fds, - libc::SOL_SOCKET, - libc::SCM_RIGHTS, - ) - } - - /// Add credentials to the ancillary data. - /// - /// The function returns `true` if there was enough space in the buffer. - /// If there was not enough space then no credentials was appended. - /// Technically, that means this operation adds a control message with the level `SOL_SOCKET` - /// and type `SCM_CREDENTIALS` or `SCM_CREDS`. - /// - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { - self.truncated = false; - add_to_ancillary_data( - &mut self.buffer, - &mut self.length, - creds, - libc::SOL_SOCKET, - libc::SCM_CREDENTIALS, - ) - } - - /// Clears the ancillary data, removing all values. - /// - /// # Example - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixStream::connect("/tmp/sock")?; - /// - /// let mut fds1 = [0; 8]; - /// let mut fds2 = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// - /// let mut buf = [1; 8]; - /// let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..]; - /// - /// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {}", fd); - /// } - /// } - /// } - /// - /// ancillary.clear(); - /// - /// sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {}", fd); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn clear(&mut self) { - self.length = 0; - self.truncated = false; - } -} diff --git a/library/std/src/sys/unix/ext/net/datagram.rs b/library/std/src/sys/unix/ext/net/datagram.rs deleted file mode 100644 index 9e39f70f68e..00000000000 --- a/library/std/src/sys/unix/ext/net/datagram.rs +++ /dev/null @@ -1,902 +0,0 @@ -#[cfg(any( - doc, - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; -use super::{sockaddr_un, SocketAddr}; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -use crate::io::{IoSlice, IoSliceMut}; -use crate::net::Shutdown; -use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use crate::path::Path; -use crate::sys::cvt; -use crate::sys::net::Socket; -use crate::sys_common::{AsInner, FromInner, IntoInner}; -use crate::time::Duration; -use crate::{fmt, io}; - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "haiku" -))] -use libc::MSG_NOSIGNAL; -#[cfg(not(any( - target_os = "linux", - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "haiku" -)))] -const MSG_NOSIGNAL: libc::c_int = 0x0; - -/// A Unix datagram socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixDatagram; -/// -/// fn main() -> std::io::Result<()> { -/// let socket = UnixDatagram::bind("/path/to/my/socket")?; -/// socket.send_to(b"hello world", "/path/to/other/socket")?; -/// let mut buf = [0; 100]; -/// let (count, address) = socket.recv_from(&mut buf)?; -/// println!("socket {:?} sent {:?}", address, &buf[..count]); -/// Ok(()) -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixDatagram(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixDatagram { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixDatagram"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixDatagram { - /// Creates a Unix datagram socket bound to the given path. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = match UnixDatagram::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't bind: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> { - unsafe { - 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 _))?; - - Ok(socket) - } - } - - /// Creates a Unix Datagram socket which is not bound to any address. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let sock = match UnixDatagram::unbound() { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't unbound: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn unbound() -> io::Result<UnixDatagram> { - let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; - Ok(UnixDatagram(inner)) - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixDatagrams`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// let (sock1, sock2) = match UnixDatagram::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't unbound: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { - let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; - Ok((UnixDatagram(i1), UnixDatagram(i2))) - } - - /// Connects the socket to the specified address. - /// - /// The [`send`] method may be used to send data to the specified address. - /// [`recv`] and [`recv_from`] will only receive data from that address. - /// - /// [`send`]: UnixDatagram::send - /// [`recv`]: UnixDatagram::recv - /// [`recv_from`]: UnixDatagram::recv_from - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// match sock.connect("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return Err(e) - /// } - /// }; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { - unsafe { - let (addr, len) = sockaddr_un(path.as_ref())?; - - cvt(libc::connect(*self.0.as_inner(), &addr as *const _ as *const _, len))?; - } - Ok(()) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixDatagram` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one side will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::bind("/path/to/the/socket")?; - /// let sock_copy = sock.try_clone().expect("try_clone failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result<UnixDatagram> { - self.0.duplicate().map(UnixDatagram) - } - - /// Returns the address of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::bind("/path/to/the/socket")?; - /// let addr = sock.local_addr().expect("Couldn't get local address"); - /// Ok(()) - /// } - /// ``` - #[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) }) - } - - /// Returns the address of this socket's peer. - /// - /// The [`connect`] method will connect the socket to a peer. - /// - /// [`connect`]: UnixDatagram::connect - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.connect("/path/to/the/socket")?; - /// - /// let addr = sock.peer_addr().expect("Couldn't get peer address"); - /// Ok(()) - /// } - /// ``` - #[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) }) - } - - fn recv_from_flags( - &self, - buf: &mut [u8], - flags: libc::c_int, - ) -> io::Result<(usize, SocketAddr)> { - let mut count = 0; - let addr = SocketAddr::new(|addr, len| unsafe { - count = libc::recvfrom( - *self.0.as_inner(), - buf.as_mut_ptr() as *mut _, - buf.len(), - flags, - addr, - len, - ); - if count > 0 { - 1 - } else if count == 0 { - 0 - } else { - -1 - } - })?; - - Ok((count as usize, addr)) - } - - /// Receives data from the socket. - /// - /// On success, returns the number of bytes read and the address from - /// whence the data came. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let mut buf = vec![0; 10]; - /// let (size, sender) = sock.recv_from(buf.as_mut_slice())?; - /// println!("received {} bytes from {:?}", size, sender); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - self.recv_from_flags(buf, 0) - } - - /// Receives data from the socket. - /// - /// On success, returns the number of bytes read. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::bind("/path/to/the/socket")?; - /// let mut buf = vec![0; 10]; - /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { - self.0.read(buf) - } - - /// Receives data and ancillary data from socket. - /// - /// On success, returns the number of bytes read, if the data was truncated and the address from whence the msg came. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; - /// let mut bufs = &mut [ - /// IoSliceMut::new(&mut buf1), - /// IoSliceMut::new(&mut buf2), - /// IoSliceMut::new(&mut buf3), - /// ][..]; - /// let mut fds = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// let (size, _truncated, sender) = sock.recv_vectored_with_ancillary_from(bufs, &mut ancillary)?; - /// println!("received {}", size); - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {}", fd); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn recv_vectored_with_ancillary_from( - &self, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<(usize, bool, SocketAddr)> { - let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; - let addr = addr?; - - Ok((count, truncated, addr)) - } - - /// Receives data and ancillary data from socket. - /// - /// On success, returns the number of bytes read and if the data was truncated. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; - /// let mut bufs = &mut [ - /// IoSliceMut::new(&mut buf1), - /// IoSliceMut::new(&mut buf2), - /// IoSliceMut::new(&mut buf3), - /// ][..]; - /// let mut fds = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// let (size, _truncated) = sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// println!("received {}", size); - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {}", fd); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn recv_vectored_with_ancillary( - &self, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<(usize, bool)> { - let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; - addr?; - - Ok((count, truncated)) - } - - /// Sends data on the socket to the specified address. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> { - unsafe { - let (addr, len) = sockaddr_un(path.as_ref())?; - - let count = cvt(libc::sendto( - *self.0.as_inner(), - buf.as_ptr() as *const _, - buf.len(), - MSG_NOSIGNAL, - &addr as *const _ as *const _, - len, - ))?; - Ok(count as usize) - } - } - - /// Sends data on the socket to the socket's peer. - /// - /// The peer address may be set by the `connect` method, and this method - /// will return an error if the socket has not already been connected. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.connect("/some/sock").expect("Couldn't connect"); - /// sock.send(b"omelette au fromage").expect("send_to function failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn send(&self, buf: &[u8]) -> io::Result<usize> { - self.0.write(buf) - } - - /// Sends data and ancillary data on the socket to the specified address. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary}; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let buf1 = [1; 8]; - /// let buf2 = [2; 16]; - /// let buf3 = [3; 8]; - /// let bufs = &[ - /// IoSlice::new(&buf1), - /// IoSlice::new(&buf2), - /// IoSlice::new(&buf3), - /// ][..]; - /// let fds = [0, 1, 2]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&fds[..]); - /// sock.send_vectored_with_ancillary_to(bufs, &mut ancillary, "/some/sock") - /// .expect("send_vectored_with_ancillary_to function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn send_vectored_with_ancillary_to<P: AsRef<Path>>( - &self, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, - path: P, - ) -> io::Result<usize> { - send_vectored_with_ancillary_to(&self.0, Some(path.as_ref()), bufs, ancillary) - } - - /// Sends data and ancillary data on the socket. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixDatagram, SocketAncillary}; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// let buf1 = [1; 8]; - /// let buf2 = [2; 16]; - /// let buf3 = [3; 8]; - /// let bufs = &[ - /// IoSlice::new(&buf1), - /// IoSlice::new(&buf2), - /// IoSlice::new(&buf3), - /// ][..]; - /// let fds = [0, 1, 2]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&fds[..]); - /// sock.send_vectored_with_ancillary(bufs, &mut ancillary) - /// .expect("send_vectored_with_ancillary function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn send_vectored_with_ancillary( - &self, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<usize> { - send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will - /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] - /// is passed to this method. - /// - /// [`recv`]: UnixDatagram::recv - /// [`recv_from`]: UnixDatagram::recv_from - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_read_timeout(Some(Duration::new(1, 0))) - /// .expect("set_read_timeout function failed"); - /// Ok(()) - /// } - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixDatagram::unbound()?; - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_RCVTIMEO) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will - /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`send`]: UnixDatagram::send - /// [`send_to`]: UnixDatagram::send_to - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("set_write_timeout function failed"); - /// Ok(()) - /// } - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixDatagram::unbound()?; - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_SNDTIMEO) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_read_timeout(Some(Duration::new(1, 0))) - /// .expect("set_read_timeout function failed"); - /// assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0))); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - self.0.timeout(libc::SO_RCVTIMEO) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("set_write_timeout function failed"); - /// assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0))); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - self.0.timeout(libc::SO_SNDTIMEO) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ``` - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. - /// - /// Set the socket option `SO_PASSCRED`. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_passcred(true).expect("set_passcred function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - self.0.set_passcred(passcred) - } - - /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. - /// This value can be change by [`set_passcred`]. - /// - /// Get the socket option `SO_PASSCRED`. - /// - /// [`set_passcred`]: UnixDatagram::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn passcred(&self) -> io::Result<bool> { - self.0.passcred() - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// if let Ok(Some(err)) = sock.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - self.0.take_error() - } - - /// Shut down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// ```no_run - /// use std::os::unix::net::UnixDatagram; - /// use std::net::Shutdown; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } - - /// Receives data on the socket from the remote address to which it is - /// connected, without removing that data from the queue. On success, - /// returns the number of bytes peeked. - /// - /// Successive calls return the same data. This is accomplished by passing - /// `MSG_PEEK` as a flag to the underlying `recv` system call. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_peek)] - /// - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixDatagram::bind("/tmp/sock")?; - /// let mut buf = [0; 10]; - /// let len = socket.peek(&mut buf).expect("peek failed"); - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_peek", issue = "76923")] - pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { - self.0.peek(buf) - } - - /// Receives a single datagram message on the socket, without removing it from the - /// queue. On success, returns the number of bytes read and the origin. - /// - /// The function must be called with valid byte array `buf` of sufficient size to - /// hold the message bytes. If a message is too long to fit in the supplied buffer, - /// excess bytes may be discarded. - /// - /// Successive calls return the same data. This is accomplished by passing - /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call. - /// - /// Do not use this function to implement busy waiting, instead use `libc::poll` to - /// synchronize IO events on one or more sockets. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_peek)] - /// - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixDatagram::bind("/tmp/sock")?; - /// let mut buf = [0; 10]; - /// let (len, addr) = socket.peek_from(&mut buf).expect("peek failed"); - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_peek", issue = "76923")] - pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - self.recv_from_flags(buf, libc::MSG_PEEK) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixDatagram { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixDatagram { - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { - UnixDatagram(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixDatagram { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} diff --git a/library/std/src/sys/unix/ext/net/listener.rs b/library/std/src/sys/unix/ext/net/listener.rs deleted file mode 100644 index bdd08fe8380..00000000000 --- a/library/std/src/sys/unix/ext/net/listener.rs +++ /dev/null @@ -1,322 +0,0 @@ -use super::{sockaddr_un, SocketAddr, UnixStream}; -use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use crate::path::Path; -use crate::sys::cvt; -use crate::sys::net::Socket; -use crate::sys_common::{AsInner, FromInner, IntoInner}; -use crate::{fmt, io, mem}; - -/// A structure representing a Unix domain socket server. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// fn main() -> std::io::Result<()> { -/// let listener = UnixListener::bind("/path/to/the/socket")?; -/// -/// // accept connections and process them, spawning a new thread for each one -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// /* connection succeeded */ -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// /* connection failed */ -/// break; -/// } -/// } -/// } -/// Ok(()) -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixListener(Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixListener { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixListener"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - builder.finish() - } -} - -impl UnixListener { - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// let listener = match UnixListener::bind("/path/to/the/socket") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> { - unsafe { - 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))?; - - Ok(UnixListener(inner)) - } - } - - /// Accepts a new incoming connection to this listener. - /// - /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corresponding [`UnixStream`] and - /// the remote peer's address will be returned. - /// - /// [`UnixStream`]: crate::os::unix::net::UnixStream - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// fn main() -> std::io::Result<()> { - /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// - /// match listener.accept() { - /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), - /// Err(e) => println!("accept function failed: {:?}", e), - /// } - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; - let mut len = mem::size_of_val(&storage) as libc::socklen_t; - let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?; - let addr = SocketAddr::from_parts(storage, len)?; - Ok((UnixStream(sock), addr)) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixListener` is a reference to the same socket that this - /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// fn main() -> std::io::Result<()> { - /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// let listener_copy = listener.try_clone().expect("try_clone failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result<UnixListener> { - self.0.duplicate().map(UnixListener) - } - - /// Returns the local socket address of this listener. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// fn main() -> std::io::Result<()> { - /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// let addr = listener.local_addr().expect("Couldn't get local address"); - /// Ok(()) - /// } - /// ``` - #[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) }) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// This will result in the `accept` operation becoming nonblocking, - /// i.e., immediately returning from their calls. If the IO operation is - /// successful, `Ok` is returned and no further action is required. If the - /// IO operation could not be completed and needs to be retried, an error - /// with kind [`io::ErrorKind::WouldBlock`] is returned. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// fn main() -> std::io::Result<()> { - /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixListener; - /// - /// fn main() -> std::io::Result<()> { - /// let listener = UnixListener::bind("/tmp/sock")?; - /// - /// if let Ok(Some(err)) = listener.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// Ok(()) - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns `None`. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - self.0.take_error() - } - - /// Returns an iterator over incoming connections. - /// - /// The iterator will never return [`None`] and will also not yield the - /// peer's [`SocketAddr`] structure. - /// - /// # Examples - /// - /// ```no_run - /// use std::thread; - /// use std::os::unix::net::{UnixStream, UnixListener}; - /// - /// fn handle_client(stream: UnixStream) { - /// // ... - /// } - /// - /// fn main() -> std::io::Result<()> { - /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// - /// for stream in listener.incoming() { - /// match stream { - /// Ok(stream) => { - /// thread::spawn(|| handle_client(stream)); - /// } - /// Err(err) => { - /// break; - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn incoming(&self) -> Incoming<'_> { - Incoming { listener: self } - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixListener { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixListener { - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> UnixListener { - UnixListener(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixListener { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> IntoIterator for &'a UnixListener { - type Item = io::Result<UnixStream>; - type IntoIter = Incoming<'a>; - - fn into_iter(self) -> Incoming<'a> { - self.incoming() - } -} - -/// An iterator over incoming connections to a [`UnixListener`]. -/// -/// It will never return [`None`]. -/// -/// # Examples -/// -/// ```no_run -/// use std::thread; -/// use std::os::unix::net::{UnixStream, UnixListener}; -/// -/// fn handle_client(stream: UnixStream) { -/// // ... -/// } -/// -/// fn main() -> std::io::Result<()> { -/// let listener = UnixListener::bind("/path/to/the/socket")?; -/// -/// for stream in listener.incoming() { -/// match stream { -/// Ok(stream) => { -/// thread::spawn(|| handle_client(stream)); -/// } -/// Err(err) => { -/// break; -/// } -/// } -/// } -/// Ok(()) -/// } -/// ``` -#[derive(Debug)] -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct Incoming<'a> { - listener: &'a UnixListener, -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> Iterator for Incoming<'a> { - type Item = io::Result<UnixStream>; - - fn next(&mut self) -> Option<io::Result<UnixStream>> { - Some(self.listener.accept().map(|s| s.0)) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (usize::MAX, None) - } -} diff --git a/library/std/src/sys/unix/ext/net/mod.rs b/library/std/src/sys/unix/ext/net/mod.rs deleted file mode 100644 index 3088ffb5e5c..00000000000 --- a/library/std/src/sys/unix/ext/net/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Unix-specific networking functionality - -#![stable(feature = "unix_socket", since = "1.10.0")] - -mod addr; -#[doc(cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -)))] -#[cfg(any( - doc, - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -mod ancillary; -mod datagram; -mod listener; -mod raw_fd; -mod stream; -#[cfg(all(test, not(target_os = "emscripten")))] -mod tests; - -#[stable(feature = "unix_socket", since = "1.10.0")] -pub use self::addr::*; -#[cfg(any( - doc, - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] -pub use self::ancillary::*; -#[stable(feature = "unix_socket", since = "1.10.0")] -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::*; diff --git a/library/std/src/sys/unix/ext/net/raw_fd.rs b/library/std/src/sys/unix/ext/net/raw_fd.rs deleted file mode 100644 index b3f12844101..00000000000 --- a/library/std/src/sys/unix/ext/net/raw_fd.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; -use crate::{net, sys}; - -macro_rules! impl_as_raw_fd { - ($($t:ident)*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] - impl AsRawFd for net::$t { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self.as_inner().socket().as_inner() - } - } - )*}; -} -impl_as_raw_fd! { TcpStream TcpListener UdpSocket } - -macro_rules! impl_from_raw_fd { - ($($t:ident)*) => {$( - #[stable(feature = "from_raw_os", since = "1.1.0")] - 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)) - } - } - )*}; -} -impl_from_raw_fd! { TcpStream TcpListener UdpSocket } - -macro_rules! impl_into_raw_fd { - ($($t:ident)*) => {$( - #[stable(feature = "into_raw_os", since = "1.4.0")] - impl IntoRawFd for net::$t { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } - } - )*}; -} -impl_into_raw_fd! { TcpStream TcpListener UdpSocket } diff --git a/library/std/src/sys/unix/ext/net/stream.rs b/library/std/src/sys/unix/ext/net/stream.rs deleted file mode 100644 index a6f6e091305..00000000000 --- a/library/std/src/sys/unix/ext/net/stream.rs +++ /dev/null @@ -1,677 +0,0 @@ -#[cfg(any( - doc, - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; -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}; -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" -))] -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::time::Duration; - -#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" -))] -pub use ucred::UCred; - -/// A Unix stream socket. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::net::UnixStream; -/// use std::io::prelude::*; -/// -/// fn main() -> std::io::Result<()> { -/// let mut stream = UnixStream::connect("/path/to/my/socket")?; -/// stream.write_all(b"hello world")?; -/// let mut response = String::new(); -/// stream.read_to_string(&mut response)?; -/// println!("{}", response); -/// Ok(()) -/// } -/// ``` -#[stable(feature = "unix_socket", since = "1.10.0")] -pub struct UnixStream(pub(super) Socket); - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl fmt::Debug for UnixStream { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_struct("UnixStream"); - builder.field("fd", self.0.as_inner()); - if let Ok(addr) = self.local_addr() { - builder.field("local", &addr); - } - if let Ok(addr) = self.peer_addr() { - builder.field("peer", &addr); - } - builder.finish() - } -} - -impl UnixStream { - /// Connects to the socket named by `path`. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let socket = match UnixStream::connect("/tmp/sock") { - /// Ok(sock) => sock, - /// Err(e) => { - /// println!("Couldn't connect: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> { - unsafe { - 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))?; - Ok(UnixStream(inner)) - } - } - - /// Creates an unnamed pair of connected sockets. - /// - /// Returns two `UnixStream`s which are connected to each other. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// let (sock1, sock2) = match UnixStream::pair() { - /// Ok((sock1, sock2)) => (sock1, sock2), - /// Err(e) => { - /// println!("Couldn't create a pair of sockets: {:?}", e); - /// return - /// } - /// }; - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn pair() -> io::Result<(UnixStream, UnixStream)> { - let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; - Ok((UnixStream(i1), UnixStream(i2))) - } - - /// Creates a new independently owned handle to the underlying socket. - /// - /// The returned `UnixStream` is a reference to the same stream that this - /// object references. Both handles will read and write the same stream of - /// data, and options set on one stream will be propagated to the other - /// stream. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn try_clone(&self) -> io::Result<UnixStream> { - self.0.duplicate().map(UnixStream) - } - - /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); - /// Ok(()) - /// } - /// ``` - #[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) }) - } - - /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); - /// Ok(()) - /// } - /// ``` - #[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) }) - } - - /// Gets the peer credentials for this Unix domain socket. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(peer_credentials_unix_socket)] - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let peer_cred = socket.peer_cred().expect("Couldn't get peer credentials"); - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] - #[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" - ))] - pub fn peer_cred(&self) -> io::Result<UCred> { - ucred::peer_cred(self) - } - - /// Sets the read timeout for the socket. - /// - /// If the provided value is [`None`], then [`read`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method. - /// - /// [`read`]: io::Read::read - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// Ok(()) - /// } - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_RCVTIMEO) - } - - /// Sets the write timeout for the socket. - /// - /// If the provided value is [`None`], then [`write`] calls will block - /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is - /// passed to this method. - /// - /// [`read`]: io::Read::read - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("Couldn't set write timeout"); - /// Ok(()) - /// } - /// ``` - /// - /// An [`Err`] is returned if the zero [`Duration`] is passed to this - /// method: - /// - /// ```no_run - /// use std::io; - /// use std::net::UdpSocket; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UdpSocket::bind("127.0.0.1:34254")?; - /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); - /// let err = result.unwrap_err(); - /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { - self.0.set_timeout(timeout, libc::SO_SNDTIMEO) - } - - /// Returns the read timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); - /// assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0))); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - self.0.timeout(libc::SO_RCVTIMEO) - } - - /// Returns the write timeout of this socket. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("Couldn't set write timeout"); - /// assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0))); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - self.0.timeout(libc::SO_SNDTIMEO) - } - - /// Moves the socket into or out of nonblocking mode. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - self.0.set_nonblocking(nonblocking) - } - - /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. - /// - /// Set the socket option `SO_PASSCRED`. - /// - /// # Examples - /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_passcred(true).expect("Couldn't set passcred"); - /// Ok(()) - /// } - /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - self.0.set_passcred(passcred) - } - - /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. - /// This value can be change by [`set_passcred`]. - /// - /// Get the socket option `SO_PASSCRED`. - /// - /// [`set_passcred`]: UnixStream::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn passcred(&self) -> io::Result<bool> { - self.0.passcred() - } - - /// Returns the value of the `SO_ERROR` option. - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// if let Ok(Some(err)) = socket.take_error() { - /// println!("Got error: {:?}", err); - /// } - /// Ok(()) - /// } - /// ``` - /// - /// # Platform specific - /// On Redox this always returns `None`. - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - self.0.take_error() - } - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This function will cause all pending and future I/O calls on the - /// specified portions to immediately return with an appropriate value - /// (see the documentation of [`Shutdown`]). - /// - /// # Examples - /// - /// ```no_run - /// use std::os::unix::net::UnixStream; - /// use std::net::Shutdown; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "unix_socket", since = "1.10.0")] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.0.shutdown(how) - } - - /// Receives data on the socket from the remote address to which it is - /// connected, without removing that data from the queue. On success, - /// returns the number of bytes peeked. - /// - /// Successive calls return the same data. This is accomplished by passing - /// `MSG_PEEK` as a flag to the underlying `recv` system call. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_peek)] - /// - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let mut buf = [0; 10]; - /// let len = socket.peek(&mut buf).expect("peek failed"); - /// Ok(()) - /// } - /// ``` - #[unstable(feature = "unix_socket_peek", issue = "76923")] - pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { - self.0.peek(buf) - } - - /// Receives data and ancillary data from socket. - /// - /// On success, returns the number of bytes read. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData}; - /// use std::io::IoSliceMut; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; - /// let mut bufs = &mut [ - /// IoSliceMut::new(&mut buf1), - /// IoSliceMut::new(&mut buf2), - /// IoSliceMut::new(&mut buf3), - /// ][..]; - /// let mut fds = [0; 8]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// let size = socket.recv_vectored_with_ancillary(bufs, &mut ancillary)?; - /// println!("received {}", size); - /// for ancillary_result in ancillary.messages() { - /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { - /// for fd in scm_rights { - /// println!("receive file descriptor: {}", fd); - /// } - /// } - /// } - /// Ok(()) - /// } - /// ``` - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn recv_vectored_with_ancillary( - &self, - bufs: &mut [IoSliceMut<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<usize> { - let (count, _, _) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; - - Ok(count) - } - - /// Sends data and ancillary data on the socket. - /// - /// On success, returns the number of bytes written. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::{UnixStream, SocketAncillary}; - /// use std::io::IoSlice; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// let buf1 = [1; 8]; - /// let buf2 = [2; 16]; - /// let buf3 = [3; 8]; - /// let bufs = &[ - /// IoSlice::new(&buf1), - /// IoSlice::new(&buf2), - /// IoSlice::new(&buf3), - /// ][..]; - /// let fds = [0, 1, 2]; - /// let mut ancillary_buffer = [0; 128]; - /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); - /// ancillary.add_fds(&fds[..]); - /// socket.send_vectored_with_ancillary(bufs, &mut ancillary) - /// .expect("send_vectored_with_ancillary function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn send_vectored_with_ancillary( - &self, - bufs: &[IoSlice<'_>], - ancillary: &mut SocketAncillary<'_>, - ) -> io::Result<usize> { - send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Read for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - io::Read::read(&mut &*self, buf) - } - - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - io::Read::read_vectored(&mut &*self, bufs) - } - - #[inline] - fn is_read_vectored(&self) -> bool { - io::Read::is_read_vectored(&&*self) - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Read for &'a UnixStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - self.0.read(buf) - } - - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - self.0.read_vectored(bufs) - } - - #[inline] - fn is_read_vectored(&self) -> bool { - self.0.is_read_vectored() - } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl io::Write for UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - io::Write::write(&mut &*self, buf) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - io::Write::write_vectored(&mut &*self, bufs) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - io::Write::is_write_vectored(&&*self) - } - - fn flush(&mut self) -> io::Result<()> { - io::Write::flush(&mut &*self) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl<'a> io::Write for &'a UnixStream { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.0.write(buf) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - self.0.write_vectored(bufs) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - self.0.is_write_vectored() - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl AsRawFd for UnixStream { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self.0.as_inner() - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl FromRawFd for UnixStream { - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> UnixStream { - UnixStream(Socket::from_inner(fd)) - } -} - -#[stable(feature = "unix_socket", since = "1.10.0")] -impl IntoRawFd for UnixStream { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.0.into_inner() - } -} diff --git a/library/std/src/sys/unix/ext/net/tests.rs b/library/std/src/sys/unix/ext/net/tests.rs deleted file mode 100644 index bd9b6dd727b..00000000000 --- a/library/std/src/sys/unix/ext/net/tests.rs +++ /dev/null @@ -1,640 +0,0 @@ -use super::*; -use crate::io::prelude::*; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut}; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -use crate::iter::FromIterator; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -use crate::os::unix::io::AsRawFd; -use crate::sys_common::io::test::tmpdir; -use crate::thread; -use crate::time::Duration; - -macro_rules! or_panic { - ($e:expr) => { - match $e { - Ok(e) => e, - Err(e) => panic!("{}", e), - } - }; -} - -#[test] -fn basic() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - let msg1 = b"hello"; - let msg2 = b"world!"; - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()).0; - let mut buf = [0; 5]; - or_panic!(stream.read(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(stream.write_all(msg2)); - }); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - assert_eq!(Some(&*socket_path), stream.peer_addr().unwrap().as_pathname()); - or_panic!(stream.write_all(msg1)); - let mut buf = vec![]; - or_panic!(stream.read_to_end(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - drop(stream); - - thread.join().unwrap(); -} - -#[test] -fn vectored() { - let (mut s1, mut s2) = or_panic!(UnixStream::pair()); - - let len = or_panic!(s1.write_vectored(&[ - IoSlice::new(b"hello"), - IoSlice::new(b" "), - IoSlice::new(b"world!") - ],)); - assert_eq!(len, 12); - - let mut buf1 = [0; 6]; - let mut buf2 = [0; 7]; - let len = - or_panic!(s2.read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)); - assert_eq!(len, 12); - assert_eq!(&buf1, b"hello "); - assert_eq!(&buf2, b"world!\0"); -} - -#[test] -fn pair() { - let msg1 = b"hello"; - let msg2 = b"world!"; - - let (mut s1, mut s2) = or_panic!(UnixStream::pair()); - let thread = thread::spawn(move || { - // s1 must be moved in or the test will hang! - let mut buf = [0; 5]; - or_panic!(s1.read(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(s1.write_all(msg2)); - }); - - or_panic!(s2.write_all(msg1)); - let mut buf = vec![]; - or_panic!(s2.read_to_end(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - drop(s2); - - thread.join().unwrap(); -} - -#[test] -fn try_clone() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - let msg1 = b"hello"; - let msg2 = b"world"; - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()).0; - or_panic!(stream.write_all(msg1)); - or_panic!(stream.write_all(msg2)); - }); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - let mut stream2 = or_panic!(stream.try_clone()); - - let mut buf = [0; 5]; - or_panic!(stream.read(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(stream2.read(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - - thread.join().unwrap(); -} - -#[test] -fn iter() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let thread = thread::spawn(move || { - for stream in listener.incoming().take(2) { - let mut stream = or_panic!(stream); - let mut buf = [0]; - or_panic!(stream.read(&mut buf)); - } - }); - - for _ in 0..2 { - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - or_panic!(stream.write_all(&[0])); - } - - thread.join().unwrap(); -} - -#[test] -fn long_path() { - let dir = tmpdir(); - let socket_path = dir.path().join( - "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfa\ - sasdfasdfasdasdfasdfasdfadfasdfasdfasdfasdfasdf", - ); - match UnixStream::connect(&socket_path) { - Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} - Err(e) => panic!("unexpected error {}", e), - Ok(_) => panic!("unexpected success"), - } - - match UnixListener::bind(&socket_path) { - Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} - Err(e) => panic!("unexpected error {}", e), - Ok(_) => panic!("unexpected success"), - } - - match UnixDatagram::bind(&socket_path) { - Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} - Err(e) => panic!("unexpected error {}", e), - Ok(_) => panic!("unexpected success"), - } -} - -#[test] -fn timeouts() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let _listener = or_panic!(UnixListener::bind(&socket_path)); - - let stream = or_panic!(UnixStream::connect(&socket_path)); - let dur = Duration::new(15410, 0); - - assert_eq!(None, or_panic!(stream.read_timeout())); - - or_panic!(stream.set_read_timeout(Some(dur))); - assert_eq!(Some(dur), or_panic!(stream.read_timeout())); - - assert_eq!(None, or_panic!(stream.write_timeout())); - - or_panic!(stream.set_write_timeout(Some(dur))); - assert_eq!(Some(dur), or_panic!(stream.write_timeout())); - - or_panic!(stream.set_read_timeout(None)); - assert_eq!(None, or_panic!(stream.read_timeout())); - - or_panic!(stream.set_write_timeout(None)); - assert_eq!(None, or_panic!(stream.write_timeout())); -} - -#[test] -fn test_read_timeout() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let _listener = or_panic!(UnixListener::bind(&socket_path)); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); - - let mut buf = [0; 10]; - let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); - assert!( - kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, - "unexpected_error: {:?}", - kind - ); -} - -#[test] -fn test_read_with_timeout() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&socket_path)); - - let mut stream = or_panic!(UnixStream::connect(&socket_path)); - or_panic!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); - - let mut other_end = or_panic!(listener.accept()).0; - or_panic!(other_end.write_all(b"hello world")); - - let mut buf = [0; 11]; - or_panic!(stream.read(&mut buf)); - assert_eq!(b"hello world", &buf[..]); - - let kind = stream.read_exact(&mut buf).err().expect("expected error").kind(); - assert!( - kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut, - "unexpected_error: {:?}", - kind - ); -} - -// Ensure the `set_read_timeout` and `set_write_timeout` calls return errors -// when passed zero Durations -#[test] -fn test_unix_stream_timeout_zero_duration() { - let dir = tmpdir(); - let socket_path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&socket_path)); - let stream = or_panic!(UnixStream::connect(&socket_path)); - - let result = stream.set_write_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - - let result = stream.set_read_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - - drop(listener); -} - -#[test] -fn test_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::bind(&path2)); - - let msg = b"hello world"; - or_panic!(sock1.send_to(msg, &path2)); - let mut buf = [0; 11]; - or_panic!(sock2.recv_from(&mut buf)); - assert_eq!(msg, &buf[..]); -} - -#[test] -fn test_unnamed_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::unbound()); - - let msg = b"hello world"; - or_panic!(sock2.send_to(msg, &path1)); - let mut buf = [0; 11]; - let (usize, addr) = or_panic!(sock1.recv_from(&mut buf)); - assert_eq!(usize, 11); - assert!(addr.is_unnamed()); - assert_eq!(msg, &buf[..]); -} - -#[test] -fn test_connect_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let bsock1 = or_panic!(UnixDatagram::bind(&path1)); - let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - let sock = or_panic!(UnixDatagram::unbound()); - or_panic!(sock.connect(&path1)); - - // Check send() - let msg = b"hello there"; - or_panic!(sock.send(msg)); - let mut buf = [0; 11]; - let (usize, addr) = or_panic!(bsock1.recv_from(&mut buf)); - assert_eq!(usize, 11); - assert!(addr.is_unnamed()); - assert_eq!(msg, &buf[..]); - - // Changing default socket works too - or_panic!(sock.connect(&path2)); - or_panic!(sock.send(msg)); - or_panic!(bsock2.recv_from(&mut buf)); -} - -#[test] -fn test_unix_datagram_recv() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::unbound()); - or_panic!(sock2.connect(&path1)); - - let msg = b"hello world"; - or_panic!(sock2.send(msg)); - let mut buf = [0; 11]; - let size = or_panic!(sock1.recv(&mut buf)); - assert_eq!(size, 11); - assert_eq!(msg, &buf[..]); -} - -#[test] -fn datagram_pair() { - let msg1 = b"hello"; - let msg2 = b"world!"; - - let (s1, s2) = or_panic!(UnixDatagram::pair()); - let thread = thread::spawn(move || { - // s1 must be moved in or the test will hang! - let mut buf = [0; 5]; - or_panic!(s1.recv(&mut buf)); - assert_eq!(&msg1[..], &buf[..]); - or_panic!(s1.send(msg2)); - }); - - or_panic!(s2.send(msg1)); - let mut buf = [0; 6]; - or_panic!(s2.recv(&mut buf)); - assert_eq!(&msg2[..], &buf[..]); - drop(s2); - - thread.join().unwrap(); -} - -// Ensure the `set_read_timeout` and `set_write_timeout` calls return errors -// when passed zero Durations -#[test] -fn test_unix_datagram_timeout_zero_duration() { - let dir = tmpdir(); - let path = dir.path().join("sock"); - - let datagram = or_panic!(UnixDatagram::bind(&path)); - - let result = datagram.set_write_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); - - let result = datagram.set_read_timeout(Some(Duration::new(0, 0))); - let err = result.unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidInput); -} - -#[test] -fn abstract_namespace_not_allowed() { - assert!(UnixStream::connect("\0asdf").is_err()); -} - -#[test] -fn test_unix_stream_peek() { - let (txdone, rxdone) = crate::sync::mpsc::channel(); - - let dir = tmpdir(); - let path = dir.path().join("sock"); - - let listener = or_panic!(UnixListener::bind(&path)); - let thread = thread::spawn(move || { - let mut stream = or_panic!(listener.accept()).0; - or_panic!(stream.write_all(&[1, 3, 3, 7])); - or_panic!(rxdone.recv()); - }); - - let mut stream = or_panic!(UnixStream::connect(&path)); - let mut buf = [0; 10]; - for _ in 0..2 { - assert_eq!(or_panic!(stream.peek(&mut buf)), 4); - } - assert_eq!(or_panic!(stream.read(&mut buf)), 4); - - or_panic!(stream.set_nonblocking(true)); - match stream.peek(&mut buf) { - Ok(_) => panic!("expected error"), - Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} - Err(e) => panic!("unexpected error: {}", e), - } - - or_panic!(txdone.send(())); - thread.join().unwrap(); -} - -#[test] -fn test_unix_datagram_peek() { - let dir = tmpdir(); - let path1 = dir.path().join("sock"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::unbound()); - or_panic!(sock2.connect(&path1)); - - let msg = b"hello world"; - or_panic!(sock2.send(msg)); - for _ in 0..2 { - let mut buf = [0; 11]; - let size = or_panic!(sock1.peek(&mut buf)); - assert_eq!(size, 11); - assert_eq!(msg, &buf[..]); - } - - let mut buf = [0; 11]; - let size = or_panic!(sock1.recv(&mut buf)); - assert_eq!(size, 11); - assert_eq!(msg, &buf[..]); -} - -#[test] -fn test_unix_datagram_peek_from() { - let dir = tmpdir(); - let path1 = dir.path().join("sock"); - - let sock1 = or_panic!(UnixDatagram::bind(&path1)); - let sock2 = or_panic!(UnixDatagram::unbound()); - or_panic!(sock2.connect(&path1)); - - let msg = b"hello world"; - or_panic!(sock2.send(msg)); - for _ in 0..2 { - let mut buf = [0; 11]; - let (size, _) = or_panic!(sock1.peek_from(&mut buf)); - assert_eq!(size, 11); - assert_eq!(msg, &buf[..]); - } - - let mut buf = [0; 11]; - let size = or_panic!(sock1.recv(&mut buf)); - assert_eq!(size, 11); - assert_eq!(msg, &buf[..]); -} - -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -#[test] -fn test_send_vectored_fds_unix_stream() { - let (s1, s2) = or_panic!(UnixStream::pair()); - - let buf1 = [1; 8]; - let bufs_send = &[IoSlice::new(&buf1[..])][..]; - - let mut ancillary1_buffer = [0; 128]; - let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); - assert!(ancillary1.add_fds(&[s1.as_raw_fd()][..])); - - let usize = or_panic!(s1.send_vectored_with_ancillary(&bufs_send, &mut ancillary1)); - assert_eq!(usize, 8); - - let mut buf2 = [0; 8]; - let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; - - let mut ancillary2_buffer = [0; 128]; - let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); - - let usize = or_panic!(s2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2)); - assert_eq!(usize, 8); - assert_eq!(buf1, buf2); - - let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); - assert_eq!(ancillary_data_vec.len(), 1); - if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() { - let fd_vec = Vec::from_iter(scm_rights); - assert_eq!(fd_vec.len(), 1); - unsafe { - libc::close(fd_vec[0]); - } - } else { - unreachable!("must be ScmRights"); - } -} - -#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux",))] -#[test] -fn test_send_vectored_with_ancillary_to_unix_datagram() { - fn getpid() -> libc::pid_t { - unsafe { libc::getpid() } - } - - fn getuid() -> libc::uid_t { - unsafe { libc::getuid() } - } - - fn getgid() -> libc::gid_t { - unsafe { libc::getgid() } - } - - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let bsock1 = or_panic!(UnixDatagram::bind(&path1)); - let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - - or_panic!(bsock2.set_passcred(true)); - - let buf1 = [1; 8]; - let bufs_send = &[IoSlice::new(&buf1[..])][..]; - - let mut ancillary1_buffer = [0; 128]; - let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); - let mut cred1 = SocketCred::new(); - cred1.set_pid(getpid()); - cred1.set_uid(getuid()); - cred1.set_gid(getgid()); - assert!(ancillary1.add_creds(&[cred1.clone()][..])); - - let usize = - or_panic!(bsock1.send_vectored_with_ancillary_to(&bufs_send, &mut ancillary1, &path2)); - assert_eq!(usize, 8); - - let mut buf2 = [0; 8]; - let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; - - let mut ancillary2_buffer = [0; 128]; - let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); - - let (usize, truncated, _addr) = - or_panic!(bsock2.recv_vectored_with_ancillary_from(&mut bufs_recv, &mut ancillary2)); - assert_eq!(ancillary2.truncated(), false); - assert_eq!(usize, 8); - assert_eq!(truncated, false); - assert_eq!(buf1, buf2); - - let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); - assert_eq!(ancillary_data_vec.len(), 1); - if let AncillaryData::ScmCredentials(scm_credentials) = - ancillary_data_vec.pop().unwrap().unwrap() - { - let cred_vec = Vec::from_iter(scm_credentials); - assert_eq!(cred_vec.len(), 1); - assert_eq!(cred1.get_pid(), cred_vec[0].get_pid()); - assert_eq!(cred1.get_uid(), cred_vec[0].get_uid()); - assert_eq!(cred1.get_gid(), cred_vec[0].get_gid()); - } else { - unreachable!("must be ScmCredentials"); - } -} - -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", -))] -#[test] -fn test_send_vectored_with_ancillary_unix_datagram() { - let dir = tmpdir(); - let path1 = dir.path().join("sock1"); - let path2 = dir.path().join("sock2"); - - let bsock1 = or_panic!(UnixDatagram::bind(&path1)); - let bsock2 = or_panic!(UnixDatagram::bind(&path2)); - - let buf1 = [1; 8]; - let bufs_send = &[IoSlice::new(&buf1[..])][..]; - - let mut ancillary1_buffer = [0; 128]; - let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]); - assert!(ancillary1.add_fds(&[bsock1.as_raw_fd()][..])); - - or_panic!(bsock1.connect(&path2)); - let usize = or_panic!(bsock1.send_vectored_with_ancillary(&bufs_send, &mut ancillary1)); - assert_eq!(usize, 8); - - let mut buf2 = [0; 8]; - let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..]; - - let mut ancillary2_buffer = [0; 128]; - let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]); - - let (usize, truncated) = - or_panic!(bsock2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2)); - assert_eq!(usize, 8); - assert_eq!(truncated, false); - assert_eq!(buf1, buf2); - - let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages()); - assert_eq!(ancillary_data_vec.len(), 1); - if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() { - let fd_vec = Vec::from_iter(scm_rights); - assert_eq!(fd_vec.len(), 1); - unsafe { - libc::close(fd_vec[0]); - } - } else { - unreachable!("must be ScmRights"); - } -} diff --git a/library/std/src/sys/unix/ext/process.rs b/library/std/src/sys/unix/ext/process.rs deleted file mode 100644 index 355855bcd10..00000000000 --- a/library/std/src/sys/unix/ext/process.rs +++ /dev/null @@ -1,337 +0,0 @@ -//! Unix-specific extensions to primitives in the `std::process` module. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::ffi::OsStr; -use crate::io; -use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use crate::process; -use crate::sealed::Sealed; -use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; - -/// Unix-specific extensions to the [`process::Command`] builder. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait CommandExt: Sealed { - /// Sets the child process's user ID. This translates to a - /// `setuid` call in the child process. Failure in the `setuid` - /// call will cause the spawn to fail. - #[stable(feature = "rust1", since = "1.0.0")] - fn uid( - &mut self, - #[cfg(not(target_os = "vxworks"))] id: u32, - #[cfg(target_os = "vxworks")] id: u16, - ) -> &mut process::Command; - - /// Similar to `uid`, but sets the group ID of the child process. This has - /// the same semantics as the `uid` field. - #[stable(feature = "rust1", since = "1.0.0")] - fn gid( - &mut self, - #[cfg(not(target_os = "vxworks"))] id: u32, - #[cfg(target_os = "vxworks")] id: u16, - ) -> &mut process::Command; - - /// Sets the supplementary group IDs for the calling process. Translates to - /// a `setgroups` call in the child process. - #[unstable(feature = "setgroups", issue = "38527", reason = "")] - fn groups( - &mut self, - #[cfg(not(target_os = "vxworks"))] groups: &[u32], - #[cfg(target_os = "vxworks")] groups: &[u16], - ) -> &mut process::Command; - - /// Schedules a closure to be run just before the `exec` function is - /// invoked. - /// - /// The closure is allowed to return an I/O error whose OS error code will - /// be communicated back to the parent and returned as an error from when - /// the spawn was requested. - /// - /// Multiple closures can be registered and they will be called in order of - /// their registration. If a closure returns `Err` then no further closures - /// will be called and the spawn operation will immediately return with a - /// failure. - /// - /// # Notes and Safety - /// - /// This closure will be run in the context of the child process after a - /// `fork`. This primarily means that any modifications made to memory on - /// behalf of this closure will **not** be visible to the parent process. - /// This is often a very constrained environment where normal operations - /// like `malloc`, accessing environment variables through [`std::env`] - /// or acquiring a mutex are not guaranteed to work (due to - /// other threads perhaps still running when the `fork` was run). - /// - /// For further details refer to the [POSIX fork() specification] - /// and the equivalent documentation for any targeted - /// platform, especially the requirements around *async-signal-safety*. - /// - /// This also means that all resources such as file descriptors and - /// memory-mapped regions got duplicated. It is your responsibility to make - /// sure that the closure does not violate library invariants by making - /// invalid use of these duplicates. - /// - /// When this closure is run, aspects such as the stdio file descriptors and - /// working directory have successfully been changed, so output to these - /// locations may not appear where intended. - /// - /// [POSIX fork() specification]: - /// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html - /// [`std::env`]: mod@crate::env - #[stable(feature = "process_pre_exec", since = "1.34.0")] - unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command - where - F: FnMut() -> io::Result<()> + Send + Sync + 'static; - - /// Schedules a closure to be run just before the `exec` function is - /// invoked. - /// - /// This method is stable and usable, but it should be unsafe. To fix - /// that, it got deprecated in favor of the unsafe [`pre_exec`]. - /// - /// [`pre_exec`]: CommandExt::pre_exec - #[stable(feature = "process_exec", since = "1.15.0")] - #[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")] - fn before_exec<F>(&mut self, f: F) -> &mut process::Command - where - F: FnMut() -> io::Result<()> + Send + Sync + 'static, - { - unsafe { self.pre_exec(f) } - } - - /// Performs all the required setup by this `Command`, followed by calling - /// the `execvp` syscall. - /// - /// On success this function will not return, and otherwise it will return - /// an error indicating why the exec (or another part of the setup of the - /// `Command`) failed. - /// - /// `exec` not returning has the same implications as calling - /// [`process::exit`] – no destructors on the current stack or any other - /// thread’s stack will be run. Therefore, it is recommended to only call - /// `exec` at a point where it is fine to not run any destructors. Note, - /// that the `execvp` syscall independently guarantees that all memory is - /// freed and all file descriptors with the `CLOEXEC` option (set by default - /// on all file descriptors opened by the standard library) are closed. - /// - /// This function, unlike `spawn`, will **not** `fork` the process to create - /// a new child. Like spawn, however, the default behavior for the stdio - /// descriptors will be to inherited from the current process. - /// - /// # Notes - /// - /// The process may be in a "broken state" if this function returns in - /// error. For example the working directory, environment variables, signal - /// handling settings, various user/group information, or aspects of stdio - /// file descriptors may have changed. If a "transactional spawn" is - /// required to gracefully handle errors it is recommended to use the - /// cross-platform `spawn` instead. - #[stable(feature = "process_exec2", since = "1.9.0")] - fn exec(&mut self) -> io::Error; - - /// Set executable argument - /// - /// Set the first process argument, `argv[0]`, to something other than the - /// default executable path. - #[stable(feature = "process_set_argv0", since = "1.45.0")] - fn arg0<S>(&mut self, arg: S) -> &mut process::Command - where - S: AsRef<OsStr>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl CommandExt for process::Command { - fn uid( - &mut self, - #[cfg(not(target_os = "vxworks"))] id: u32, - #[cfg(target_os = "vxworks")] id: u16, - ) -> &mut process::Command { - self.as_inner_mut().uid(id); - self - } - - fn gid( - &mut self, - #[cfg(not(target_os = "vxworks"))] id: u32, - #[cfg(target_os = "vxworks")] id: u16, - ) -> &mut process::Command { - self.as_inner_mut().gid(id); - self - } - - fn groups( - &mut self, - #[cfg(not(target_os = "vxworks"))] groups: &[u32], - #[cfg(target_os = "vxworks")] groups: &[u16], - ) -> &mut process::Command { - self.as_inner_mut().groups(groups); - self - } - - unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command - where - F: FnMut() -> io::Result<()> + Send + Sync + 'static, - { - self.as_inner_mut().pre_exec(Box::new(f)); - self - } - - fn exec(&mut self) -> io::Error { - // NOTE: This may *not* be safe to call after `libc::fork`, because it - // may allocate. That may be worth fixing at some point in the future. - self.as_inner_mut().exec(sys::process::Stdio::Inherit) - } - - fn arg0<S>(&mut self, arg: S) -> &mut process::Command - where - S: AsRef<OsStr>, - { - self.as_inner_mut().set_arg_0(arg.as_ref()); - self - } -} - -/// Unix-specific extensions to [`process::ExitStatus`]. -/// -/// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as passed to the -/// `exit` system call or returned by [`ExitStatus::code()`](crate::process::ExitStatus::code). -/// It represents **any wait status**, as returned by one of the `wait` family of system calls. -/// -/// This is because a Unix wait status (a Rust `ExitStatus`) can represent a Unix exit status, but -/// can also represent other kinds of process event. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait ExitStatusExt: Sealed { - /// Creates a new `ExitStatus` from the raw underlying integer status value from `wait` - /// - /// The value should be a **wait status, not an exit status**. - #[stable(feature = "exit_status_from", since = "1.12.0")] - fn from_raw(raw: i32) -> Self; - - /// If the process was terminated by a signal, returns that signal. - /// - /// In other words, if `WIFSIGNALED`, this returns `WTERMSIG`. - #[stable(feature = "rust1", since = "1.0.0")] - fn signal(&self) -> Option<i32>; - - /// If the process was terminated by a signal, says whether it dumped core. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] - fn core_dumped(&self) -> bool; - - /// If the process was stopped by a signal, returns that signal. - /// - /// In other words, if `WIFSTOPPED`, this returns `WSTOPSIG`. This is only possible if the status came from - /// a `wait` system call which was passed `WUNTRACED`, and was then converted into an `ExitStatus`. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] - fn stopped_signal(&self) -> Option<i32>; - - /// Whether the process was continued from a stopped status. - /// - /// Ie, `WIFCONTINUED`. This is only possible if the status came from a `wait` system call - /// which was passed `WCONTINUED`, and was then converted into an `ExitStatus`. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] - fn continued(&self) -> bool; - - /// Returns the underlying raw `wait` status. - /// - /// The returned integer is a **wait status, not an exit status**. - #[unstable(feature = "unix_process_wait_more", issue = "80695")] - fn into_raw(self) -> i32; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExitStatusExt for process::ExitStatus { - fn from_raw(raw: i32) -> Self { - process::ExitStatus::from_inner(From::from(raw)) - } - - fn signal(&self) -> Option<i32> { - self.as_inner().signal() - } - - fn core_dumped(&self) -> bool { - self.as_inner().core_dumped() - } - - fn stopped_signal(&self) -> Option<i32> { - self.as_inner().stopped_signal() - } - - fn continued(&self) -> bool { - self.as_inner().continued() - } - - fn into_raw(self) -> i32 { - self.as_inner().into_raw().into() - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl FromRawFd for process::Stdio { - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio { - let fd = sys::fd::FileDesc::new(fd); - let io = sys::process::Stdio::Fd(fd); - process::Stdio::from_inner(io) - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawFd for process::ChildStdin { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.as_inner().fd().raw() - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawFd for process::ChildStdout { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.as_inner().fd().raw() - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawFd for process::ChildStderr { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.as_inner().fd().raw() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for process::ChildStdin { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_fd().into_raw() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for process::ChildStdout { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_fd().into_raw() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for process::ChildStderr { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_fd().into_raw() - } -} - -/// Returns the OS-assigned process identifier associated with this process's parent. -#[stable(feature = "unix_ppid", since = "1.27.0")] -pub fn parent_id() -> u32 { - crate::sys::os::getppid() -} diff --git a/library/std/src/sys/unix/ext/raw.rs b/library/std/src/sys/unix/ext/raw.rs deleted file mode 100644 index c292955cb4e..00000000000 --- a/library/std/src/sys/unix/ext/raw.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Unix-specific primitives available on all unix platforms. - -#![stable(feature = "raw_ext", since = "1.1.0")] -#![rustc_deprecated( - since = "1.8.0", - reason = "these type aliases are no longer supported by \ - the standard library, the `libc` crate on \ - crates.io should be used instead for the correct \ - definitions" -)] -#![allow(deprecated)] - -#[stable(feature = "raw_ext", since = "1.1.0")] -#[allow(non_camel_case_types)] -pub type uid_t = u32; - -#[stable(feature = "raw_ext", since = "1.1.0")] -#[allow(non_camel_case_types)] -pub type gid_t = u32; - -#[stable(feature = "raw_ext", since = "1.1.0")] -#[allow(non_camel_case_types)] -pub type pid_t = i32; - -#[doc(inline)] -#[stable(feature = "pthread_t", since = "1.8.0")] -pub use super::platform::raw::pthread_t; -#[doc(inline)] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub use super::platform::raw::{blkcnt_t, time_t}; -#[doc(inline)] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub use super::platform::raw::{blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t}; diff --git a/library/std/src/sys/unix/ext/thread.rs b/library/std/src/sys/unix/ext/thread.rs deleted file mode 100644 index 7221da1a9a7..00000000000 --- a/library/std/src/sys/unix/ext/thread.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! Unix-specific extensions to primitives in the `std::thread` module. - -#![stable(feature = "thread_extensions", since = "1.9.0")] - -#[allow(deprecated)] -use crate::os::unix::raw::pthread_t; -use crate::sys_common::{AsInner, IntoInner}; -use crate::thread::JoinHandle; - -#[stable(feature = "thread_extensions", since = "1.9.0")] -#[allow(deprecated)] -pub type RawPthread = pthread_t; - -/// Unix-specific extensions to [`JoinHandle`]. -#[stable(feature = "thread_extensions", since = "1.9.0")] -pub trait JoinHandleExt { - /// Extracts the raw pthread_t without taking ownership - #[stable(feature = "thread_extensions", since = "1.9.0")] - fn as_pthread_t(&self) -> RawPthread; - - /// Consumes the thread, returning the raw pthread_t - /// - /// This function **transfers ownership** of the underlying pthread_t to - /// the caller. Callers are then the unique owners of the pthread_t and - /// must either detach or join the pthread_t once it's no longer needed. - #[stable(feature = "thread_extensions", since = "1.9.0")] - fn into_pthread_t(self) -> RawPthread; -} - -#[stable(feature = "thread_extensions", since = "1.9.0")] -impl<T> JoinHandleExt for JoinHandle<T> { - fn as_pthread_t(&self) -> RawPthread { - self.as_inner().id() as RawPthread - } - - fn into_pthread_t(self) -> RawPthread { - self.into_inner().into_id() as RawPthread - } -} diff --git a/library/std/src/sys/unix/ext/ucred.rs b/library/std/src/sys/unix/ext/ucred.rs deleted file mode 100644 index 1b4c18d3d84..00000000000 --- a/library/std/src/sys/unix/ext/ucred.rs +++ /dev/null @@ -1,126 +0,0 @@ -//! Unix peer credentials. - -// NOTE: Code in this file is heavily based on work done in PR 13 from the tokio-uds repository on -// GitHub. -// -// For reference, the link is here: https://github.com/tokio-rs/tokio-uds/pull/13 -// Credit to Martin Habovštiak (GitHub username Kixunil) and contributors for this work. - -use libc::{gid_t, pid_t, uid_t}; - -/// Credentials for a UNIX process for credentials passing. -#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct UCred { - /// The UID part of the peer credential. This is the effective UID of the process at the domain - /// socket's endpoint. - pub uid: uid_t, - /// The GID part of the peer credential. This is the effective GID of the process at the domain - /// socket's endpoint. - pub gid: gid_t, - /// The PID part of the peer credential. This field is optional because the PID part of the - /// peer credentials is not supported on every platform. On platforms where the mechanism to - /// discover the PID exists, this field will be populated to the PID of the process at the - /// domain socket's endpoint. Otherwise, it will be set to None. - pub pid: Option<pid_t>, -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::impl_linux::peer_cred; - -#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] -pub use self::impl_bsd::peer_cred; - -#[cfg(any(target_os = "macos", target_os = "ios",))] -pub use self::impl_mac::peer_cred; - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub mod impl_linux { - use super::UCred; - use crate::os::unix::io::AsRawFd; - use crate::os::unix::net::UnixStream; - use crate::{io, mem}; - use libc::{c_void, getsockopt, socklen_t, ucred, SOL_SOCKET, SO_PEERCRED}; - - pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> { - let ucred_size = mem::size_of::<ucred>(); - - // Trivial sanity checks. - assert!(mem::size_of::<u32>() <= mem::size_of::<usize>()); - assert!(ucred_size <= u32::MAX as usize); - - let mut ucred_size = ucred_size as socklen_t; - let mut ucred: ucred = ucred { pid: 1, uid: 1, gid: 1 }; - - unsafe { - let ret = getsockopt( - socket.as_raw_fd(), - SOL_SOCKET, - SO_PEERCRED, - &mut ucred as *mut ucred as *mut c_void, - &mut ucred_size, - ); - - if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() { - Ok(UCred { uid: ucred.uid, gid: ucred.gid, pid: Some(ucred.pid) }) - } else { - Err(io::Error::last_os_error()) - } - } - } -} - -#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))] -pub mod impl_bsd { - use super::UCred; - use crate::io; - use crate::os::unix::io::AsRawFd; - use crate::os::unix::net::UnixStream; - - pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> { - let mut cred = UCred { uid: 1, gid: 1, pid: None }; - unsafe { - let ret = libc::getpeereid(socket.as_raw_fd(), &mut cred.uid, &mut cred.gid); - - if ret == 0 { Ok(cred) } else { Err(io::Error::last_os_error()) } - } - } -} - -#[cfg(any(target_os = "macos", target_os = "ios",))] -pub mod impl_mac { - use super::UCred; - use crate::os::unix::io::AsRawFd; - use crate::os::unix::net::UnixStream; - use crate::{io, mem}; - use libc::{c_void, getpeereid, getsockopt, pid_t, socklen_t, LOCAL_PEERPID, SOL_LOCAL}; - - pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> { - let mut cred = UCred { uid: 1, gid: 1, pid: None }; - unsafe { - let ret = getpeereid(socket.as_raw_fd(), &mut cred.uid, &mut cred.gid); - - if ret != 0 { - return Err(io::Error::last_os_error()); - } - - let mut pid: pid_t = 1; - let mut pid_size = mem::size_of::<pid_t>() as socklen_t; - - let ret = getsockopt( - socket.as_raw_fd(), - SOL_LOCAL, - LOCAL_PEERPID, - &mut pid as *mut pid_t as *mut c_void, - &mut pid_size, - ); - - if ret == 0 && pid_size as usize == mem::size_of::<pid_t>() { - cred.pid = Some(pid); - Ok(cred) - } else { - Err(io::Error::last_os_error()) - } - } - } -} diff --git a/library/std/src/sys/unix/ext/ucred/tests.rs b/library/std/src/sys/unix/ext/ucred/tests.rs deleted file mode 100644 index 42d79418cf7..00000000000 --- a/library/std/src/sys/unix/ext/ucred/tests.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::os::unix::net::UnixStream; -use libc::{getegid, geteuid, getpid}; - -#[test] -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" -))] -fn test_socket_pair() { - // Create two connected sockets and get their peer credentials. They should be equal. - let (sock_a, sock_b) = UnixStream::pair().unwrap(); - let (cred_a, cred_b) = (sock_a.peer_cred().unwrap(), sock_b.peer_cred().unwrap()); - assert_eq!(cred_a, cred_b); - - // Check that the UID and GIDs match up. - let uid = unsafe { geteuid() }; - let gid = unsafe { getegid() }; - assert_eq!(cred_a.uid, uid); - assert_eq!(cred_a.gid, gid); -} - -#[test] -#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos",))] -fn test_socket_pair_pids(arg: Type) -> RetType { - // Create two connected sockets and get their peer credentials. - let (sock_a, sock_b) = UnixStream::pair().unwrap(); - let (cred_a, cred_b) = (sock_a.peer_cred().unwrap(), sock_b.peer_cred().unwrap()); - - // On supported platforms (see the cfg above), the credentials should always include the PID. - let pid = unsafe { getpid() }; - assert_eq!(cred_a.pid, Some(pid)); - assert_eq!(cred_b.pid, Some(pid)); -} diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 562d9d92637..57d91441b6f 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -15,7 +15,6 @@ pub mod args; pub mod cmath; pub mod condvar; pub mod env; -pub mod ext; pub mod fd; pub mod fs; pub mod futex; diff --git a/library/std/src/sys/wasi/ext/ffi.rs b/library/std/src/sys/wasi/ext/ffi.rs deleted file mode 100644 index f71f316d1ba..00000000000 --- a/library/std/src/sys/wasi/ext/ffi.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! WASI-specific extension to the primitives in the `std::ffi` module - -#![stable(feature = "rust1", since = "1.0.0")] - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::os_str_bytes::*; diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs deleted file mode 100644 index ba4057bd34c..00000000000 --- a/library/std/src/sys/wasi/ext/fs.rs +++ /dev/null @@ -1,536 +0,0 @@ -//! WASI-specific extensions to primitives in the `std::fs` module. - -#![deny(unsafe_op_in_unsafe_fn)] -#![unstable(feature = "wasi_ext", issue = "none")] - -use crate::ffi::OsStr; -use crate::fs::{self, File, Metadata, OpenOptions}; -use crate::io::{self, IoSlice, IoSliceMut}; -use crate::path::{Path, PathBuf}; -use crate::sys_common::{AsInner, AsInnerMut, FromInner}; -// Used for `File::read` on intra-doc links -#[allow(unused_imports)] -use io::{Read, Write}; - -/// WASI-specific extensions to [`File`]. -pub trait FileExt { - /// Reads a number of bytes starting from a given offset. - /// - /// Returns the number of bytes read. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// Note that similar to [`File::read`], it is not an error to return with a - /// short read. - fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { - let bufs = &mut [IoSliceMut::new(buf)]; - self.read_vectored_at(bufs, offset) - } - - /// Reads a number of bytes starting from a given offset. - /// - /// Returns the number of bytes read. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// Note that similar to [`File::read_vectored`], it is not an error to - /// return with a short read. - fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize>; - - /// Reads the exact number of byte required to fill `buf` from the given offset. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`. - /// - /// [`read_at`]: FileExt::read_at - /// - /// # Errors - /// - /// If this function encounters an error of the kind - /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation - /// will continue. - /// - /// If this function encounters an "end of file" before completely filling - /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`]. - /// The contents of `buf` are unspecified in this case. - /// - /// If any other read error is encountered then this function immediately - /// returns. The contents of `buf` are unspecified in this case. - /// - /// If this function returns an error, it is unspecified how many bytes it - /// has read, but it will never read more than would be necessary to - /// completely fill the buffer. - #[stable(feature = "rw_exact_all_at", since = "1.33.0")] - fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { - while !buf.is_empty() { - match self.read_at(buf, offset) { - Ok(0) => break, - Ok(n) => { - let tmp = buf; - buf = &mut tmp[n..]; - offset += n as u64; - } - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(e) => return Err(e), - } - } - if !buf.is_empty() { - Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) - } else { - Ok(()) - } - } - - /// Writes a number of bytes starting from a given offset. - /// - /// Returns the number of bytes written. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// When writing beyond the end of the file, the file is appropriately - /// extended and the intermediate bytes are initialized with the value 0. - /// - /// Note that similar to [`File::write`], it is not an error to return a - /// short write. - fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { - let bufs = &[IoSlice::new(buf)]; - self.write_vectored_at(bufs, offset) - } - - /// Writes a number of bytes starting from a given offset. - /// - /// Returns the number of bytes written. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// When writing beyond the end of the file, the file is appropriately - /// extended and the intermediate bytes are initialized with the value 0. - /// - /// Note that similar to [`File::write_vectored`], it is not an error to return a - /// short write. - fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize>; - - /// Attempts to write an entire buffer starting from a given offset. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. - /// - /// The current file cursor is not affected by this function. - /// - /// This method will continuously call [`write_at`] until there is no more data - /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is - /// returned. This method will not return until the entire buffer has been - /// successfully written or such an error occurs. The first error that is - /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be - /// returned. - /// - /// # Errors - /// - /// This function will return the first error of - /// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns. - /// - /// [`write_at`]: FileExt::write_at - #[stable(feature = "rw_exact_all_at", since = "1.33.0")] - fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { - while !buf.is_empty() { - match self.write_at(buf, offset) { - Ok(0) => { - return Err(io::Error::new_const( - io::ErrorKind::WriteZero, - &"failed to write whole buffer", - )); - } - Ok(n) => { - buf = &buf[n..]; - offset += n as u64 - } - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} - Err(e) => return Err(e), - } - } - Ok(()) - } - - /// Returns the current position within the file. - /// - /// This corresponds to the `fd_tell` syscall and is similar to - /// `seek` where you offset 0 bytes from the current position. - fn tell(&self) -> io::Result<u64>; - - /// Adjust the flags associated with this file. - /// - /// This corresponds to the `fd_fdstat_set_flags` syscall. - fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>; - - /// Adjust the rights associated with this file. - /// - /// This corresponds to the `fd_fdstat_set_rights` syscall. - fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>; - - /// Provide file advisory information on a file descriptor. - /// - /// This corresponds to the `fd_advise` syscall. - fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>; - - /// Force the allocation of space in a file. - /// - /// This corresponds to the `fd_allocate` syscall. - fn allocate(&self, offset: u64, len: u64) -> io::Result<()>; - - /// Create a directory. - /// - /// This corresponds to the `path_create_directory` syscall. - fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()>; - - /// Read the contents of a symbolic link. - /// - /// This corresponds to the `path_readlink` syscall. - fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>; - - /// Return the attributes of a file or directory. - /// - /// This corresponds to the `path_filestat_get` syscall. - fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata>; - - /// Unlink a file. - /// - /// This corresponds to the `path_unlink_file` syscall. - fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>; - - /// Remove a directory. - /// - /// This corresponds to the `path_remove_directory` syscall. - fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()>; -} - -// FIXME: bind fd_fdstat_get - need to define a custom return type -// FIXME: bind fd_readdir - can't return `ReadDir` since we only have entry name -// FIXME: bind fd_filestat_set_times maybe? - on crates.io for unix -// FIXME: bind path_filestat_set_times maybe? - on crates.io for unix -// FIXME: bind poll_oneoff maybe? - probably should wait for I/O to settle -// FIXME: bind random_get maybe? - on crates.io for unix - -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) - } - - fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { - self.as_inner().fd().pwrite(bufs, offset) - } - - fn tell(&self) -> io::Result<u64> { - self.as_inner().fd().tell() - } - - fn fdstat_set_flags(&self, flags: u16) -> io::Result<()> { - self.as_inner().fd().set_flags(flags) - } - - fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()> { - self.as_inner().fd().set_rights(rights, inheriting) - } - - fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()> { - self.as_inner().fd().advise(offset, len, advice) - } - - fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - self.as_inner().fd().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())?) - } - - fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> { - self.as_inner().read_link(path.as_ref()) - } - - fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata> { - let m = self.as_inner().metadata_at(lookup_flags, path.as_ref())?; - Ok(FromInner::from_inner(m)) - } - - fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { - self.as_inner().fd().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())?) - } -} - -/// WASI-specific extensions to [`fs::OpenOptions`]. -pub trait OpenOptionsExt { - /// Pass custom `dirflags` argument to `path_open`. - /// - /// This option configures the `dirflags` argument to the - /// `path_open` syscall which `OpenOptions` will eventually call. The - /// `dirflags` argument configures how the file is looked up, currently - /// primarily affecting whether symlinks are followed or not. - /// - /// By default this value is `__WASI_LOOKUP_SYMLINK_FOLLOW`, or symlinks are - /// followed. You can call this method with 0 to disable following symlinks - fn lookup_flags(&mut self, flags: u32) -> &mut Self; - - /// Indicates whether `OpenOptions` must open a directory or not. - /// - /// This method will configure whether the `__WASI_O_DIRECTORY` flag is - /// passed when opening a file. When passed it will require that the opened - /// path is a directory. - /// - /// This option is by default `false` - fn directory(&mut self, dir: bool) -> &mut Self; - - /// Indicates whether `__WASI_FDFLAG_DSYNC` is passed in the `fs_flags` - /// field of `path_open`. - /// - /// This option is by default `false` - fn dsync(&mut self, dsync: bool) -> &mut Self; - - /// Indicates whether `__WASI_FDFLAG_NONBLOCK` is passed in the `fs_flags` - /// field of `path_open`. - /// - /// This option is by default `false` - fn nonblock(&mut self, nonblock: bool) -> &mut Self; - - /// Indicates whether `__WASI_FDFLAG_RSYNC` is passed in the `fs_flags` - /// field of `path_open`. - /// - /// This option is by default `false` - fn rsync(&mut self, rsync: bool) -> &mut Self; - - /// Indicates whether `__WASI_FDFLAG_SYNC` is passed in the `fs_flags` - /// field of `path_open`. - /// - /// This option is by default `false` - fn sync(&mut self, sync: bool) -> &mut Self; - - /// Indicates the value that should be passed in for the `fs_rights_base` - /// parameter of `path_open`. - /// - /// This option defaults based on the `read` and `write` configuration of - /// this `OpenOptions` builder. If this method is called, however, the - /// exact mask passed in will be used instead. - fn fs_rights_base(&mut self, rights: u64) -> &mut Self; - - /// Indicates the value that should be passed in for the - /// `fs_rights_inheriting` parameter of `path_open`. - /// - /// The default for this option is the same value as what will be passed - /// for the `fs_rights_base` parameter but if this method is called then - /// the specified value will be used instead. - fn fs_rights_inheriting(&mut self, rights: u64) -> &mut Self; - - /// Open a file or directory. - /// - /// This corresponds to the `path_open` syscall. - fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File>; -} - -impl OpenOptionsExt for OpenOptions { - fn lookup_flags(&mut self, flags: u32) -> &mut OpenOptions { - self.as_inner_mut().lookup_flags(flags); - self - } - - fn directory(&mut self, dir: bool) -> &mut OpenOptions { - self.as_inner_mut().directory(dir); - self - } - - fn dsync(&mut self, enabled: bool) -> &mut OpenOptions { - self.as_inner_mut().dsync(enabled); - self - } - - fn nonblock(&mut self, enabled: bool) -> &mut OpenOptions { - self.as_inner_mut().nonblock(enabled); - self - } - - fn rsync(&mut self, enabled: bool) -> &mut OpenOptions { - self.as_inner_mut().rsync(enabled); - self - } - - fn sync(&mut self, enabled: bool) -> &mut OpenOptions { - self.as_inner_mut().sync(enabled); - self - } - - fn fs_rights_base(&mut self, rights: u64) -> &mut OpenOptions { - self.as_inner_mut().fs_rights_base(rights); - self - } - - fn fs_rights_inheriting(&mut self, rights: u64) -> &mut OpenOptions { - self.as_inner_mut().fs_rights_inheriting(rights); - self - } - - fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File> { - let inner = file.as_inner().open_at(path.as_ref(), self.as_inner())?; - Ok(File::from_inner(inner)) - } -} - -/// WASI-specific extensions to [`fs::Metadata`]. -pub trait MetadataExt { - /// Returns the `st_dev` field of the internal `filestat_t` - fn dev(&self) -> u64; - /// Returns the `st_ino` field of the internal `filestat_t` - fn ino(&self) -> u64; - /// Returns the `st_nlink` field of the internal `filestat_t` - fn nlink(&self) -> u64; - /// Returns the `st_size` field of the internal `filestat_t` - fn size(&self) -> u64; - /// Returns the `st_atim` field of the internal `filestat_t` - fn atim(&self) -> u64; - /// Returns the `st_mtim` field of the internal `filestat_t` - fn mtim(&self) -> u64; - /// Returns the `st_ctim` field of the internal `filestat_t` - fn ctim(&self) -> u64; -} - -impl MetadataExt for fs::Metadata { - fn dev(&self) -> u64 { - self.as_inner().as_wasi().dev - } - fn ino(&self) -> u64 { - self.as_inner().as_wasi().ino - } - fn nlink(&self) -> u64 { - self.as_inner().as_wasi().nlink - } - fn size(&self) -> u64 { - self.as_inner().as_wasi().size - } - fn atim(&self) -> u64 { - self.as_inner().as_wasi().atim - } - fn mtim(&self) -> u64 { - self.as_inner().as_wasi().mtim - } - fn ctim(&self) -> u64 { - self.as_inner().as_wasi().ctim - } -} - -/// WASI-specific extensions for [`fs::FileType`]. -/// -/// Adds support for special WASI file types such as block/character devices, -/// pipes, and sockets. -pub trait FileTypeExt { - /// Returns `true` if this file type is a block device. - fn is_block_device(&self) -> bool; - /// Returns `true` if this file type is a character device. - fn is_character_device(&self) -> bool; - /// Returns `true` if this file type is a socket datagram. - fn is_socket_dgram(&self) -> bool; - /// Returns `true` if this file type is a socket stream. - fn is_socket_stream(&self) -> bool; -} - -impl FileTypeExt for fs::FileType { - fn is_block_device(&self) -> bool { - self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE - } - fn is_character_device(&self) -> bool { - self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE - } - fn is_socket_dgram(&self) -> bool { - self.as_inner().bits() == wasi::FILETYPE_SOCKET_DGRAM - } - fn is_socket_stream(&self) -> bool { - self.as_inner().bits() == wasi::FILETYPE_SOCKET_STREAM - } -} - -/// WASI-specific extension methods for [`fs::DirEntry`]. -pub trait DirEntryExt { - /// Returns the underlying `d_ino` field of the `dirent_t` - fn ino(&self) -> u64; -} - -impl DirEntryExt for fs::DirEntry { - fn ino(&self) -> u64 { - self.as_inner().ino() - } -} - -/// Create a hard link. -/// -/// This corresponds to the `path_link` syscall. -pub fn link<P: AsRef<Path>, U: AsRef<Path>>( - old_fd: &File, - old_flags: u32, - old_path: P, - new_fd: &File, - new_path: U, -) -> io::Result<()> { - old_fd.as_inner().fd().link( - old_flags, - osstr2str(old_path.as_ref().as_ref())?, - new_fd.as_inner().fd(), - osstr2str(new_path.as_ref().as_ref())?, - ) -} - -/// Rename a file or directory. -/// -/// This corresponds to the `path_rename` syscall. -pub fn rename<P: AsRef<Path>, U: AsRef<Path>>( - old_fd: &File, - old_path: P, - new_fd: &File, - new_path: U, -) -> io::Result<()> { - old_fd.as_inner().fd().rename( - osstr2str(old_path.as_ref().as_ref())?, - new_fd.as_inner().fd(), - osstr2str(new_path.as_ref().as_ref())?, - ) -} - -/// Create a symbolic link. -/// -/// This corresponds to the `path_symlink` syscall. -pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>( - old_path: P, - fd: &File, - new_path: U, -) -> io::Result<()> { - fd.as_inner() - .fd() - .symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?) -} - -/// Create a symbolic link. -/// -/// This is a convenience API similar to `std::os::unix::fs::symlink` and -/// `std::os::windows::fs::symlink_file` and `std::os::windows::fs::symlink_dir`. -pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) -> io::Result<()> { - crate::sys::fs::symlink(old_path.as_ref(), new_path.as_ref()) -} - -fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) -} diff --git a/library/std/src/sys/wasi/ext/io.rs b/library/std/src/sys/wasi/ext/io.rs deleted file mode 100644 index b2e79cc1b4a..00000000000 --- a/library/std/src/sys/wasi/ext/io.rs +++ /dev/null @@ -1,201 +0,0 @@ -//! WASI-specific extensions to general I/O primitives - -#![deny(unsafe_op_in_unsafe_fn)] -#![unstable(feature = "wasi_ext", issue = "none")] - -use crate::fs; -use crate::io; -use crate::net; -use crate::sys; -use crate::sys_common::{AsInner, FromInner, IntoInner}; - -/// Raw file descriptors. -pub type RawFd = u32; - -/// 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 as RawFd - } -} - -impl AsRawFd for io::Stdout { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd - } -} - -impl AsRawFd for io::Stderr { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd - } -} - -impl<'a> AsRawFd for io::StdinLock<'a> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd - } -} - -impl<'a> AsRawFd for io::StdoutLock<'a> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd - } -} - -impl<'a> AsRawFd for io::StderrLock<'a> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd - } -} diff --git a/library/std/src/sys/wasi/ext/mod.rs b/library/std/src/sys/wasi/ext/mod.rs deleted file mode 100644 index b08402f0776..00000000000 --- a/library/std/src/sys/wasi/ext/mod.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! Platform-specific extensions to `std` for WASI. -//! -//! Provides access to platform-level information on WASI, and exposes -//! WASI-specific functions that would otherwise be inappropriate as -//! part of the core `std` library. -//! -//! It exposes more ways to deal with platform-specific strings (`OsStr`, -//! `OsString`), allows to set permissions more granularly, extract low-level -//! file descriptors from files and sockets, and has platform-specific helpers -//! for spawning processes. -//! -//! # Examples -//! -//! ```no_run -//! use std::fs::File; -//! use std::os::wasi::prelude::*; -//! -//! fn main() -> std::io::Result<()> { -//! let f = File::create("foo.txt")?; -//! let fd = f.as_raw_fd(); -//! -//! // use fd with native WASI bindings -//! -//! Ok(()) -//! } -//! ``` - -#![deny(unsafe_op_in_unsafe_fn)] -#![doc(cfg(target_os = "wasi"))] - -pub mod ffi; -pub mod fs; -pub mod io; - -/// A prelude for conveniently writing platform-specific code. -/// -/// Includes all extension traits, and some important type definitions. -#[stable(feature = "rust1", since = "1.0.0")] -pub mod prelude { - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::ffi::{OsStrExt, OsStringExt}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::fs::FileTypeExt; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - 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}; -} diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 88b81d455d2..45a829c0cd2 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -33,7 +33,6 @@ pub mod mutex; pub mod net; pub mod os; pub use crate::sys_common::os_str_bytes as os_str; -pub mod ext; #[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/windows/ext/ffi.rs b/library/std/src/sys/windows/ext/ffi.rs deleted file mode 100644 index c89b9ff1efa..00000000000 --- a/library/std/src/sys/windows/ext/ffi.rs +++ /dev/null @@ -1,134 +0,0 @@ -//! Windows-specific extensions to the primitives in the `std::ffi` module. -//! -//! # Overview -//! -//! For historical reasons, the Windows API uses a form of potentially -//! ill-formed UTF-16 encoding for strings. Specifically, the 16-bit -//! code units in Windows strings may contain [isolated surrogate code -//! points which are not paired together][ill-formed-utf-16]. The -//! Unicode standard requires that surrogate code points (those in the -//! range U+D800 to U+DFFF) always be *paired*, because in the UTF-16 -//! encoding a *surrogate code unit pair* is used to encode a single -//! character. For compatibility with code that does not enforce -//! these pairings, Windows does not enforce them, either. -//! -//! While it is not always possible to convert such a string losslessly into -//! a valid UTF-16 string (or even UTF-8), it is often desirable to be -//! able to round-trip such a string from and to Windows APIs -//! losslessly. For example, some Rust code may be "bridging" some -//! Windows APIs together, just passing `WCHAR` strings among those -//! APIs without ever really looking into the strings. -//! -//! If Rust code *does* need to look into those strings, it can -//! convert them to valid UTF-8, possibly lossily, by substituting -//! invalid sequences with [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], as is -//! conventionally done in other Rust APIs that deal with string -//! encodings. -//! -//! # `OsStringExt` and `OsStrExt` -//! -//! [`OsString`] is the Rust wrapper for owned strings in the -//! preferred representation of the operating system. On Windows, -//! this struct gets augmented with an implementation of the -//! [`OsStringExt`] trait, which has a [`OsStringExt::from_wide`] method. This -//! lets you create an [`OsString`] from a `&[u16]` slice; presumably -//! you get such a slice out of a `WCHAR` Windows API. -//! -//! Similarly, [`OsStr`] is the Rust wrapper for borrowed strings from -//! preferred representation of the operating system. On Windows, the -//! [`OsStrExt`] trait provides the [`OsStrExt::encode_wide`] method, which -//! outputs an [`EncodeWide`] iterator. You can [`collect`] this -//! iterator, for example, to obtain a `Vec<u16>`; you can later get a -//! pointer to this vector's contents and feed it to Windows APIs. -//! -//! These traits, along with [`OsString`] and [`OsStr`], work in -//! conjunction so that it is possible to **round-trip** strings from -//! Windows and back, with no loss of data, even if the strings are -//! ill-formed UTF-16. -//! -//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16 -//! [`collect`]: crate::iter::Iterator::collect -//! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::ffi::{OsStr, OsString}; -use crate::sealed::Sealed; -use crate::sys::os_str::Buf; -use crate::sys_common::wtf8::Wtf8Buf; -use crate::sys_common::{AsInner, FromInner}; - -#[stable(feature = "rust1", since = "1.0.0")] -pub use crate::sys_common::wtf8::EncodeWide; - -/// Windows-specific extensions to [`OsString`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStringExt: Sealed { - /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of - /// 16-bit code units. - /// - /// This is lossless: calling [`OsStrExt::encode_wide`] on the resulting string - /// will always return the original code units. - /// - /// # Examples - /// - /// ``` - /// use std::ffi::OsString; - /// use std::os::windows::prelude::*; - /// - /// // UTF-16 encoding for "Unicode". - /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065]; - /// - /// let string = OsString::from_wide(&source[..]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn from_wide(wide: &[u16]) -> Self; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl OsStringExt for OsString { - fn from_wide(wide: &[u16]) -> OsString { - FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) - } -} - -/// Windows-specific extensions to [`OsStr`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait OsStrExt: Sealed { - /// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially - /// ill-formed UTF-16. - /// - /// This is lossless: calling [`OsStringExt::from_wide`] and then - /// `encode_wide` on the result will yield the original code units. - /// Note that the encoding does not add a final null terminator. - /// - /// # Examples - /// - /// ``` - /// use std::ffi::OsString; - /// use std::os::windows::prelude::*; - /// - /// // UTF-16 encoding for "Unicode". - /// let source = [0x0055, 0x006E, 0x0069, 0x0063, 0x006F, 0x0064, 0x0065]; - /// - /// let string = OsString::from_wide(&source[..]); - /// - /// let result: Vec<u16> = string.encode_wide().collect(); - /// assert_eq!(&source[..], &result[..]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - fn encode_wide(&self) -> EncodeWide<'_>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl OsStrExt for OsStr { - fn encode_wide(&self) -> EncodeWide<'_> { - self.as_inner().inner.encode_wide() - } -} diff --git a/library/std/src/sys/windows/ext/fs.rs b/library/std/src/sys/windows/ext/fs.rs deleted file mode 100644 index b20eafb4d53..00000000000 --- a/library/std/src/sys/windows/ext/fs.rs +++ /dev/null @@ -1,558 +0,0 @@ -//! Windows-specific extensions for the primitives in the `std::fs` module. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::fs::{self, Metadata, OpenOptions}; -use crate::io; -use crate::path::Path; -use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut}; - -/// Windows-specific extensions to [`fs::File`]. -#[stable(feature = "file_offset", since = "1.15.0")] -pub trait FileExt { - /// Seeks to a given position and reads a number of bytes. - /// - /// Returns the number of bytes read. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. The current cursor **is** affected by this - /// function, it is set to the end of the read. - /// - /// Reading beyond the end of the file will always return with a length of - /// 0\. - /// - /// Note that similar to `File::read`, it is not an error to return with a - /// short read. When returning from such a short read, the file pointer is - /// still updated. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs::File; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let mut file = File::open("foo.txt")?; - /// let mut buffer = [0; 10]; - /// - /// // Read 10 bytes, starting 72 bytes from the - /// // start of the file. - /// file.seek_read(&mut buffer[..], 72)?; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_offset", since = "1.15.0")] - fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>; - - /// Seeks to a given position and writes a number of bytes. - /// - /// Returns the number of bytes written. - /// - /// The offset is relative to the start of the file and thus independent - /// from the current cursor. The current cursor **is** affected by this - /// function, it is set to the end of the write. - /// - /// When writing beyond the end of the file, the file is appropriately - /// extended and the intermediate bytes are left uninitialized. - /// - /// Note that similar to `File::write`, it is not an error to return a - /// short write. When returning from such a short write, the file pointer - /// is still updated. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> std::io::Result<()> { - /// let mut buffer = File::create("foo.txt")?; - /// - /// // Write a byte string starting 72 bytes from - /// // the start of the file. - /// buffer.seek_write(b"some bytes", 72)?; - /// Ok(()) - /// } - /// ``` - #[stable(feature = "file_offset", since = "1.15.0")] - fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>; -} - -#[stable(feature = "file_offset", since = "1.15.0")] -impl FileExt for fs::File { - fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { - self.as_inner().read_at(buf, offset) - } - - fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> { - self.as_inner().write_at(buf, offset) - } -} - -/// Windows-specific extensions to [`fs::OpenOptions`]. -#[stable(feature = "open_options_ext", since = "1.10.0")] -pub trait OpenOptionsExt { - /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] - /// with the specified value. - /// - /// This will override the `read`, `write`, and `append` flags on the - /// `OpenOptions` structure. This method provides fine-grained control over - /// the permissions to read, write and append data, attributes (like hidden - /// and system), and extended attributes. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// // Open without read and write permission, for example if you only need - /// // to call `stat` on the file - /// let file = OpenOptions::new().access_mode(0).open("foo.txt"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn access_mode(&mut self, access: u32) -> &mut Self; - - /// Overrides the `dwShareMode` argument to the call to [`CreateFile`] with - /// the specified value. - /// - /// By default `share_mode` is set to - /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. This allows - /// other processes to read, write, and delete/rename the same file - /// while it is open. Removing any of the flags will prevent other - /// processes from performing the corresponding operation until the file - /// handle is closed. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// // Do not allow others to read or modify this file while we have it open - /// // for writing. - /// let file = OpenOptions::new() - /// .write(true) - /// .share_mode(0) - /// .open("foo.txt"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn share_mode(&mut self, val: u32) -> &mut Self; - - /// Sets extra flags for the `dwFileFlags` argument to the call to - /// [`CreateFile2`] to the specified value (or combines it with - /// `attributes` and `security_qos_flags` to set the `dwFlagsAndAttributes` - /// for [`CreateFile`]). - /// - /// Custom flags can only set flags, not remove flags set by Rust's options. - /// This option overwrites any previously set custom flags. - /// - /// # Examples - /// - /// ```no_run - /// # #[cfg(for_demonstration_only)] - /// extern crate winapi; - /// # mod winapi { pub const FILE_FLAG_DELETE_ON_CLOSE: u32 = 0x04000000; } - /// - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// let file = OpenOptions::new() - /// .create(true) - /// .write(true) - /// .custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE) - /// .open("foo.txt"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn custom_flags(&mut self, flags: u32) -> &mut Self; - - /// Sets the `dwFileAttributes` argument to the call to [`CreateFile2`] to - /// the specified value (or combines it with `custom_flags` and - /// `security_qos_flags` to set the `dwFlagsAndAttributes` for - /// [`CreateFile`]). - /// - /// If a _new_ file is created because it does not yet exist and - /// `.create(true)` or `.create_new(true)` are specified, the new file is - /// given the attributes declared with `.attributes()`. - /// - /// If an _existing_ file is opened with `.create(true).truncate(true)`, its - /// existing attributes are preserved and combined with the ones declared - /// with `.attributes()`. - /// - /// In all other cases the attributes get ignored. - /// - /// # Examples - /// - /// ```no_run - /// # #[cfg(for_demonstration_only)] - /// extern crate winapi; - /// # mod winapi { pub const FILE_ATTRIBUTE_HIDDEN: u32 = 2; } - /// - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// let file = OpenOptions::new() - /// .write(true) - /// .create(true) - /// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN) - /// .open("foo.txt"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn attributes(&mut self, val: u32) -> &mut Self; - - /// Sets the `dwSecurityQosFlags` argument to the call to [`CreateFile2`] to - /// the specified value (or combines it with `custom_flags` and `attributes` - /// to set the `dwFlagsAndAttributes` for [`CreateFile`]). - /// - /// By default `security_qos_flags` is not set. It should be specified when - /// opening a named pipe, to control to which degree a server process can - /// act on behalf of a client process (security impersonation level). - /// - /// When `security_qos_flags` is not set, a malicious program can gain the - /// elevated privileges of a privileged Rust process when it allows opening - /// user-specified paths, by tricking it into opening a named pipe. So - /// arguably `security_qos_flags` should also be set when opening arbitrary - /// paths. However the bits can then conflict with other flags, specifically - /// `FILE_FLAG_OPEN_NO_RECALL`. - /// - /// For information about possible values, see [Impersonation Levels] on the - /// Windows Dev Center site. The `SECURITY_SQOS_PRESENT` flag is set - /// automatically when using this method. - - /// # Examples - /// - /// ```no_run - /// # #[cfg(for_demonstration_only)] - /// extern crate winapi; - /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; } - /// use std::fs::OpenOptions; - /// use std::os::windows::prelude::*; - /// - /// let file = OpenOptions::new() - /// .write(true) - /// .create(true) - /// - /// // Sets the flag value to `SecurityIdentification`. - /// .security_qos_flags(winapi::SECURITY_IDENTIFICATION) - /// - /// .open(r"\\.\pipe\MyPipe"); - /// ``` - /// - /// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - /// [`CreateFile2`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfile2 - /// [Impersonation Levels]: - /// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level - #[stable(feature = "open_options_ext", since = "1.10.0")] - fn security_qos_flags(&mut self, flags: u32) -> &mut Self; -} - -#[stable(feature = "open_options_ext", since = "1.10.0")] -impl OpenOptionsExt for OpenOptions { - fn access_mode(&mut self, access: u32) -> &mut OpenOptions { - self.as_inner_mut().access_mode(access); - self - } - - fn share_mode(&mut self, share: u32) -> &mut OpenOptions { - self.as_inner_mut().share_mode(share); - self - } - - fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions { - self.as_inner_mut().custom_flags(flags); - self - } - - fn attributes(&mut self, attributes: u32) -> &mut OpenOptions { - self.as_inner_mut().attributes(attributes); - self - } - - fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions { - self.as_inner_mut().security_qos_flags(flags); - self - } -} - -/// Windows-specific extensions to [`fs::Metadata`]. -/// -/// The data members that this trait exposes correspond to the members -/// of the [`BY_HANDLE_FILE_INFORMATION`] structure. -/// -/// [`BY_HANDLE_FILE_INFORMATION`]: -/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information -#[stable(feature = "metadata_ext", since = "1.1.0")] -pub trait MetadataExt { - /// Returns the value of the `dwFileAttributes` field of this metadata. - /// - /// This field contains the file system attribute information for a file - /// or directory. For possible values and their descriptions, see - /// [File Attribute Constants] in the Windows Dev Center. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let attributes = metadata.file_attributes(); - /// Ok(()) - /// } - /// ``` - /// - /// [File Attribute Constants]: - /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn file_attributes(&self) -> u32; - - /// Returns the value of the `ftCreationTime` field of this metadata. - /// - /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, - /// which represents the number of 100-nanosecond intervals since - /// January 1, 1601 (UTC). The struct is automatically - /// converted to a `u64` value, as that is the recommended way - /// to use it. - /// - /// If the underlying filesystem does not support creation time, the - /// returned value is 0. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let creation_time = metadata.creation_time(); - /// Ok(()) - /// } - /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn creation_time(&self) -> u64; - - /// Returns the value of the `ftLastAccessTime` field of this metadata. - /// - /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, - /// which represents the number of 100-nanosecond intervals since - /// January 1, 1601 (UTC). The struct is automatically - /// converted to a `u64` value, as that is the recommended way - /// to use it. - /// - /// For a file, the value specifies the last time that a file was read - /// from or written to. For a directory, the value specifies when - /// the directory was created. For both files and directories, the - /// specified date is correct, but the time of day is always set to - /// midnight. - /// - /// If the underlying filesystem does not support last access time, the - /// returned value is 0. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_access_time = metadata.last_access_time(); - /// Ok(()) - /// } - /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn last_access_time(&self) -> u64; - - /// Returns the value of the `ftLastWriteTime` field of this metadata. - /// - /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, - /// which represents the number of 100-nanosecond intervals since - /// January 1, 1601 (UTC). The struct is automatically - /// converted to a `u64` value, as that is the recommended way - /// to use it. - /// - /// For a file, the value specifies the last time that a file was written - /// to. For a directory, the structure specifies when the directory was - /// created. - /// - /// If the underlying filesystem does not support the last write time, - /// the returned value is 0. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let last_write_time = metadata.last_write_time(); - /// Ok(()) - /// } - /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn last_write_time(&self) -> u64; - - /// Returns the value of the `nFileSize{High,Low}` fields of this - /// metadata. - /// - /// The returned value does not have meaning for directories. - /// - /// # Examples - /// - /// ```no_run - /// use std::io; - /// use std::fs; - /// use std::os::windows::prelude::*; - /// - /// fn main() -> io::Result<()> { - /// let metadata = fs::metadata("foo.txt")?; - /// let file_size = metadata.file_size(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "metadata_ext", since = "1.1.0")] - fn file_size(&self) -> u64; - - /// Returns the value of the `dwVolumeSerialNumber` field of this - /// metadata. - /// - /// This will return `None` if the `Metadata` instance was created from a - /// call to `DirEntry::metadata`. If this `Metadata` was created by using - /// `fs::metadata` or `File::metadata`, then this will return `Some`. - #[unstable(feature = "windows_by_handle", issue = "63010")] - fn volume_serial_number(&self) -> Option<u32>; - - /// Returns the value of the `nNumberOfLinks` field of this - /// metadata. - /// - /// This will return `None` if the `Metadata` instance was created from a - /// call to `DirEntry::metadata`. If this `Metadata` was created by using - /// `fs::metadata` or `File::metadata`, then this will return `Some`. - #[unstable(feature = "windows_by_handle", issue = "63010")] - fn number_of_links(&self) -> Option<u32>; - - /// Returns the value of the `nFileIndex{Low,High}` fields of this - /// metadata. - /// - /// This will return `None` if the `Metadata` instance was created from a - /// call to `DirEntry::metadata`. If this `Metadata` was created by using - /// `fs::metadata` or `File::metadata`, then this will return `Some`. - #[unstable(feature = "windows_by_handle", issue = "63010")] - fn file_index(&self) -> Option<u64>; -} - -#[stable(feature = "metadata_ext", since = "1.1.0")] -impl MetadataExt for Metadata { - fn file_attributes(&self) -> u32 { - self.as_inner().attrs() - } - fn creation_time(&self) -> u64 { - self.as_inner().created_u64() - } - fn last_access_time(&self) -> u64 { - self.as_inner().accessed_u64() - } - fn last_write_time(&self) -> u64 { - self.as_inner().modified_u64() - } - fn file_size(&self) -> u64 { - self.as_inner().size() - } - fn volume_serial_number(&self) -> Option<u32> { - self.as_inner().volume_serial_number() - } - fn number_of_links(&self) -> Option<u32> { - self.as_inner().number_of_links() - } - fn file_index(&self) -> Option<u64> { - self.as_inner().file_index() - } -} - -/// Windows-specific extensions to [`fs::FileType`]. -/// -/// On Windows, a symbolic link knows whether it is a file or directory. -#[unstable(feature = "windows_file_type_ext", issue = "none")] -pub trait FileTypeExt { - /// Returns `true` if this file type is a symbolic link that is also a directory. - #[unstable(feature = "windows_file_type_ext", issue = "none")] - fn is_symlink_dir(&self) -> bool; - /// Returns `true` if this file type is a symbolic link that is also a file. - #[unstable(feature = "windows_file_type_ext", issue = "none")] - fn is_symlink_file(&self) -> bool; -} - -#[unstable(feature = "windows_file_type_ext", issue = "none")] -impl FileTypeExt for fs::FileType { - fn is_symlink_dir(&self) -> bool { - self.as_inner().is_symlink_dir() - } - fn is_symlink_file(&self) -> bool { - self.as_inner().is_symlink_file() - } -} - -/// Creates a new file symbolic link on the filesystem. -/// -/// The `link` path will be a file symbolic link pointing to the `original` -/// path. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::windows::fs; -/// -/// fn main() -> std::io::Result<()> { -/// fs::symlink_file("a.txt", "b.txt")?; -/// Ok(()) -/// } -/// ``` -#[stable(feature = "symlink", since = "1.1.0")] -pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> { - sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false) -} - -/// Creates a new directory symlink on the filesystem. -/// -/// The `link` path will be a directory symbolic link pointing to the `original` -/// path. -/// -/// # Examples -/// -/// ```no_run -/// use std::os::windows::fs; -/// -/// fn main() -> std::io::Result<()> { -/// fs::symlink_dir("a", "b")?; -/// Ok(()) -/// } -/// ``` -#[stable(feature = "symlink", since = "1.1.0")] -pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> { - sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true) -} diff --git a/library/std/src/sys/windows/ext/io.rs b/library/std/src/sys/windows/ext/io.rs deleted file mode 100644 index 31b5d015ed0..00000000000 --- a/library/std/src/sys/windows/ext/io.rs +++ /dev/null @@ -1,234 +0,0 @@ -//! Windows-specific extensions to general I/O primitives. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::fs; -use crate::io; -use crate::net; -use crate::os::windows::raw; -use crate::sys; -use crate::sys::c; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; - -/// Raw HANDLEs. -#[stable(feature = "rust1", since = "1.0.0")] -pub type RawHandle = raw::HANDLE; - -/// Raw SOCKETs. -#[stable(feature = "rust1", since = "1.0.0")] -pub type RawSocket = raw::SOCKET; - -/// Extracts raw handles. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait AsRawHandle { - /// Extracts the raw handle, without taking any ownership. - #[stable(feature = "rust1", since = "1.0.0")] - fn as_raw_handle(&self) -> RawHandle; -} - -/// Construct I/O objects from raw handles. -#[stable(feature = "from_raw_os", since = "1.1.0")] -pub trait FromRawHandle { - /// Constructs a new I/O object from the specified raw handle. - /// - /// This function will **consume ownership** of the handle given, - /// passing responsibility for closing the handle to the returned - /// object. - /// - /// 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. - #[stable(feature = "from_raw_os", since = "1.1.0")] - unsafe fn from_raw_handle(handle: RawHandle) -> Self; -} - -/// A trait to express the ability to consume an object and acquire ownership of -/// its raw `HANDLE`. -#[stable(feature = "into_raw_os", since = "1.4.0")] -pub trait IntoRawHandle { - /// Consumes this object, returning the raw underlying handle. - /// - /// This function **transfers ownership** of the underlying handle to the - /// caller. Callers are then the unique owners of the handle and must close - /// it once it's no longer needed. - #[stable(feature = "into_raw_os", since = "1.4.0")] - fn into_raw_handle(self) -> RawHandle; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawHandle for fs::File { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as RawHandle - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawHandle for io::Stdin { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawHandle for io::Stdout { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio", since = "1.21.0")] -impl AsRawHandle for io::Stderr { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawHandle for io::StdinLock<'a> { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_INPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawHandle for io::StdoutLock<'a> { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_OUTPUT_HANDLE) as RawHandle } - } -} - -#[stable(feature = "asraw_stdio_locks", since = "1.35.0")] -impl<'a> AsRawHandle for io::StderrLock<'a> { - fn as_raw_handle(&self) -> RawHandle { - unsafe { c::GetStdHandle(c::STD_ERROR_HANDLE) as RawHandle } - } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -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)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawHandle for fs::File { - #[inline] - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} - -/// Extracts raw sockets. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait AsRawSocket { - /// Extracts the underlying raw socket from this object. - #[stable(feature = "rust1", since = "1.0.0")] - fn as_raw_socket(&self) -> RawSocket; -} - -/// Creates I/O objects from raw sockets. -#[stable(feature = "from_raw_os", since = "1.1.0")] -pub trait FromRawSocket { - /// Creates a new I/O object from the given raw socket. - /// - /// This function will **consume ownership** of the socket provided and - /// it will be closed when the returned 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. - #[stable(feature = "from_raw_os", since = "1.1.0")] - unsafe fn from_raw_socket(sock: RawSocket) -> Self; -} - -/// A trait to express the ability to consume an object and acquire ownership of -/// its raw `SOCKET`. -#[stable(feature = "into_raw_os", since = "1.4.0")] -pub trait IntoRawSocket { - /// Consumes this object, returning the raw underlying socket. - /// - /// This function **transfers ownership** of the underlying socket to the - /// caller. Callers are then the unique owners of the socket and must close - /// it once it's no longer needed. - #[stable(feature = "into_raw_os", since = "1.4.0")] - fn into_raw_socket(self) -> RawSocket; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawSocket for net::TcpStream { - #[inline] - fn as_raw_socket(&self) -> RawSocket { - *self.as_inner().socket().as_inner() - } -} -#[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() - } -} -#[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() - } -} - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawSocket for net::TcpStream { - #[inline] - unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { - let sock = sys::net::Socket::from_inner(sock); - net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) - } -} -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawSocket for net::TcpListener { - #[inline] - unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { - let sock = sys::net::Socket::from_inner(sock); - net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) - } -} -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawSocket for net::UdpSocket { - #[inline] - unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { - let sock = sys::net::Socket::from_inner(sock); - net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawSocket for net::TcpStream { - #[inline] - fn into_raw_socket(self) -> RawSocket { - self.into_inner().into_socket().into_inner() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawSocket for net::TcpListener { - #[inline] - fn into_raw_socket(self) -> RawSocket { - self.into_inner().into_socket().into_inner() - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawSocket for net::UdpSocket { - #[inline] - fn into_raw_socket(self) -> RawSocket { - self.into_inner().into_socket().into_inner() - } -} diff --git a/library/std/src/sys/windows/ext/mod.rs b/library/std/src/sys/windows/ext/mod.rs deleted file mode 100644 index 613d3dc189a..00000000000 --- a/library/std/src/sys/windows/ext/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Platform-specific extensions to `std` for Windows. -//! -//! Provides access to platform-level information for Windows, and exposes -//! Windows-specific idioms that would otherwise be inappropriate as part -//! the core `std` library. These extensions allow developers to use -//! `std` types and idioms with Windows in a way that the normal -//! platform-agnostic idioms would not normally support. - -#![stable(feature = "rust1", since = "1.0.0")] -#![doc(cfg(windows))] -#![allow(missing_docs)] - -pub mod ffi; -pub mod fs; -pub mod io; -pub mod process; -pub mod raw; -pub mod thread; - -/// A prelude for conveniently writing platform-specific code. -/// -/// Includes all extension traits, and some important type definitions. -#[stable(feature = "rust1", since = "1.0.0")] -pub mod prelude { - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::ffi::{OsStrExt, OsStringExt}; - #[doc(no_inline)] - #[stable(feature = "file_offset", since = "1.15.0")] - pub use super::fs::FileExt; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::fs::{MetadataExt, OpenOptionsExt}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::io::{AsRawHandle, AsRawSocket, RawHandle, RawSocket}; - #[doc(no_inline)] - #[stable(feature = "rust1", since = "1.0.0")] - pub use super::io::{FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket}; -} diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs deleted file mode 100644 index 67756b15531..00000000000 --- a/library/std/src/sys/windows/ext/process.rs +++ /dev/null @@ -1,141 +0,0 @@ -//! Extensions to `std::process` for Windows. - -#![stable(feature = "process_extensions", since = "1.2.0")] - -use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; -use crate::process; -use crate::sealed::Sealed; -use crate::sys; -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 io = sys::process::Stdio::Handle(handle); - process::Stdio::from_inner(io) - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::Child { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[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 _ - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::ChildStdin { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::ChildStdout { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "process_extensions", since = "1.2.0")] -impl AsRawHandle for process::ChildStderr { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() 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 _ - } -} - -#[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 _ - } -} - -#[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 _ - } -} - -/// Windows-specific extensions to [`process::ExitStatus`]. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "exit_status_from", since = "1.12.0")] -pub trait ExitStatusExt: Sealed { - /// Creates a new `ExitStatus` from the raw underlying `u32` return value of - /// a process. - #[stable(feature = "exit_status_from", since = "1.12.0")] - fn from_raw(raw: u32) -> Self; -} - -#[stable(feature = "exit_status_from", since = "1.12.0")] -impl ExitStatusExt for process::ExitStatus { - fn from_raw(raw: u32) -> Self { - process::ExitStatus::from_inner(From::from(raw)) - } -} - -/// Windows-specific extensions to the [`process::Command`] builder. -/// -/// This trait is sealed: it cannot be implemented outside the standard library. -/// This is so that future additional methods are not breaking changes. -#[stable(feature = "windows_process_extensions", since = "1.16.0")] -pub trait CommandExt: Sealed { - /// Sets the [process creation flags][1] to be passed to `CreateProcess`. - /// - /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`. - /// - /// [1]: https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags - #[stable(feature = "windows_process_extensions", since = "1.16.0")] - fn creation_flags(&mut self, flags: u32) -> &mut process::Command; - - /// Forces all arguments to be wrapped in quote (`"`) characters. - /// - /// This is useful for passing arguments to [MSYS2/Cygwin][1] based - /// executables: these programs will expand unquoted arguments containing - /// wildcard characters (`?` and `*`) by searching for any file paths - /// matching the wildcard pattern. - /// - /// Adding quotes has no effect when passing arguments to programs - /// that use [msvcrt][2]. This includes programs built with both - /// MinGW and MSVC. - /// - /// [1]: <https://github.com/msys2/MSYS2-packages/issues/2176> - /// [2]: <https://msdn.microsoft.com/en-us/library/17w5ykft.aspx> - #[unstable(feature = "windows_process_extensions_force_quotes", issue = "82227")] - fn force_quotes(&mut self, enabled: bool) -> &mut process::Command; -} - -#[stable(feature = "windows_process_extensions", since = "1.16.0")] -impl CommandExt for process::Command { - fn creation_flags(&mut self, flags: u32) -> &mut process::Command { - self.as_inner_mut().creation_flags(flags); - self - } - - fn force_quotes(&mut self, enabled: bool) -> &mut process::Command { - self.as_inner_mut().force_quotes(enabled); - self - } -} diff --git a/library/std/src/sys/windows/ext/raw.rs b/library/std/src/sys/windows/ext/raw.rs deleted file mode 100644 index 5014e008eb5..00000000000 --- a/library/std/src/sys/windows/ext/raw.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Windows-specific primitives. - -#![stable(feature = "raw_ext", since = "1.1.0")] - -use crate::os::raw::c_void; - -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type HANDLE = *mut c_void; -#[cfg(target_pointer_width = "32")] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type SOCKET = u32; -#[cfg(target_pointer_width = "64")] -#[stable(feature = "raw_ext", since = "1.1.0")] -pub type SOCKET = u64; diff --git a/library/std/src/sys/windows/ext/thread.rs b/library/std/src/sys/windows/ext/thread.rs deleted file mode 100644 index 6bd02054f71..00000000000 --- a/library/std/src/sys/windows/ext/thread.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Extensions to `std::thread` for Windows. - -#![stable(feature = "thread_extensions", since = "1.9.0")] - -use crate::os::windows::io::{AsRawHandle, IntoRawHandle, RawHandle}; -use crate::sys_common::{AsInner, IntoInner}; -use crate::thread; - -#[stable(feature = "thread_extensions", since = "1.9.0")] -impl<T> AsRawHandle for thread::JoinHandle<T> { - #[inline] - fn as_raw_handle(&self) -> RawHandle { - self.as_inner().handle().raw() as *mut _ - } -} - -#[stable(feature = "thread_extensions", since = "1.9.0")] -impl<T> IntoRawHandle for thread::JoinHandle<T> { - #[inline] - fn into_raw_handle(self) -> RawHandle { - self.into_inner().into_handle().into_raw() as *mut _ - } -} diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 2208ff025c0..cc60ca375ea 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -18,7 +18,6 @@ pub mod c; pub mod cmath; pub mod condvar; pub mod env; -pub mod ext; pub mod fs; pub mod handle; pub mod io; |
