@@ -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, 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) ) ]
@@ -22,8 +22,9 @@ fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
22
22
path - base
23
23
}
24
24
25
- pub ( super ) unsafe fn sockaddr_un ( path : & Path ) -> io:: Result < ( libc:: sockaddr_un , libc:: socklen_t ) > {
26
- let mut addr: libc:: sockaddr_un = mem:: zeroed ( ) ;
25
+ pub ( super ) fn sockaddr_un ( path : & Path ) -> io:: Result < ( libc:: sockaddr_un , libc:: socklen_t ) > {
26
+ // SAFETY: All zeros is a valid representation for `sockaddr_un`.
27
+ let mut addr: libc:: sockaddr_un = unsafe { mem:: zeroed ( ) } ;
27
28
addr. sun_family = libc:: AF_UNIX as libc:: sa_family_t ;
28
29
29
30
let bytes = path. as_os_str ( ) . as_bytes ( ) ;
@@ -41,11 +42,13 @@ pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un,
41
42
& "path must be shorter than SUN_LEN" ,
42
43
) ) ;
43
44
}
44
- for ( dst, src) in iter:: zip ( & mut addr. sun_path , bytes) {
45
- * dst = * src as libc:: c_char ;
46
- }
47
- // null byte for pathname addresses is already there because we zeroed the
48
- // struct
45
+ // SAFETY: `bytes` and `addr.sun_path` are not overlapping and
46
+ // both point to valid memory.
47
+ // NOTE: We zeroed the memory above, so the path is already null
48
+ // terminated.
49
+ unsafe {
50
+ ptr:: copy_nonoverlapping ( bytes. as_ptr ( ) , addr. sun_path . as_mut_ptr ( ) . cast ( ) , bytes. len ( ) )
51
+ } ;
49
52
50
53
let mut len = sun_path_offset ( & addr) + bytes. len ( ) ;
51
54
match bytes. get ( 0 ) {
@@ -127,6 +130,43 @@ impl SocketAddr {
127
130
Ok ( SocketAddr { addr, len } )
128
131
}
129
132
133
+ /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
134
+ ///
135
+ /// # Errors
136
+ ///
137
+ /// Returns an error if the path is longer than `SUN_LEN` or if it contains
138
+ /// NULL bytes.
139
+ ///
140
+ /// # Examples
141
+ ///
142
+ /// ```
143
+ /// #![feature(unix_socket_creation)]
144
+ /// use std::os::unix::net::SocketAddr;
145
+ /// use std::path::Path;
146
+ ///
147
+ /// # fn main() -> std::io::Result<()> {
148
+ /// let address = SocketAddr::from_path("/path/to/socket")?;
149
+ /// assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket")));
150
+ /// # Ok(())
151
+ /// # }
152
+ /// ```
153
+ ///
154
+ /// Creating a `SocketAddr` with a NULL byte results in an error.
155
+ ///
156
+ /// ```
157
+ /// #![feature(unix_socket_creation)]
158
+ /// use std::os::unix::net::SocketAddr;
159
+ ///
160
+ /// assert!(SocketAddr::from_path("/path/with/\0/bytes").is_err());
161
+ /// ```
162
+ #[ unstable( feature = "unix_socket_creation" , issue = "93423" ) ]
163
+ pub fn from_path < P > ( path : P ) -> io:: Result < SocketAddr >
164
+ where
165
+ P : AsRef < Path > ,
166
+ {
167
+ sockaddr_un ( path. as_ref ( ) ) . map ( |( addr, len) | SocketAddr { addr, len } )
168
+ }
169
+
130
170
/// Returns `true` if the address is unnamed.
131
171
///
132
172
/// # Examples
0 commit comments