about summary refs log tree commit diff
path: root/library/std/src/os/unix
diff options
context:
space:
mode:
authorJohn Millikin <john@john-millikin.com>2023-10-25 17:01:21 +0900
committerJohn Millikin <john@john-millikin.com>2023-10-25 17:01:21 +0900
commit93f2f2c8ee44a8cb469fd7e656599c2b9546a1af (patch)
tree0b13df0e4eafa08383ffbe8e13f69b876748e3b3 /library/std/src/os/unix
parentd3d145ea1cae47ad392173f890577788117da3d9 (diff)
downloadrust-93f2f2c8ee44a8cb469fd7e656599c2b9546a1af.tar.gz
rust-93f2f2c8ee44a8cb469fd7e656599c2b9546a1af.zip
Convert `Unix{Datagram,Stream}::{set_}passcred()` to per-OS traits
These methods are the pre-stabilized API for obtaining peer credentials
from an `AF_UNIX` socket, part of the `unix_socket_ancillary_data` feature.

Their current behavior is to get/set one of the `SO_PASSCRED` (Linux),
`LOCAL_CREDS_PERSISTENT` (FreeBSD), or `LOCAL_CREDS` (NetBSD) socket
options. On other targets the `{set_}passcred()` methods do not exist.

There are two problems with this approach:

1. Having public methods only exist for certain targets isn't permitted
   in a stable `std` API.

2. These options have generally similar purposes, but they are non-POSIX
   and their details can differ in subtle and surprising ways (such as
   whether they continue to be set after the next call to `recvmsg()`).

Splitting into OS-specific extension traits is the preferred solution to
both problems.
Diffstat (limited to 'library/std/src/os/unix')
-rw-r--r--library/std/src/os/unix/net/datagram.rs75
-rw-r--r--library/std/src/os/unix/net/stream.rs75
-rw-r--r--library/std/src/os/unix/net/tests.rs4
3 files changed, 26 insertions, 128 deletions
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index 0b4d955294c..df698c17f6c 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -6,6 +6,7 @@ use crate::io::{IoSlice, IoSliceMut};
 use crate::net::Shutdown;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
 use crate::path::Path;
+use crate::sealed::Sealed;
 use crate::sys::cvt;
 use crate::sys::net::Socket;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -54,6 +55,10 @@ const MSG_NOSIGNAL: libc::c_int = 0x0;
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct UnixDatagram(Socket);
 
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for UnixDatagram {}
+
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixDatagram {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -802,69 +807,6 @@ impl UnixDatagram {
         self.0.set_nonblocking(nonblocking)
     }
 
-    /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
-    ///
-    /// Set the socket option `SO_PASSCRED`.
-    ///
-    /// # Examples
-    ///
-    #[cfg_attr(
-        any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd",
-        ),
-        doc = "```no_run"
-    )]
-    #[cfg_attr(
-        not(any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd"
-        )),
-        doc = "```ignore"
-    )]
-    /// #![feature(unix_socket_ancillary_data)]
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_passcred(true).expect("set_passcred function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
-        self.0.set_passcred(passcred)
-    }
-
-    /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
-    /// This value can be change by [`set_passcred`].
-    ///
-    /// Get the socket option `SO_PASSCRED`.
-    ///
-    /// [`set_passcred`]: UnixDatagram::set_passcred
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn passcred(&self) -> io::Result<bool> {
-        self.0.passcred()
-    }
-
     /// Set the id of the socket for network filtering purpose
     ///
     #[cfg_attr(
@@ -1038,3 +980,10 @@ impl From<OwnedFd> for UnixDatagram {
         unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
     }
 }
+
+impl AsInner<Socket> for UnixDatagram {
+    #[inline]
+    fn as_inner(&self) -> &Socket {
+        &self.0
+    }
+}
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index b1cd504e219..9205160455d 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -19,6 +19,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned
 ))]
 use crate::os::unix::ucred;
 use crate::path::Path;
+use crate::sealed::Sealed;
 use crate::sys::cvt;
 use crate::sys::net::Socket;
 use crate::sys_common::{AsInner, FromInner};
@@ -59,6 +60,10 @@ pub use ucred::UCred;
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct UnixStream(pub(super) Socket);
 
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for UnixStream {}
+
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixStream {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -394,69 +399,6 @@ impl UnixStream {
         self.0.set_nonblocking(nonblocking)
     }
 
-    /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
-    ///
-    /// Set the socket option `SO_PASSCRED`.
-    ///
-    /// # Examples
-    ///
-    #[cfg_attr(
-        any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd"
-        ),
-        doc = "```no_run"
-    )]
-    #[cfg_attr(
-        not(any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd"
-        )),
-        doc = "```ignore"
-    )]
-    /// #![feature(unix_socket_ancillary_data)]
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_passcred(true).expect("Couldn't set passcred");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
-        self.0.set_passcred(passcred)
-    }
-
-    /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
-    /// This value can be change by [`set_passcred`].
-    ///
-    /// Get the socket option `SO_PASSCRED`.
-    ///
-    /// [`set_passcred`]: UnixStream::set_passcred
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn passcred(&self) -> io::Result<bool> {
-        self.0.passcred()
-    }
-
     /// Set the id of the socket for network filtering purpose
     ///
     #[cfg_attr(
@@ -766,3 +708,10 @@ impl From<OwnedFd> for UnixStream {
         unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
     }
 }
+
+impl AsInner<Socket> for UnixStream {
+    #[inline]
+    fn as_inner(&self) -> &Socket {
+        &self.0
+    }
+}
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index 6a6af9efd78..e456e41b21c 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -8,10 +8,10 @@ use crate::thread;
 use crate::time::Duration;
 
 #[cfg(target_os = "android")]
-use crate::os::android::net::SocketAddrExt;
+use crate::os::android::net::{SocketAddrExt, UnixSocketExt};
 
 #[cfg(target_os = "linux")]
-use crate::os::linux::net::SocketAddrExt;
+use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
 
 macro_rules! or_panic {
     ($e:expr) => {