diff options
Diffstat (limited to 'library/std/src/os/unix/net/addr.rs')
-rw-r--r-- | library/std/src/os/unix/net/addr.rs | 93 |
1 files changed, 25 insertions, 68 deletions
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 094085e19..81ac829d2 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -1,6 +1,9 @@ use crate::ffi::OsStr; +#[cfg(any(doc, target_os = "android", target_os = "linux"))] +use crate::os::net::linux_ext; use crate::os::unix::ffi::OsStrExt; use crate::path::Path; +use crate::sealed::Sealed; use crate::sys::cvt; use crate::{fmt, io, mem, ptr}; @@ -224,31 +227,6 @@ impl SocketAddr { if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } } - /// Returns the contents of this address if it is an abstract namespace - /// without the leading null byte. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_abstract)] - /// use std::os::unix::net::{UnixListener, SocketAddr}; - /// - /// fn main() -> std::io::Result<()> { - /// let namespace = b"hidden"; - /// let namespace_addr = SocketAddr::from_abstract_namespace(&namespace[..])?; - /// let socket = UnixListener::bind_addr(&namespace_addr)?; - /// let local_addr = socket.local_addr().expect("Couldn't get local address"); - /// assert_eq!(local_addr.as_abstract_namespace(), Some(&namespace[..])); - /// Ok(()) - /// } - /// ``` - #[doc(cfg(any(target_os = "android", target_os = "linux")))] - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_abstract", issue = "85410")] - pub fn as_abstract_namespace(&self) -> Option<&[u8]> { - if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } - } - fn address(&self) -> AddressKind<'_> { let len = self.len as usize - sun_path_offset(&self.addr); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; @@ -265,62 +243,41 @@ impl SocketAddr { AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) } } +} - /// Creates an abstract domain socket address from a namespace - /// - /// An abstract address does not create a file unlike traditional path-based - /// Unix sockets. The advantage of this is that the address will disappear when - /// the socket bound to it is closed, so no filesystem clean up is required. - /// - /// The leading null byte for the abstract namespace is automatically added. - /// - /// This is a Linux-specific extension. See more at [`unix(7)`]. - /// - /// [`unix(7)`]: https://man7.org/linux/man-pages/man7/unix.7.html - /// - /// # Errors - /// - /// This will return an error if the given namespace is too long - /// - /// # Examples - /// - /// ```no_run - /// #![feature(unix_socket_abstract)] - /// use std::os::unix::net::{UnixListener, SocketAddr}; - /// - /// fn main() -> std::io::Result<()> { - /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; - /// let listener = match UnixListener::bind_addr(&addr) { - /// Ok(sock) => sock, - /// Err(err) => { - /// println!("Couldn't bind: {err:?}"); - /// return Err(err); - /// } - /// }; - /// Ok(()) - /// } - /// ``` - #[doc(cfg(any(target_os = "android", target_os = "linux")))] - #[cfg(any(doc, target_os = "android", target_os = "linux",))] - #[unstable(feature = "unix_socket_abstract", issue = "85410")] - pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result<SocketAddr> { +#[unstable(feature = "unix_socket_abstract", issue = "85410")] +impl Sealed for SocketAddr {} + +#[doc(cfg(any(target_os = "android", target_os = "linux")))] +#[cfg(any(doc, target_os = "android", target_os = "linux"))] +#[unstable(feature = "unix_socket_abstract", issue = "85410")] +impl linux_ext::addr::SocketAddrExt for SocketAddr { + fn as_abstract_name(&self) -> Option<&[u8]> { + if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } + } + + fn from_abstract_name<N>(name: &N) -> crate::io::Result<Self> + where + N: AsRef<[u8]>, + { + let name = name.as_ref(); unsafe { let mut addr: libc::sockaddr_un = mem::zeroed(); addr.sun_family = libc::AF_UNIX as libc::sa_family_t; - if namespace.len() + 1 > addr.sun_path.len() { + if name.len() + 1 > addr.sun_path.len() { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, - "namespace must be shorter than SUN_LEN", + "abstract socket name must be shorter than SUN_LEN", )); } crate::ptr::copy_nonoverlapping( - namespace.as_ptr(), + name.as_ptr(), addr.sun_path.as_mut_ptr().add(1) as *mut u8, - namespace.len(), + name.len(), ); - let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t; + let len = (sun_path_offset(&addr) + 1 + name.len()) as libc::socklen_t; SocketAddr::from_parts(addr, len) } } |