about summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/unix/fs.rs57
-rw-r--r--library/std/src/sys/unix/pipe.rs4
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs5
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs5
-rw-r--r--library/std/src/sys/unix/process/process_unsupported.rs4
-rw-r--r--library/std/src/sys/unix/process/process_vxworks.rs5
-rw-r--r--library/std/src/sys/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/unsupported/once.rs89
-rw-r--r--library/std/src/sys/unsupported/pipe.rs4
-rw-r--r--library/std/src/sys/unsupported/process.rs4
-rw-r--r--library/std/src/sys/wasi/mod.rs2
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/windows/pipe.rs6
-rw-r--r--library/std/src/sys/windows/process.rs5
14 files changed, 154 insertions, 39 deletions
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 818914a2df0..d5f50d77911 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -243,17 +243,15 @@ struct InnerReadDir {
 
 pub struct ReadDir {
     inner: Arc<InnerReadDir>,
-    #[cfg(not(any(
-        target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
-        target_os = "illumos",
-        target_os = "fuchsia",
-        target_os = "redox",
-    )))]
     end_of_stream: bool,
 }
 
+impl ReadDir {
+    fn new(inner: InnerReadDir) -> Self {
+        Self { inner: Arc::new(inner), end_of_stream: false }
+    }
+}
+
 struct Dir(*mut libc::DIR);
 
 unsafe impl Send for Dir {}
@@ -594,6 +592,10 @@ impl Iterator for ReadDir {
         target_os = "illumos"
     ))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        if self.end_of_stream {
+            return None;
+        }
+
         unsafe {
             loop {
                 // As of POSIX.1-2017, readdir() is not required to be thread safe; only
@@ -604,8 +606,12 @@ impl Iterator for ReadDir {
                 super::os::set_errno(0);
                 let entry_ptr = readdir64(self.inner.dirp.0);
                 if entry_ptr.is_null() {
-                    // null can mean either the end is reached or an error occurred.
-                    // So we had to clear errno beforehand to check for an error now.
+                    // We either encountered an error, or reached the end.  Either way,
+                    // the next call to next() should return None.
+                    self.end_of_stream = true;
+
+                    // To distinguish between errors and end-of-directory, we had to clear
+                    // errno beforehand to check for an error now.
                     return match super::os::errno() {
                         0 => None,
                         e => Some(Err(Error::from_raw_os_error(e))),
@@ -1363,18 +1369,7 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
     } else {
         let root = path.to_path_buf();
         let inner = InnerReadDir { dirp: Dir(ptr), root };
-        Ok(ReadDir {
-            inner: Arc::new(inner),
-            #[cfg(not(any(
-                target_os = "android",
-                target_os = "linux",
-                target_os = "solaris",
-                target_os = "illumos",
-                target_os = "fuchsia",
-                target_os = "redox",
-            )))]
-            end_of_stream: false,
-        })
+        Ok(ReadDir::new(inner))
     }
 }
 
@@ -1755,7 +1750,6 @@ mod remove_dir_impl {
     use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
     use crate::os::unix::prelude::{OwnedFd, RawFd};
     use crate::path::{Path, PathBuf};
-    use crate::sync::Arc;
     use crate::sys::common::small_c_string::run_path_with_cstr;
     use crate::sys::{cvt, cvt_r};
 
@@ -1832,21 +1826,8 @@ mod remove_dir_impl {
         // a valid root is not needed because we do not call any functions involving the full path
         // of the DirEntrys.
         let dummy_root = PathBuf::new();
-        Ok((
-            ReadDir {
-                inner: Arc::new(InnerReadDir { dirp, root: dummy_root }),
-                #[cfg(not(any(
-                    target_os = "android",
-                    target_os = "linux",
-                    target_os = "solaris",
-                    target_os = "illumos",
-                    target_os = "fuchsia",
-                    target_os = "redox",
-                )))]
-                end_of_stream: false,
-            },
-            new_parent_fd,
-        ))
+        let inner = InnerReadDir { dirp, root: dummy_root };
+        Ok((ReadDir::new(inner), new_parent_fd))
     }
 
     #[cfg(any(
diff --git a/library/std/src/sys/unix/pipe.rs b/library/std/src/sys/unix/pipe.rs
index a56c275c942..a744d0ab640 100644
--- a/library/std/src/sys/unix/pipe.rs
+++ b/library/std/src/sys/unix/pipe.rs
@@ -58,6 +58,10 @@ impl AnonPipe {
         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)
     }
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index 66ea3db2015..4c99d758c93 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -35,6 +35,11 @@ impl Command {
         Ok((Process { handle: Handle::new(process_handle) }, ours))
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
+
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         if self.saw_nul() {
             return io::const_io_error!(
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index c0716a089bc..39d1c8b1d8e 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -133,6 +133,11 @@ impl Command {
         }
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
+
     // Attempts to fork the process. If successful, returns Ok((0, -1))
     // in the child, and Ok((child_pid, -1)) in the parent.
     #[cfg(not(target_os = "linux"))]
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
index 72f9f3f9ca7..f28ca58d020 100644
--- a/library/std/src/sys/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/unix/process/process_unsupported.rs
@@ -20,6 +20,10 @@ impl Command {
         unsupported()
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        unsupported()
+    }
+
     pub fn exec(&mut self, _default: Stdio) -> io::Error {
         unsupported_err()
     }
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index 200ef671967..f549d37c301 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -108,6 +108,11 @@ impl Command {
         }
     }
 
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
+
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         let ret = Command::spawn(self, default, false);
         match ret {
diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs
index 7bf6d40b76d..15b22c620d5 100644
--- a/library/std/src/sys/unsupported/mod.rs
+++ b/library/std/src/sys/unsupported/mod.rs
@@ -9,6 +9,7 @@ pub mod fs;
 pub mod io;
 pub mod locks;
 pub mod net;
+pub mod once;
 pub mod os;
 #[path = "../unix/os_str.rs"]
 pub mod os_str;
diff --git a/library/std/src/sys/unsupported/once.rs b/library/std/src/sys/unsupported/once.rs
new file mode 100644
index 00000000000..b4bb4975f41
--- /dev/null
+++ b/library/std/src/sys/unsupported/once.rs
@@ -0,0 +1,89 @@
+use crate::cell::Cell;
+use crate::sync as public;
+
+pub struct Once {
+    state: Cell<State>,
+}
+
+pub struct OnceState {
+    poisoned: bool,
+    set_state_to: Cell<State>,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+enum State {
+    Incomplete,
+    Poisoned,
+    Running,
+    Complete,
+}
+
+struct CompletionGuard<'a> {
+    state: &'a Cell<State>,
+    set_state_on_drop_to: State,
+}
+
+impl<'a> Drop for CompletionGuard<'a> {
+    fn drop(&mut self) {
+        self.state.set(self.set_state_on_drop_to);
+    }
+}
+
+// Safety: threads are not supported on this platform.
+unsafe impl Sync for Once {}
+
+impl Once {
+    #[inline]
+    #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
+    pub const fn new() -> Once {
+        Once { state: Cell::new(State::Incomplete) }
+    }
+
+    #[inline]
+    pub fn is_completed(&self) -> bool {
+        self.state.get() == State::Complete
+    }
+
+    #[cold]
+    #[track_caller]
+    pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
+        let state = self.state.get();
+        match state {
+            State::Poisoned if !ignore_poisoning => {
+                // Panic to propagate the poison.
+                panic!("Once instance has previously been poisoned");
+            }
+            State::Incomplete | State::Poisoned => {
+                self.state.set(State::Running);
+                // `guard` will set the new state on drop.
+                let mut guard =
+                    CompletionGuard { state: &self.state, set_state_on_drop_to: State::Poisoned };
+                // Run the function, letting it know if we're poisoned or not.
+                let f_state = public::OnceState {
+                    inner: OnceState {
+                        poisoned: state == State::Poisoned,
+                        set_state_to: Cell::new(State::Complete),
+                    },
+                };
+                f(&f_state);
+                guard.set_state_on_drop_to = f_state.inner.set_state_to.get();
+            }
+            State::Running => {
+                panic!("one-time initialization may not be performed recursively");
+            }
+            State::Complete => {}
+        }
+    }
+}
+
+impl OnceState {
+    #[inline]
+    pub fn is_poisoned(&self) -> bool {
+        self.poisoned
+    }
+
+    #[inline]
+    pub fn poison(&self) {
+        self.set_state_to.set(State::Poisoned)
+    }
+}
diff --git a/library/std/src/sys/unsupported/pipe.rs b/library/std/src/sys/unsupported/pipe.rs
index 25514c2322f..0bba673b458 100644
--- a/library/std/src/sys/unsupported/pipe.rs
+++ b/library/std/src/sys/unsupported/pipe.rs
@@ -15,6 +15,10 @@ impl AnonPipe {
         self.0
     }
 
+    pub fn read_to_end(&self, _buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.0
+    }
+
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
         self.0
     }
diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs
index 633f17c054b..a494f2d6b4c 100644
--- a/library/std/src/sys/unsupported/process.rs
+++ b/library/std/src/sys/unsupported/process.rs
@@ -75,6 +75,10 @@ impl Command {
     ) -> io::Result<(Process, StdioPipes)> {
         unsupported()
     }
+
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        unsupported()
+    }
 }
 
 impl From<AnonPipe> for Stdio {
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index c8c47763a34..1dc3f2b2026 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -32,6 +32,8 @@ pub mod io;
 #[path = "../unsupported/locks/mod.rs"]
 pub mod locks;
 pub mod net;
+#[path = "../unsupported/once.rs"]
+pub mod once;
 pub mod os;
 #[path = "../unix/os_str.rs"]
 pub mod os_str;
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index d68c3e5f1df..77ebe3c4ac6 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -66,6 +66,8 @@ cfg_if::cfg_if! {
     } else {
         #[path = "../unsupported/locks/mod.rs"]
         pub mod locks;
+        #[path = "../unsupported/once.rs"]
+        pub mod once;
         #[path = "../unsupported/thread.rs"]
         pub mod thread;
     }
diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs
index 9f26acc4520..7b25edaa556 100644
--- a/library/std/src/sys/windows/pipe.rs
+++ b/library/std/src/sys/windows/pipe.rs
@@ -1,7 +1,7 @@
 use crate::os::windows::prelude::*;
 
 use crate::ffi::OsStr;
-use crate::io::{self, IoSlice, IoSliceMut};
+use crate::io::{self, IoSlice, IoSliceMut, Read};
 use crate::mem;
 use crate::path::Path;
 use crate::ptr;
@@ -261,6 +261,10 @@ impl AnonPipe {
         self.inner.is_read_vectored()
     }
 
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.handle().read_to_end(buf)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         unsafe {
             let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 31e9b34fb9e..10bc949e1f4 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -351,6 +351,11 @@ impl Command {
             ))
         }
     }
+
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
+        crate::sys_common::process::wait_with_output(proc, pipes)
+    }
 }
 
 impl fmt::Debug for Command {