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