@@ -27,6 +27,120 @@ pub struct OwnedFd {
27
27
inner : ManuallyDrop < crate :: imp:: fd:: OwnedFd > ,
28
28
}
29
29
30
+ impl OwnedFd {
31
+ /// Creates a new `OwnedFd` instance that shares the same underlying file handle
32
+ /// as the existing `OwnedFd` instance.
33
+ #[ cfg( all( unix, not( target_os = "wasi" ) ) ) ]
34
+ pub fn try_clone ( & self ) -> crate :: io:: Result < Self > {
35
+ // We want to atomically duplicate this file descriptor and set the
36
+ // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
37
+ // is a POSIX flag that was added to Linux in 2.6.24.
38
+ #[ cfg( not( target_os = "espidf" ) ) ]
39
+ let fd = crate :: fs:: fcntl_dupfd_cloexec ( self , 0 ) ?;
40
+
41
+ // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
42
+ // will never be supported, as this is a bare metal framework with
43
+ // no capabilities for multi-process execution. While F_DUPFD is also
44
+ // not supported yet, it might be (currently it returns ENOSYS).
45
+ #[ cfg( target_os = "espidf" ) ]
46
+ let fd = crate :: fs:: fcntl_dupfd ( self ) ?;
47
+
48
+ Ok ( fd)
49
+ }
50
+
51
+ /// Creates a new `OwnedFd` instance that shares the same underlying file handle
52
+ /// as the existing `OwnedFd` instance.
53
+ #[ cfg( target_os = "wasi" ) ]
54
+ pub fn try_clone ( & self ) -> std:: io:: Result < Self > {
55
+ Err ( std:: io:: Error :: new (
56
+ std:: io:: ErrorKind :: Unsupported ,
57
+ "operation not supported on WASI yet" ,
58
+ ) )
59
+ }
60
+
61
+ /// Creates a new `OwnedFd` instance that shares the same underlying file
62
+ /// handle as the existing `OwnedFd` instance.
63
+ #[ cfg( target_os = "windows" ) ]
64
+ pub fn try_clone ( & self ) -> std:: io:: Result < Self > {
65
+ use winapi:: um:: processthreadsapi:: GetCurrentProcessId ;
66
+ use winapi:: um:: winsock2:: {
67
+ WSADuplicateSocketW , WSAGetLastError , WSASocketW , INVALID_SOCKET , WSAEINVAL ,
68
+ WSAEPROTOTYPE , WSAPROTOCOL_INFOW , WSA_FLAG_NO_HANDLE_INHERIT , WSA_FLAG_OVERLAPPED ,
69
+ } ;
70
+
71
+ let mut info = unsafe { std:: mem:: zeroed :: < WSAPROTOCOL_INFOW > ( ) } ;
72
+ let result =
73
+ unsafe { WSADuplicateSocketW ( self . as_raw_fd ( ) as _ , GetCurrentProcessId ( ) , & mut info) } ;
74
+ match result {
75
+ SOCKET_ERROR => return Err ( std:: io:: Error :: last_os_error ( ) ) ,
76
+ 0 => ( ) ,
77
+ _ => panic ! ( ) ,
78
+ }
79
+ let socket = unsafe {
80
+ WSASocketW (
81
+ info. iAddressFamily ,
82
+ info. iSocketType ,
83
+ info. iProtocol ,
84
+ & mut info,
85
+ 0 ,
86
+ WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT ,
87
+ )
88
+ } ;
89
+
90
+ if socket != INVALID_SOCKET {
91
+ unsafe { Ok ( Self :: from_raw_fd ( socket as _ ) ) }
92
+ } else {
93
+ let error = unsafe { WSAGetLastError ( ) } ;
94
+
95
+ if error != WSAEPROTOTYPE && error != WSAEINVAL {
96
+ return Err ( std:: io:: Error :: from_raw_os_error ( error) ) ;
97
+ }
98
+
99
+ let socket = unsafe {
100
+ WSASocketW (
101
+ info. iAddressFamily ,
102
+ info. iSocketType ,
103
+ info. iProtocol ,
104
+ & mut info,
105
+ 0 ,
106
+ WSA_FLAG_OVERLAPPED ,
107
+ )
108
+ } ;
109
+
110
+ if socket == INVALID_SOCKET {
111
+ return Err ( std:: io:: Error :: last_os_error ( ) ) ;
112
+ }
113
+
114
+ unsafe {
115
+ let socket = Self :: from_raw_fd ( socket as _ ) ;
116
+ socket. set_no_inherit ( ) ?;
117
+ Ok ( socket)
118
+ }
119
+ }
120
+ }
121
+
122
+ #[ cfg( windows) ]
123
+ #[ cfg( not( target_vendor = "uwp" ) ) ]
124
+ fn set_no_inherit ( & self ) -> std:: io:: Result < ( ) > {
125
+ use winapi:: um:: handleapi:: SetHandleInformation ;
126
+ use winapi:: um:: winbase:: HANDLE_FLAG_INHERIT ;
127
+ use winapi:: um:: winnt:: HANDLE ;
128
+ match unsafe { SetHandleInformation ( self . as_raw_fd ( ) as HANDLE , HANDLE_FLAG_INHERIT , 0 ) } {
129
+ 0 => return Err ( std:: io:: Error :: last_os_error ( ) ) ,
130
+ _ => Ok ( ( ) ) ,
131
+ }
132
+ }
133
+
134
+ #[ cfg( windows) ]
135
+ #[ cfg( target_vendor = "uwp" ) ]
136
+ fn set_no_inherit ( & self ) -> std:: io:: Result < ( ) > {
137
+ Err ( io:: Error :: new_const (
138
+ std:: io:: ErrorKind :: Unsupported ,
139
+ & "Unavailable on UWP" ,
140
+ ) )
141
+ }
142
+ }
143
+
30
144
#[ cfg( not( windows) ) ]
31
145
impl AsFd for OwnedFd {
32
146
#[ inline]
0 commit comments