diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-01-28 15:20:23 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-28 15:20:23 +0100 |
| commit | 18c8d0da644682e69268c2247aed1f74b9132018 (patch) | |
| tree | 68f421e35819c89015e81a334661c95cdc4292c2 | |
| parent | 9f15c4d08b7d5eec77f6a6e4caa2ee720fbc51c2 (diff) | |
| parent | 35f578fc789a14106b2e32b80846ecd62ccf9672 (diff) | |
| download | rust-18c8d0da644682e69268c2247aed1f74b9132018.tar.gz rust-18c8d0da644682e69268c2247aed1f74b9132018.zip | |
Rollup merge of #93239 - Thomasdezeeuw:socketaddr_creation, r=m-ou-se
Add os::unix::net::SocketAddr::from_path Creates a new SocketAddr from a path, supports both regular paths and abstract namespaces. Note that `SocketAddr::from_abstract_namespace` could be removed after this as `SocketAddr::unix` also supports abstract namespaces. Updates #65275 Unblocks https://github.com/tokio-rs/mio/issues/1527 r? `@m-ou-se`
| -rw-r--r-- | library/std/src/os/unix/net/addr.rs | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index f450e41bfea..9dbd4548bc9 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -2,7 +2,7 @@ use crate::ffi::OsStr; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; use crate::sys::cvt; -use crate::{ascii, fmt, io, iter, mem}; +use crate::{ascii, fmt, io, mem, ptr}; // FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? #[cfg(not(unix))] @@ -22,8 +22,9 @@ fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { path - base } -pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { - let mut addr: libc::sockaddr_un = mem::zeroed(); +pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { + // SAFETY: All zeros is a valid representation for `sockaddr_un`. + let mut addr: libc::sockaddr_un = unsafe { mem::zeroed() }; addr.sun_family = libc::AF_UNIX as libc::sa_family_t; 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, &"path must be shorter than SUN_LEN", )); } - for (dst, src) in iter::zip(&mut addr.sun_path, bytes) { - *dst = *src as libc::c_char; - } - // null byte for pathname addresses is already there because we zeroed the - // struct + // SAFETY: `bytes` and `addr.sun_path` are not overlapping and + // both point to valid memory. + // NOTE: We zeroed the memory above, so the path is already null + // terminated. + unsafe { + ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len()) + }; let mut len = sun_path_offset(&addr) + bytes.len(); match bytes.get(0) { @@ -127,6 +130,43 @@ impl SocketAddr { Ok(SocketAddr { addr, len }) } + /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path. + /// + /// # Errors + /// + /// Returns an error if the path is longer than `SUN_LEN` or if it contains + /// NULL bytes. + /// + /// # Examples + /// + /// ``` + /// #![feature(unix_socket_creation)] + /// use std::os::unix::net::SocketAddr; + /// use std::path::Path; + /// + /// # fn main() -> std::io::Result<()> { + /// let address = SocketAddr::from_path("/path/to/socket")?; + /// assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); + /// # Ok(()) + /// # } + /// ``` + /// + /// Creating a `SocketAddr` with a NULL byte results in an error. + /// + /// ``` + /// #![feature(unix_socket_creation)] + /// use std::os::unix::net::SocketAddr; + /// + /// assert!(SocketAddr::from_path("/path/with/\0/bytes").is_err()); + /// ``` + #[unstable(feature = "unix_socket_creation", issue = "93423")] + pub fn from_path<P>(path: P) -> io::Result<SocketAddr> + where + P: AsRef<Path>, + { + sockaddr_un(path.as_ref()).map(|(addr, len)| SocketAddr { addr, len }) + } + /// Returns `true` if the address is unnamed. /// /// # Examples |
