rustix/backend/linux_raw/net/
addr.rs
1#![allow(unsafe_code)]
8
9use crate::backend::c;
10use crate::ffi::CStr;
11use crate::net::addr::SocketAddrLen;
12use crate::net::AddressFamily;
13use crate::{io, path};
14use core::cmp::Ordering;
15use core::hash::{Hash, Hasher};
16use core::{fmt, slice};
17#[cfg(feature = "alloc")]
18use {crate::ffi::CString, alloc::borrow::Cow, alloc::vec::Vec};
19
20#[derive(Clone)]
22#[doc(alias = "sockaddr_un")]
23pub struct SocketAddrUnix {
24 pub(crate) unix: c::sockaddr_un,
25 len: c::socklen_t,
26}
27
28impl SocketAddrUnix {
29 #[inline]
31 pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
32 path.into_with_c_str(Self::_new)
33 }
34
35 #[inline]
36 fn _new(path: &CStr) -> io::Result<Self> {
37 let mut unix = Self::init();
38 let mut bytes = path.to_bytes_with_nul();
39 if bytes.len() > unix.sun_path.len() {
40 bytes = path.to_bytes(); if bytes.len() > unix.sun_path.len() {
42 return Err(io::Errno::NAMETOOLONG);
43 }
44 }
45 for (i, b) in bytes.iter().enumerate() {
46 unix.sun_path[i] = bitcast!(*b);
47 }
48 let len = offsetof_sun_path() + bytes.len();
49 let len = len.try_into().unwrap();
50 Ok(Self { unix, len })
51 }
52
53 #[inline]
55 pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
56 let mut unix = Self::init();
57 let id = &mut unix.sun_path[1..];
58
59 let id = unsafe { slice::from_raw_parts_mut(id.as_mut_ptr().cast::<u8>(), id.len()) };
61
62 if let Some(id) = id.get_mut(..name.len()) {
63 id.copy_from_slice(name);
64 let len = offsetof_sun_path() + 1 + name.len();
65 let len = len.try_into().unwrap();
66 Ok(Self { unix, len })
67 } else {
68 Err(io::Errno::NAMETOOLONG)
69 }
70 }
71
72 #[inline]
83 pub fn new_unnamed() -> Self {
84 Self {
85 unix: Self::init(),
86 len: offsetof_sun_path() as SocketAddrLen,
87 }
88 }
89
90 const fn init() -> c::sockaddr_un {
91 c::sockaddr_un {
92 sun_family: c::AF_UNIX as _,
93 sun_path: [0; 108],
94 }
95 }
96
97 #[inline]
99 #[cfg(feature = "alloc")]
100 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
101 pub fn path(&self) -> Option<Cow<'_, CStr>> {
102 let bytes = self.bytes()?;
103 if !bytes.is_empty() && bytes[0] != 0 {
104 if self.unix.sun_path.len() == bytes.len() {
105 unsafe { Self::path_with_termination(bytes) }
107 } else {
108 Some(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) }.into())
111 }
112 } else {
113 None
114 }
115 }
116
117 #[cfg(feature = "alloc")]
121 #[cold]
122 unsafe fn path_with_termination(bytes: &[u8]) -> Option<Cow<'_, CStr>> {
123 let mut owned = Vec::with_capacity(bytes.len() + 1);
124 owned.extend_from_slice(bytes);
125 owned.push(b'\0');
126 Some(Cow::Owned(
129 CString::from_vec_with_nul_unchecked(owned).into(),
130 ))
131 }
132
133 #[inline]
136 pub fn path_bytes(&self) -> Option<&[u8]> {
137 let bytes = self.bytes()?;
138 if !bytes.is_empty() && bytes[0] != 0 {
139 if self.unix.sun_path.len() == self.len() - offsetof_sun_path() {
140 Some(bytes)
142 } else {
143 Some(&bytes[..bytes.len() - 1])
145 }
146 } else {
147 None
148 }
149 }
150
151 #[inline]
153 pub fn abstract_name(&self) -> Option<&[u8]> {
154 if let [0, bytes @ ..] = self.bytes()? {
155 Some(bytes)
156 } else {
157 None
158 }
159 }
160
161 #[inline]
163 pub fn is_unnamed(&self) -> bool {
164 self.bytes() == Some(&[])
165 }
166
167 #[inline]
168 pub(crate) fn addr_len(&self) -> SocketAddrLen {
169 bitcast!(self.len)
170 }
171
172 #[inline]
173 pub(crate) fn len(&self) -> usize {
174 self.addr_len() as usize
175 }
176
177 #[inline]
178 fn bytes(&self) -> Option<&[u8]> {
179 let len = self.len();
180 if len != 0 {
181 let bytes = &self.unix.sun_path[..len - offsetof_sun_path()];
182 Some(unsafe { slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len()) })
184 } else {
185 None
186 }
187 }
188}
189
190impl PartialEq for SocketAddrUnix {
191 #[inline]
192 fn eq(&self, other: &Self) -> bool {
193 let self_len = self.len() - offsetof_sun_path();
194 let other_len = other.len() - offsetof_sun_path();
195 self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
196 }
197}
198
199impl Eq for SocketAddrUnix {}
200
201impl PartialOrd for SocketAddrUnix {
202 #[inline]
203 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
204 Some(self.cmp(other))
205 }
206}
207
208impl Ord for SocketAddrUnix {
209 #[inline]
210 fn cmp(&self, other: &Self) -> Ordering {
211 let self_len = self.len() - offsetof_sun_path();
212 let other_len = other.len() - offsetof_sun_path();
213 self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
214 }
215}
216
217impl Hash for SocketAddrUnix {
218 #[inline]
219 fn hash<H: Hasher>(&self, state: &mut H) {
220 let self_len = self.len() - offsetof_sun_path();
221 self.unix.sun_path[..self_len].hash(state)
222 }
223}
224
225impl fmt::Debug for SocketAddrUnix {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 #[cfg(feature = "alloc")]
228 if let Some(path) = self.path() {
229 return path.fmt(f);
230 }
231 if let Some(bytes) = self.path_bytes() {
232 if let Ok(s) = core::str::from_utf8(bytes) {
233 return s.fmt(f);
234 }
235 return bytes.fmt(f);
236 }
237 if let Some(name) = self.abstract_name() {
238 return name.fmt(f);
239 }
240 "(unnamed)".fmt(f)
241 }
242}
243
244#[repr(transparent)]
249#[derive(Copy, Clone)]
250#[doc(alias = "sockaddr_storage")]
251pub struct SocketAddrStorage(c::sockaddr_storage);
252
253unsafe impl Send for SocketAddrStorage {}
257
258unsafe impl Sync for SocketAddrStorage {}
260
261impl SocketAddrStorage {
262 pub fn zeroed() -> Self {
265 assert_eq!(c::AF_UNSPEC, 0);
266 unsafe { core::mem::zeroed() }
268 }
269
270 pub fn family(&self) -> AddressFamily {
272 unsafe {
274 AddressFamily::from_raw(crate::backend::net::read_sockaddr::read_sa_family(
275 crate::utils::as_ptr(&self.0).cast::<c::sockaddr>(),
276 ))
277 }
278 }
279
280 pub fn clear_family(&mut self) {
283 unsafe {
285 crate::backend::net::read_sockaddr::initialize_family_to_unspec(
286 crate::utils::as_mut_ptr(&mut self.0).cast::<c::sockaddr>(),
287 )
288 }
289 }
290}
291
292#[inline]
294pub(crate) fn offsetof_sun_path() -> usize {
295 let z = c::sockaddr_un {
296 sun_family: 0_u16,
297 sun_path: [0; 108],
298 };
299 (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
300}