mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
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`
This commit is contained in:
commit
18c8d0da64
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user