diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 60851db831bf9..767ddafa0cb6b 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -86,6 +86,15 @@ impl PidFd { pub fn try_wait(&self) -> Result> { Ok(self.inner.try_wait()?.map(FromInner::from_inner)) } + + /// Obtains a duplicate of the file descriptor `targetfd` + /// + /// So we can get file descriptors from another process + /// without relying on that process to explicitly send them via + /// `SCM_RIGHTS` or similar mechanisms + pub fn getfd(&self, targetfd: RawFd) -> Result { + self.inner.getfd(targetfd) + } } impl AsInner for PidFd { diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs index 671046949aa16..a91fc89d3d45d 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -1,5 +1,5 @@ use crate::io; -use crate::os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::fd::FileDesc; use crate::sys::process::ExitStatus; use crate::sys::{AsInner, FromInner, IntoInner, cvt}; @@ -95,6 +95,13 @@ impl PidFd { .map(drop) } + #[cfg(any(test, target_env = "gnu", target_env = "musl"))] + pub fn getfd(&self, targetfd: RawFd) -> io::Result { + let fd = + cvt(unsafe { libc::syscall(libc::SYS_pidfd_getfd, self.0.as_raw_fd(), targetfd, 0) })?; + Ok(unsafe { OwnedFd::from_raw_fd(fd as RawFd) }) + } + pub fn wait(&self) -> io::Result { let r = self.waitid(libc::WEXITED)?; match r {