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