summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/imp/libc/net/addr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/imp/libc/net/addr.rs')
-rw-r--r--vendor/rustix/src/imp/libc/net/addr.rs320
1 files changed, 320 insertions, 0 deletions
diff --git a/vendor/rustix/src/imp/libc/net/addr.rs b/vendor/rustix/src/imp/libc/net/addr.rs
new file mode 100644
index 000000000..1aeda5e5d
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/net/addr.rs
@@ -0,0 +1,320 @@
+//! IPv4, IPv6, and Socket addresses.
+
+use super::super::c;
+#[cfg(unix)]
+use crate::ffi::CStr;
+#[cfg(unix)]
+use crate::io;
+#[cfg(unix)]
+use crate::path;
+#[cfg(not(windows))]
+use core::convert::TryInto;
+#[cfg(unix)]
+use core::fmt;
+#[cfg(unix)]
+use core::slice;
+
+/// `struct sockaddr_un`
+#[cfg(unix)]
+#[derive(Clone)]
+#[doc(alias = "sockaddr_un")]
+pub struct SocketAddrUnix {
+ pub(crate) unix: c::sockaddr_un,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ len: c::socklen_t,
+}
+
+#[cfg(unix)]
+impl SocketAddrUnix {
+ /// Construct a new Unix-domain address from a filesystem path.
+ #[inline]
+ pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
+ path.into_with_c_str(Self::_new)
+ }
+
+ #[inline]
+ fn _new(path: &CStr) -> io::Result<Self> {
+ let mut unix = Self::init();
+ let bytes = path.to_bytes_with_nul();
+ if bytes.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ for (i, b) in bytes.iter().enumerate() {
+ unix.sun_path[i] = *b as c::c_char;
+ }
+
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ {
+ unix.sun_len = (offsetof_sun_path() + bytes.len()).try_into().unwrap();
+ }
+
+ Ok(Self {
+ unix,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ len: (offsetof_sun_path() + bytes.len()).try_into().unwrap(),
+ })
+ }
+
+ /// Construct a new abstract Unix-domain address from a byte slice.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
+ let mut unix = Self::init();
+ if 1 + name.len() > unix.sun_path.len() {
+ return Err(io::Errno::NAMETOOLONG);
+ }
+ unix.sun_path[0] = b'\0' as c::c_char;
+ for (i, b) in name.iter().enumerate() {
+ unix.sun_path[1 + i] = *b as c::c_char;
+ }
+ let len = offsetof_sun_path() + 1 + name.len();
+ let len = len.try_into().unwrap();
+ Ok(Self {
+ unix,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ len,
+ })
+ }
+
+ fn init() -> c::sockaddr_un {
+ c::sockaddr_un {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_len: 0,
+ sun_family: c::AF_UNIX as _,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_path: [0; 104],
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sun_path: [0; 108],
+ }
+ }
+
+ /// For a filesystem path address, return the path.
+ #[inline]
+ pub fn path(&self) -> Option<&CStr> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
+ // `from_bytes_with_nul_unchecked` since the string is NUL-terminated.
+ unsafe {
+ Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
+ bytes.as_ptr().cast(),
+ bytes.len(),
+ )))
+ }
+ } else {
+ None
+ }
+ }
+
+ /// For an abstract address, return the identifier.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+ pub fn abstract_name(&self) -> Option<&[u8]> {
+ let len = self.len();
+ if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char {
+ let end = len as usize - offsetof_sun_path();
+ let bytes = &self.unix.sun_path[1..end];
+ // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
+ unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub(crate) fn addr_len(&self) -> c::socklen_t {
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ {
+ self.len
+ }
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ {
+ c::socklen_t::from(self.unix.sun_len)
+ }
+ }
+
+ #[inline]
+ pub(crate) fn len(&self) -> usize {
+ self.addr_len() as usize
+ }
+}
+
+#[cfg(unix)]
+impl PartialEq for SocketAddrUnix {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
+ }
+}
+
+#[cfg(unix)]
+impl Eq for SocketAddrUnix {}
+
+#[cfg(unix)]
+impl PartialOrd for SocketAddrUnix {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+#[cfg(unix)]
+impl Ord for SocketAddrUnix {
+ #[inline]
+ fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+ let self_len = self.len() - offsetof_sun_path();
+ let other_len = other.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
+ }
+}
+
+#[cfg(unix)]
+impl core::hash::Hash for SocketAddrUnix {
+ #[inline]
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ let self_len = self.len() - offsetof_sun_path();
+ self.unix.sun_path[..self_len].hash(state)
+ }
+}
+
+#[cfg(unix)]
+impl fmt::Debug for SocketAddrUnix {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(path) = self.path() {
+ path.fmt(fmt)
+ } else {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ if let Some(name) = self.abstract_name() {
+ return name.fmt(fmt);
+ }
+
+ "(unnamed)".fmt(fmt)
+ }
+ }
+}
+
+/// `struct sockaddr_storage` as a raw struct.
+pub type SocketAddrStorage = c::sockaddr_storage;
+
+/// Return the offset of the `sun_path` field of `sockaddr_un`.
+#[cfg(not(windows))]
+#[inline]
+pub(crate) fn offsetof_sun_path() -> usize {
+ let z = c::sockaddr_un {
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_len: 0_u8,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_family: 0_u8,
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sun_family: 0_u16,
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ ))]
+ sun_path: [0; 104],
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ sun_path: [0; 108],
+ };
+ (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
+}