diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/rustix/src/io/owned_fd.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustix/src/io/owned_fd.rs')
-rw-r--r-- | vendor/rustix/src/io/owned_fd.rs | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/vendor/rustix/src/io/owned_fd.rs b/vendor/rustix/src/io/owned_fd.rs new file mode 100644 index 000000000..63c6145b0 --- /dev/null +++ b/vendor/rustix/src/io/owned_fd.rs @@ -0,0 +1,272 @@ +//! A wrapper around [`io_lifetimes::OwnedFd`]. +//! +//! rustix needs to wrap io-lifetimes' `OwnedFd` type so that it can call its +//! own [`close`] function when the `OwnedFd` is dropped. +//! +//! [`close`]: crate::io::close +//! +//! # Safety +//! +//! We wrap an `OwnedFd` in a `ManuallyDrop` so that we can extract the +//! file descriptor and close it ourselves. +#![allow(unsafe_code)] + +use crate::imp::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; +#[cfg(all(not(io_lifetimes_use_std), feature = "std"))] +use crate::imp::fd::{FromFd, IntoFd}; +use crate::io::close; +use core::fmt; +use core::mem::{forget, ManuallyDrop}; + +/// A wrapper around [`io_lifetimes::OwnedFd`] which closes the file descriptor +/// using rustix's own [`close`] rather than libc's `close`. +/// +/// [`close`]: crate::io::close +#[repr(transparent)] +pub struct OwnedFd { + inner: ManuallyDrop<crate::imp::fd::OwnedFd>, +} + +impl OwnedFd { + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// handle as the existing `OwnedFd` instance. + #[cfg(all(unix, not(target_os = "wasi")))] + pub fn try_clone(&self) -> crate::io::Result<Self> { + // We want to atomically duplicate this file descriptor and set the + // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This + // is a POSIX flag that was added to Linux in 2.6.24. + #[cfg(not(target_os = "espidf"))] + let fd = crate::fs::fcntl_dupfd_cloexec(self, 0)?; + + // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics + // will never be supported, as this is a bare metal framework with + // no capabilities for multi-process execution. While F_DUPFD is also + // not supported yet, it might be (currently it returns ENOSYS). + #[cfg(target_os = "espidf")] + let fd = crate::fs::fcntl_dupfd(self)?; + + Ok(fd) + } + + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// handle as the existing `OwnedFd` instance. + #[cfg(target_os = "wasi")] + pub fn try_clone(&self) -> std::io::Result<Self> { + Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "operation not supported on WASI yet", + )) + } + + /// Creates a new `OwnedFd` instance that shares the same underlying file + /// handle as the existing `OwnedFd` instance. + #[cfg(target_os = "windows")] + pub fn try_clone(&self) -> std::io::Result<Self> { + use windows_sys::Win32::Networking::WinSock::{ + WSADuplicateSocketW, WSAGetLastError, WSASocketW, INVALID_SOCKET, SOCKET_ERROR, + WSAEINVAL, WSAEPROTOTYPE, WSAPROTOCOL_INFOW, WSA_FLAG_NO_HANDLE_INHERIT, + WSA_FLAG_OVERLAPPED, + }; + use windows_sys::Win32::System::Threading::GetCurrentProcessId; + + let mut info = unsafe { std::mem::zeroed::<WSAPROTOCOL_INFOW>() }; + let result = + unsafe { WSADuplicateSocketW(self.as_raw_fd() as _, GetCurrentProcessId(), &mut info) }; + match result { + SOCKET_ERROR => return Err(std::io::Error::last_os_error()), + 0 => (), + _ => panic!(), + } + let socket = unsafe { + WSASocketW( + info.iAddressFamily, + info.iSocketType, + info.iProtocol, + &mut info, + 0, + WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT, + ) + }; + + if socket != INVALID_SOCKET { + unsafe { Ok(Self::from_raw_fd(socket as _)) } + } else { + let error = unsafe { WSAGetLastError() }; + + if error != WSAEPROTOTYPE && error != WSAEINVAL { + return Err(std::io::Error::from_raw_os_error(error)); + } + + let socket = unsafe { + WSASocketW( + info.iAddressFamily, + info.iSocketType, + info.iProtocol, + &mut info, + 0, + WSA_FLAG_OVERLAPPED, + ) + }; + + if socket == INVALID_SOCKET { + return Err(std::io::Error::last_os_error()); + } + + unsafe { + let socket = Self::from_raw_fd(socket as _); + socket.set_no_inherit()?; + Ok(socket) + } + } + } + + #[cfg(windows)] + #[cfg(not(target_vendor = "uwp"))] + fn set_no_inherit(&self) -> std::io::Result<()> { + use windows_sys::Win32::Foundation::{SetHandleInformation, HANDLE, HANDLE_FLAG_INHERIT}; + match unsafe { SetHandleInformation(self.as_raw_fd() as HANDLE, HANDLE_FLAG_INHERIT, 0) } { + 0 => return Err(std::io::Error::last_os_error()), + _ => Ok(()), + } + } + + #[cfg(windows)] + #[cfg(target_vendor = "uwp")] + fn set_no_inherit(&self) -> std::io::Result<()> { + Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "Unavailable on UWP", + )) + } +} + +#[cfg(not(windows))] +impl AsFd for OwnedFd { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + self.inner.as_fd() + } +} + +#[cfg(windows)] +impl io_lifetimes::AsSocket for OwnedFd { + #[inline] + fn as_socket(&self) -> BorrowedFd<'_> { + self.inner.as_socket() + } +} + +#[cfg(any(io_lifetimes_use_std, not(feature = "std")))] +impl From<OwnedFd> for crate::imp::fd::OwnedFd { + #[inline] + fn from(owned_fd: OwnedFd) -> Self { + let raw_fd = owned_fd.inner.as_fd().as_raw_fd(); + forget(owned_fd); + + // Safety: We use `as_fd().as_raw_fd()` to extract the raw file + // descriptor from `self.inner`, and then `forget` `self` so + // that they remain valid until the new `OwnedFd` acquires them. + unsafe { crate::imp::fd::OwnedFd::from_raw_fd(raw_fd) } + } +} + +#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))] +impl IntoFd for OwnedFd { + #[inline] + fn into_fd(self) -> crate::imp::fd::OwnedFd { + let raw_fd = self.inner.as_fd().as_raw_fd(); + forget(self); + + // Safety: We use `as_fd().as_raw_fd()` to extract the raw file + // descriptor from `self.inner`, and then `forget` `self` so + // that they remain valid until the new `OwnedFd` acquires them. + unsafe { crate::imp::fd::OwnedFd::from_raw_fd(raw_fd) } + } +} + +#[cfg(any(io_lifetimes_use_std, not(feature = "std")))] +impl From<crate::imp::fd::OwnedFd> for OwnedFd { + #[inline] + fn from(owned_fd: crate::imp::fd::OwnedFd) -> Self { + Self { + inner: ManuallyDrop::new(owned_fd), + } + } +} + +#[cfg(all(not(io_lifetimes_use_std), feature = "std"))] +impl FromFd for OwnedFd { + #[inline] + fn from_fd(owned_fd: crate::imp::fd::OwnedFd) -> Self { + Self { + inner: ManuallyDrop::new(owned_fd), + } + } +} + +#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))] +impl From<crate::imp::fd::OwnedFd> for OwnedFd { + #[inline] + fn from(fd: crate::imp::fd::OwnedFd) -> Self { + Self { + inner: ManuallyDrop::new(fd), + } + } +} + +#[cfg(not(any(io_lifetimes_use_std, not(feature = "std"))))] +impl From<OwnedFd> for crate::imp::fd::OwnedFd { + #[inline] + fn from(fd: OwnedFd) -> Self { + let raw_fd = fd.inner.as_fd().as_raw_fd(); + forget(fd); + + // Safety: We use `as_fd().as_raw_fd()` to extract the raw file + // descriptor from `self.inner`, and then `forget` `self` so + // that they remain valid until the new `OwnedFd` acquires them. + unsafe { Self::from_raw_fd(raw_fd) } + } +} + +impl AsRawFd for OwnedFd { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.inner.as_raw_fd() + } +} + +impl IntoRawFd for OwnedFd { + #[inline] + fn into_raw_fd(self) -> RawFd { + let raw_fd = self.inner.as_fd().as_raw_fd(); + forget(self); + raw_fd + } +} + +impl FromRawFd for OwnedFd { + #[inline] + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self { + inner: ManuallyDrop::new(crate::imp::fd::OwnedFd::from_raw_fd(raw_fd)), + } + } +} + +impl Drop for OwnedFd { + #[inline] + fn drop(&mut self) { + // Safety: We use `as_fd().as_raw_fd()` to extract the raw file + // descriptor from `self.inner`. `self.inner` is wrapped with + // `ManuallyDrop` so dropping it doesn't invalid them. + unsafe { + close(self.as_fd().as_raw_fd()); + } + } +} + +impl fmt::Debug for OwnedFd { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} |