]> git.proxmox.com Git - rustc.git/blame - vendor/rustix/src/backend/libc/net/addr.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / vendor / rustix / src / backend / libc / net / addr.rs
CommitLineData
fe692bf9 1//! Socket address utilities.
064997fb 2
fe692bf9 3use crate::backend::c;
064997fb 4#[cfg(unix)]
fe692bf9
FG
5use {
6 crate::ffi::CStr,
7 crate::io,
8 crate::path,
9 core::cmp::Ordering,
10 core::fmt,
11 core::hash::{Hash, Hasher},
12 core::slice,
13};
064997fb
FG
14
15/// `struct sockaddr_un`
16#[cfg(unix)]
17#[derive(Clone)]
18#[doc(alias = "sockaddr_un")]
19pub struct SocketAddrUnix {
20 pub(crate) unix: c::sockaddr_un,
353b0b11 21 #[cfg(not(any(bsd, target_os = "haiku")))]
064997fb
FG
22 len: c::socklen_t,
23}
24
25#[cfg(unix)]
26impl SocketAddrUnix {
27 /// Construct a new Unix-domain address from a filesystem path.
28 #[inline]
29 pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
30 path.into_with_c_str(Self::_new)
31 }
32
33 #[inline]
34 fn _new(path: &CStr) -> io::Result<Self> {
35 let mut unix = Self::init();
36 let bytes = path.to_bytes_with_nul();
37 if bytes.len() > unix.sun_path.len() {
38 return Err(io::Errno::NAMETOOLONG);
39 }
40 for (i, b) in bytes.iter().enumerate() {
41 unix.sun_path[i] = *b as c::c_char;
42 }
43
353b0b11 44 #[cfg(any(bsd, target_os = "haiku"))]
064997fb
FG
45 {
46 unix.sun_len = (offsetof_sun_path() + bytes.len()).try_into().unwrap();
47 }
48
49 Ok(Self {
50 unix,
353b0b11 51 #[cfg(not(any(bsd, target_os = "haiku")))]
064997fb
FG
52 len: (offsetof_sun_path() + bytes.len()).try_into().unwrap(),
53 })
54 }
55
56 /// Construct a new abstract Unix-domain address from a byte slice.
fe692bf9 57 #[cfg(linux_kernel)]
064997fb
FG
58 #[inline]
59 pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
60 let mut unix = Self::init();
61 if 1 + name.len() > unix.sun_path.len() {
62 return Err(io::Errno::NAMETOOLONG);
63 }
fe692bf9 64 unix.sun_path[0] = 0;
064997fb
FG
65 for (i, b) in name.iter().enumerate() {
66 unix.sun_path[1 + i] = *b as c::c_char;
67 }
68 let len = offsetof_sun_path() + 1 + name.len();
69 let len = len.try_into().unwrap();
70 Ok(Self {
71 unix,
353b0b11 72 #[cfg(not(any(bsd, target_os = "haiku")))]
064997fb
FG
73 len,
74 })
75 }
76
77 fn init() -> c::sockaddr_un {
78 c::sockaddr_un {
781aab86 79 #[cfg(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto"))]
064997fb 80 sun_len: 0,
ed00b5ec
FG
81 #[cfg(target_os = "vita")]
82 ss_len: 0,
064997fb 83 sun_family: c::AF_UNIX as _,
add651ee 84 #[cfg(any(bsd, target_os = "nto"))]
064997fb 85 sun_path: [0; 104],
781aab86 86 #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto")))]
064997fb 87 sun_path: [0; 108],
487cf647
FG
88 #[cfg(target_os = "haiku")]
89 sun_path: [0; 126],
781aab86
FG
90 #[cfg(target_os = "aix")]
91 sun_path: [0; 1023],
064997fb
FG
92 }
93 }
94
95 /// For a filesystem path address, return the path.
96 #[inline]
97 pub fn path(&self) -> Option<&CStr> {
98 let len = self.len();
fe692bf9 99 if len != 0 && self.unix.sun_path[0] != 0 {
064997fb
FG
100 let end = len as usize - offsetof_sun_path();
101 let bytes = &self.unix.sun_path[..end];
fe692bf9
FG
102 // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
103 // And `from_bytes_with_nul_unchecked` since the string is
104 // NUL-terminated.
064997fb
FG
105 unsafe {
106 Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
107 bytes.as_ptr().cast(),
108 bytes.len(),
109 )))
110 }
111 } else {
112 None
113 }
114 }
115
116 /// For an abstract address, return the identifier.
fe692bf9 117 #[cfg(linux_kernel)]
064997fb
FG
118 #[inline]
119 pub fn abstract_name(&self) -> Option<&[u8]> {
120 let len = self.len();
fe692bf9 121 if len != 0 && self.unix.sun_path[0] == 0 {
064997fb
FG
122 let end = len as usize - offsetof_sun_path();
123 let bytes = &self.unix.sun_path[1..end];
353b0b11 124 // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
064997fb
FG
125 unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
126 } else {
127 None
128 }
129 }
130
131 #[inline]
132 pub(crate) fn addr_len(&self) -> c::socklen_t {
353b0b11 133 #[cfg(not(any(bsd, target_os = "haiku")))]
064997fb
FG
134 {
135 self.len
136 }
353b0b11 137 #[cfg(any(bsd, target_os = "haiku"))]
064997fb
FG
138 {
139 c::socklen_t::from(self.unix.sun_len)
140 }
141 }
142
143 #[inline]
144 pub(crate) fn len(&self) -> usize {
145 self.addr_len() as usize
146 }
147}
148
149#[cfg(unix)]
150impl PartialEq for SocketAddrUnix {
151 #[inline]
152 fn eq(&self, other: &Self) -> bool {
153 let self_len = self.len() - offsetof_sun_path();
154 let other_len = other.len() - offsetof_sun_path();
155 self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
156 }
157}
158
159#[cfg(unix)]
160impl Eq for SocketAddrUnix {}
161
162#[cfg(unix)]
163impl PartialOrd for SocketAddrUnix {
164 #[inline]
fe692bf9 165 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
781aab86 166 Some(self.cmp(other))
064997fb
FG
167 }
168}
169
170#[cfg(unix)]
171impl Ord for SocketAddrUnix {
172 #[inline]
fe692bf9 173 fn cmp(&self, other: &Self) -> Ordering {
064997fb
FG
174 let self_len = self.len() - offsetof_sun_path();
175 let other_len = other.len() - offsetof_sun_path();
176 self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
177 }
178}
179
180#[cfg(unix)]
fe692bf9 181impl Hash for SocketAddrUnix {
064997fb 182 #[inline]
fe692bf9 183 fn hash<H: Hasher>(&self, state: &mut H) {
064997fb
FG
184 let self_len = self.len() - offsetof_sun_path();
185 self.unix.sun_path[..self_len].hash(state)
186 }
187}
188
189#[cfg(unix)]
190impl fmt::Debug for SocketAddrUnix {
191 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
192 if let Some(path) = self.path() {
193 path.fmt(fmt)
194 } else {
fe692bf9 195 #[cfg(linux_kernel)]
064997fb
FG
196 if let Some(name) = self.abstract_name() {
197 return name.fmt(fmt);
198 }
199
200 "(unnamed)".fmt(fmt)
201 }
202 }
203}
204
205/// `struct sockaddr_storage` as a raw struct.
206pub type SocketAddrStorage = c::sockaddr_storage;
207
208/// Return the offset of the `sun_path` field of `sockaddr_un`.
209#[cfg(not(windows))]
210#[inline]
211pub(crate) fn offsetof_sun_path() -> usize {
212 let z = c::sockaddr_un {
781aab86 213 #[cfg(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto"))]
064997fb 214 sun_len: 0_u8,
ed00b5ec
FG
215 #[cfg(target_os = "vita")]
216 ss_len: 0,
781aab86
FG
217 #[cfg(any(
218 bsd,
219 target_os = "aix",
220 target_os = "espidf",
221 target_os = "haiku",
ed00b5ec
FG
222 target_os = "nto",
223 target_os = "vita"
781aab86 224 ))]
064997fb 225 sun_family: 0_u8,
781aab86
FG
226 #[cfg(not(any(
227 bsd,
228 target_os = "aix",
229 target_os = "espidf",
230 target_os = "haiku",
ed00b5ec
FG
231 target_os = "nto",
232 target_os = "vita"
781aab86 233 )))]
064997fb 234 sun_family: 0_u16,
add651ee 235 #[cfg(any(bsd, target_os = "nto"))]
064997fb 236 sun_path: [0; 104],
781aab86 237 #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "nto")))]
064997fb 238 sun_path: [0; 108],
487cf647
FG
239 #[cfg(target_os = "haiku")]
240 sun_path: [0; 126],
781aab86
FG
241 #[cfg(target_os = "aix")]
242 sun_path: [0; 1023],
064997fb
FG
243 };
244 (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
245}