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