@@ -2,7 +2,7 @@ use crate::ffi::OsStr;
2
2
use crate :: os:: unix:: ffi:: OsStrExt ;
3
3
use crate :: path:: Path ;
4
4
use crate :: sys:: cvt;
5
- use crate :: { ascii, fmt, io, iter, mem} ;
5
+ use crate :: { ascii, fmt, io, iter, mem, ptr } ;
6
6
7
7
// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
8
8
#[ cfg( not( unix) ) ]
@@ -127,6 +127,73 @@ impl SocketAddr {
127
127
Ok ( SocketAddr { addr, len } )
128
128
}
129
129
130
+ /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
131
+ ///
132
+ /// # Errors
133
+ ///
134
+ /// Returns an error if the path is longer than `SUN_LEN`.
135
+ ///
136
+ /// # Examples
137
+ ///
138
+ /// ```
139
+ /// #![feature(unix_socket_creation)]
140
+ /// use std::os::unix::net::SocketAddr;
141
+ /// use std::path::Path;
142
+ ///
143
+ /// # fn main() -> std::io::Result<()> {
144
+ /// let address = SocketAddr::unix("/path/to/socket")?;
145
+ /// assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket")));
146
+ /// # Ok(())
147
+ /// # }
148
+ /// ```
149
+ #[ unstable( feature = "unix_socket_creation" , issue = "65275" ) ]
150
+ pub fn unix < P > ( path : P ) -> io:: Result < SocketAddr >
151
+ where
152
+ P : AsRef < Path > ,
153
+ {
154
+ // SAFETY: All zeros is a valid representation for `sockaddr_un`.
155
+ let mut storage: libc:: sockaddr_un = unsafe { mem:: zeroed ( ) } ;
156
+
157
+ let bytes = path. as_ref ( ) . as_os_str ( ) . as_bytes ( ) ;
158
+ let too_long = match bytes. first ( ) {
159
+ None => false ,
160
+ // linux abstract namespaces aren't null-terminated.
161
+ Some ( & 0 ) => bytes. len ( ) > storage. sun_path . len ( ) ,
162
+ Some ( _) => bytes. len ( ) >= storage. sun_path . len ( ) ,
163
+ } ;
164
+ if too_long {
165
+ return Err ( io:: Error :: new (
166
+ io:: ErrorKind :: InvalidInput ,
167
+ "path must be shorter than SUN_LEN" ,
168
+ ) ) ;
169
+ }
170
+
171
+ storage. sun_family = libc:: AF_UNIX as _ ;
172
+ // SAFETY: `bytes` and `addr.sun_path` are not overlapping and
173
+ // both point to valid memory.
174
+ // NOTE: We zeroed the memory above, so the path is already null
175
+ // terminated.
176
+ unsafe {
177
+ ptr:: copy_nonoverlapping (
178
+ bytes. as_ptr ( ) ,
179
+ storage. sun_path . as_mut_ptr ( ) . cast ( ) ,
180
+ bytes. len ( ) ,
181
+ )
182
+ } ;
183
+
184
+ let base = & storage as * const _ as usize ;
185
+ let path = & storage. sun_path as * const _ as usize ;
186
+ let sun_path_offset = path - base;
187
+ let length = sun_path_offset
188
+ + bytes. len ( )
189
+ + match bytes. first ( ) {
190
+ Some ( & 0 ) | None => 0 ,
191
+ Some ( _) => 1 ,
192
+ } ;
193
+
194
+ Ok ( SocketAddr { addr : storage, len : length as _ } )
195
+ }
196
+
130
197
/// Returns `true` if the address is unnamed.
131
198
///
132
199
/// # Examples
0 commit comments