std: reorganize pipe implementations
This commit is contained in:
parent
3391c01336
commit
860716faa3
39 changed files with 296 additions and 517 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use crate::io;
|
||||
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
|
||||
use crate::sys::pipe as imp;
|
||||
use crate::sys_common::{FromInner, IntoInner};
|
||||
|
||||
/// Creates an anonymous pipe.
|
||||
|
|
@ -84,39 +84,39 @@ use crate::sys_common::{FromInner, IntoInner};
|
|||
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
|
||||
pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
|
||||
imp::pipe().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
|
||||
}
|
||||
|
||||
/// Read end of an anonymous pipe.
|
||||
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct PipeReader(pub(crate) AnonPipe);
|
||||
pub struct PipeReader(pub(crate) imp::Pipe);
|
||||
|
||||
/// Write end of an anonymous pipe.
|
||||
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct PipeWriter(pub(crate) AnonPipe);
|
||||
pub struct PipeWriter(pub(crate) imp::Pipe);
|
||||
|
||||
impl FromInner<AnonPipe> for PipeReader {
|
||||
fn from_inner(inner: AnonPipe) -> Self {
|
||||
impl FromInner<imp::Pipe> for PipeReader {
|
||||
fn from_inner(inner: imp::Pipe) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for PipeReader {
|
||||
fn into_inner(self) -> AnonPipe {
|
||||
impl IntoInner<imp::Pipe> for PipeReader {
|
||||
fn into_inner(self) -> imp::Pipe {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<AnonPipe> for PipeWriter {
|
||||
fn from_inner(inner: AnonPipe) -> Self {
|
||||
impl FromInner<imp::Pipe> for PipeWriter {
|
||||
fn from_inner(inner: imp::Pipe) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for PipeWriter {
|
||||
fn into_inner(self) -> AnonPipe {
|
||||
impl IntoInner<imp::Pipe> for PipeWriter {
|
||||
fn into_inner(self) -> imp::Pipe {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ 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::process::ChildPipe;
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
use crate::{io, process, sys};
|
||||
|
||||
|
|
@ -511,7 +512,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
|
|||
/// Takes ownership of a [`ChildStdin`](crate::process::ChildStdin)'s file descriptor.
|
||||
#[inline]
|
||||
fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
|
||||
child_stdin.into_inner().into_inner().into_inner()
|
||||
child_stdin.into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -523,8 +524,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
|
|||
impl From<OwnedFd> for process::ChildStdin {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::ChildStdin {
|
||||
let fd = sys::fd::FileDesc::from_inner(fd);
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||
let pipe = ChildPipe::from_inner(fd);
|
||||
process::ChildStdin::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
@ -542,7 +542,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
|
|||
/// Takes ownership of a [`ChildStdout`](crate::process::ChildStdout)'s file descriptor.
|
||||
#[inline]
|
||||
fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
|
||||
child_stdout.into_inner().into_inner().into_inner()
|
||||
child_stdout.into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -554,8 +554,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
|
|||
impl From<OwnedFd> for process::ChildStdout {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::ChildStdout {
|
||||
let fd = sys::fd::FileDesc::from_inner(fd);
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||
let pipe = ChildPipe::from_inner(fd);
|
||||
process::ChildStdout::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
@ -573,7 +572,7 @@ impl From<crate::process::ChildStderr> for OwnedFd {
|
|||
/// Takes ownership of a [`ChildStderr`](crate::process::ChildStderr)'s file descriptor.
|
||||
#[inline]
|
||||
fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
|
||||
child_stderr.into_inner().into_inner().into_inner()
|
||||
child_stderr.into_inner().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -585,8 +584,7 @@ impl From<crate::process::ChildStderr> for OwnedFd {
|
|||
impl From<OwnedFd> for process::ChildStderr {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::ChildStderr {
|
||||
let fd = sys::fd::FileDesc::from_inner(fd);
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||
let pipe = ChildPipe::from_inner(fd);
|
||||
process::ChildStderr::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ impl IntoRawHandle for process::ChildStderr {
|
|||
impl From<OwnedHandle> for process::ChildStdin {
|
||||
fn from(handle: OwnedHandle) -> process::ChildStdin {
|
||||
let handle = sys::handle::Handle::from_inner(handle);
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(handle);
|
||||
let pipe = sys::process::ChildPipe::from_inner(handle);
|
||||
process::ChildStdin::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ impl From<OwnedHandle> for process::ChildStdin {
|
|||
impl From<OwnedHandle> for process::ChildStdout {
|
||||
fn from(handle: OwnedHandle) -> process::ChildStdout {
|
||||
let handle = sys::handle::Handle::from_inner(handle);
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(handle);
|
||||
let pipe = sys::process::ChildPipe::from_inner(handle);
|
||||
process::ChildStdout::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ impl From<OwnedHandle> for process::ChildStdout {
|
|||
impl From<OwnedHandle> for process::ChildStderr {
|
||||
fn from(handle: OwnedHandle) -> process::ChildStderr {
|
||||
let handle = sys::handle::Handle::from_inner(handle);
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(handle);
|
||||
let pipe = sys::process::ChildPipe::from_inner(handle);
|
||||
process::ChildStderr::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,7 +166,6 @@ use crate::io::prelude::*;
|
|||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::num::NonZero;
|
||||
use crate::path::Path;
|
||||
use crate::sys::pipe::{AnonPipe, read2};
|
||||
use crate::sys::process as imp;
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
use crate::{fmt, fs, str};
|
||||
|
|
@ -300,9 +299,9 @@ impl fmt::Debug for Child {
|
|||
///
|
||||
/// Used to pass pipe handles between this module and [`imp`].
|
||||
pub(crate) struct StdioPipes {
|
||||
pub stdin: Option<AnonPipe>,
|
||||
pub stdout: Option<AnonPipe>,
|
||||
pub stderr: Option<AnonPipe>,
|
||||
pub stdin: Option<imp::ChildPipe>,
|
||||
pub stdout: Option<imp::ChildPipe>,
|
||||
pub stderr: Option<imp::ChildPipe>,
|
||||
}
|
||||
|
||||
/// A handle to a child process's standard input (stdin).
|
||||
|
|
@ -317,7 +316,7 @@ pub(crate) struct StdioPipes {
|
|||
/// [dropped]: Drop
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ChildStdin {
|
||||
inner: AnonPipe,
|
||||
inner: imp::ChildPipe,
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `ChildStdin` also has `impl`s for
|
||||
|
|
@ -366,21 +365,21 @@ impl Write for &ChildStdin {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsInner<AnonPipe> for ChildStdin {
|
||||
impl AsInner<imp::ChildPipe> for ChildStdin {
|
||||
#[inline]
|
||||
fn as_inner(&self) -> &AnonPipe {
|
||||
fn as_inner(&self) -> &imp::ChildPipe {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for ChildStdin {
|
||||
fn into_inner(self) -> AnonPipe {
|
||||
impl IntoInner<imp::ChildPipe> for ChildStdin {
|
||||
fn into_inner(self) -> imp::ChildPipe {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<AnonPipe> for ChildStdin {
|
||||
fn from_inner(pipe: AnonPipe) -> ChildStdin {
|
||||
impl FromInner<imp::ChildPipe> for ChildStdin {
|
||||
fn from_inner(pipe: imp::ChildPipe) -> ChildStdin {
|
||||
ChildStdin { inner: pipe }
|
||||
}
|
||||
}
|
||||
|
|
@ -403,7 +402,7 @@ impl fmt::Debug for ChildStdin {
|
|||
/// [dropped]: Drop
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ChildStdout {
|
||||
inner: AnonPipe,
|
||||
inner: imp::ChildPipe,
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `ChildStdout` also has `impl`s for
|
||||
|
|
@ -436,21 +435,21 @@ impl Read for ChildStdout {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsInner<AnonPipe> for ChildStdout {
|
||||
impl AsInner<imp::ChildPipe> for ChildStdout {
|
||||
#[inline]
|
||||
fn as_inner(&self) -> &AnonPipe {
|
||||
fn as_inner(&self) -> &imp::ChildPipe {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for ChildStdout {
|
||||
fn into_inner(self) -> AnonPipe {
|
||||
impl IntoInner<imp::ChildPipe> for ChildStdout {
|
||||
fn into_inner(self) -> imp::ChildPipe {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<AnonPipe> for ChildStdout {
|
||||
fn from_inner(pipe: AnonPipe) -> ChildStdout {
|
||||
impl FromInner<imp::ChildPipe> for ChildStdout {
|
||||
fn from_inner(pipe: imp::ChildPipe) -> ChildStdout {
|
||||
ChildStdout { inner: pipe }
|
||||
}
|
||||
}
|
||||
|
|
@ -473,7 +472,7 @@ impl fmt::Debug for ChildStdout {
|
|||
/// [dropped]: Drop
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ChildStderr {
|
||||
inner: AnonPipe,
|
||||
inner: imp::ChildPipe,
|
||||
}
|
||||
|
||||
// In addition to the `impl`s here, `ChildStderr` also has `impl`s for
|
||||
|
|
@ -506,21 +505,21 @@ impl Read for ChildStderr {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsInner<AnonPipe> for ChildStderr {
|
||||
impl AsInner<imp::ChildPipe> for ChildStderr {
|
||||
#[inline]
|
||||
fn as_inner(&self) -> &AnonPipe {
|
||||
fn as_inner(&self) -> &imp::ChildPipe {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<AnonPipe> for ChildStderr {
|
||||
fn into_inner(self) -> AnonPipe {
|
||||
impl IntoInner<imp::ChildPipe> for ChildStderr {
|
||||
fn into_inner(self) -> imp::ChildPipe {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<AnonPipe> for ChildStderr {
|
||||
fn from_inner(pipe: AnonPipe) -> ChildStderr {
|
||||
impl FromInner<imp::ChildPipe> for ChildStderr {
|
||||
fn from_inner(pipe: imp::ChildPipe) -> ChildStderr {
|
||||
ChildStderr { inner: pipe }
|
||||
}
|
||||
}
|
||||
|
|
@ -2380,7 +2379,7 @@ impl Child {
|
|||
res.unwrap();
|
||||
}
|
||||
(Some(out), Some(err)) => {
|
||||
let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
|
||||
let res = imp::read_output(out.inner, &mut stdout, err.inner, &mut stderr);
|
||||
res.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
use crate::io;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::pipe::anon_pipe;
|
||||
use crate::sys_common::IntoInner;
|
||||
|
||||
pub type AnonPipe = FileDesc;
|
||||
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
use crate::io;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::pipe::anon_pipe;
|
||||
use crate::sys_common::IntoInner;
|
||||
|
||||
pub type AnonPipe = FileDesc;
|
||||
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
use crate::io;
|
||||
pub use crate::sys::pipe::AnonPipe;
|
||||
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ mod pal;
|
|||
mod alloc;
|
||||
mod personality;
|
||||
|
||||
pub mod anonymous_pipe;
|
||||
pub mod args;
|
||||
pub mod backtrace;
|
||||
pub mod cmath;
|
||||
|
|
@ -26,6 +25,7 @@ pub mod io;
|
|||
pub mod net;
|
||||
pub mod os_str;
|
||||
pub mod path;
|
||||
pub mod pipe;
|
||||
pub mod platform_version;
|
||||
pub mod process;
|
||||
pub mod random;
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ use crate::sys::env;
|
|||
|
||||
pub mod futex;
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub mod time;
|
||||
|
||||
pub fn unsupported<T>() -> crate::io::Result<T> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod os;
|
||||
pub mod pipe;
|
||||
pub mod time;
|
||||
|
||||
pub use moto_rt::futex;
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::map_motor_error;
|
||||
use crate::sys_common::{FromInner, IntoInner};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnonPipe(FileDesc);
|
||||
|
||||
impl From<moto_rt::RtFd> for AnonPipe {
|
||||
fn from(rt_fd: moto_rt::RtFd) -> AnonPipe {
|
||||
unsafe { AnonPipe::from_raw_fd(rt_fd) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
moto_rt::fs::read(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
crate::io::default_read_buf(|buf| self.read(buf), cursor)
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_read_vectored(|b| self.read(b), bufs)
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
moto_rt::fs::write(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_write_vectored(|b| self.write(b), bufs)
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
let mut temp_vec = Vec::new();
|
||||
let mut size = 0_usize;
|
||||
loop {
|
||||
temp_vec.resize(256, 0_u8);
|
||||
match self.read(&mut temp_vec[..]) {
|
||||
Ok(sz) => {
|
||||
if sz == 0 {
|
||||
return Ok(size);
|
||||
}
|
||||
size += sz;
|
||||
temp_vec.truncate(sz);
|
||||
buf.append(&mut temp_vec);
|
||||
}
|
||||
Err(err) => {
|
||||
if size != 0 {
|
||||
return Ok(size);
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for AnonPipe {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for AnonPipe {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
let desc = FileDesc::from_raw_fd(fd);
|
||||
Self(desc)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for AnonPipe {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for AnonPipe {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<OwnedFd> for AnonPipe {
|
||||
fn into_inner(self) -> OwnedFd {
|
||||
self.0.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<FileDesc> for AnonPipe {
|
||||
fn into_inner(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<OwnedFd> for AnonPipe {
|
||||
fn from_inner(owned_fd: OwnedFd) -> Self {
|
||||
Self(FileDesc::from_inner(owned_fd))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read2(_p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
Err(io::Error::from_raw_os_error(moto_rt::E_NOT_IMPLEMENTED.into()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
|
|
@ -11,8 +11,6 @@ use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
|
|||
pub mod abi;
|
||||
mod libunwind_integration;
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub mod thread_parking;
|
||||
pub mod time;
|
||||
pub mod waitqueue;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ pub mod itron {
|
|||
// `crate::sys::error`
|
||||
pub(crate) mod error;
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub use self::itron::thread_parking;
|
||||
pub mod time;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[path = "../unix/time.rs"]
|
||||
pub mod time;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
mod common;
|
||||
#[path = "../unsupported/os.rs"]
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
#[path = "../unsupported/time.rs"]
|
||||
pub mod time;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
pub mod helpers;
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub mod time;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ pub mod futex;
|
|||
#[cfg(target_os = "linux")]
|
||||
pub mod linux;
|
||||
pub mod os;
|
||||
pub mod pipe;
|
||||
pub mod stack_overflow;
|
||||
pub mod sync;
|
||||
pub mod thread_parking;
|
||||
|
|
|
|||
|
|
@ -1,184 +0,0 @@
|
|||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::mem;
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::{cvt, cvt_r};
|
||||
use crate::sys_common::{FromInner, IntoInner};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Anonymous pipes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnonPipe(FileDesc);
|
||||
|
||||
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
let mut fds = [0; 2];
|
||||
|
||||
// The only known way right now to create atomically set the CLOEXEC flag is
|
||||
// to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9
|
||||
// and musl 0.9.3, and some other targets also have it.
|
||||
cfg_select! {
|
||||
any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "cygwin",
|
||||
target_os = "redox"
|
||||
) => {
|
||||
unsafe {
|
||||
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?;
|
||||
Ok((AnonPipe(FileDesc::from_raw_fd(fds[0])), AnonPipe(FileDesc::from_raw_fd(fds[1]))))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unsafe {
|
||||
cvt(libc::pipe(fds.as_mut_ptr()))?;
|
||||
|
||||
let fd0 = FileDesc::from_raw_fd(fds[0]);
|
||||
let fd1 = FileDesc::from_raw_fd(fds[1]);
|
||||
fd0.set_cloexec()?;
|
||||
fd1.set_cloexec()?;
|
||||
Ok((AnonPipe(fd0), AnonPipe(fd1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
#[allow(dead_code)]
|
||||
// FIXME: This function seems legitimately unused.
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.0.duplicate().map(Self)
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0.read_buf(buf)
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
|
||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
// FIXME: This function seems legitimately unused.
|
||||
pub fn as_file_desc(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<FileDesc> for AnonPipe {
|
||||
fn into_inner(self) -> FileDesc {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
// Set both pipes into nonblocking mode as we're gonna be reading from both
|
||||
// in the `select` loop below, and we wouldn't want one to block the other!
|
||||
let p1 = p1.into_inner();
|
||||
let p2 = p2.into_inner();
|
||||
p1.set_nonblocking(true)?;
|
||||
p2.set_nonblocking(true)?;
|
||||
|
||||
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
|
||||
fds[0].fd = p1.as_raw_fd();
|
||||
fds[0].events = libc::POLLIN;
|
||||
fds[1].fd = p2.as_raw_fd();
|
||||
fds[1].events = libc::POLLIN;
|
||||
loop {
|
||||
// wait for either pipe to become readable using `poll`
|
||||
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
|
||||
|
||||
if fds[0].revents != 0 && read(&p1, v1)? {
|
||||
p2.set_nonblocking(false)?;
|
||||
return p2.read_to_end(v2).map(drop);
|
||||
}
|
||||
if fds[1].revents != 0 && read(&p2, v2)? {
|
||||
p1.set_nonblocking(false)?;
|
||||
return p1.read_to_end(v1).map(drop);
|
||||
}
|
||||
}
|
||||
|
||||
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
|
||||
// EAGAIN. If we hit EOF, then this will happen because the underlying
|
||||
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
|
||||
// this case we flip the other fd back into blocking mode and read
|
||||
// whatever's leftover on that file descriptor.
|
||||
fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
|
||||
match fd.read_to_end(dst) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => {
|
||||
if e.raw_os_error() == Some(libc::EWOULDBLOCK)
|
||||
|| e.raw_os_error() == Some(libc::EAGAIN)
|
||||
{
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for AnonPipe {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for AnonPipe {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for AnonPipe {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for AnonPipe {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FromRawFd::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<FileDesc> for AnonPipe {
|
||||
fn from_inner(fd: FileDesc) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod os;
|
||||
pub mod pipe;
|
||||
pub mod time;
|
||||
|
||||
mod common;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@
|
|||
pub mod futex;
|
||||
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub mod stack_overflow;
|
||||
#[path = "../unix/time.rs"]
|
||||
pub mod time;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#[path = "../unsupported/os.rs"]
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
#[path = "../unsupported/time.rs"]
|
||||
pub mod time;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ pub mod c;
|
|||
pub mod futex;
|
||||
pub mod handle;
|
||||
pub mod os;
|
||||
pub mod pipe;
|
||||
pub mod time;
|
||||
cfg_select! {
|
||||
// We don't care about printing nice error messages for panic=immediate-abort
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
use crate::os::xous::ffi::exit;
|
||||
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
pub mod time;
|
||||
|
||||
#[path = "../unsupported/common.rs"]
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ pub const WORD_SIZE: usize = size_of::<u32>();
|
|||
|
||||
pub mod abi;
|
||||
pub mod os;
|
||||
#[path = "../unsupported/pipe.rs"]
|
||||
pub mod pipe;
|
||||
#[path = "../unsupported/time.rs"]
|
||||
pub mod time;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,18 +3,18 @@
|
|||
cfg_select! {
|
||||
unix => {
|
||||
mod unix;
|
||||
pub use unix::{AnonPipe, pipe};
|
||||
pub use unix::{Pipe, pipe};
|
||||
}
|
||||
windows => {
|
||||
mod windows;
|
||||
pub use windows::{AnonPipe, pipe};
|
||||
pub use windows::{Pipe, pipe};
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::{AnonPipe, pipe};
|
||||
pub use motor::{Pipe, pipe};
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::{AnonPipe, pipe};
|
||||
pub use unsupported::{Pipe, pipe};
|
||||
}
|
||||
}
|
||||
9
library/std/src/sys/pipe/motor.rs
Normal file
9
library/std/src/sys/pipe/motor.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::io;
|
||||
use crate::sys::fd::FileDesc;
|
||||
|
||||
pub type Pipe = FileDesc;
|
||||
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
44
library/std/src/sys/pipe/unix.rs
Normal file
44
library/std/src/sys/pipe/unix.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use crate::io;
|
||||
use crate::os::fd::FromRawFd;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::pal::cvt;
|
||||
|
||||
pub type Pipe = FileDesc;
|
||||
|
||||
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
|
||||
let mut fds = [0; 2];
|
||||
|
||||
// The only known way right now to create atomically set the CLOEXEC flag is
|
||||
// to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9
|
||||
// and musl 0.9.3, and some other targets also have it.
|
||||
cfg_select! {
|
||||
any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "cygwin",
|
||||
target_os = "redox"
|
||||
) => {
|
||||
unsafe {
|
||||
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?;
|
||||
Ok((Pipe::from_raw_fd(fds[0]), Pipe::from_raw_fd(fds[1])))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unsafe {
|
||||
cvt(libc::pipe(fds.as_mut_ptr()))?;
|
||||
|
||||
let fd0 = Pipe::from_raw_fd(fds[0]);
|
||||
let fd1 = Pipe::from_raw_fd(fds[1]);
|
||||
fd0.set_cloexec()?;
|
||||
fd1.set_cloexec()?;
|
||||
Ok((fd0, fd1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
use crate::fmt;
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::sys_common::{FromInner, IntoInner};
|
||||
|
||||
pub struct AnonPipe(!);
|
||||
pub struct Pipe(!);
|
||||
|
||||
impl fmt::Debug for AnonPipe {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
impl Pipe {
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.0
|
||||
}
|
||||
|
|
@ -52,56 +50,52 @@ impl AnonPipe {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
match p1.0 {}
|
||||
}
|
||||
|
||||
impl FromInner<!> for AnonPipe {
|
||||
fn from_inner(inner: !) -> Self {
|
||||
inner
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<!> for AnonPipe {
|
||||
fn into_inner(self) -> ! {
|
||||
impl fmt::Debug for Pipe {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
mod unix_traits {
|
||||
use super::AnonPipe;
|
||||
use super::Pipe;
|
||||
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||
use crate::sys_common::FromInner;
|
||||
use crate::sys_common::{FromInner, IntoInner};
|
||||
|
||||
impl AsRawFd for AnonPipe {
|
||||
impl AsRawFd for Pipe {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for AnonPipe {
|
||||
impl AsFd for Pipe {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for AnonPipe {
|
||||
impl IntoRawFd for Pipe {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for AnonPipe {
|
||||
impl FromRawFd for Pipe {
|
||||
unsafe fn from_raw_fd(_: RawFd) -> Self {
|
||||
panic!("creating pipe on this platform is unsupported!")
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<OwnedFd> for AnonPipe {
|
||||
impl FromInner<OwnedFd> for Pipe {
|
||||
fn from_inner(_: OwnedFd) -> Self {
|
||||
panic!("creating pipe on this platform is unsupported!")
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<OwnedFd> for Pipe {
|
||||
fn into_inner(self) -> OwnedFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,9 @@ use crate::sys::c;
|
|||
use crate::sys::handle::Handle;
|
||||
use crate::{io, ptr};
|
||||
|
||||
pub type AnonPipe = Handle;
|
||||
pub type Pipe = Handle;
|
||||
|
||||
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
|
||||
let mut read_pipe = c::INVALID_HANDLE_VALUE;
|
||||
let mut write_pipe = c::INVALID_HANDLE_VALUE;
|
||||
|
||||
|
|
@ -28,7 +28,8 @@ mod env;
|
|||
|
||||
pub use env::CommandEnvs;
|
||||
pub use imp::{
|
||||
Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio,
|
||||
ChildPipe, Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio,
|
||||
read_output,
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
|
|
@ -45,8 +46,6 @@ pub use imp::{
|
|||
target_os = "motor"
|
||||
))]
|
||||
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
use crate::sys::pipe::read2;
|
||||
|
||||
let (mut process, mut pipes) = cmd.spawn(Stdio::MakePipe, false)?;
|
||||
|
||||
drop(pipes.stdin.take());
|
||||
|
|
@ -62,7 +61,7 @@ pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<
|
|||
res.unwrap();
|
||||
}
|
||||
(Some(out), Some(err)) => {
|
||||
let res = read2(out, &mut stdout, err, &mut stderr);
|
||||
let res = read_output(out, &mut stdout, err, &mut stderr);
|
||||
res.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use crate::path::Path;
|
|||
use crate::process::StdioPipes;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::map_motor_error;
|
||||
use crate::sys::pipe::AnonPipe;
|
||||
use crate::sys_common::{AsInner, FromInner};
|
||||
use crate::{fmt, io};
|
||||
|
||||
|
|
@ -150,20 +149,26 @@ impl Command {
|
|||
Ok((
|
||||
Process { handle },
|
||||
StdioPipes {
|
||||
stdin: if stdin >= 0 { Some(stdin.into()) } else { None },
|
||||
stdout: if stdout >= 0 { Some(stdout.into()) } else { None },
|
||||
stderr: if stderr >= 0 { Some(stderr.into()) } else { None },
|
||||
stdin: if stdin >= 0 {
|
||||
Some(unsafe { ChildPipe::from_raw_fd(stdin) })
|
||||
} else {
|
||||
None
|
||||
},
|
||||
stdout: if stdout >= 0 {
|
||||
Some(unsafe { ChildPipe::from_raw_fd(stdout) })
|
||||
} else {
|
||||
None
|
||||
},
|
||||
stderr: if stderr >= 0 {
|
||||
Some(unsafe { ChildPipe::from_raw_fd(stderr) })
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
unsafe { Stdio::Fd(crate::sys::fd::FileDesc::from_raw_fd(pipe.into_raw_fd())) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::sys::fd::FileDesc> for Stdio {
|
||||
fn from(fd: crate::sys::fd::FileDesc) -> Stdio {
|
||||
Stdio::Fd(fd)
|
||||
|
|
@ -315,3 +320,14 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
|
|||
f.debug_list().entries(self.iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub type ChildPipe = crate::sys::pipe::Pipe;
|
||||
|
||||
pub fn read_output(
|
||||
_out: ChildPipe,
|
||||
_stdout: &mut Vec<u8>,
|
||||
_err: ChildPipe,
|
||||
_stderr: &mut Vec<u8>,
|
||||
) -> io::Result<()> {
|
||||
Err(io::Error::from_raw_os_error(moto_rt::E_NOT_IMPLEMENTED.into()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use crate::process::StdioPipes;
|
|||
use crate::sys::fs::File;
|
||||
use crate::sys::pal::helpers;
|
||||
use crate::sys::pal::os::error_string;
|
||||
use crate::sys::pipe::AnonPipe;
|
||||
use crate::sys::unsupported;
|
||||
use crate::{fmt, io};
|
||||
|
||||
|
|
@ -204,8 +203,8 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>
|
|||
Ok((ExitStatus(stat), stdout, stderr))
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
impl From<ChildPipe> for Stdio {
|
||||
fn from(pipe: ChildPipe) -> Stdio {
|
||||
pipe.diverge()
|
||||
}
|
||||
}
|
||||
|
|
@ -356,6 +355,17 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub type ChildPipe = crate::sys::pipe::Pipe;
|
||||
|
||||
pub fn read_output(
|
||||
out: ChildPipe,
|
||||
_stdout: &mut Vec<u8>,
|
||||
_err: ChildPipe,
|
||||
_stderr: &mut Vec<u8>,
|
||||
) -> io::Result<()> {
|
||||
match out.diverge() {}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod uefi_command_internal {
|
||||
use r_efi::protocols::{loaded_image, simple_text_input, simple_text_output};
|
||||
|
|
|
|||
|
|
@ -10,14 +10,15 @@ use crate::ffi::{CStr, CString, OsStr, OsString};
|
|||
use crate::os::unix::prelude::*;
|
||||
use crate::path::Path;
|
||||
use crate::process::StdioPipes;
|
||||
use crate::sys::cvt_r;
|
||||
use crate::sys::fd::FileDesc;
|
||||
use crate::sys::fs::File;
|
||||
#[cfg(not(target_os = "fuchsia"))]
|
||||
use crate::sys::fs::OpenOptions;
|
||||
use crate::sys::pipe::{self, AnonPipe};
|
||||
use crate::sys::pipe::pipe;
|
||||
use crate::sys::process::env::{CommandEnv, CommandEnvs};
|
||||
use crate::sys_common::{FromInner, IntoInner};
|
||||
use crate::{fmt, io};
|
||||
use crate::{fmt, io, mem};
|
||||
|
||||
mod cstring_array;
|
||||
|
||||
|
|
@ -393,7 +394,7 @@ fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStr
|
|||
}
|
||||
|
||||
impl Stdio {
|
||||
pub fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option<AnonPipe>)> {
|
||||
pub fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option<ChildPipe>)> {
|
||||
match *self {
|
||||
Stdio::Inherit => Ok((ChildStdio::Inherit, None)),
|
||||
|
||||
|
|
@ -418,9 +419,9 @@ impl Stdio {
|
|||
}
|
||||
|
||||
Stdio::MakePipe => {
|
||||
let (reader, writer) = pipe::anon_pipe()?;
|
||||
let (reader, writer) = pipe()?;
|
||||
let (ours, theirs) = if readable { (writer, reader) } else { (reader, writer) };
|
||||
Ok((ChildStdio::Owned(theirs.into_inner()), Some(ours)))
|
||||
Ok((ChildStdio::Owned(theirs), Some(ours)))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "fuchsia"))]
|
||||
|
|
@ -438,12 +439,6 @@ impl Stdio {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
Stdio::Fd(pipe.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FileDesc> for Stdio {
|
||||
fn from(fd: FileDesc) -> Stdio {
|
||||
Stdio::Fd(fd)
|
||||
|
|
@ -632,3 +627,56 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
|
|||
f.debug_list().entries(self.iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub type ChildPipe = crate::sys::pipe::Pipe;
|
||||
|
||||
pub fn read_output(
|
||||
out: ChildPipe,
|
||||
stdout: &mut Vec<u8>,
|
||||
err: ChildPipe,
|
||||
stderr: &mut Vec<u8>,
|
||||
) -> io::Result<()> {
|
||||
// Set both pipes into nonblocking mode as we're gonna be reading from both
|
||||
// in the `select` loop below, and we wouldn't want one to block the other!
|
||||
out.set_nonblocking(true)?;
|
||||
err.set_nonblocking(true)?;
|
||||
|
||||
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
|
||||
fds[0].fd = out.as_raw_fd();
|
||||
fds[0].events = libc::POLLIN;
|
||||
fds[1].fd = err.as_raw_fd();
|
||||
fds[1].events = libc::POLLIN;
|
||||
loop {
|
||||
// wait for either pipe to become readable using `poll`
|
||||
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
|
||||
|
||||
if fds[0].revents != 0 && read(&out, stdout)? {
|
||||
err.set_nonblocking(false)?;
|
||||
return err.read_to_end(stderr).map(drop);
|
||||
}
|
||||
if fds[1].revents != 0 && read(&err, stderr)? {
|
||||
out.set_nonblocking(false)?;
|
||||
return out.read_to_end(stdout).map(drop);
|
||||
}
|
||||
}
|
||||
|
||||
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
|
||||
// EAGAIN. If we hit EOF, then this will happen because the underlying
|
||||
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
|
||||
// this case we flip the other fd back into blocking mode and read
|
||||
// whatever's leftover on that file descriptor.
|
||||
fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
|
||||
match fd.read_to_end(dst) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => {
|
||||
if e.raw_os_error() == Some(libc::EWOULDBLOCK)
|
||||
|| e.raw_os_error() == Some(libc::EAGAIN)
|
||||
{
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ cfg_select! {
|
|||
|
||||
pub use imp::{ExitStatus, ExitStatusError, Process};
|
||||
|
||||
pub use self::common::{Command, CommandArgs, ExitCode, Stdio};
|
||||
pub use self::common::{ChildPipe, Command, CommandArgs, ExitCode, Stdio, read_output};
|
||||
pub use crate::ffi::OsString as EnvKey;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ impl Command {
|
|||
let (input, output) = sys::net::Socket::new_pair(libc::AF_UNIX, libc::SOCK_SEQPACKET)?;
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let (input, output) = sys::pipe::anon_pipe()?;
|
||||
let (input, output) = sys::pipe::pipe()?;
|
||||
|
||||
// Whatever happens after the fork is almost for sure going to touch or
|
||||
// look at the environment in one way or another (PATH in `execvp` or
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use crate::num::NonZero;
|
|||
use crate::path::Path;
|
||||
use crate::process::StdioPipes;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::pipe::AnonPipe;
|
||||
use crate::sys::unsupported;
|
||||
use crate::{fmt, io};
|
||||
|
||||
|
|
@ -107,8 +106,8 @@ pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)>
|
|||
unsupported()
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
impl From<ChildPipe> for Stdio {
|
||||
fn from(pipe: ChildPipe) -> Stdio {
|
||||
pipe.diverge()
|
||||
}
|
||||
}
|
||||
|
|
@ -317,3 +316,14 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
|
|||
f.debug_list().entries(self.iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub type ChildPipe = crate::sys::pipe::Pipe;
|
||||
|
||||
pub fn read_output(
|
||||
out: ChildPipe,
|
||||
_stdout: &mut Vec<u8>,
|
||||
_err: ChildPipe,
|
||||
_stderr: &mut Vec<u8>,
|
||||
) -> io::Result<()> {
|
||||
match out.diverge() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,14 @@ use crate::sys::fs::{File, OpenOptions};
|
|||
use crate::sys::handle::Handle;
|
||||
use crate::sys::pal::api::{self, WinError, utf16};
|
||||
use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
|
||||
use crate::sys::pipe::{self, AnonPipe};
|
||||
use crate::sys::{cvt, path, stdio};
|
||||
use crate::sys_common::IntoInner;
|
||||
use crate::{cmp, env, fmt, ptr};
|
||||
|
||||
mod child_pipe;
|
||||
|
||||
pub use self::child_pipe::{ChildPipe, read_output};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -167,7 +170,7 @@ pub enum Stdio {
|
|||
InheritSpecific { from_stdio_id: u32 },
|
||||
Null,
|
||||
MakePipe,
|
||||
Pipe(AnonPipe),
|
||||
Pipe(ChildPipe),
|
||||
Handle(Handle),
|
||||
}
|
||||
|
||||
|
|
@ -596,7 +599,7 @@ fn program_exists(path: &Path) -> Option<Vec<u16>> {
|
|||
}
|
||||
|
||||
impl Stdio {
|
||||
fn to_handle(&self, stdio_id: u32, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> {
|
||||
fn to_handle(&self, stdio_id: u32, pipe: &mut Option<ChildPipe>) -> io::Result<Handle> {
|
||||
let use_stdio_id = |stdio_id| match stdio::get_handle(stdio_id) {
|
||||
Ok(io) => unsafe {
|
||||
let io = Handle::from_raw_handle(io);
|
||||
|
|
@ -613,14 +616,15 @@ impl Stdio {
|
|||
|
||||
Stdio::MakePipe => {
|
||||
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
|
||||
let pipes = pipe::anon_pipe(ours_readable, true)?;
|
||||
let pipes = child_pipe::child_pipe(ours_readable, true)?;
|
||||
*pipe = Some(pipes.ours);
|
||||
Ok(pipes.theirs.into_handle())
|
||||
}
|
||||
|
||||
Stdio::Pipe(ref source) => {
|
||||
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
|
||||
pipe::spawn_pipe_relay(source, ours_readable, true).map(AnonPipe::into_handle)
|
||||
child_pipe::spawn_pipe_relay(source, ours_readable, true)
|
||||
.map(ChildPipe::into_handle)
|
||||
}
|
||||
|
||||
Stdio::Handle(ref handle) => handle.duplicate(0, true, c::DUPLICATE_SAME_ACCESS),
|
||||
|
|
@ -639,8 +643,8 @@ impl Stdio {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
impl From<ChildPipe> for Stdio {
|
||||
fn from(pipe: ChildPipe) -> Stdio {
|
||||
Stdio::Pipe(pipe)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,39 +6,37 @@ use crate::sys::{api, c};
|
|||
use crate::sys_common::{FromInner, IntoInner};
|
||||
use crate::{mem, ptr};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Anonymous pipes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct AnonPipe {
|
||||
pub struct ChildPipe {
|
||||
inner: Handle,
|
||||
}
|
||||
|
||||
impl IntoInner<Handle> for AnonPipe {
|
||||
impl IntoInner<Handle> for ChildPipe {
|
||||
fn into_inner(self) -> Handle {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<Handle> for AnonPipe {
|
||||
fn from_inner(inner: Handle) -> AnonPipe {
|
||||
impl FromInner<Handle> for ChildPipe {
|
||||
fn from_inner(inner: Handle) -> ChildPipe {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pipes {
|
||||
pub ours: AnonPipe,
|
||||
pub theirs: AnonPipe,
|
||||
pub(super) struct Pipes {
|
||||
pub ours: ChildPipe,
|
||||
pub theirs: ChildPipe,
|
||||
}
|
||||
|
||||
/// Although this looks similar to `anon_pipe` in the Unix module it's actually
|
||||
/// subtly different. Here we'll return two pipes in the `Pipes` return value,
|
||||
/// but one is intended for "us" where as the other is intended for "someone
|
||||
/// else".
|
||||
/// Creates an anonymous pipe suitable for communication with a child process.
|
||||
///
|
||||
/// Currently the only use case for this function is pipes for stdio on
|
||||
/// processes in the standard library, so "ours" is the one that'll stay in our
|
||||
/// process whereas "theirs" will be inherited to a child.
|
||||
/// Windows unfortunately does not have a way of performing asynchronous operations
|
||||
/// on a handle originally created for synchronous operation. As `read_output` can
|
||||
/// only be correctly implemented with asynchronous reads but the pipe created by
|
||||
/// `CreatePipe` is synchronous, we cannot use it (and thus [`io::pipe`]) to create
|
||||
/// a pipe for communicating with a child. Instead, this function uses the NT API
|
||||
/// to create a pipe where one pipe handle (`ours`) is asynchronous and one is
|
||||
/// synchronous and can be inherited by a child for use as a console handle
|
||||
/// (`theirs`).
|
||||
///
|
||||
/// The ours/theirs pipes are *not* specifically readable or writable. Each
|
||||
/// one only supports a read or a write, but which is which depends on the
|
||||
|
|
@ -50,7 +48,11 @@ pub struct Pipes {
|
|||
/// mode. This means that technically speaking it should only ever be used
|
||||
/// with `OVERLAPPED` instances, but also works out ok if it's only ever used
|
||||
/// once at a time (which we do indeed guarantee).
|
||||
pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
|
||||
// FIXME(joboet): No, we don't guarantee that? E.g. `&Stdout` is both `Read`
|
||||
// and `Sync`, so there could be multiple operations at the same
|
||||
// time. All the functions below that forward to the inner handle
|
||||
// methods could abort if used concurrently.
|
||||
pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
|
||||
// A 64kb pipe capacity is the same as a typical Linux default.
|
||||
const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024;
|
||||
|
||||
|
|
@ -166,7 +168,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
|
|||
}
|
||||
};
|
||||
|
||||
Ok(Pipes { ours: AnonPipe { inner: ours }, theirs: AnonPipe { inner: theirs } })
|
||||
Ok(Pipes { ours: ChildPipe { inner: ours }, theirs: ChildPipe { inner: theirs } })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,16 +177,16 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
|
|||
///
|
||||
/// This is achieved by creating a new set of pipes and spawning a thread that
|
||||
/// relays messages between the source and the synchronous pipe.
|
||||
pub fn spawn_pipe_relay(
|
||||
source: &AnonPipe,
|
||||
pub(super) fn spawn_pipe_relay(
|
||||
source: &ChildPipe,
|
||||
ours_readable: bool,
|
||||
their_handle_inheritable: bool,
|
||||
) -> io::Result<AnonPipe> {
|
||||
) -> io::Result<ChildPipe> {
|
||||
// We need this handle to live for the lifetime of the thread spawned below.
|
||||
let source = source.try_clone()?;
|
||||
|
||||
// create a new pair of anon pipes.
|
||||
let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?;
|
||||
let Pipes { theirs, ours } = child_pipe(ours_readable, their_handle_inheritable)?;
|
||||
|
||||
// Spawn a thread that passes messages from one pipe to the other.
|
||||
// Any errors will simply cause the thread to exit.
|
||||
|
|
@ -210,7 +212,7 @@ pub fn spawn_pipe_relay(
|
|||
Ok(theirs)
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
impl ChildPipe {
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&self.inner
|
||||
}
|
||||
|
|
@ -219,7 +221,7 @@ impl AnonPipe {
|
|||
}
|
||||
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner })
|
||||
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| ChildPipe { inner })
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
|
|
@ -347,18 +349,17 @@ impl AnonPipe {
|
|||
|
||||
// STEP 3: The callback.
|
||||
unsafe extern "system" fn callback(
|
||||
dwErrorCode: u32,
|
||||
dwNumberOfBytesTransferred: u32,
|
||||
lpOverlapped: *mut c::OVERLAPPED,
|
||||
error: u32,
|
||||
transferred: u32,
|
||||
overlapped: *mut c::OVERLAPPED,
|
||||
) {
|
||||
// Set `async_result` using a pointer smuggled through `hEvent`.
|
||||
// SAFETY:
|
||||
// At this point, the OVERLAPPED struct will have been written to by the OS,
|
||||
// except for our `hEvent` field which we set to a valid AsyncResult pointer (see below)
|
||||
unsafe {
|
||||
let result =
|
||||
AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred };
|
||||
*(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
|
||||
let result = AsyncResult { error, transferred };
|
||||
*(*overlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +396,12 @@ impl AnonPipe {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
pub fn read_output(
|
||||
p1: ChildPipe,
|
||||
v1: &mut Vec<u8>,
|
||||
p2: ChildPipe,
|
||||
v2: &mut Vec<u8>,
|
||||
) -> io::Result<()> {
|
||||
let p1 = p1.into_handle();
|
||||
let p2 = p2.into_handle();
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
|
|||
impl From<OwnedFd> for process::ChildStdin {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::ChildStdin {
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||
let pipe = sys::process::ChildPipe::from_inner(fd);
|
||||
process::ChildStdin::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
|
|||
impl From<OwnedFd> for process::ChildStdout {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::ChildStdout {
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||
let pipe = sys::process::ChildPipe::from_inner(fd);
|
||||
process::ChildStdout::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
@ -226,7 +226,7 @@ impl From<crate::process::ChildStderr> for OwnedFd {
|
|||
impl From<OwnedFd> for process::ChildStderr {
|
||||
#[inline]
|
||||
fn from(fd: OwnedFd) -> process::ChildStderr {
|
||||
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||
let pipe = sys::process::ChildPipe::from_inner(fd);
|
||||
process::ChildStderr::from_inner(pipe)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue