uds_fork/addr.rs
1
2#[cfg(windows)]
3use std::borrow::Cow;
4use std::
5{
6 ffi::{CStr, OsStr, c_char},
7 fmt::{self, Debug, Display},
8 hash::{Hash, Hasher},
9 io::{self, ErrorKind},
10 mem,
11 path::Path,
12 slice
13};
14
15#[cfg(unix)]
16use std::os::unix::{ffi::OsStrExt, net};
17
18#[cfg(unix)]
19use libc::{AF_UNIX, sa_family_t, sockaddr, sockaddr_storage, sockaddr_un, socklen_t};
20
21#[cfg(windows)]
22pub use windows_sys::Win32::Networking::WinSock::
23{
24 AF_UNIX, SOCKADDR_STORAGE as sockaddr_storage, socklen_t, SOCKADDR as sockaddr,
25 SOCKADDR_UN as sockaddr_un, ADDRESS_FAMILY as sa_family_t
26};
27
28/// Offset of `.sun_path` in `sockaddr_un`.
29///
30/// This is not always identical to `mem::size_of::<sa_family_t>()`,
31/// as there can be other fields before or after `.sun_family`.
32fn path_offset() -> socklen_t
33{
34 unsafe
35 {
36 let total_size = mem::size_of::<sockaddr_un>();
37 let name_size = mem::size_of_val(&mem::zeroed::<sockaddr_un>().sun_path);
38
39 (total_size - name_size) as socklen_t
40 }
41}
42
43const
44fn as_u8(slice: &[c_char]) -> &[u8]
45{
46 unsafe { &*(slice as *const[c_char] as *const[u8]) }
47}
48
49const
50fn as_char(slice: &[u8]) -> &[c_char]
51{
52 unsafe { &*(slice as *const[u8] as *const[c_char]) }
53}
54
55const TOO_LONG_DESC: &str = "address is too long";
56
57
58/// A unix domain socket address.
59///
60/// # Differences from `std`'s `unix::net::SocketAddr`
61///
62/// This type fully supports Linux's abstract socket addresses,
63/// and can be created by user code instead of just returned by `accept()`
64/// and similar.
65///
66/// # Examples
67///
68/// Creating an abstract address (fails if the OS doesn't support them):
69///
70#[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
71#[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
72/// use uds_fork::UnixSocketAddr;
73///
74/// let addr = UnixSocketAddr::new("@abstract").unwrap();
75/// assert!(addr.is_abstract());
76/// assert_eq!(addr.to_string(), "@abstract");
77/// ```
78#[derive(Clone, Copy)]
79pub struct UnixSocketAddr
80{
81 addr: sockaddr_un,
82
83 /// How many bytes of addr are in use.
84 ///
85 /// Must never be greater than `size_of::<sockaddr_un>()`.
86 ///
87 /// On BSDs and macOS, `sockaddr_un` has a (non-standard) `.sun_len` field
88 /// that *could* be used to store the length instead, but doing that is
89 /// not a very good idea:
90 /// At least [NetBSD ignores it](http://mail-index.netbsd.org/tech-net/2006/10/11/0008.html)
91 /// so we would still need to pass a correctly set `socklen_t`,
92 /// in some cases by referece.
93 /// Because it's rarely used and some BSDs aren't afraid to break stuff,
94 /// it could even dissappear in the future.
95 /// The size this extra field is also rather minor compared to the size of
96 /// `sockaddr_un`, so the possible benefit is tiny.
97 len: socklen_t,
98}
99
100
101
102/// An enum representation of an unix socket address.
103///
104/// Useful for pattern matching an [`UnixSocketAddr`](struct.UnixSocketAddr.html)
105/// via [`UnixSocketAddr.name()`](struct.UnixSocketAddr.html#method.name).
106///
107/// It cannot be used to bind or connect a socket directly as it
108/// doesn't contain a `sockaddr_un`, but a `UnixSocketAddr` can be created
109/// from it.
110///
111/// # Examples
112///
113/// Cleaning up pathname socket files after ourselves:
114///
115/// ```no_run
116/// # use uds_fork::{UnixSocketAddr, AddrName};
117/// let addr = UnixSocketAddr::from_path("/var/run/socket.sock").unwrap();
118/// if let AddrName::Path(path) = addr.name() {
119/// let _ = std::fs::remove_file(path);
120/// }
121/// ```
122#[derive(Clone,Copy, PartialEq,Eq,Hash, Debug)]
123pub enum AddrName<'a>
124{
125 /// Unnamed / anonymous address.
126 Unnamed,
127 /// Regular file path based address.
128 ///
129 /// Can be both relative and absolute.
130 Path(&'a Path),
131 /// Address in the abstract namespace.
132 Abstract(&'a [u8]),
133}
134
135impl<'a> From<&'a UnixSocketAddr> for AddrName<'a>
136{
137 fn from(addr: &'a UnixSocketAddr) -> AddrName<'a>
138 {
139 let name_len = addr.len as isize - path_offset() as isize;
140
141 if addr.is_unnamed() == true
142 {
143 AddrName::Unnamed
144 }
145 else if addr.is_abstract() == true
146 {
147 let slice = &addr.addr.sun_path[1..name_len as usize];
148 AddrName::Abstract(as_u8(slice))
149 }
150 else
151 {
152 let mut slice = &addr.addr.sun_path[..name_len as usize];
153
154 // remove trailing NUL if present (and multiple NULs on OpenBSD)
155 while let Some(&0) = slice.last()
156 {
157 slice = &slice[..slice.len()-1];
158 }
159
160 #[cfg(unix)]
161 return
162 AddrName::Path(Path::new(OsStr::from_bytes(as_u8(slice))));
163
164 // sun_path is UTF-8
165 #[cfg(windows)]
166 {
167 //let utf8_valid = str::from_utf8(as_u8(slice)).unwrap();
168
169 return
170 AddrName::Path(Path::new(unsafe{ OsStr::from_encoded_bytes_unchecked(as_u8(slice)) } ))
171 }
172 }
173 }
174}
175
176pub type UnixSocketAddrRef<'a> = AddrName<'a>;
177
178impl Debug for UnixSocketAddr
179{
180 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result
181 {
182 #[derive(Debug)]
183 struct Unnamed;
184 #[derive(Debug)]
185 struct Path<'a>(&'a std::path::Path);
186 #[cfg(unix)]
187 #[derive(Debug)]
188 struct Abstract<'a>(&'a OsStr);
189
190 #[cfg(windows)]
191 #[derive(Debug)]
192 struct Abstract<'a>(Cow<'a, str>);
193
194 // doesn't live long enough if created inside match
195 let mut path_type = Path("".as_ref());
196 #[cfg(unix)]
197 let mut abstract_type = Abstract(OsStr::new(""));
198
199 #[cfg(windows)]
200 let mut abstract_type = Abstract(Cow::Borrowed(""));
201
202 let variant: &dyn Debug =
203 match self.into()
204 {
205 UnixSocketAddrRef::Unnamed =>
206 &Unnamed,
207 UnixSocketAddrRef::Path(path) =>
208 {
209 path_type.0 = path;
210 &path_type
211 },
212 UnixSocketAddrRef::Abstract(name) =>
213 {
214 #[cfg(unix)]
215 {
216 abstract_type.0 = OsStr::from_bytes(name);
217 }
218
219 #[cfg(windows)]
220 {
221 let utf8_valid = String::from_utf8_lossy(name);
222 abstract_type.0 = utf8_valid;
223 }
224
225 &abstract_type
226 },
227 };
228 fmtr.debug_tuple("UnixSocketAddr").field(variant).finish()
229 }
230}
231
232impl Display for UnixSocketAddr
233{
234 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result
235 {
236 match self.into()
237 {
238 UnixSocketAddrRef::Unnamed =>
239 fmtr.write_str("unnamed"),
240 UnixSocketAddrRef::Path(path) =>
241 write!(fmtr, "{}", path.display()), // TODO check that display() doesn't print \n as-is
242 #[cfg(unix)]
243 UnixSocketAddrRef::Abstract(name) =>
244 {
245 write!(fmtr, "@{}", OsStr::from_bytes(name).to_string_lossy()) // FIXME escape to sane characters
246 }
247 #[cfg(windows)]
248 UnixSocketAddrRef::Abstract(name) =>
249 {
250 let utf8_valid = String::from_utf8_lossy(name);
251
252 write!(fmtr, "@{}", utf8_valid) // FIXME escape to sane characters
253 }
254 }
255 }
256}
257
258#[cfg(windows)]
259impl UnixSocketAddr
260{
261 /// Allows creating abstract, path or unspecified address based on an
262 /// user-supplied string.
263 ///
264 /// A leading `'@'` or `'\0'` signifies an abstract address,
265 /// an empty slice is taken as the unnamed address, and anything else is a
266 /// path address.
267 /// If a relative path address starts with `@`, escape it by prepending
268 /// `"./"`.
269 /// To avoid surprises, abstract addresses will be detected regargsless of
270 /// wheither the OS supports them, and result in an error if it doesn't.
271 ///
272 /// # Errors
273 ///
274 /// * A path or abstract address is too long.
275 /// * A path address contains `'\0'`.
276 /// * An abstract name was supplied on an OS that doesn't support them.
277 ///
278 /// # Examples
279 ///
280 /// Abstract address:
281 ///
282 /// ```
283 /// # use uds_fork::UnixSocketAddr;
284 /// if UnixSocketAddr::has_abstract_addresses() {
285 /// assert!(UnixSocketAddr::new("@abstract").unwrap().is_abstract());
286 /// assert!(UnixSocketAddr::new("\0abstract").unwrap().is_abstract());
287 /// } else {
288 /// assert!(UnixSocketAddr::new("@abstract").is_err());
289 /// assert!(UnixSocketAddr::new("\0abstract").is_err());
290 /// }
291 /// ```
292 ///
293 /// Escaped path address:
294 ///
295 /// ```
296 /// # use uds_fork::UnixSocketAddr;
297 /// assert!(UnixSocketAddr::new("./@path").unwrap().is_relative_path());
298 /// ```
299 ///
300 /// Unnamed address:
301 ///
302 #[cfg_attr(not(target_family="windows"), doc="```")]
303 #[cfg_attr(target_family="windows", doc="```no_run")]
304 /// # use uds_fork::UnixSocketAddr;
305 /// assert!(UnixSocketAddr::new("").unwrap().is_unnamed());
306 /// ```
307 pub
308 fn new<A: AsRef<[u8]>+?Sized>(addr: &A) -> Result<Self, io::Error>
309 {
310 fn parse(addr: &[u8]) -> Result<UnixSocketAddr, io::Error>
311 {
312 match addr.first()
313 {
314 Some(&b'@') | Some(&b'\0') =>
315 return
316 Err(
317 io::Error::new(
318 ErrorKind::AddrNotAvailable,
319 format!( "abstract unix domain socket addresses are not available on {}",
320 std::env::consts::OS)
321 )
322 ),
323 Some(_) =>
324 {
325 let utf8_valid =
326 str::from_utf8(addr)
327 .map_err(|e| io::Error::new(ErrorKind::InvalidInput, e)
328 )?;
329
330 UnixSocketAddr::from_path(Path::new(utf8_valid))
331 },
332 None =>
333 return
334 Err(
335 io::Error::new(
336 ErrorKind::AddrNotAvailable,
337 format!( "unspecified unix domain socket addresses are not available on {}",
338 std::env::consts::OS)
339 )
340 ),
341 }
342 }
343
344 return parse(addr.as_ref());
345 }
346
347 /// Allows creating abstract, path or unspecified address based on an
348 /// user-supplied string for Windows UTF-16 path.
349 ///
350 /// A leading `'@'` or `'\0'` signifies an abstract address,
351 /// an empty slice is taken as the unnamed address, and anything else is a
352 /// path address. (Windows does not support abstract addresses)
353 /// If a relative path address starts with `@`, escape it by prepending
354 /// `"./"`.
355 /// To avoid surprises, abstract addresses will be detected regargsless of
356 /// wheither the OS supports them, and result in an error if it doesn't.
357 ///
358 /// # Errors
359 ///
360 /// * A path or abstract address is too long.
361 /// * A path address contains `'\0'`.
362 /// * An abstract name was supplied on an OS that doesn't support them.
363 pub
364 fn new_utf16<A: AsRef<[u16]>+?Sized>(addr_v: &A) -> Result<Self, io::Error>
365 {
366 use std::{ffi::OsString, os::windows::ffi::OsStringExt};
367 let addr = addr_v.as_ref();
368
369 let first =
370 if addr.len() > 0
371 {
372 Some(OsString::from_wide(&addr[0..1]))
373 }
374 else
375 {
376 None
377 };
378
379 match first.as_ref().map(|v| v.as_encoded_bytes())
380 {
381 Some(b"@") | Some(b"\0") =>
382 return
383 Err(
384 io::Error::new(
385 ErrorKind::AddrNotAvailable,
386 format!( "abstract unix domain socket addresses are not available on {}",
387 std::env::consts::OS)
388 )
389 ),
390 Some(_) =>
391 {
392
393 let osstr = OsString::from_wide(addr);
394
395 return UnixSocketAddr::from_path(Path::new( &osstr ));
396 },
397 None =>
398 return
399 Err(
400 io::Error::new(
401 ErrorKind::AddrNotAvailable,
402 format!( "unspecified unix domain socket addresses are not available on {}",
403 std::env::consts::OS)
404 )
405 ),
406 }
407 }
408}
409
410#[cfg(unix)]
411impl UnixSocketAddr
412{
413 /// Allows creating abstract, path or unspecified address based on an
414 /// user-supplied string.
415 ///
416 /// A leading `'@'` or `'\0'` signifies an abstract address,
417 /// an empty slice is taken as the unnamed address, and anything else is a
418 /// path address.
419 /// If a relative path address starts with `@`, escape it by prepending
420 /// `"./"`.
421 /// To avoid surprises, abstract addresses will be detected regargsless of
422 /// wheither the OS supports them, and result in an error if it doesn't.
423 ///
424 /// # Errors
425 ///
426 /// * A path or abstract address is too long.
427 /// * A path address contains `'\0'`.
428 /// * An abstract name was supplied on an OS that doesn't support them.
429 ///
430 /// # Examples
431 ///
432 /// Abstract address:
433 ///
434 /// ```
435 /// # use uds_fork::UnixSocketAddr;
436 /// if UnixSocketAddr::has_abstract_addresses() {
437 /// assert!(UnixSocketAddr::new("@abstract").unwrap().is_abstract());
438 /// assert!(UnixSocketAddr::new("\0abstract").unwrap().is_abstract());
439 /// } else {
440 /// assert!(UnixSocketAddr::new("@abstract").is_err());
441 /// assert!(UnixSocketAddr::new("\0abstract").is_err());
442 /// }
443 /// ```
444 ///
445 /// Escaped path address:
446 ///
447 /// ```
448 /// # use uds_fork::UnixSocketAddr;
449 /// assert!(UnixSocketAddr::new("./@path").unwrap().is_relative_path());
450 /// ```
451 ///
452 /// Unnamed address:
453 ///
454 /// ```
455 /// # use uds_fork::UnixSocketAddr;
456 /// assert!(UnixSocketAddr::new("").unwrap().is_unnamed());
457 /// ```
458 pub
459 fn new<A: AsRef<[u8]>+?Sized>(addr: &A) -> Result<Self, io::Error>
460 {
461 fn parse(addr: &[u8]) -> Result<UnixSocketAddr, io::Error>
462 {
463 match addr.first()
464 {
465 Some(&b'@') | Some(&b'\0') =>
466 UnixSocketAddr::from_abstract(&addr[1..]),
467 Some(_) =>
468 UnixSocketAddr::from_path(Path::new(OsStr::from_bytes(addr))),
469 None =>
470 Ok(UnixSocketAddr::new_unspecified()),
471 }
472 }
473
474 return parse(addr.as_ref());
475 }
476}
477
478impl UnixSocketAddr
479{
480 /// Creates an unnamed address, which on Linux can be used for auto-bind.
481 ///
482 /// Binding a socket to the unnamed address is different from not binding
483 /// at all:
484 ///
485 /// On Linux doing so binds the socket to a random abstract address
486 /// determined by the OS.
487 ///
488 /// # Examples
489 ///
490 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
491 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```ignore")]
492 /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
493 /// # use std::os::unix::net::UnixDatagram;
494 /// let addr = UnixSocketAddr::new_unspecified();
495 /// assert!(addr.is_unnamed());
496 /// let socket = UnixDatagram::unbound().unwrap();
497 /// socket.bind_to_unix_addr(&addr).unwrap();
498 /// assert!(socket.local_unix_addr().unwrap().is_abstract());
499 /// ```
500 pub
501 fn new_unspecified() -> Self
502 {
503 let mut addr: sockaddr_un = unsafe { mem::zeroed() };
504 addr.sun_family = AF_UNIX as sa_family_t;
505
506 return
507 UnixSocketAddr
508 {
509 len: path_offset(),
510 addr,
511 };
512 }
513
514 /// Returns the maximum size of pathname addresses supported by `UnixSocketAddr`.
515 ///
516 /// Is the size of the underlying `sun_path` field, minus 1 if the OS
517 /// is known to either require a trailing NUL (`'\0'`) byte,
518 /// or supports longer paths that go past the end of `sun_path`.
519 ///
520 /// These OSes are:
521 ///
522 /// * OpenBSD: Enforces that `sun_path`` is NUL-terminated.
523 /// * macOS / iOS / anything else Apple: I haven't found a manpage,
524 /// but it supports longer paths.
525 /// * Illumos: [The manpage](https://illumos.org/man/3SOCKET/sockaddr_un)
526 /// says it must be NUL-terminated (and that it cannot be longer),
527 /// but when I tested on an older version, neither of these constraints seem to be the case.
528 /// * Solaris: Assumed to be identical to Illumos.
529 ///
530 /// OSes that have been tested that they allow using the full `sun_path`
531 /// without NUL and no longer paths, and whose manpages don't state the opposite:
532 ///
533 /// * [Linux](https://www.man7.org/linux/man-pages/man7/unix.7.html)
534 /// * [FreeBSD](https://man.freebsd.org/cgi/man.cgi?query=unix&sektion=4)
535 /// * [NetBSD](https://man.netbsd.org/unix.4)
536 /// * [Dragonfly BSD](https://man.dragonflybsd.org/?command=unix§ion=4)
537 pub
538 fn max_path_len() -> usize
539 {
540 let always_nul_terminate =
541 cfg!(any(
542 target_os="openbsd",
543 target_vendor="apple",
544 target_os="illumos",
545 target_os="solaris",
546 ));
547
548 return
549 if always_nul_terminate == true
550 {
551 mem::size_of_val(&Self::new_unspecified().addr.sun_path) - 1
552 }
553 else
554 {
555 mem::size_of_val(&Self::new_unspecified().addr.sun_path)
556 };
557 }
558
559 /// Creates a pathname unix socket address.
560 ///
561 /// # Errors
562 ///
563 /// This function will return an error if the path is too long for the
564 /// underlying `sockaddr_un` type, or contains NUL (`'\0'`) bytes.
565 pub
566 fn from_path<P: AsRef<Path>+?Sized>(path: &P) -> Result<Self, io::Error>
567 {
568 fn from_path_inner(path: &[u8]) -> Result<UnixSocketAddr, io::Error>
569 {
570 let mut addr = UnixSocketAddr::new_unspecified();
571 let capacity = UnixSocketAddr::max_path_len();
572
573 if path.is_empty() == true
574 {
575 return Err(io::Error::new(ErrorKind::NotFound, "path is empty"));
576 }
577 else if path.len() > capacity
578 {
579 let message = "path is too long for an unix socket address";
580
581 return Err(io::Error::new(ErrorKind::InvalidInput, message));
582 }
583 else if path.iter().any(|&b| b == b'\0' ) == true
584 {
585 return Err(io::Error::new(ErrorKind::InvalidInput, "path cannot contain nul bytes"));
586 }
587 else
588 {
589 addr.addr.sun_path[..path.len()].copy_from_slice(as_char(path));
590 addr.len = path_offset() + path.len() as socklen_t;
591
592 if path.len() < capacity
593 {
594 addr.len += 1; // for increased portability
595 }
596
597 return Ok(addr);
598 }
599 }
600
601 #[cfg(unix)]
602 return from_path_inner(path.as_ref().as_os_str().as_bytes());
603
604 #[cfg(windows)]
605 return from_path_inner(path.as_ref().as_os_str().as_encoded_bytes());
606 }
607
608 /// Returns maximum size of abstract addesses supported by `UnixSocketAddr`.
609 ///
610 /// Is the size of the underlying `sun_path` field minus 1 for the
611 /// leading `'\0'` byte.
612 ///
613 /// This value is also returned on operating systems that doesn't support
614 /// abstract addresses.
615 pub
616 fn max_abstract_len() -> usize
617 {
618 mem::size_of_val(&Self::new_unspecified().addr.sun_path) - 1
619 }
620
621 /// Returns whether the operating system is known to support
622 /// abstract unix domain socket addresses.
623 ///
624 /// Is `true` for Linux & Android, and `false` for all other OSes.
625 pub const
626 fn has_abstract_addresses() -> bool
627 {
628 cfg!(any(target_os="linux", target_os="android"))
629 }
630
631 /// Creates an abstract unix domain socket address.
632 ///
633 /// Abstract addresses use a namespace separate from the file system,
634 /// that doesn't have directories (ie. is flat) or permissions.
635 /// The advandage of it is that the address disappear when the socket bound
636 /// to it is closed, which frees one from dealing with removing it when
637 /// shutting down cleanly.
638 ///
639 /// They are a Linux-only feature though, and this function will fail
640 /// if abstract addresses are not supported.
641 ///
642 /// # Errors
643 ///
644 /// This function will return an error if the name is too long.
645 /// Call [`max_abstract_len()`](#method.max_abstract_len)
646 /// get the limit.
647 ///
648 /// It will also fail on operating systems that don't support abstract
649 /// addresses. (ie. anything other than Linux and Android)
650 pub
651 fn from_abstract<N: AsRef<[u8]>+?Sized>(name: &N) -> Result<Self, io::Error>
652 {
653 fn from_abstract_inner(name: &[u8]) -> Result<UnixSocketAddr, io::Error>
654 {
655 let mut addr = UnixSocketAddr::new_unspecified();
656
657 if UnixSocketAddr::has_abstract_addresses() == false
658 {
659 return
660 Err(
661 io::Error::new(
662 ErrorKind::AddrNotAvailable,
663 format!( "abstract unix domain socket addresses are not available on {}",
664 std::env::consts::OS)
665 )
666 );
667 }
668 else if name.len() > UnixSocketAddr::max_abstract_len()
669 {
670 return
671 Err(io::Error::new(ErrorKind::InvalidInput, "abstract name is too long"));
672 }
673 else
674 {
675 addr.addr.sun_path[1..1+name.len()].copy_from_slice(as_char(name));
676 addr.len = path_offset() + 1 + name.len() as socklen_t;
677 return Ok(addr);
678 }
679 }
680
681 return from_abstract_inner(name.as_ref());
682 }
683
684 /// Tries to convert a `std::os::unix::net::SocketAddr` into an `UnixSocketAddr`.
685 ///
686 /// This can fail (produce `None`) on Linux and Android
687 /// if the `std` `SocketAddr` represents an abstract address,
688 /// as it provides no method for viewing abstract addresses.
689 /// (other than parsing its `Debug` output, anyway.)
690 #[cfg(unix)]
691 pub
692 fn from_std(addr: net::SocketAddr) -> Option<Self>
693 {
694 return
695 if let Some(path) = addr.as_pathname()
696 {
697 Some(Self::from_path(path).expect("pathname addr cannot be converted"))
698 }
699 else if addr.is_unnamed()
700 {
701 Some(Self::new_unspecified())
702 }
703 else
704 {
705 None
706 };
707 }
708
709 /// Returns unnamed addres for empty strings, and path addresses otherwise.
710 ///
711 /// # Errors
712 ///
713 /// Returns ENAMETOOLONG if path (without the trailing `'\0'`) is too long
714 /// for `sockaddr_un.sun_path`.
715 pub
716 fn from_c_str(path: &CStr) -> Result<Self, io::Error>
717 {
718 let path = path.to_bytes();
719 let mut addr = Self::new_unspecified();
720
721 if path.is_empty()
722 {
723 return Ok(addr);
724 }
725 else if path.len() > mem::size_of_val(&addr.addr.sun_path)
726 {
727 let message = "path is too long for unix socket address";
728
729 return Err(io::Error::new(ErrorKind::InvalidInput, message));
730 }
731 else
732 {
733 addr.addr.sun_path[..path.len()].copy_from_slice(as_char(path));
734 addr.len = path_offset() + path.len() as socklen_t;
735
736 if path.len() < mem::size_of_val(&addr.addr.sun_path)
737 {
738 addr.len += 1;
739 }
740
741 return Ok(addr);
742 }
743 }
744
745 /// Checks whether the address is unnamed.
746 #[inline]
747 pub
748 fn is_unnamed(&self) -> bool
749 {
750 if Self::has_abstract_addresses()
751 {
752 return self.len <= path_offset();
753 }
754 else
755 {
756 // MacOS can apparently return non-empty addresses but with
757 // all-zeroes path for unnamed addresses.
758 return self.len <= path_offset() || self.addr.sun_path[0] as u8 == b'\0';
759 }
760 }
761
762 /// Checks whether the address is a name in the abstract namespace.
763 ///
764 /// Always returns `false` on operating systems that don't support abstract
765 /// addresses.
766 pub
767 fn is_abstract(&self) -> bool
768 {
769 if Self::has_abstract_addresses() == true
770 {
771 return self.len > path_offset() && self.addr.sun_path[0] as u8 == b'\0';
772 }
773 else
774 {
775 return false;
776 }
777 }
778
779 /// Checks whether the address is a path that begins with '/'.
780 #[cfg(unix)]
781 #[inline]
782 pub
783 fn is_absolute_path(&self) -> bool
784 {
785 self.len > path_offset() && self.addr.sun_path[0] as u8 == b'/'
786 }
787
788 /// Checks whether the address is a path that begins with '/' or "C:\".
789 #[cfg(windows)]
790 #[inline]
791 pub
792 fn is_absolute_path(&self) -> bool
793 {
794 self.len > path_offset() &&
795 (
796 self.addr.sun_path[0] as u8 == b'/' ||
797 (self.addr.sun_path[0] as u8 as char).is_ascii_alphabetic() == true
798 )
799 }
800
801 /// Checks whether the address is a path that doesn't begin with '/'.
802 #[inline]
803 pub
804 fn is_relative_path(&self) -> bool
805 {
806 self.len > path_offset()
807 && self.addr.sun_path[0] as u8 != b'\0'
808 && self.addr.sun_path[0] as u8 != b'/'
809 }
810 /// Checks whether the address is a path.
811 #[inline]
812 pub
813 fn is_path(&self) -> bool
814 {
815 self.len > path_offset() && self.addr.sun_path[0] as u8 != b'\0'
816 }
817
818 /// Returns a view of the address that can be pattern matched
819 /// to the differnt types of addresses.
820 ///
821 /// # Examples
822 ///
823 /// ```
824 /// use uds_fork::{UnixSocketAddr, AddrName};
825 /// use std::path::Path;
826 ///
827 /// assert_eq!(
828 /// UnixSocketAddr::new_unspecified().name(),
829 /// AddrName::Unnamed
830 /// );
831 /// assert_eq!(
832 /// UnixSocketAddr::from_path("/var/run/socket.sock").unwrap().name(),
833 /// AddrName::Path(Path::new("/var/run/socket.sock"))
834 /// );
835 /// if UnixSocketAddr::has_abstract_addresses() {
836 /// assert_eq!(
837 /// UnixSocketAddr::from_abstract("tcartsba").unwrap().name(),
838 /// AddrName::Abstract(b"tcartsba")
839 /// );
840 /// }
841 /// ```
842 pub
843 fn name(&self) -> AddrName<'_>
844 {
845 AddrName::from(self)
846 }
847
848 /// Returns the path of a path-based address.
849 pub
850 fn as_pathname(&self) -> Option<&Path>
851 {
852 let UnixSocketAddrRef::Path(path) = UnixSocketAddrRef::from(self)
853 else { return None };
854
855 return Some(path);
856 }
857
858 /// Returns the name of an address which is in the abstract namespace.
859 pub
860 fn as_abstract(&self) -> Option<&[u8]>
861 {
862 let UnixSocketAddrRef::Abstract(name) = UnixSocketAddrRef::from(self)
863 else {return None};
864
865 return Some(name);
866 }
867
868 /// Returns a view that can be pattern matched to the differnt types of
869 /// addresses.
870 ///
871 /// # Examples
872 ///
873 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
874 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```ignore")]
875 /// use uds_fork::{UnixDatagramExt, UnixSocketAddr, UnixSocketAddrRef};
876 /// use std::os::unix::net::UnixDatagram;
877 /// use tempfile::TempDir;
878 /// use std::path::Path;
879 ///
880 /// let dir = tempfile::tempdir().unwrap();
881 /// let path = dir.path().join("dgram.socket");
882 ///
883 /// let receiver = UnixDatagram::bind(&path).expect("create datagram socket");
884 /// assert_eq!(
885 /// receiver.local_unix_addr().unwrap().as_ref(),
886 /// UnixSocketAddrRef::Path(&path)
887 /// );
888 ///
889 /// let sender = UnixDatagram::unbound().expect("create unbound datagram socket");
890 /// sender.send_to(b"I can't hear you", &path).expect("send");
891 ///
892 /// let mut buf = [0; 100];
893 /// let (len, addr) = receiver.recv_from_unix_addr(&mut buf).unwrap();
894 /// assert_eq!(addr.as_ref(), UnixSocketAddrRef::Unnamed);
895 /// ```
896 pub
897 fn as_ref(&self) -> UnixSocketAddrRef<'_>
898 {
899 UnixSocketAddrRef::from(self)
900 }
901
902 /// Creates an address from a slice of bytes to place in `sun_path`.
903 ///
904 /// This is a low-level but simple interface for creating addresses by
905 /// other unix socket wrappers without exposing any libc types.
906 /// The meaning of a slice can vary between operating systems.
907 ///
908 /// `addr` should point to thes start of the "path" part of a socket
909 /// address, with length being the number of valid bytes of the path.
910 /// (Trailing NULs are not stripped by this function.)
911 ///
912 /// # Errors
913 ///
914 /// If the slice is longer than `sun_path`, an error of kind `Other` is
915 /// returned. No other validation of the bytes is performed.
916 ///
917 /// # Examples
918 ///
919 /// A normal path-based address
920 ///
921 /// ```
922 /// # use std::path::Path;
923 /// # use uds_fork::UnixSocketAddr;
924 /// let addr = UnixSocketAddr::from_raw_bytes(b"/tmp/a.sock\0").unwrap();
925 /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/a.sock")));
926 /// assert_eq!(addr.as_raw_bytes(), b"/tmp/a.sock\0");
927 /// ```
928 ///
929 /// On Linux:
930 ///
931 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
932 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
933 /// # use uds_fork::UnixSocketAddr;
934 /// let addr = UnixSocketAddr::from_raw_bytes(b"\0a").unwrap();
935 /// assert_eq!(addr.as_abstract(), Some(&b"a"[..]));
936 /// assert_eq!(addr.as_raw_bytes(), b"\0a");
937 /// ```
938 ///
939 /// Elsewhere:
940 ///
941 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```")]
942 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```no_run")]
943 /// # use uds_fork::UnixSocketAddr;
944 /// let addr = UnixSocketAddr::from_raw_bytes(b"\0a").unwrap();
945 /// assert!(addr.is_unnamed());
946 /// assert_eq!(addr.as_raw_bytes().len(), 2);
947 /// ```
948 ///
949 /// A portable unnamed address:
950 ///
951 /// ```
952 /// # use uds_fork::UnixSocketAddr;
953 /// let addr = UnixSocketAddr::from_raw_bytes(&[]).expect("not too long");
954 /// assert!(addr.is_unnamed());
955 /// assert!(addr.as_raw_bytes().is_empty());
956 /// ```
957 pub
958 fn from_raw_bytes(addr: &[u8]) -> Result<Self, io::Error>
959 {
960 if addr.len() <= Self::max_path_len()
961 {
962 let name = addr;
963 let mut addr = Self::default();
964 addr.addr.sun_path[..name.len()].copy_from_slice(as_char(name));
965 addr.len = path_offset() + name.len() as socklen_t;
966
967 return Ok(addr);
968 }
969 else
970 {
971 return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
972 }
973 }
974 /// Returns a low-level view of the address without using any libc types.
975 ///
976 /// The returned slice points to the start of `sun_addr` of the contained
977 /// `sockaddr_un`, and the length is the number of bytes of `sun_addr`
978 /// that were filled out by the OS. Any trailing NUL(s) will be preserved.
979 ///
980 /// # Examples
981 ///
982 /// A normal path-based address:
983 ///
984 #[cfg_attr(any(target_vendor="apple", target_os="openbsd"), doc="```")]
985 #[cfg_attr(not(any(target_vendor="apple", target_os="openbsd")), doc="```ignore")]
986 /// # use std::path::Path;
987 /// # use std::os::unix::net::UnixDatagram;
988 /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
989 /// let pathname = "/tmp/a_file";
990 /// let socket = UnixDatagram::bind(pathname).expect("create datagram socket");
991 /// # let _ = std::fs::remove_file(pathname);
992 /// let addr = socket.local_unix_addr().expect("get its address");
993 /// assert!(addr.as_raw_bytes().starts_with(pathname.as_bytes()));
994 /// assert!(addr.as_raw_bytes()[pathname.len()..].iter().all(|&b| b == b'\0' ));
995 /// assert_eq!(addr.as_pathname(), Some(Path::new(pathname)));
996 /// ```
997 ///
998 /// Abstract address:
999 ///
1000 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1001 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1002 /// # use uds_fork::UnixSocketAddr;
1003 /// let addr = UnixSocketAddr::new("@someone@").unwrap();
1004 /// assert_eq!(addr.as_raw_bytes(), b"\0someone@");
1005 /// ```
1006 ///
1007 /// Unnamed address on macOS, OpenBSD and maybe others:
1008 ///
1009 #[cfg_attr(any(target_vendor="apple", target_os="openbsd"), doc="```")]
1010 #[cfg_attr(not(any(target_vendor="apple", target_os="openbsd")), doc="```ignore")]
1011 /// # use std::os::unix::net::UnixDatagram;
1012 /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
1013 /// let socket = UnixDatagram::unbound().expect("create datagram socket");
1014 /// let addr = socket.local_unix_addr().expect("get its unbound address");
1015 /// let bytes = addr.as_raw_bytes();
1016 /// assert!(bytes.len() > 0);
1017 /// assert!(bytes.iter().all(|&b| b == b'\0' ));
1018 /// assert!(addr.is_unnamed());
1019 /// ```
1020 pub
1021 fn as_raw_bytes(&self) -> &[u8]
1022 {
1023 as_u8(&self.addr.sun_path[..(self.len-path_offset()) as usize])
1024 }
1025
1026 /// Prepares a `struct sockaddr*` and `socklen_t*` for passing to FFI
1027 /// (such as `getsockname()`, `getpeername()`, or `accept()`),
1028 /// and validate and normalize the produced address afterwards.
1029 ///
1030 /// Validation:
1031 ///
1032 /// * Check that the address family is `AF_UNIX`.
1033 /// * Check that the address wasn't truncated (the `socklen_t` is too big).
1034 ///
1035 /// Normalization:
1036 ///
1037 /// * Ensure path addresses have a trailing NUL byte if there is space.
1038 pub
1039 fn new_from_ffi<R, F>(call: F) -> Result<(R, Self), io::Error>
1040 where
1041 F: FnOnce(&mut sockaddr, &mut socklen_t) -> Result<R, io::Error>
1042 {
1043 let mut addr = Self::new_unspecified();
1044 let capacity = mem::size_of_val(&addr.addr) as socklen_t;
1045 addr.len = capacity;
1046
1047 unsafe
1048 {
1049 let (addr_ptr, addr_len_ptr) = addr.as_raw_mut_general();
1050 let ret = call(addr_ptr, addr_len_ptr)?;
1051
1052 if addr.addr.sun_family != AF_UNIX as sa_family_t
1053 {
1054 return Err(
1055 io::Error::new(
1056 ErrorKind::InvalidData,
1057 "file descriptor did not correspond to a Unix socket" // identical to std's
1058 )
1059 );
1060 }
1061
1062 if addr.is_abstract() == true
1063 {
1064 if addr.len > capacity
1065 {
1066 return Err(
1067 io::Error::new(ErrorKind::InvalidData, "abstract name was too long")
1068 );
1069 }
1070 }
1071 else if addr.is_path() == true
1072 {
1073 if addr.len > capacity+1
1074 {
1075 return Err(io::Error::new(ErrorKind::InvalidData, "path was too long"));
1076 // accept lengths one too big; assume the truncated byte was NUL
1077 }
1078 else
1079 {
1080 // normalize addr.len to include terminating NUL byte if possible
1081 // and not be greater than capacity
1082 if addr.len >= capacity
1083 {
1084 addr.len = capacity;
1085 }
1086 else if addr.addr.sun_path[(addr.len-1-path_offset()) as usize] != 0
1087 {
1088 addr.len += 1;
1089 addr.addr.sun_path[(addr.len-1-path_offset()) as usize] = 0;
1090 }
1091 }
1092 }
1093
1094 return Ok((ret, addr));
1095 }
1096 }
1097
1098 pub unsafe
1099 fn from_ref(addr: &sockaddr, len: socklen_t) -> Result<Self, io::Error>
1100 {
1101 let mut copy = Self::new_unspecified();
1102
1103 if len < path_offset()
1104 {
1105 return Err(io::Error::new(ErrorKind::InvalidInput, "address length is too short"));
1106 }
1107 else if len > mem::size_of::<sockaddr_un>() as socklen_t
1108 {
1109 return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
1110 }
1111 else if addr.sa_family != AF_UNIX as sa_family_t
1112 {
1113 return Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"));
1114 }
1115 else
1116 {
1117 let addr = addr as *const sockaddr as *const sockaddr_un;
1118 let sun_path_ptr = unsafe { (&*addr).sun_path.as_ptr() };
1119 let path_len = (len - path_offset()) as usize;
1120 let sun_path = unsafe { slice::from_raw_parts(sun_path_ptr, path_len) };
1121
1122 copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
1123 copy.len = len;
1124
1125 return Ok(copy);
1126 }
1127 }
1128
1129 /// Creates an `UnixSocketAddr` from a pointer to a generic [libc::sockaddr_storage] and
1130 /// a length.
1131 ///
1132 /// If len is == 0 or < path_offset() an `unspecified` type is returned.
1133 ///
1134 /// # Safety
1135 ///
1136 /// * `len` must not be greater than the size of the memory `addr` points to.
1137 /// * `addr` must point to valid memory if `len` is greater than zero, or be NULL.
1138 pub unsafe
1139 fn from_sockaddr_storage(addr: &sockaddr_storage, len: socklen_t) -> Result<Self, io::Error>
1140 {
1141 let mut copy = Self::new_unspecified();
1142
1143 if len < path_offset()
1144 {
1145 return Ok(copy);
1146 }
1147 else if len > mem::size_of::<sockaddr_un>() as socklen_t
1148 {
1149 return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
1150 }
1151 else if addr.ss_family != AF_UNIX as sa_family_t
1152 {
1153 return Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"));
1154 }
1155 else
1156 {
1157 let addr = addr as *const sockaddr_storage as *const sockaddr_un;
1158 let sun_path_ptr = unsafe { (&*addr).sun_path.as_ptr() };
1159 let path_len = (len - path_offset()) as usize;
1160 let sun_path = unsafe { slice::from_raw_parts(sun_path_ptr, path_len) };
1161
1162 copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
1163 copy.len = len;
1164
1165 return Ok(copy);
1166 }
1167 }
1168
1169 /// Creates an `UnixSocketAddr` from a pointer to a generic `sockaddr` and
1170 /// a length.
1171 ///
1172 /// # Safety
1173 ///
1174 /// * `len` must not be greater than the size of the memory `addr` points to.
1175 /// * `addr` must point to valid memory if `len` is greater than zero, or be NULL.
1176 pub unsafe
1177 fn from_raw(addr: *const sockaddr, len: socklen_t) -> Result<Self, io::Error>
1178 {
1179 let mut copy = Self::new_unspecified();
1180
1181 if addr.is_null() == true && len == 0
1182 {
1183 return Ok(Self::new_unspecified());
1184 }
1185 else if addr.is_null() == true
1186 {
1187 return Err(io::Error::new(ErrorKind::InvalidInput, "addr is NULL"));
1188 }
1189 else if len < path_offset()
1190 {
1191 return Err(io::Error::new(ErrorKind::InvalidInput, "address length is too short"));
1192 }
1193 else if len > mem::size_of::<sockaddr_un>() as socklen_t
1194 {
1195 return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
1196 }
1197 else if unsafe { (&*addr).sa_family } != AF_UNIX as sa_family_t
1198 {
1199 return Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"));
1200 }
1201 else
1202 {
1203 let addr = addr as *const sockaddr_un;
1204 let sun_path_ptr = unsafe { (&*addr).sun_path.as_ptr() };
1205 let path_len = (len - path_offset()) as usize;
1206 let sun_path = unsafe { slice::from_raw_parts(sun_path_ptr, path_len) };
1207
1208 copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
1209 copy.len = len;
1210
1211 return Ok(copy);
1212 }
1213 }
1214
1215 /// Creates an `UnixSocketAddr` without any validation.
1216 ///
1217 /// # Safety
1218 ///
1219 /// * `len` must be `<= size_of::<sockaddr_un>()`.
1220 /// * `addr.sun_family` should be `AF_UNIX` or strange things might happen.
1221 /// * `addr.sun_len`, if it exists, should be zero (but is probably ignored).
1222 pub unsafe
1223 fn from_raw_unchecked(addr: sockaddr_un, len: socklen_t) -> Self
1224 {
1225 Self{addr, len}
1226 }
1227
1228 /// Splits the address into its inner, raw parts.
1229 pub
1230 fn into_raw(self) -> (sockaddr_un, socklen_t)
1231 {
1232 (self.addr, self.len)
1233 }
1234
1235 /// Returns a general `sockaddr` reference to the address and its length.
1236 ///
1237 /// Useful for passing to `bind()`, `connect()`, `sendto()` or other FFI.
1238 ///
1239 /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1240 /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1241 /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.
1242 /// Therefore do not call `SUN_LEN()` on unknown addresses.
1243 /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects.
1244 pub
1245 fn as_raw_general(&self) -> (&sockaddr, socklen_t)
1246 {
1247 // SAFETY: sockaddr is a super-type of sockaddr_un.
1248 (unsafe { &*(&self.addr as *const sockaddr_un as *const sockaddr) }, self.len)
1249 }
1250
1251 /// Returns a reference to the inner `struct sockaddr_un`, and length.
1252 ///
1253 /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1254 /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1255 /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.
1256 /// Therefore do not call `SUN_LEN()` on unknown addresses.
1257 /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects.
1258 pub
1259 fn as_raw(&self) -> (&sockaddr_un, socklen_t)
1260 {
1261 (&self.addr, self.len)
1262 }
1263
1264 /// Returns mutable references to a general `struct sockaddr` and `socklen_t`.
1265 ///
1266 /// If passing to `getpeername()`, `accept()` or similar, remember to set
1267 /// the length to the capacity,
1268 /// and consider using [`new_from_ffi()`](#method.new_from_ffi) instead.
1269 ///
1270 /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1271 /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1272 /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.
1273 /// Therefore do not call `SUN_LEN()` on unknown addresses.
1274 /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects.
1275 ///
1276 /// # Safety
1277 ///
1278 /// Assigning a value > `sizeof(struct sockaddr_un)` to the `socklen_t`
1279 /// reference might lead to out-of-bounds reads later.
1280 pub unsafe
1281 fn as_raw_mut_general(&mut self) -> (&mut sockaddr, &mut socklen_t)
1282 {
1283 // SAFETY: sockaddr is a super-type of sockaddr_un.
1284 (unsafe { &mut*(&mut self.addr as *mut sockaddr_un as *mut sockaddr) }, &mut self.len)
1285 }
1286
1287 pub unsafe
1288 fn as_raw_ptr_general(&self) -> (*const sockaddr, socklen_t)
1289 {
1290 // SAFETY: sockaddr is a super-type of sockaddr_un.
1291 (&self.addr as *const sockaddr_un as *const sockaddr, self.len)
1292 }
1293
1294 /// Returns mutable references to the inner `struct sockaddr_un` and length.
1295 ///
1296 /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1297 /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1298 /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.
1299 /// Therefore do not call `SUN_LEN()` on unknown addresses.
1300 /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects
1301 ///
1302 /// # Safety
1303 ///
1304 /// Assigning a value > `sizeof(struct sockaddr_un)` to the `socklen_t`
1305 /// reference might lead to out-of-bounds reads later.
1306 pub unsafe
1307 fn as_raw_mut(&mut self) -> (&mut sockaddr_un, &mut socklen_t)
1308 {
1309 (&mut self.addr, &mut self.len)
1310 }
1311}
1312
1313impl Default for UnixSocketAddr
1314{
1315 fn default() -> Self
1316 {
1317 Self::new_unspecified()
1318 }
1319}
1320
1321impl PartialEq for UnixSocketAddr
1322{
1323 fn eq(&self, other: &Self) -> bool
1324 {
1325 self.as_ref() == other.as_ref()
1326 }
1327}
1328
1329impl Eq for UnixSocketAddr {}
1330
1331impl Hash for UnixSocketAddr
1332{
1333 fn hash<H: Hasher>(&self, hasher: &mut H)
1334 {
1335 self.as_ref().hash(hasher)
1336 }
1337}
1338
1339impl PartialEq<[u8]> for UnixSocketAddr
1340{
1341 fn eq(&self, unescaped: &[u8]) -> bool
1342 {
1343 match (self.as_ref(), unescaped.first())
1344 {
1345 #[cfg(unix)]
1346 (UnixSocketAddrRef::Path(path), Some(_)) =>
1347 path.as_os_str().as_bytes() == unescaped,
1348 #[cfg(windows)]
1349 (UnixSocketAddrRef::Path(path), Some(_)) =>
1350 path.as_os_str().as_encoded_bytes() == unescaped,
1351 (UnixSocketAddrRef::Abstract(name), Some(b'\0')) =>
1352 name == &unescaped[1..],
1353 (UnixSocketAddrRef::Unnamed, None) =>
1354 true,
1355 (_, _) =>
1356 false,
1357 }
1358 }
1359}
1360impl PartialEq<UnixSocketAddr> for [u8]
1361{
1362 fn eq(&self, addr: &UnixSocketAddr) -> bool
1363 {
1364 addr == self
1365 }
1366}
1367