1
1
use super :: sa_family_t;
2
+ use cfg_if:: cfg_if;
2
3
use crate :: { Result , NixPath } ;
3
4
use crate :: errno:: Errno ;
4
5
use memoffset:: offset_of;
@@ -580,7 +581,13 @@ pub struct UnixAddr {
580
581
sun : libc:: sockaddr_un ,
581
582
/// The length of the valid part of `sun`, including the sun_family field
582
583
/// but excluding any trailing nul.
583
- sun_len : u8 ,
584
+ // On the BSDs, this field is built into sun
585
+ #[ cfg( any( target_os = "android" ,
586
+ target_os = "fuchsia" ,
587
+ target_os = "illumos" ,
588
+ target_os = "linux"
589
+ ) ) ]
590
+ sun_len : u8
584
591
}
585
592
586
593
// linux man page unix(7) says there are 3 kinds of unix socket:
@@ -611,7 +618,18 @@ impl<'a> UnixAddrKind<'a> {
611
618
return Self :: Abstract ( name) ;
612
619
}
613
620
let pathname = slice:: from_raw_parts ( sun. sun_path . as_ptr ( ) as * const u8 , path_len) ;
614
- Self :: Pathname ( Path :: new ( OsStr :: from_bytes ( pathname) ) )
621
+ if pathname. last ( ) == Some ( & 0 ) {
622
+ // A trailing NUL is not considered part of the path, and it does
623
+ // not need to be included in the addrlen passed to functions like
624
+ // bind(). However, Linux adds a trailing NUL, even if one was not
625
+ // originally present, when returning addrs from functions like
626
+ // getsockname() (the BSDs do not do that). So we need to filter
627
+ // out any trailing NUL here, so sockaddrs can round-trip through
628
+ // the kernel and still compare equal.
629
+ Self :: Pathname ( Path :: new ( OsStr :: from_bytes ( & pathname[ 0 ..pathname. len ( ) - 1 ] ) ) )
630
+ } else {
631
+ Self :: Pathname ( Path :: new ( OsStr :: from_bytes ( pathname) ) )
632
+ }
615
633
}
616
634
}
617
635
@@ -640,7 +658,6 @@ impl UnixAddr {
640
658
target_os = "ios" ,
641
659
target_os = "macos" ,
642
660
target_os = "netbsd" ,
643
- target_os = "illumos" ,
644
661
target_os = "openbsd" ) ) ]
645
662
{
646
663
ret. sun_len = sun_len;
@@ -657,7 +674,7 @@ impl UnixAddr {
657
674
/// Create a new `sockaddr_un` representing an address in the "abstract namespace".
658
675
///
659
676
/// The leading nul byte for the abstract namespace is automatically added;
660
- /// thus the input `path` is expected to be the bare name, not null -prefixed.
677
+ /// thus the input `path` is expected to be the bare name, not NUL -prefixed.
661
678
/// This is a Linux-specific extension, primarily used to allow chrooted
662
679
/// processes to communicate with processes having a different filesystem view.
663
680
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
@@ -699,23 +716,24 @@ impl UnixAddr {
699
716
/// - if this is a unix addr with a pathname, sun.sun_path is a
700
717
/// fs path, not necessarily nul-terminated.
701
718
pub ( crate ) unsafe fn from_raw_parts ( sun : libc:: sockaddr_un , sun_len : u8 ) -> UnixAddr {
702
- #[ cfg( any( target_os = "dragonfly" ,
703
- target_os = "freebsd" ,
704
- target_os = "ios" ,
705
- target_os = "macos" ,
706
- target_os = "netbsd" ,
707
- target_os = "illumos" ,
708
- target_os = "openbsd" ) ) ]
709
- {
710
- assert_eq ! ( sun_len, sun. sun_len) ;
719
+ cfg_if ! {
720
+ if #[ cfg( any( target_os = "android" ,
721
+ target_os = "fuchsia" ,
722
+ target_os = "illumos" ,
723
+ target_os = "linux"
724
+ ) ) ]
725
+ {
726
+ UnixAddr { sun, sun_len }
727
+ } else {
728
+ assert_eq!( sun_len, sun. sun_len) ;
729
+ UnixAddr { sun}
730
+ }
711
731
}
712
-
713
- UnixAddr { sun, sun_len }
714
732
}
715
733
716
734
fn kind ( & self ) -> UnixAddrKind < ' _ > {
717
735
// SAFETY: our sockaddr is always valid because of the invariant on the struct
718
- unsafe { UnixAddrKind :: get ( & self . sun , self . sun_len ) }
736
+ unsafe { UnixAddrKind :: get ( & self . sun , self . sun_len ( ) ) }
719
737
}
720
738
721
739
/// If this address represents a filesystem path, return that path.
@@ -729,7 +747,7 @@ impl UnixAddr {
729
747
/// If this address represents an abstract socket, return its name.
730
748
///
731
749
/// For abstract sockets only the bare name is returned, without the
732
- /// leading null byte. `None` is returned for unnamed or path-backed sockets.
750
+ /// leading NUL byte. `None` is returned for unnamed or path-backed sockets.
733
751
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
734
752
#[ cfg_attr( docsrs, doc( cfg( all( ) ) ) ) ]
735
753
pub fn as_abstract ( & self ) -> Option < & [ u8 ] > {
@@ -742,7 +760,7 @@ impl UnixAddr {
742
760
/// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
743
761
#[ inline]
744
762
pub fn path_len ( & self ) -> usize {
745
- self . sun_len as usize - offset_of ! ( libc:: sockaddr_un, sun_path)
763
+ self . sun_len ( ) as usize - offset_of ! ( libc:: sockaddr_un, sun_path)
746
764
}
747
765
/// Returns a pointer to the raw `sockaddr_un` struct
748
766
#[ inline]
@@ -754,6 +772,21 @@ impl UnixAddr {
754
772
pub fn as_mut_ptr ( & mut self ) -> * mut libc:: sockaddr_un {
755
773
& mut self . sun
756
774
}
775
+
776
+ fn sun_len ( & self ) -> u8 {
777
+ cfg_if ! {
778
+ if #[ cfg( any( target_os = "android" ,
779
+ target_os = "fuchsia" ,
780
+ target_os = "illumos" ,
781
+ target_os = "linux"
782
+ ) ) ]
783
+ {
784
+ self . sun_len
785
+ } else {
786
+ self . sun. sun_len
787
+ }
788
+ }
789
+ }
757
790
}
758
791
759
792
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
@@ -987,12 +1020,12 @@ impl SockAddr {
987
1020
} ,
988
1021
mem:: size_of_val ( addr) as libc:: socklen_t
989
1022
) ,
990
- SockAddr :: Unix ( UnixAddr { ref sun , sun_len } ) => (
1023
+ SockAddr :: Unix ( ref unix_addr ) => (
991
1024
// This cast is always allowed in C
992
1025
unsafe {
993
- & * ( sun as * const libc:: sockaddr_un as * const libc:: sockaddr )
1026
+ & * ( & unix_addr . sun as * const libc:: sockaddr_un as * const libc:: sockaddr )
994
1027
} ,
995
- sun_len as libc:: socklen_t
1028
+ unix_addr . sun_len ( ) as libc:: socklen_t
996
1029
) ,
997
1030
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
998
1031
SockAddr :: Netlink ( NetlinkAddr ( ref sa) ) => (
0 commit comments