]> git.proxmox.com Git - rustc.git/blob - vendor/rustix-0.37.20/src/backend/linux_raw/net/addr.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / vendor / rustix-0.37.20 / src / backend / linux_raw / net / addr.rs
1 //! Socket address utilities.
2 //!
3 //! # Safety
4 //!
5 //! This file uses `CStr::from_bytes_with_nul_unchecked` on a string it knows
6 //! to be NUL-terminated.
7 #![allow(unsafe_code)]
8
9 use super::super::c;
10 use crate::ffi::CStr;
11 use crate::{io, path};
12 use core::cmp::Ordering;
13 use core::convert::TryInto;
14 use core::fmt;
15 use core::hash::{Hash, Hasher};
16
17 /// `struct sockaddr_un`
18 #[derive(Clone)]
19 #[doc(alias = "sockaddr_un")]
20 pub struct SocketAddrUnix {
21 pub(crate) unix: c::sockaddr_un,
22 len: c::socklen_t,
23 }
24
25 impl SocketAddrUnix {
26 /// Construct a new Unix-domain address from a filesystem path.
27 #[inline]
28 pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
29 path.into_with_c_str(Self::_new)
30 }
31
32 #[inline]
33 fn _new(path: &CStr) -> io::Result<Self> {
34 let mut unix = Self::init();
35 let bytes = path.to_bytes_with_nul();
36 if bytes.len() > unix.sun_path.len() {
37 return Err(io::Errno::NAMETOOLONG);
38 }
39 for (i, b) in bytes.iter().enumerate() {
40 unix.sun_path[i] = *b;
41 }
42 let len = offsetof_sun_path() + bytes.len();
43 let len = len.try_into().unwrap();
44 Ok(Self { unix, len })
45 }
46
47 /// Construct a new abstract Unix-domain address from a byte slice.
48 #[inline]
49 pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
50 let mut unix = Self::init();
51 let id = &mut unix.sun_path[1..];
52 if let Some(id) = id.get_mut(..name.len()) {
53 id.copy_from_slice(name);
54 let len = offsetof_sun_path() + 1 + name.len();
55 let len = len.try_into().unwrap();
56 Ok(Self { unix, len })
57 } else {
58 Err(io::Errno::NAMETOOLONG)
59 }
60 }
61
62 const fn init() -> c::sockaddr_un {
63 c::sockaddr_un {
64 sun_family: c::AF_UNIX as _,
65 sun_path: [0; 108],
66 }
67 }
68
69 /// For a filesystem path address, return the path.
70 #[inline]
71 pub fn path(&self) -> Option<&CStr> {
72 let len = self.len();
73 if len != 0 && self.unix.sun_path[0] != b'\0' {
74 let end = len as usize - offsetof_sun_path();
75 let bytes = &self.unix.sun_path[..end];
76 // SAFETY: `from_bytes_with_nul_unchecked` since the string is
77 // NUL-terminated.
78 unsafe { Some(CStr::from_bytes_with_nul_unchecked(bytes)) }
79 } else {
80 None
81 }
82 }
83
84 /// For an abstract address, return the identifier.
85 #[inline]
86 pub fn abstract_name(&self) -> Option<&[u8]> {
87 let len = self.len();
88 if len != 0 && self.unix.sun_path[0] == b'\0' {
89 let end = len as usize - offsetof_sun_path();
90 Some(&self.unix.sun_path[1..end])
91 } else {
92 None
93 }
94 }
95
96 #[inline]
97 pub(crate) fn addr_len(&self) -> c::socklen_t {
98 self.len
99 }
100
101 #[inline]
102 pub(crate) fn len(&self) -> usize {
103 self.addr_len() as usize
104 }
105 }
106
107 impl PartialEq for SocketAddrUnix {
108 #[inline]
109 fn eq(&self, other: &Self) -> bool {
110 let self_len = self.len() - offsetof_sun_path();
111 let other_len = other.len() - offsetof_sun_path();
112 self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
113 }
114 }
115
116 impl Eq for SocketAddrUnix {}
117
118 impl PartialOrd for SocketAddrUnix {
119 #[inline]
120 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
121 let self_len = self.len() - offsetof_sun_path();
122 let other_len = other.len() - offsetof_sun_path();
123 self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len])
124 }
125 }
126
127 impl Ord for SocketAddrUnix {
128 #[inline]
129 fn cmp(&self, other: &Self) -> Ordering {
130 let self_len = self.len() - offsetof_sun_path();
131 let other_len = other.len() - offsetof_sun_path();
132 self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
133 }
134 }
135
136 impl Hash for SocketAddrUnix {
137 #[inline]
138 fn hash<H: Hasher>(&self, state: &mut H) {
139 let self_len = self.len() - offsetof_sun_path();
140 self.unix.sun_path[..self_len].hash(state)
141 }
142 }
143
144 impl fmt::Debug for SocketAddrUnix {
145 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
146 if let Some(path) = self.path() {
147 path.fmt(fmt)
148 } else if let Some(name) = self.abstract_name() {
149 name.fmt(fmt)
150 } else {
151 "(unnamed)".fmt(fmt)
152 }
153 }
154 }
155
156 /// `struct sockaddr_storage` as a raw struct.
157 pub type SocketAddrStorage = c::sockaddr;
158
159 /// Return the offset of the `sun_path` field of `sockaddr_un`.
160 #[inline]
161 pub(crate) fn offsetof_sun_path() -> usize {
162 let z = c::sockaddr_un {
163 sun_family: 0_u16,
164 sun_path: [0; 108],
165 };
166 (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
167 }