@@ -2,7 +2,7 @@ use crate::ffi::OsStr;
22use crate :: os:: unix:: ffi:: OsStrExt ;
33use crate :: path:: Path ;
44use crate :: sys:: cvt;
5- use crate :: { ascii, fmt, io, iter, mem} ;
5+ use crate :: { ascii, fmt, io, iter, mem, ptr } ;
66
77// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
88#[ cfg( not( unix) ) ]
@@ -127,6 +127,73 @@ impl SocketAddr {
127127 Ok ( SocketAddr { addr, len } )
128128 }
129129
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+
130197 /// Returns `true` if the address is unnamed.
131198 ///
132199 /// # Examples
0 commit comments