diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/ffi/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/io/pipe.rs | 38 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 4 | ||||
| -rw-r--r-- | library/std/src/os/net/linux_ext/addr.rs | 6 | ||||
| -rw-r--r-- | library/std/src/os/net/linux_ext/socket.rs | 3 | ||||
| -rw-r--r-- | library/std/src/os/net/linux_ext/tcp.rs | 6 | ||||
| -rw-r--r-- | library/std/src/os/unix/process.rs | 18 | ||||
| -rw-r--r-- | library/std/src/process.rs | 14 | ||||
| -rw-r--r-- | library/std/src/sys/process/unix/common.rs | 13 | ||||
| -rw-r--r-- | library/std/src/sys/process/unix/unix.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys/process/unix/vxworks.rs | 6 | 
11 files changed, 98 insertions, 22 deletions
| diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 56791609910..024cb71b915 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -172,7 +172,7 @@ pub use core::ffi::c_void; all supported platforms", issue = "44930" )] -pub use core::ffi::{VaList, VaListImpl}; +pub use core::ffi::{VaArgSafe, VaList, VaListImpl}; #[stable(feature = "core_ffi_c", since = "1.64.0")] pub use core::ffi::{ c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index 47243806cd2..16727d44541 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -38,30 +38,44 @@ use crate::sys_common::{FromInner, IntoInner}; /// > not rely on a particular capacity: an application should be designed so that a reading process /// > consumes data as soon as it is available, so that a writing process does not remain blocked. /// -/// # Examples +/// # Example /// /// ```no_run /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { +/// use std::io::{Read, Write, pipe}; /// use std::process::Command; -/// use std::io::{pipe, Read, Write}; -/// let (ping_rx, mut ping_tx) = pipe()?; -/// let (mut pong_rx, pong_tx) = pipe()?; +/// let (ping_reader, mut ping_writer) = pipe()?; +/// let (mut pong_reader, pong_writer) = pipe()?; /// -/// // Spawn a process that echoes its input. -/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?; +/// // Spawn a child process that echoes its input. +/// let mut echo_command = Command::new("cat"); +/// echo_command.stdin(ping_reader); +/// echo_command.stdout(pong_writer); +/// let mut echo_child = echo_command.spawn()?; /// -/// ping_tx.write_all(b"hello")?; -/// // Close to unblock echo_server's reader. -/// drop(ping_tx); +/// // Send input to the child process. Note that because we're writing all the input before we +/// // read any output, this could deadlock if the child's input and output pipe buffers both +/// // filled up. Those buffers are usually at least a few KB, so "hello" is fine, but for longer +/// // inputs we'd need to read and write at the same time, e.g. using threads. +/// ping_writer.write_all(b"hello")?; +/// +/// // `cat` exits when it reads EOF from stdin, but that can't happen while any ping writer +/// // remains open. We need to drop our ping writer, or read_to_string will deadlock below. +/// drop(ping_writer); +/// +/// // The pong reader can't report EOF while any pong writer remains open. Our Command object is +/// // holding a pong writer, and again read_to_string will deadlock if we don't drop it. +/// drop(echo_command); /// /// let mut buf = String::new(); -/// // Block until echo_server's writer is closed. -/// pong_rx.read_to_string(&mut buf)?; +/// // Block until `cat` closes its stdout (a pong writer). +/// pong_reader.read_to_string(&mut buf)?; /// assert_eq!(&buf, "hello"); /// -/// echo_server.wait()?; +/// // At this point we know `cat` has exited, but we still need to wait to clean up the "zombie". +/// echo_child.wait()?; /// # Ok(()) /// # } /// ``` diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ef41b47384d..4d984617739 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -700,8 +700,8 @@ mod panicking; #[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)] mod backtrace_rs; -#[unstable(feature = "cfg_match", issue = "115585")] -pub use core::cfg_match; +#[unstable(feature = "cfg_select", issue = "115585")] +pub use core::cfg_select; #[unstable( feature = "concat_bytes", issue = "87555", diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs index aed772056e1..41009c0e284 100644 --- a/library/std/src/os/net/linux_ext/addr.rs +++ b/library/std/src/os/net/linux_ext/addr.rs @@ -23,7 +23,10 @@ pub trait SocketAddrExt: Sealed { /// /// ```no_run /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// #[cfg(target_os = "linux")] /// use std::os::linux::net::SocketAddrExt; + /// #[cfg(target_os = "android")] + /// use std::os::android::net::SocketAddrExt; /// /// fn main() -> std::io::Result<()> { /// let addr = SocketAddr::from_abstract_name(b"hidden")?; @@ -48,7 +51,10 @@ pub trait SocketAddrExt: Sealed { /// /// ```no_run /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// #[cfg(target_os = "linux")] /// use std::os::linux::net::SocketAddrExt; + /// #[cfg(target_os = "android")] + /// use std::os::android::net::SocketAddrExt; /// /// fn main() -> std::io::Result<()> { /// let name = b"hidden"; diff --git a/library/std/src/os/net/linux_ext/socket.rs b/library/std/src/os/net/linux_ext/socket.rs index 4e4168f693c..a15feb6bd9f 100644 --- a/library/std/src/os/net/linux_ext/socket.rs +++ b/library/std/src/os/net/linux_ext/socket.rs @@ -27,7 +27,10 @@ pub trait UnixSocketExt: Sealed { /// /// ```no_run /// #![feature(unix_socket_ancillary_data)] + /// #[cfg(target_os = "linux")] /// use std::os::linux::net::UnixSocketExt; + /// #[cfg(target_os = "android")] + /// use std::os::android::net::UnixSocketExt; /// use std::os::unix::net::UnixDatagram; /// /// fn main() -> std::io::Result<()> { diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs index c8d012962d4..95dffb3bc43 100644 --- a/library/std/src/os/net/linux_ext/tcp.rs +++ b/library/std/src/os/net/linux_ext/tcp.rs @@ -25,7 +25,10 @@ pub trait TcpStreamExt: Sealed { /// ```no_run /// #![feature(tcp_quickack)] /// use std::net::TcpStream; + /// #[cfg(target_os = "linux")] /// use std::os::linux::net::TcpStreamExt; + /// #[cfg(target_os = "android")] + /// use std::os::android::net::TcpStreamExt; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); @@ -43,7 +46,10 @@ pub trait TcpStreamExt: Sealed { /// ```no_run /// #![feature(tcp_quickack)] /// use std::net::TcpStream; + /// #[cfg(target_os = "linux")] /// use std::os::linux::net::TcpStreamExt; + /// #[cfg(target_os = "android")] + /// use std::os::android::net::TcpStreamExt; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 7c3fa7d6507..57ce3c5a4bf 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -8,6 +8,7 @@ use cfg_if::cfg_if; use crate::ffi::OsStr; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; +use crate::path::Path; use crate::sealed::Sealed; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::{io, process, sys}; @@ -197,6 +198,18 @@ pub trait CommandExt: Sealed { /// ``` #[stable(feature = "process_set_process_group", since = "1.64.0")] fn process_group(&mut self, pgroup: i32) -> &mut process::Command; + + /// Set the root of the child process. This calls `chroot` in the child process before executing + /// the command. + /// + /// This happens before changing to the directory specified with + /// [`process::Command::current_dir`], and that directory will be relative to the new root. + /// + /// If no directory has been specified with [`process::Command::current_dir`], this will set the + /// directory to `/`, to avoid leaving the current directory outside the chroot. (This is an + /// intentional difference from the underlying `chroot` system call.) + #[unstable(feature = "process_chroot", issue = "141298")] + fn chroot<P: AsRef<Path>>(&mut self, dir: P) -> &mut process::Command; } #[stable(feature = "rust1", since = "1.0.0")] @@ -242,6 +255,11 @@ impl CommandExt for process::Command { self.as_inner_mut().pgroup(pgroup); self } + + fn chroot<P: AsRef<Path>>(&mut self, dir: P) -> &mut process::Command { + self.as_inner_mut().chroot(dir.as_ref()); + self + } } /// Unix-specific extensions to [`process::ExitStatus`] and diff --git a/library/std/src/process.rs b/library/std/src/process.rs index df6b9a6e563..373584d0117 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1348,7 +1348,7 @@ impl Output { /// /// ``` /// #![feature(exit_status_error)] - /// # #[cfg(unix)] { + /// # #[cfg(all(unix, not(target_os = "android")))] { /// use std::process::Command; /// assert!(Command::new("false").output().unwrap().exit_ok().is_err()); /// # } @@ -1695,7 +1695,7 @@ impl From<io::Stdout> for Stdio { /// # Ok(()) /// # } /// # - /// # if cfg!(unix) { + /// # if cfg!(all(unix, not(target_os = "android"))) { /// # test().unwrap(); /// # } /// ``` @@ -1724,7 +1724,7 @@ impl From<io::Stderr> for Stdio { /// # Ok(()) /// # } /// # - /// # if cfg!(unix) { + /// # if cfg!(all(unix, not(target_os = "android"))) { /// # test().unwrap(); /// # } /// ``` @@ -1907,7 +1907,7 @@ impl crate::sealed::Sealed for ExitStatusError {} /// /// ``` /// #![feature(exit_status_error)] -/// # if cfg!(unix) { +/// # if cfg!(all(unix, not(target_os = "android"))) { /// use std::process::{Command, ExitStatusError}; /// /// fn run(cmd: &str) -> Result<(), ExitStatusError> { @@ -1950,7 +1950,7 @@ impl ExitStatusError { /// /// ``` /// #![feature(exit_status_error)] - /// # #[cfg(unix)] { + /// # #[cfg(all(unix, not(target_os = "android")))] { /// use std::process::Command; /// /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err(); @@ -1975,7 +1975,7 @@ impl ExitStatusError { /// ``` /// #![feature(exit_status_error)] /// - /// # if cfg!(unix) { + /// # if cfg!(all(unix, not(target_os = "android"))) { /// use std::num::NonZero; /// use std::process::Command; /// @@ -2532,7 +2532,7 @@ pub fn id() -> u32 { #[rustc_on_unimplemented(on( cause = "MainFunctionType", message = "`main` has invalid return type `{Self}`", - label = "`main` can only return types that implement `{Termination}`" + label = "`main` can only return types that implement `{This}`" ))] pub trait Termination { /// Is called to get the representation of the value as status code. diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs index a9c2510e6d4..e205a839005 100644 --- a/library/std/src/sys/process/unix/common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -88,6 +88,7 @@ pub struct Command { program_kind: ProgramKind, cwd: Option<CString>, + chroot: Option<CString>, uid: Option<uid_t>, gid: Option<gid_t>, saw_nul: bool, @@ -182,6 +183,7 @@ impl Command { program_kind, env: Default::default(), cwd: None, + chroot: None, uid: None, gid: None, saw_nul, @@ -206,6 +208,7 @@ impl Command { program_kind, env: Default::default(), cwd: None, + chroot: None, uid: None, gid: None, saw_nul, @@ -254,6 +257,12 @@ impl Command { pub fn pgroup(&mut self, pgroup: pid_t) { self.pgroup = Some(pgroup); } + pub fn chroot(&mut self, dir: &Path) { + self.chroot = Some(os2c(dir.as_os_str(), &mut self.saw_nul)); + if self.cwd.is_none() { + self.cwd(&OsStr::new("/")); + } + } #[cfg(target_os = "linux")] pub fn create_pidfd(&mut self, val: bool) { @@ -326,6 +335,10 @@ impl Command { pub fn get_pgroup(&self) -> Option<pid_t> { self.pgroup } + #[allow(dead_code)] + pub fn get_chroot(&self) -> Option<&CStr> { + self.chroot.as_deref() + } pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> { &mut self.closures diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 1b3bd2de265..4f595ac9a1c 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -323,6 +323,15 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } + if let Some(chroot) = self.get_chroot() { + #[cfg(not(target_os = "fuchsia"))] + cvt(libc::chroot(chroot.as_ptr()))?; + #[cfg(target_os = "fuchsia")] + return Err(io::const_error!( + io::ErrorKind::Unsupported, + "chroot not supported by fuchsia" + )); + } if let Some(cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } @@ -447,6 +456,7 @@ impl Command { || (self.env_saw_path() && !self.program_is_path()) || !self.get_closures().is_empty() || self.get_groups().is_some() + || self.get_chroot().is_some() { return Ok(None); } diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index fab3b36ebf3..f33b4a375da 100644 --- a/library/std/src/sys/process/unix/vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -27,6 +27,12 @@ impl Command { "nul byte found in provided data", )); } + if self.get_chroot().is_some() { + return Err(io::const_error!( + ErrorKind::Unsupported, + "chroot not supported by vxworks", + )); + } let (ours, theirs) = self.setup_io(default, needs_stdin)?; let mut p = Process { pid: 0, status: None }; | 
