about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorDan Gohman <dev@sunfishcode.online>2021-09-09 14:05:10 -0700
committerDan Gohman <dev@sunfishcode.online>2021-09-09 14:16:28 -0700
commit18c14add399c35153883f8b84a2e11a7c22f6721 (patch)
treecc11eb72236251b79e7cb576f24a34b54c969d21 /library/std/src
parent497ee321af3b8496eaccd7af7b437f18bab81abf (diff)
downloadrust-18c14add399c35153883f8b84a2e11a7c22f6721.tar.gz
rust-18c14add399c35153883f8b84a2e11a7c22f6721.zip
Add a `try_clone()` function to `OwnedFd`.
As suggested in #88564. This adds a `try_clone()` to `OwnedFd` by
refactoring the code out of the existing `File`/`Socket` code.
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/os/fd/owned.rs23
-rw-r--r--library/std/src/os/windows/io/handle.rs33
-rw-r--r--library/std/src/os/windows/io/socket.rs54
-rw-r--r--library/std/src/sys/unix/fd.rs17
-rw-r--r--library/std/src/sys/windows/fs.rs2
-rw-r--r--library/std/src/sys/windows/handle.rs15
-rw-r--r--library/std/src/sys/windows/net.rs47
7 files changed, 115 insertions, 76 deletions
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 52d7d4690d3..597e050b00d 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -8,6 +8,7 @@ use crate::fmt;
 use crate::fs;
 use crate::marker::PhantomData;
 use crate::mem::forget;
+use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 /// A borrowed file descriptor.
@@ -67,6 +68,28 @@ impl BorrowedFd<'_> {
     }
 }
 
+impl OwnedFd {
+    /// Creates a new `OwnedFd` instance that shares the same underlying file handle
+    /// as the existing `OwnedFd` instance.
+    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 cmd = libc::F_DUPFD_CLOEXEC;
+
+        // 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 cmd = libc::F_DUPFD;
+
+        let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?;
+        Ok(unsafe { Self::from_raw_fd(fd) })
+    }
+}
+
 #[unstable(feature = "io_safety", issue = "87074")]
 impl AsRawFd for BorrowedFd<'_> {
     #[inline]
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 72a17adb3b4..64c37615114 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -11,6 +11,7 @@ use crate::marker::PhantomData;
 use crate::mem::forget;
 use crate::ptr::NonNull;
 use crate::sys::c;
+use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
 /// A borrowed handle.
@@ -110,6 +111,38 @@ impl BorrowedHandle<'_> {
     }
 }
 
+impl OwnedHandle {
+    /// Creates a new `OwnedHandle` instance that shares the same underlying file handle
+    /// as the existing `OwnedHandle` instance.
+    pub fn try_clone(&self) -> crate::io::Result<FileDesc> {
+        let handle = self.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)?;
+
+        Ok(unsafe { OwnedHandle::from_raw_handle(handle) })
+    }
+
+    pub(crate) fn duplicate(
+        &self,
+        access: c::DWORD,
+        inherit: bool,
+        options: c::DWORD,
+    ) -> io::Result<Self> {
+        let mut ret = 0 as c::HANDLE;
+        cvt(unsafe {
+            let cur_proc = c::GetCurrentProcess();
+            c::DuplicateHandle(
+                cur_proc,
+                self.as_raw_handle(),
+                cur_proc,
+                &mut ret,
+                access,
+                inherit as c::BOOL,
+                options,
+            )
+        })?;
+        unsafe { Ok(Self::from_raw_handle(ret)) }
+    }
+}
+
 impl TryFrom<HandleOrInvalid> for OwnedHandle {
     type Error = ();
 
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 23db66df09f..9e27ead90fb 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -7,6 +7,7 @@ use crate::fmt;
 use crate::marker::PhantomData;
 use crate::mem::forget;
 use crate::sys::c;
+use crate::sys::cvt;
 
 /// A borrowed socket.
 ///
@@ -69,6 +70,59 @@ impl BorrowedSocket<'_> {
     }
 }
 
+impl OwnedSocket {
+    /// Creates a new `OwnedSocket` instance that shares the same underlying socket
+    /// as the existing `OwnedSocket` instance.
+    pub fn try_clone(&self) -> io::Result<Self> {
+        let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
+        let result = unsafe {
+            c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info)
+        };
+        cvt(result)?;
+        let socket = unsafe {
+            c::WSASocketW(
+                info.iAddressFamily,
+                info.iSocketType,
+                info.iProtocol,
+                &mut info,
+                0,
+                c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
+            )
+        };
+
+        if socket != c::INVALID_SOCKET {
+            unsafe { Ok(Self::from_inner(OwnedSocket::from_raw_socket(socket))) }
+        } else {
+            let error = unsafe { c::WSAGetLastError() };
+
+            if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
+                return Err(io::Error::from_raw_os_error(error));
+            }
+
+            let socket = unsafe {
+                c::WSASocketW(
+                    info.iAddressFamily,
+                    info.iSocketType,
+                    info.iProtocol,
+                    &mut info,
+                    0,
+                    c::WSA_FLAG_OVERLAPPED,
+                )
+            };
+
+            if socket == c::INVALID_SOCKET {
+                return Err(last_error());
+            }
+
+            unsafe {
+                let socket = Self::from_inner(OwnedSocket::from_raw_socket(socket));
+                socket.set_no_inherit()?;
+                Ok(socket)
+            }
+        }
+    }
+}
+
 impl AsRawSocket for BorrowedSocket<'_> {
     #[inline]
     fn as_raw_socket(&self) -> RawSocket {
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index 0956726084e..3c2b36fe691 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -266,22 +266,9 @@ impl FileDesc {
         }
     }
 
+    #[inline]
     pub fn duplicate(&self) -> io::Result<FileDesc> {
-        // 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 cmd = libc::F_DUPFD_CLOEXEC;
-
-        // 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 cmd = libc::F_DUPFD;
-
-        let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?;
-        Ok(unsafe { FileDesc::from_raw_fd(fd) })
+        Ok(Self(self.0.try_clone()?))
     }
 }
 
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 0c1a50e231c..08ff35361f4 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -455,7 +455,7 @@ impl File {
     }
 
     pub fn duplicate(&self) -> io::Result<File> {
-        Ok(File { handle: self.handle.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)? })
+        Ok(Self(self.0.try_clone()?))
     }
 
     fn reparse_point<'a>(
diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs
index 21d86b00226..8de5729daa3 100644
--- a/library/std/src/sys/windows/handle.rs
+++ b/library/std/src/sys/windows/handle.rs
@@ -235,20 +235,7 @@ impl Handle {
         inherit: bool,
         options: c::DWORD,
     ) -> io::Result<Handle> {
-        let mut ret = 0 as c::HANDLE;
-        cvt(unsafe {
-            let cur_proc = c::GetCurrentProcess();
-            c::DuplicateHandle(
-                cur_proc,
-                self.as_raw_handle(),
-                cur_proc,
-                &mut ret,
-                access,
-                inherit as c::BOOL,
-                options,
-            )
-        })?;
-        unsafe { Ok(Handle::from_raw_handle(ret)) }
+        Ok(Self(self.0.duplicate(access, inherit, options)?))
     }
 }
 
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index 33152cc97ab..681875985bd 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -208,52 +208,7 @@ impl Socket {
     }
 
     pub fn duplicate(&self) -> io::Result<Socket> {
-        let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
-        let result = unsafe {
-            c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info)
-        };
-        cvt(result)?;
-        let socket = unsafe {
-            c::WSASocketW(
-                info.iAddressFamily,
-                info.iSocketType,
-                info.iProtocol,
-                &mut info,
-                0,
-                c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
-            )
-        };
-
-        if socket != c::INVALID_SOCKET {
-            unsafe { Ok(Self::from_inner(OwnedSocket::from_raw_socket(socket))) }
-        } else {
-            let error = unsafe { c::WSAGetLastError() };
-
-            if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
-                return Err(io::Error::from_raw_os_error(error));
-            }
-
-            let socket = unsafe {
-                c::WSASocketW(
-                    info.iAddressFamily,
-                    info.iSocketType,
-                    info.iProtocol,
-                    &mut info,
-                    0,
-                    c::WSA_FLAG_OVERLAPPED,
-                )
-            };
-
-            if socket == c::INVALID_SOCKET {
-                return Err(last_error());
-            }
-
-            unsafe {
-                let socket = Self::from_inner(OwnedSocket::from_raw_socket(socket));
-                socket.set_no_inherit()?;
-                Ok(socket)
-            }
-        }
+        Ok(Self(self.0.duplicate()?))
     }
 
     fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {