diff options
Diffstat (limited to 'library/std/src')
69 files changed, 898 insertions, 592 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f9a360585e8..801baf3d990 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -665,6 +665,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -673,7 +674,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn lock(&self) -> io::Result<()> { self.inner.lock() } @@ -717,6 +718,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -725,7 +727,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn lock_shared(&self) -> io::Result<()> { self.inner.lock_shared() } @@ -774,6 +776,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -782,7 +785,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn try_lock(&self) -> io::Result<bool> { self.inner.try_lock() } @@ -830,6 +833,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -838,7 +842,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn try_lock_shared(&self) -> io::Result<bool> { self.inner.try_lock_shared() } @@ -866,6 +870,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -875,7 +880,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn unlock(&self) -> io::Result<()> { self.inner.unlock() } @@ -1343,6 +1348,9 @@ impl Seek for Arc<File> { fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (&**self).seek(pos) } + fn stream_position(&mut self) -> io::Result<u64> { + (&**self).stream_position() + } } impl OpenOptions { @@ -2362,7 +2370,7 @@ impl AsInner<fs_imp::DirEntry> for DirEntry { #[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> { - fs_imp::unlink(path.as_ref()) + fs_imp::remove_file(path.as_ref()) } /// Given a path, queries the file system to get information about a file, @@ -2401,7 +2409,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> { #[doc(alias = "stat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { - fs_imp::stat(path.as_ref()).map(Metadata) + fs_imp::metadata(path.as_ref()).map(Metadata) } /// Queries the metadata about a file without following symlinks. @@ -2436,7 +2444,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { #[doc(alias = "lstat")] #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> { - fs_imp::lstat(path.as_ref()).map(Metadata) + fs_imp::symlink_metadata(path.as_ref()).map(Metadata) } /// Renames a file or directory to a new name, replacing the original file if @@ -2590,7 +2598,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { #[doc(alias = "CreateHardLink", alias = "linkat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> { - fs_imp::link(original.as_ref(), link.as_ref()) + fs_imp::hard_link(original.as_ref(), link.as_ref()) } /// Creates a new symbolic link on the filesystem. @@ -2656,7 +2664,7 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Re /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> { - fs_imp::readlink(path.as_ref()) + fs_imp::read_link(path.as_ref()) } /// Returns the canonical, absolute form of a path with all intermediate @@ -2832,7 +2840,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { #[doc(alias = "rmdir", alias = "RemoveDirectory")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { - fs_imp::rmdir(path.as_ref()) + fs_imp::remove_dir(path.as_ref()) } /// Removes a directory at this path, after removing all its contents. Use @@ -2959,7 +2967,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> { #[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { - fs_imp::readdir(path.as_ref()).map(ReadDir) + fs_imp::read_dir(path.as_ref()).map(ReadDir) } /// Changes the permissions found on a file or a directory. @@ -2995,7 +3003,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { #[doc(alias = "chmod", alias = "SetFileAttributes")] #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> { - fs_imp::set_perm(path.as_ref(), perm.0) + fs_imp::set_permissions(path.as_ref(), perm.0) } impl DirBuilder { diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 6dd18e4f4c8..4712e58980c 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1719,6 +1719,23 @@ fn test_eq_direntry_metadata() { } } +/// Test that windows file type equality is not affected by attributes unrelated +/// to the file type. +#[test] +#[cfg(target_os = "windows")] +fn test_eq_windows_file_type() { + let tmpdir = tmpdir(); + let file1 = File::create(tmpdir.join("file1")).unwrap(); + let file2 = File::create(tmpdir.join("file2")).unwrap(); + assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type()); + + // Change the readonly attribute of one file. + let mut perms = file1.metadata().unwrap().permissions(); + perms.set_readonly(true); + file1.set_permissions(perms).unwrap(); + assert_eq!(file1.metadata().unwrap().file_type(), file2.metadata().unwrap().file_type()); +} + /// Regression test for https://github.com/rust-lang/rust/issues/50619. #[test] #[cfg(target_os = "linux")] diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 6579b6887aa..314cbb45d49 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2989,11 +2989,11 @@ impl<T: Read> Read for Take<T> { return Ok(()); } - if self.limit <= buf.capacity() as u64 { - // if we just use an as cast to convert, limit may wrap around on a 32 bit target - let limit = cmp::min(self.limit, usize::MAX as u64) as usize; + if self.limit < buf.capacity() as u64 { + // The condition above guarantees that `self.limit` fits in `usize`. + let limit = self.limit as usize; - let extra_init = cmp::min(limit as usize, buf.init_ref().len()); + let extra_init = cmp::min(limit, buf.init_ref().len()); // SAFETY: no uninit data is written to ibuf let ibuf = unsafe { &mut buf.as_mut()[..limit] }; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index ce46241f8e8..8fc16331339 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -97,15 +97,15 @@ const fn stderr_raw() -> StderrRaw { impl Read for StdinRaw { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - handle_ebadf(self.0.read(buf), 0) + handle_ebadf(self.0.read(buf), || Ok(0)) } fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { - handle_ebadf(self.0.read_buf(buf), ()) + handle_ebadf(self.0.read_buf(buf), || Ok(())) } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - handle_ebadf(self.0.read_vectored(bufs), 0) + handle_ebadf(self.0.read_vectored(bufs), || Ok(0)) } #[inline] @@ -113,23 +113,37 @@ impl Read for StdinRaw { self.0.is_read_vectored() } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if buf.is_empty() { + return Ok(()); + } + handle_ebadf(self.0.read_exact(buf), || Err(io::Error::READ_EXACT_EOF)) + } + + fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + if buf.capacity() == 0 { + return Ok(()); + } + handle_ebadf(self.0.read_buf_exact(buf), || Err(io::Error::READ_EXACT_EOF)) + } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - handle_ebadf(self.0.read_to_end(buf), 0) + handle_ebadf(self.0.read_to_end(buf), || Ok(0)) } fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - handle_ebadf(self.0.read_to_string(buf), 0) + handle_ebadf(self.0.read_to_string(buf), || Ok(0)) } } impl Write for StdoutRaw { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - handle_ebadf(self.0.write(buf), buf.len()) + handle_ebadf(self.0.write(buf), || Ok(buf.len())) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - let total = || bufs.iter().map(|b| b.len()).sum(); - handle_ebadf_lazy(self.0.write_vectored(bufs), total) + let total = || Ok(bufs.iter().map(|b| b.len()).sum()); + handle_ebadf(self.0.write_vectored(bufs), total) } #[inline] @@ -138,30 +152,30 @@ impl Write for StdoutRaw { } fn flush(&mut self) -> io::Result<()> { - handle_ebadf(self.0.flush(), ()) + handle_ebadf(self.0.flush(), || Ok(())) } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - handle_ebadf(self.0.write_all(buf), ()) + handle_ebadf(self.0.write_all(buf), || Ok(())) } fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - handle_ebadf(self.0.write_all_vectored(bufs), ()) + handle_ebadf(self.0.write_all_vectored(bufs), || Ok(())) } fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { - handle_ebadf(self.0.write_fmt(fmt), ()) + handle_ebadf(self.0.write_fmt(fmt), || Ok(())) } } impl Write for StderrRaw { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - handle_ebadf(self.0.write(buf), buf.len()) + handle_ebadf(self.0.write(buf), || Ok(buf.len())) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - let total = || bufs.iter().map(|b| b.len()).sum(); - handle_ebadf_lazy(self.0.write_vectored(bufs), total) + let total = || Ok(bufs.iter().map(|b| b.len()).sum()); + handle_ebadf(self.0.write_vectored(bufs), total) } #[inline] @@ -170,32 +184,25 @@ impl Write for StderrRaw { } fn flush(&mut self) -> io::Result<()> { - handle_ebadf(self.0.flush(), ()) + handle_ebadf(self.0.flush(), || Ok(())) } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - handle_ebadf(self.0.write_all(buf), ()) + handle_ebadf(self.0.write_all(buf), || Ok(())) } fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - handle_ebadf(self.0.write_all_vectored(bufs), ()) + handle_ebadf(self.0.write_all_vectored(bufs), || Ok(())) } fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { - handle_ebadf(self.0.write_fmt(fmt), ()) - } -} - -fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> { - match r { - Err(ref e) if stdio::is_ebadf(e) => Ok(default), - r => r, + handle_ebadf(self.0.write_fmt(fmt), || Ok(())) } } -fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Result<T> { +fn handle_ebadf<T>(r: io::Result<T>, default: impl FnOnce() -> io::Result<T>) -> io::Result<T> { match r { - Err(ref e) if stdio::is_ebadf(e) => Ok(default()), + Err(ref e) if stdio::is_ebadf(e) => default(), r => r, } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ad005833ad5..9dcedaa13f6 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -297,6 +297,7 @@ #![feature(extended_varargs_abi_support)] #![feature(f128)] #![feature(f16)] +#![feature(ffi_const)] #![feature(formatting_options)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index a7b5cdf4ec0..03003037b29 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -315,12 +315,8 @@ fn read_buf() { let mut buf = BorrowedBuf::from(buf.as_mut_slice()); t!(s.read_buf(buf.unfilled())); assert_eq!(buf.filled(), &[1, 2, 3, 4]); - - // FIXME: sgx uses default_read_buf that initializes the buffer. - if cfg!(not(target_env = "sgx")) { - // TcpStream::read_buf should omit buffer initialization. - assert_eq!(buf.init_len(), 4); - } + // TcpStream::read_buf should omit buffer initialization. + assert_eq!(buf.init_len(), 4); t.join().ok().expect("thread panicked"); }) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 2dcbfc96618..be73e7dee9c 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -15,9 +15,8 @@ use crate::mem::ManuallyDrop; target_os = "trusty" )))] use crate::sys::cvt; -use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] -use crate::sys_common::{AsInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, io}; type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>; @@ -507,6 +506,7 @@ impl<'a> AsFd for io::StderrLock<'a> { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeReader { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() @@ -514,6 +514,7 @@ impl AsFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From<io::PipeReader> for OwnedFd { fn from(pipe: io::PipeReader) -> Self { pipe.0.into_inner() @@ -521,6 +522,7 @@ impl From<io::PipeReader> for OwnedFd { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeWriter { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() @@ -528,6 +530,7 @@ impl AsFd for io::PipeWriter { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From<io::PipeWriter> for OwnedFd { fn from(pipe: io::PipeWriter) -> Self { pipe.0.into_inner() @@ -535,6 +538,7 @@ impl From<io::PipeWriter> for OwnedFd { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From<OwnedFd> for io::PipeReader { fn from(owned_fd: OwnedFd) -> Self { Self(FromInner::from_inner(owned_fd)) @@ -542,6 +546,7 @@ impl From<OwnedFd> for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl From<OwnedFd> for io::PipeWriter { fn from(owned_fd: OwnedFd) -> Self { Self(FromInner::from_inner(owned_fd)) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 596b21a5204..c800c1489ad 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -18,9 +18,8 @@ use crate::os::unix::io::AsFd; use crate::os::unix::io::OwnedFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; -use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] -use crate::sys_common::{AsInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; /// Raw file descriptors. #[stable(feature = "rust1", since = "1.0.0")] @@ -287,6 +286,7 @@ impl<T: AsRawFd> AsRawFd for Box<T> { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeReader { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() @@ -294,6 +294,7 @@ impl AsRawFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeReader { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) @@ -301,6 +302,7 @@ impl FromRawFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeReader { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() @@ -308,6 +310,7 @@ impl IntoRawFd for io::PipeReader { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeWriter { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() @@ -315,6 +318,7 @@ impl AsRawFd for io::PipeWriter { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeWriter { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) @@ -322,6 +326,7 @@ impl FromRawFd for io::PipeWriter { } #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeWriter { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() diff --git a/library/std/src/process.rs b/library/std/src/process.rs index f81ce8e1a1a..3b765a9537b 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1836,7 +1836,7 @@ impl crate::sealed::Sealed for ExitStatusError {} /// # if cfg!(unix) { /// use std::process::{Command, ExitStatusError}; /// -/// fn run(cmd: &str) -> Result<(),ExitStatusError> { +/// fn run(cmd: &str) -> Result<(), ExitStatusError> { /// Command::new(cmd).status().unwrap().exit_ok()?; /// Ok(()) /// } diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 5b50a3c6ccf..e67b4f6f22f 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -176,6 +176,8 @@ pub use core::sync::Exclusive; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; +#[unstable(feature = "unique_rc_arc", issue = "112566")] +pub use alloc_crate::sync::UniqueArc; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::sync::{Arc, Weak}; diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index c2e19eb393a..3b176d0d16c 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -1,28 +1,115 @@ #![deny(unsafe_op_in_unsafe_fn)] +use crate::io; +use crate::path::{Path, PathBuf}; + pub mod common; cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { mod unix; - pub use unix::*; + use unix as imp; + pub use unix::{chown, fchown, lchown}; + #[cfg(not(target_os = "fuchsia"))] + pub use unix::chroot; + pub(crate) use unix::debug_assert_fd_is_open; + #[cfg(any(target_os = "linux", target_os = "android"))] + pub(crate) use unix::CachedFileMetadata; + use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path; } else if #[cfg(target_os = "windows")] { mod windows; - pub use windows::*; + use windows as imp; + pub use windows::{symlink_inner, junction_point}; } else if #[cfg(target_os = "hermit")] { mod hermit; - pub use hermit::*; + use hermit as imp; } else if #[cfg(target_os = "solid_asp3")] { mod solid; - pub use solid::*; + use solid as imp; } else if #[cfg(target_os = "uefi")] { mod uefi; - pub use uefi::*; + use uefi as imp; } else if #[cfg(target_os = "wasi")] { mod wasi; - pub use wasi::*; + use wasi as imp; } else { mod unsupported; - pub use unsupported::*; + use unsupported as imp; } } + +// FIXME: Replace this with platform-specific path conversion functions. +#[cfg(not(target_family = "unix"))] +#[inline] +pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> { + f(path) +} + +pub use imp::{ + DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions, + ReadDir, +}; + +pub fn read_dir(path: &Path) -> io::Result<ReadDir> { + // FIXME: use with_native_path + imp::readdir(path) +} + +pub fn remove_file(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::unlink) +} + +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new))) +} + +pub fn remove_dir(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::rmdir) +} + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + // FIXME: use with_native_path + imp::remove_dir_all(path) +} + +pub fn read_link(path: &Path) -> io::Result<PathBuf> { + with_native_path(path, &imp::readlink) +} + +pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::symlink(original, link)) + }) +} + +pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::link(original, link)) + }) +} + +pub fn metadata(path: &Path) -> io::Result<FileAttr> { + with_native_path(path, &imp::stat) +} + +pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> { + with_native_path(path, &imp::lstat) +} + +pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> { + with_native_path(path, &|path| imp::set_perm(path, perm.clone())) +} + +pub fn canonicalize(path: &Path) -> io::Result<PathBuf> { + with_native_path(path, &imp::canonicalize) +} + +pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { + // FIXME: use with_native_path + imp::copy(from, to) +} + +pub fn exists(path: &Path) -> io::Result<bool> { + // FIXME: use with_native_path + imp::exists(path) +} diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index defc1681d38..d6ae86bd3d2 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -1,3 +1,5 @@ +use r_efi::protocols::file; + use crate::ffi::OsString; use crate::fmt; use crate::hash::Hash; @@ -22,7 +24,12 @@ pub struct ReadDir(!); pub struct DirEntry(!); #[derive(Clone, Debug)] -pub struct OpenOptions {} +pub struct OpenOptions { + mode: u64, + append: bool, + truncate: bool, + create_new: bool, +} #[derive(Copy, Clone, Debug, Default)] pub struct FileTimes {} @@ -36,7 +43,7 @@ pub struct FilePermissions(bool); pub struct FileType(bool); #[derive(Debug)] -pub struct DirBuilder {} +pub struct DirBuilder; impl FileAttr { pub fn size(&self) -> u64 { @@ -141,15 +148,58 @@ impl DirEntry { impl OpenOptions { pub fn new() -> OpenOptions { - OpenOptions {} + OpenOptions { mode: 0, append: false, create_new: false, truncate: false } + } + + pub fn read(&mut self, read: bool) { + if read { + self.mode |= file::MODE_READ; + } else { + self.mode &= !file::MODE_READ; + } + } + + pub fn write(&mut self, write: bool) { + if write { + // Valid Combinations: Read, Read/Write, Read/Write/Create + self.read(true); + self.mode |= file::MODE_WRITE; + } else { + self.mode &= !file::MODE_WRITE; + } + } + + pub fn append(&mut self, append: bool) { + // Docs state that `.write(true).append(true)` has the same effect as `.append(true)` + if append { + self.write(true); + } + self.append = append; + } + + pub fn truncate(&mut self, truncate: bool) { + self.truncate = truncate; + } + + pub fn create(&mut self, create: bool) { + if create { + self.mode |= file::MODE_CREATE; + } else { + self.mode &= !file::MODE_CREATE; + } } - pub fn read(&mut self, _read: bool) {} - pub fn write(&mut self, _write: bool) {} - pub fn append(&mut self, _append: bool) {} - pub fn truncate(&mut self, _truncate: bool) {} - pub fn create(&mut self, _create: bool) {} - pub fn create_new(&mut self, _create_new: bool) {} + pub fn create_new(&mut self, create_new: bool) { + self.create_new = create_new; + } + + #[expect(dead_code)] + const fn is_mode_valid(&self) -> bool { + // Valid Combinations: Read, Read/Write, Read/Write/Create + self.mode == file::MODE_READ + || self.mode == (file::MODE_READ | file::MODE_WRITE) + || self.mode == (file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE) + } } impl File { @@ -248,11 +298,11 @@ impl File { impl DirBuilder { pub fn new() -> DirBuilder { - DirBuilder {} + DirBuilder } - pub fn mkdir(&self, _p: &Path) -> io::Result<()> { - unsupported() + pub fn mkdir(&self, p: &Path) -> io::Result<()> { + uefi_fs::mkdir(p) } } @@ -311,12 +361,12 @@ pub fn stat(_p: &Path) -> io::Result<FileAttr> { unsupported() } -pub fn lstat(_p: &Path) -> io::Result<FileAttr> { - unsupported() +pub fn lstat(p: &Path) -> io::Result<FileAttr> { + stat(p) } -pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> { - unsupported() +pub fn canonicalize(p: &Path) -> io::Result<PathBuf> { + crate::path::absolute(p) } pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> { @@ -452,4 +502,30 @@ mod uefi_fs { } } } + + /// An implementation of mkdir to allow creating new directory without having to open the + /// volume twice (once for checking and once for creating) + pub(crate) fn mkdir(path: &Path) -> io::Result<()> { + let absolute = crate::path::absolute(path)?; + + let p = helpers::OwnedDevicePath::from_text(absolute.as_os_str())?; + let (vol, mut path_remaining) = File::open_volume_from_device_path(p.borrow())?; + + // Check if file exists + match vol.open(&mut path_remaining, file::MODE_READ, 0) { + Ok(_) => { + return Err(io::Error::new(io::ErrorKind::AlreadyExists, "Path already exists")); + } + Err(e) if e.kind() == io::ErrorKind::NotFound => {} + Err(e) => return Err(e), + } + + let _ = vol.open( + &mut path_remaining, + file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE, + file::DIRECTORY, + )?; + + Ok(()) + } } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 7c3ed8029f7..87865be0387 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -155,15 +155,15 @@ cfg_has_statx! {{ enum STATX_STATE{ Unknown = 0, Present, Unavailable } static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8); - syscall! { + syscall!( fn statx( fd: c_int, pathname: *const c_char, flags: c_int, mask: libc::c_uint, - statxbuf: *mut libc::statx - ) -> c_int - } + statxbuf: *mut libc::statx, + ) -> c_int; + ); let statx_availability = STATX_SAVED_STATE.load(Ordering::Relaxed); if statx_availability == STATX_STATE::Unavailable as u8 { @@ -926,7 +926,7 @@ impl DirEntry { miri ))] pub fn metadata(&self) -> io::Result<FileAttr> { - lstat(&self.path()) + run_path_with_cstr(&self.path(), &lstat) } #[cfg(any( @@ -1540,7 +1540,9 @@ impl File { let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; // futimens requires Android API level 19 cvt(unsafe { - weak!(fn futimens(c_int, *const libc::timespec) -> c_int); + weak!( + fn futimens(fd: c_int, times: *const libc::timespec) -> c_int; + ); match futimens.get() { Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()), None => return Err(io::const_error!( @@ -1556,7 +1558,9 @@ impl File { use crate::sys::{time::__timespec64, weak::weak}; // Added in glibc 2.34 - weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int); + weak!( + fn __futimens64(fd: c_int, times: *const __timespec64) -> c_int; + ); if let Some(futimens64) = __futimens64.get() { let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64()) @@ -1653,7 +1657,7 @@ impl fmt::Debug for File { fn get_path(fd: c_int) -> Option<PathBuf> { let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - readlink(&p).ok() + run_path_with_cstr(&p, &readlink).ok() } #[cfg(any(target_vendor = "apple", target_os = "netbsd"))] @@ -1671,7 +1675,7 @@ impl fmt::Debug for File { // fallback to procfs as last resort let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - return readlink(&p).ok(); + return run_path_with_cstr(&p, &readlink).ok() } else { return None; } @@ -1826,127 +1830,106 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> { } } -pub fn unlink(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())) +pub fn unlink(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()) } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - run_path_with_cstr(old, &|old| { - run_path_with_cstr(new, &|new| { - cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) - }) - }) +pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())) +pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> { + cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()) } -pub fn rmdir(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())) +pub fn rmdir(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()) } -pub fn readlink(p: &Path) -> io::Result<PathBuf> { - run_path_with_cstr(p, &|c_path| { - let p = c_path.as_ptr(); +pub fn readlink(c_path: &CStr) -> io::Result<PathBuf> { + let p = c_path.as_ptr(); - let mut buf = Vec::with_capacity(256); + let mut buf = Vec::with_capacity(256); - loop { - let buf_read = - cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? - as usize; - - unsafe { - buf.set_len(buf_read); - } + loop { + let buf_read = + cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize; - if buf_read != buf.capacity() { - buf.shrink_to_fit(); + unsafe { + buf.set_len(buf_read); + } - return Ok(PathBuf::from(OsString::from_vec(buf))); - } + if buf_read != buf.capacity() { + buf.shrink_to_fit(); - // Trigger the internal buffer resizing logic of `Vec` by requiring - // more space than the current capacity. The length is guaranteed to be - // the same as the capacity due to the if statement above. - buf.reserve(1); + return Ok(PathBuf::from(OsString::from_vec(buf))); } - }) + + // Trigger the internal buffer resizing logic of `Vec` by requiring + // more space than the current capacity. The length is guaranteed to be + // the same as the capacity due to the if statement above. + buf.reserve(1); + } } -pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) - }) - }) +pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> { + cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) } -pub fn link(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { - // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves - // it implementation-defined whether `link` follows symlinks, so rely on the - // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. - // Android has `linkat` on newer versions, but we happen to know `link` - // always has the correct behavior, so it's here as well. - cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; - } else { - // Where we can, use `linkat` instead of `link`; see the comment above - // this one for details on why. - cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; - } - } - Ok(()) - }) - }) +pub fn link(original: &CStr, link: &CStr) -> io::Result<()> { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { + // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves + // it implementation-defined whether `link` follows symlinks, so rely on the + // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. + // Android has `linkat` on newer versions, but we happen to know `link` + // always has the correct behavior, so it's here as well. + cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; + } else { + // Where we can, use `linkat` instead of `link`; see the comment above + // this one for details on why. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; + } + } + Ok(()) } -pub fn stat(p: &Path) -> io::Result<FileAttr> { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } +pub fn stat(p: &CStr) -> io::Result<FileAttr> { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; } + } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) } -pub fn lstat(p: &Path) -> io::Result<FileAttr> { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } +pub fn lstat(p: &CStr) -> io::Result<FileAttr> { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; } + } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) } -pub fn canonicalize(p: &Path) -> io::Result<PathBuf> { - let r = run_path_with_cstr(p, &|path| unsafe { - Ok(libc::realpath(path.as_ptr(), ptr::null_mut())) - })?; +pub fn canonicalize(path: &CStr) -> io::Result<PathBuf> { + let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) }; if r.is_null() { return Err(io::Error::last_os_error()); } @@ -2324,19 +2307,19 @@ mod remove_dir_impl { Ok(()) } - fn remove_dir_all_modern(p: &Path) -> io::Result<()> { + fn remove_dir_all_modern(p: &CStr) -> io::Result<()> { // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks. let attr = lstat(p)?; if attr.file_type().is_symlink() { - crate::fs::remove_file(p) + super::unlink(p) } else { - run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p)) + remove_dir_all_recursive(None, &p) } } pub fn remove_dir_all(p: &Path) -> io::Result<()> { - remove_dir_all_modern(p) + run_path_with_cstr(p, &remove_dir_all_modern) } } diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 362e64abf1a..15727c99683 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -41,8 +41,8 @@ pub struct FileAttr { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { - attributes: u32, - reparse_tag: u32, + is_directory: bool, + is_symlink: bool, } pub struct ReadDir { @@ -547,7 +547,7 @@ impl File { ))?; attr.file_size = info.AllocationSize as u64; attr.number_of_links = Some(info.NumberOfLinks); - if attr.file_type().is_reparse_point() { + if attr.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed(); cvt(c::GetFileInformationByHandleEx( self.handle.as_raw_handle(), @@ -1111,32 +1111,29 @@ impl FileTimes { } impl FileType { - fn new(attrs: u32, reparse_tag: u32) -> FileType { - FileType { attributes: attrs, reparse_tag } + fn new(attributes: u32, reparse_tag: u32) -> FileType { + let is_directory = attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0; + let is_symlink = { + let is_reparse_point = attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0; + let is_reparse_tag_name_surrogate = reparse_tag & 0x20000000 != 0; + is_reparse_point && is_reparse_tag_name_surrogate + }; + FileType { is_directory, is_symlink } } pub fn is_dir(&self) -> bool { - !self.is_symlink() && self.is_directory() + !self.is_symlink && self.is_directory } pub fn is_file(&self) -> bool { - !self.is_symlink() && !self.is_directory() + !self.is_symlink && !self.is_directory } pub fn is_symlink(&self) -> bool { - self.is_reparse_point() && self.is_reparse_tag_name_surrogate() + self.is_symlink } pub fn is_symlink_dir(&self) -> bool { - self.is_symlink() && self.is_directory() + self.is_symlink && self.is_directory } pub fn is_symlink_file(&self) -> bool { - self.is_symlink() && !self.is_directory() - } - fn is_directory(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_DIRECTORY != 0 - } - fn is_reparse_point(&self) -> bool { - self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 - } - fn is_reparse_tag_name_surrogate(&self) -> bool { - self.reparse_tag & 0x20000000 != 0 + self.is_symlink && !self.is_directory } } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 09677b9d642..f0cfb9b2773 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -17,6 +17,7 @@ pub mod io; pub mod net; pub mod os_str; pub mod path; +pub mod process; pub mod random; pub mod stdio; pub mod sync; diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 283b1fe9a33..e8aea8b706a 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -324,7 +324,7 @@ impl TcpStream { } Ok(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.local_port, 0, 0))) } - _ => Err(io::const_error!(io::ErrorKind::InvalidInput, "tnternal error")), + _ => Err(io::const_error!(io::ErrorKind::InvalidInput, "internal error")), } } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 608245bd430..67eab96fa40 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -25,8 +25,6 @@ pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index bb419c2530e..fe43cfd2caf 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -16,8 +16,6 @@ mod libunwind_integration; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod thread_parking; pub mod time; diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index e4a61fdcfe3..22052a168fd 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -25,8 +25,6 @@ pub(crate) mod error; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub use self::itron::{thread, thread_parking}; pub mod time; diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 41b25121592..c1921a2f40d 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -14,8 +14,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; #[allow(non_upper_case_globals)] #[path = "../unix/time.rs"] diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs index 7034b643d8e..5295d3fdc91 100644 --- a/library/std/src/sys/pal/trusty/mod.rs +++ b/library/std/src/sys/pal/trusty/mod.rs @@ -11,8 +11,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../unsupported/thread.rs"] pub mod thread; #[path = "../unsupported/time.rs"] diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 2faa733f23f..309022bcccf 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -120,39 +120,6 @@ pub(crate) fn open_protocol<T>( } } -pub(crate) fn create_event( - signal: u32, - tpl: efi::Tpl, - handler: Option<efi::EventNotify>, - context: *mut crate::ffi::c_void, -) -> io::Result<NonNull<crate::ffi::c_void>> { - let boot_services: NonNull<efi::BootServices> = - boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let mut event: r_efi::efi::Event = crate::ptr::null_mut(); - let r = unsafe { - let create_event = (*boot_services.as_ptr()).create_event; - (create_event)(signal, tpl, handler, context, &mut event) - }; - if r.is_error() { - Err(crate::io::Error::from_raw_os_error(r.as_usize())) - } else { - NonNull::new(event).ok_or(const_error!(io::ErrorKind::Other, "null protocol")) - } -} - -/// # SAFETY -/// - The supplied event must be valid -pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result<()> { - let boot_services: NonNull<efi::BootServices> = - boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let r = unsafe { - let close_event = (*boot_services.as_ptr()).close_event; - (close_event)(evt.as_ptr()) - }; - - if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } -} - /// Gets the Protocol for current system handle. /// /// Note: Some protocols need to be manually freed. It is the caller's responsibility to do so. @@ -735,3 +702,56 @@ impl Drop for ServiceProtocol { } } } + +#[repr(transparent)] +pub(crate) struct OwnedEvent(NonNull<crate::ffi::c_void>); + +impl OwnedEvent { + pub(crate) fn new( + signal: u32, + tpl: efi::Tpl, + handler: Option<efi::EventNotify>, + context: Option<NonNull<crate::ffi::c_void>>, + ) -> io::Result<Self> { + let boot_services: NonNull<efi::BootServices> = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let mut event: r_efi::efi::Event = crate::ptr::null_mut(); + let context = context.map(NonNull::as_ptr).unwrap_or(crate::ptr::null_mut()); + + let r = unsafe { + let create_event = (*boot_services.as_ptr()).create_event; + (create_event)(signal, tpl, handler, context, &mut event) + }; + + if r.is_error() { + Err(crate::io::Error::from_raw_os_error(r.as_usize())) + } else { + NonNull::new(event) + .ok_or(const_error!(io::ErrorKind::Other, "failed to create event")) + .map(Self) + } + } + + pub(crate) fn into_raw(self) -> *mut crate::ffi::c_void { + let r = self.0.as_ptr(); + crate::mem::forget(self); + r + } + + /// SAFETY: Assumes that ptr is a non-null valid UEFI event + pub(crate) unsafe fn from_raw(ptr: *mut crate::ffi::c_void) -> Self { + Self(unsafe { NonNull::new_unchecked(ptr) }) + } +} + +impl Drop for OwnedEvent { + fn drop(&mut self) { + if let Some(boot_services) = boot_services() { + let bt: NonNull<r_efi::efi::BootServices> = boot_services.cast(); + unsafe { + let close_event = (*bt.as_ptr()).close_event; + (close_event)(self.0.as_ptr()) + }; + } + } +} diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 714dc392688..9760a23084a 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -19,7 +19,6 @@ pub mod helpers; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -pub mod process; pub mod thread; pub mod time; @@ -47,17 +46,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { uefi::env::init_globals(image_handle, system_table) }; // Register exit boot services handler - match helpers::create_event( + match helpers::OwnedEvent::new( r_efi::efi::EVT_SIGNAL_EXIT_BOOT_SERVICES, r_efi::efi::TPL_NOTIFY, Some(exit_boot_service_handler), - crate::ptr::null_mut(), + None, ) { Ok(x) => { if EXIT_BOOT_SERVICE_EVENT .compare_exchange( crate::ptr::null_mut(), - x.as_ptr(), + x.into_raw(), Ordering::Release, Ordering::Acquire, ) @@ -77,7 +76,7 @@ pub unsafe fn cleanup() { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire)) { - let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) }; } } @@ -143,7 +142,7 @@ pub fn abort_internal() -> ! { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire)) { - let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) }; } if let (Some(boot_services), Some(handle)) = diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index f03c440e30e..2ec8d01c13f 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -232,14 +232,14 @@ impl FileDesc { // implementation if `preadv` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { - super::weak::syscall! { + super::weak::syscall!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, n_iovec: libc::c_int, - offset: off64_t - ) -> isize - } + offset: off64_t, + ) -> isize; + ); let ret = cvt(unsafe { preadv( @@ -257,7 +257,14 @@ impl FileDesc { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { - super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn preadv64( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match preadv64.get() { Some(preadv) => { @@ -286,7 +293,14 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { - super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn preadv( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match preadv.get() { Some(preadv) => { @@ -428,14 +442,14 @@ impl FileDesc { // implementation if `pwritev` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { - super::weak::syscall! { + super::weak::syscall!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, n_iovec: libc::c_int, - offset: off64_t - ) -> isize - } + offset: off64_t, + ) -> isize; + ); let ret = cvt(unsafe { pwritev( @@ -450,7 +464,14 @@ impl FileDesc { #[cfg(all(target_os = "android", target_pointer_width = "32"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { - super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn pwritev64( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match pwritev64.get() { Some(pwritev) => { @@ -479,7 +500,14 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { - super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn pwritev( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match pwritev.get() { Some(pwritev) => { diff --git a/library/std/src/sys/pal/unix/process/zircon.rs b/library/std/src/sys/pal/unix/fuchsia.rs index 7932bd26d76..7932bd26d76 100644 --- a/library/std/src/sys/pal/unix/process/zircon.rs +++ b/library/std/src/sys/pal/unix/fuchsia.rs diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs index bbf29f32523..d42a7e2a7fc 100644 --- a/library/std/src/sys/pal/unix/kernel_copy.rs +++ b/library/std/src/sys/pal/unix/kernel_copy.rs @@ -604,16 +604,16 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> _ => true, }; - syscall! { + syscall!( fn copy_file_range( fd_in: libc::c_int, off_in: *mut libc::loff_t, fd_out: libc::c_int, off_out: *mut libc::loff_t, len: libc::size_t, - flags: libc::c_uint - ) -> libc::ssize_t - } + flags: libc::c_uint, + ) -> libc::ssize_t; + ); fn probe_copy_file_range_support() -> u8 { // In some cases, we cannot determine availability from the first @@ -727,16 +727,16 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> // Android builds use feature level 14, but the libc wrapper for splice is // gated on feature level 21+, so we have to invoke the syscall directly. #[cfg(target_os = "android")] - syscall! { + syscall!( fn splice( srcfd: libc::c_int, src_offset: *const i64, dstfd: libc::c_int, dst_offset: *const i64, len: libc::size_t, - flags: libc::c_int - ) -> libc::ssize_t - } + flags: libc::c_int, + ) -> libc::ssize_t; + ); #[cfg(target_os = "linux")] use libc::splice; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index e2e537b7bd3..413fda1d8d8 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -9,6 +9,8 @@ pub mod weak; pub mod args; pub mod env; pub mod fd; +#[cfg(target_os = "fuchsia")] +pub mod fuchsia; pub mod futex; #[cfg(any(target_os = "linux", target_os = "android"))] pub mod kernel_copy; @@ -16,7 +18,6 @@ pub mod kernel_copy; pub mod linux; pub mod os; pub mod pipe; -pub mod process; pub mod stack_overflow; pub mod sync; pub mod thread; @@ -419,7 +420,7 @@ cfg_if::cfg_if! { } #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] -mod unsupported { +pub mod unsupported { use crate::io; pub fn unsupported<T>() -> io::Result<T> { diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 30282fbf655..f47421c6705 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -59,11 +59,14 @@ unsafe extern "C" { #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] #[cfg_attr(target_os = "aix", link_name = "_Errno")] + // SAFETY: this will always return the same pointer on a given thread. + #[unsafe(ffi_const)] fn errno_location() -> *mut c_int; } /// Returns the platform-specific value of errno #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] +#[inline] pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } } @@ -72,16 +75,19 @@ pub fn errno() -> i32 { // needed for readdir and syscall! #[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] #[allow(dead_code)] // but not all target cfgs actually end up using it +#[inline] pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } } #[cfg(target_os = "vxworks")] +#[inline] pub fn errno() -> i32 { unsafe { libc::errnoGet() } } #[cfg(target_os = "rtems")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -92,6 +98,7 @@ pub fn errno() -> i32 { } #[cfg(target_os = "dragonfly")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -103,6 +110,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "dragonfly")] #[allow(dead_code)] +#[inline] pub fn set_errno(e: i32) { unsafe extern "C" { #[thread_local] diff --git a/library/std/src/sys/pal/unix/process/mod.rs b/library/std/src/sys/pal/unix/process/mod.rs deleted file mode 100644 index 2751d51c44d..00000000000 --- a/library/std/src/sys/pal/unix/process/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes}; -pub use self::process_inner::{ExitStatus, ExitStatusError, Process}; -pub use crate::ffi::OsString as EnvKey; - -#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))] -mod process_common; - -#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] -mod process_unsupported; - -cfg_if::cfg_if! { - if #[cfg(target_os = "fuchsia")] { - #[path = "process_fuchsia.rs"] - mod process_inner; - mod zircon; - } else if #[cfg(target_os = "vxworks")] { - #[path = "process_vxworks.rs"] - mod process_inner; - } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] { - mod process_inner { - pub use super::process_unsupported::*; - } - } else { - #[path = "process_unix.rs"] - mod process_inner; - } -} diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 0ecccdc8812..34b3948e3f6 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -424,18 +424,32 @@ mod imp { let pages = PAGES.get_or_init(|| { use crate::sys::weak::dlsym; - dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int); + dlsym!( + fn sysctlbyname( + name: *const libc::c_char, + oldp: *mut libc::c_void, + oldlenp: *mut libc::size_t, + newp: *const libc::c_void, + newlen: libc::size_t, + ) -> libc::c_int; + ); let mut guard: usize = 0; let mut size = size_of_val(&guard); let oid = c"security.bsd.stack_guard_page"; match sysctlbyname.get() { - Some(fcn) if unsafe { - fcn(oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0) == 0 - } => guard, + Some(fcn) + if unsafe { + fcn( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) == 0 + } => + { + guard + } _ => 1, } }); @@ -585,6 +599,7 @@ mod imp { target_os = "openbsd", target_os = "solaris", target_os = "illumos", + target_os = "cygwin", )))] mod imp { pub unsafe fn init() {} @@ -597,3 +612,89 @@ mod imp { pub unsafe fn drop_handler(_data: *mut libc::c_void) {} } + +#[cfg(target_os = "cygwin")] +mod imp { + mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option<unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; + + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } + + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], + } + } + + /// Reserve stack space for use in stack overflow exceptions. + fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + } + + unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or("<unknown>"); + rtprintpanic!("\nthread '{name}' has overflowed its stack\n"); + }); + } + c::EXCEPTION_CONTINUE_SEARCH + } + } + + pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); + } + // Set the thread stack guarantee for the main thread. + reserve_stack(); + } + + pub unsafe fn cleanup() {} + + pub unsafe fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); + } + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index bffe2536299..9078dd1c231 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -143,8 +143,8 @@ impl Thread { pub fn set_name(name: &CStr) { unsafe { cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { - // Linux limits the allowed length of the name. + if #[cfg(any(target_os = "linux", target_os = "cygwin"))] { + // Linux and Cygwin limits the allowed length of the name. const TASK_COMM_LEN: usize = 16; let name = truncate_cstr::<{ TASK_COMM_LEN }>(name); } else { @@ -193,11 +193,12 @@ impl Thread { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn set_name(name: &CStr) { - weak! { + weak!( fn pthread_setname_np( - libc::pthread_t, *const libc::c_char - ) -> libc::c_int - } + thread: libc::pthread_t, + name: *const libc::c_char, + ) -> libc::c_int; + ); if let Some(f) = pthread_setname_np.get() { #[cfg(target_os = "nto")] @@ -346,6 +347,7 @@ impl Drop for Thread { target_os = "solaris", target_os = "illumos", target_os = "vxworks", + target_os = "cygwin", target_vendor = "apple", ))] fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] { @@ -761,7 +763,9 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628) // We shouldn't really be using such an internal symbol, but there's currently // no other way to account for the TLS size. - dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t); + dlsym!( + fn __pthread_get_minstack(attr: *const libc::pthread_attr_t) -> libc::size_t; + ); match __pthread_get_minstack.get() { None => libc::PTHREAD_STACK_MIN, diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index c0a3044660b..b8469b1681f 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -123,7 +123,12 @@ impl Timespec { // __clock_gettime64 was added to 32-bit arches in glibc 2.34, // and it handles both vDSO calls and ENOSYS fallbacks itself. - weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int); + weak!( + fn __clock_gettime64( + clockid: libc::clockid_t, + tp: *mut __timespec64, + ) -> libc::c_int; + ); if let Some(clock_gettime64) = __clock_gettime64.get() { let mut t = MaybeUninit::uninit(); diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index ce3f66a8374..e7f4e005cc4 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -29,7 +29,7 @@ use crate::{mem, ptr}; // We can use true weak linkage on ELF targets. #[cfg(all(unix, not(target_vendor = "apple")))] pub(crate) macro weak { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = { unsafe extern "C" { #[linkage = "extern_weak"] @@ -62,10 +62,16 @@ impl<F: Copy> ExternWeak<F> { } pub(crate) macro dlsym { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( - dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( + dlsym!( + #[link_name = stringify!($name)] + fn $name($($param : $t),*) -> $ret; + ); ), - (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( + ( + #[link_name = $sym:expr] + fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty; + ) => ( static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> = DlsymWeak::new(concat!($sym, '\0')); let $name = &DLSYM; @@ -143,15 +149,15 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { #[cfg(not(any(target_os = "linux", target_os = "android")))] pub(crate) macro syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( // FIXME(#115199): Rust currently omits weak function definitions // and its metadata from LLVM IR. #[no_sanitize(cfi)] - unsafe fn $name($($arg_name: $t),*) -> $ret { - weak! { fn $name($($t),*) -> $ret } + unsafe fn $name($($param: $t),*) -> $ret { + weak!(fn $name($($param: $t),*) -> $ret;); if let Some(fun) = $name.get() { - fun($($arg_name),*) + fun($($param),*) } else { super::os::set_errno(libc::ENOSYS); -1 @@ -162,16 +168,18 @@ pub(crate) macro syscall { #[cfg(any(target_os = "linux", target_os = "android"))] pub(crate) macro syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( - unsafe fn $name($($arg_name:$t),*) -> $ret { - weak! { fn $name($($t),*) -> $ret } + ( + fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty; + ) => ( + unsafe fn $name($($param: $t),*) -> $ret { + weak!(fn $name($($param: $t),*) -> $ret;); // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` // interposition, but if it's not found just use a raw syscall. if let Some(fun) = $name.get() { - fun($($arg_name),*) + fun($($param),*) } else { - libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } ) @@ -179,9 +187,9 @@ pub(crate) macro syscall { #[cfg(any(target_os = "linux", target_os = "android"))] pub(crate) macro raw_syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( - unsafe fn $name($($arg_name:$t),*) -> $ret { - libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( + unsafe fn $name($($param: $t),*) -> $ret { + libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } ) } diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index bcea699f3b2..38838b915b5 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -4,7 +4,6 @@ pub mod args; pub mod env; pub mod os; pub mod pipe; -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index c89832857dd..cdd613f76b6 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -23,8 +23,6 @@ pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index c85b03d4a89..cc569bb3daf 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -67,7 +67,7 @@ cfg_if::cfg_if! { } } -pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; +pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 3008ba88753..6ac28f1bf4f 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -20,8 +20,6 @@ pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../wasi/thread.rs"] pub mod thread; #[path = "../wasi/time.rs"] diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs index afdb159fe6f..dd5aff391fd 100644 --- a/library/std/src/sys/pal/wasm/atomics/thread.rs +++ b/library/std/src/sys/pal/wasm/atomics/thread.rs @@ -6,7 +6,7 @@ use crate::time::Duration; pub struct Thread(!); -pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; +pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 175fe75357f..8d39b70d039 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -23,8 +23,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../unsupported/time.rs"] pub mod time; diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 3447a0157e4..d973743639a 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -6,13 +6,13 @@ #[cfg(test)] mod tests; +use super::ensure_no_nuls; use super::os::current_exe; use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; use crate::os::windows::prelude::*; use crate::path::{Path, PathBuf}; use crate::sys::path::get_long_path; -use crate::sys::process::ensure_no_nuls; use crate::sys::{c, to_u16s}; use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 6eb68f3a3bc..bdf0cc2c59c 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -22,7 +22,6 @@ pub mod futex; pub mod handle; pub mod os; pub mod pipe; -pub mod process; pub mod thread; pub mod time; cfg_if::cfg_if! { @@ -287,6 +286,14 @@ pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] { } } +pub fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> crate::io::Result<T> { + if s.as_ref().encode_wide().any(|b| b == 0) { + Err(crate::io::const_error!(ErrorKind::InvalidInput, "nul byte found in provided data")) + } else { + Ok(s) + } +} + pub trait IsZero { fn is_zero(&self) -> bool; } diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index 8521cf4162f..c7852464922 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -74,7 +74,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res let ours; let mut name; let mut tries = 0; - let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS; loop { tries += 1; name = format!( @@ -96,7 +95,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res c::PIPE_TYPE_BYTE | c::PIPE_READMODE_BYTE | c::PIPE_WAIT - | reject_remote_clients_flag, + | c::PIPE_REJECT_REMOTE_CLIENTS, 1, PIPE_BUFFER_CAPACITY, PIPE_BUFFER_CAPACITY, @@ -112,30 +111,15 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res // // Don't try again too much though as this could also perhaps be a // legit error. - // If `ERROR_INVALID_PARAMETER` is returned, this probably means we're - // running on pre-Vista version where `PIPE_REJECT_REMOTE_CLIENTS` is - // not supported, so we continue retrying without it. This implies - // reduced security on Windows versions older than Vista by allowing - // connections to this pipe from remote machines. - // Proper fix would increase the number of FFI imports and introduce - // significant amount of Windows XP specific code with no clean - // testing strategy - // For more info, see https://github.com/rust-lang/rust/pull/37677. if handle == c::INVALID_HANDLE_VALUE { let error = api::get_last_error(); - if tries < 10 { - if error == WinError::ACCESS_DENIED { - continue; - } else if reject_remote_clients_flag != 0 - && error == WinError::INVALID_PARAMETER - { - reject_remote_clients_flag = 0; - tries -= 1; - continue; - } + if tries < 10 && error == WinError::ACCESS_DENIED { + continue; + } else { + return Err(io::Error::from_raw_os_error(error.code as i32)); } - return Err(io::Error::from_raw_os_error(error.code as i32)); } + ours = Handle::from_raw_handle(handle); break; } diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 7d823012ad1..58926e2beb1 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -6,8 +6,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 499e2787201..4659dad16e8 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -17,8 +17,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../unsupported/thread.rs"] pub mod thread; #[path = "../unsupported/time.rs"] diff --git a/library/std/src/sys/process/mod.rs b/library/std/src/sys/process/mod.rs new file mode 100644 index 00000000000..92cfac7f47c --- /dev/null +++ b/library/std/src/sys/process/mod.rs @@ -0,0 +1,19 @@ +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod unix; + use unix as imp; + } else if #[cfg(target_os = "windows")] { + mod windows; + use windows as imp; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + use uefi as imp; + } else { + mod unsupported; + use unsupported as imp; + } +} + +pub use imp::{ + Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio, StdioPipes, +}; diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/process/uefi.rs index 1203d51e531..b46418ae9bb 100644 --- a/library/std/src/sys/pal/uefi/process.rs +++ b/library/std/src/sys/process/uefi.rs @@ -1,12 +1,13 @@ use r_efi::protocols::simple_text_output; -use super::helpers; use crate::collections::BTreeMap; pub use crate::ffi::OsString as EnvKey; use crate::ffi::{OsStr, OsString}; use crate::num::{NonZero, NonZeroI32}; use crate::path::Path; 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::sys_common::process::{CommandEnv, CommandEnvs}; @@ -225,7 +226,7 @@ impl ExitStatus { impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let err_str = super::os::error_string(self.0.as_usize()); + let err_str = error_string(self.0.as_usize()); write!(f, "{}", err_str) } } @@ -241,7 +242,7 @@ pub struct ExitStatusError(r_efi::efi::Status); impl fmt::Debug for ExitStatusError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let err_str = super::os::error_string(self.0.as_usize()); + let err_str = error_string(self.0.as_usize()); write!(f, "{}", err_str) } } @@ -335,7 +336,6 @@ impl<'a> fmt::Debug for CommandArgs<'a> { mod uefi_command_internal { use r_efi::protocols::{loaded_image, simple_text_output}; - use super::super::helpers; use crate::ffi::{OsStr, OsString}; use crate::io::{self, const_error}; use crate::mem::MaybeUninit; @@ -343,7 +343,7 @@ mod uefi_command_internal { use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::ptr::NonNull; use crate::slice; - use crate::sys::pal::uefi::helpers::OwnedTable; + use crate::sys::pal::helpers::{self, OwnedTable}; use crate::sys_common::wstr::WStrUnits; pub struct Image { diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/process/unix/common.rs index a1c747c8df4..8bc17f31491 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -54,7 +54,7 @@ cfg_if::cfg_if! { let bit = (signum - 1) as usize; if set.is_null() || bit >= (8 * size_of::<sigset_t>()) { - crate::sys::pal::unix::os::set_errno(libc::EINVAL); + crate::sys::pal::os::set_errno(libc::EINVAL); return -1; } let raw = slice::from_raw_parts_mut( diff --git a/library/std/src/sys/pal/unix/process/process_common/tests.rs b/library/std/src/sys/process/unix/common/tests.rs index e5c8dd6e341..e5c8dd6e341 100644 --- a/library/std/src/sys/pal/unix/process/process_common/tests.rs +++ b/library/std/src/sys/process/unix/common/tests.rs diff --git a/library/std/src/sys/pal/unix/process/process_fuchsia.rs b/library/std/src/sys/process/unix/fuchsia.rs index 05c9ace470e..0de32ecffd4 100644 --- a/library/std/src/sys/pal/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/process/unix/fuchsia.rs @@ -1,8 +1,8 @@ use libc::{c_int, size_t}; +use super::common::*; use crate::num::NonZero; -use crate::sys::process::process_common::*; -use crate::sys::process::zircon::{Handle, zx_handle_t}; +use crate::sys::pal::fuchsia::*; use crate::{fmt, io, mem, ptr}; //////////////////////////////////////////////////////////////////////////////// @@ -58,8 +58,6 @@ impl Command { stdio: ChildPipes, maybe_envp: Option<&CStringArray>, ) -> io::Result<zx_handle_t> { - use crate::sys::process::zircon::*; - let envp = match maybe_envp { // None means to clone the current environment, which is done in the // flags below. @@ -152,8 +150,6 @@ impl Process { } pub fn kill(&mut self) -> io::Result<()> { - use crate::sys::process::zircon::*; - unsafe { zx_cvt(zx_task_kill(self.handle.raw()))?; } @@ -162,8 +158,6 @@ impl Process { } pub fn wait(&mut self) -> io::Result<ExitStatus> { - use crate::sys::process::zircon::*; - let mut proc_info: zx_info_process_t = Default::default(); let mut actual: size_t = 0; let mut avail: size_t = 0; @@ -194,8 +188,6 @@ impl Process { } pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { - use crate::sys::process::zircon::*; - let mut proc_info: zx_info_process_t = Default::default(); let mut actual: size_t = 0; let mut avail: size_t = 0; @@ -251,7 +243,7 @@ impl ExitStatus { None } - // FIXME: The actually-Unix implementation in process_unix.rs uses WSTOPSIG, WCOREDUMP et al. + // FIXME: The actually-Unix implementation in unix.rs uses WSTOPSIG, WCOREDUMP et al. // I infer from the implementation of `success`, `code` and `signal` above that these are not // available on Fuchsia. // diff --git a/library/std/src/sys/process/unix/mod.rs b/library/std/src/sys/process/unix/mod.rs new file mode 100644 index 00000000000..2e8b38f7de1 --- /dev/null +++ b/library/std/src/sys/process/unix/mod.rs @@ -0,0 +1,23 @@ +#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))] +mod common; + +cfg_if::cfg_if! { + if #[cfg(target_os = "fuchsia")] { + mod fuchsia; + use fuchsia as imp; + } else if #[cfg(target_os = "vxworks")] { + mod vxworks; + use vxworks as imp; + } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] { + mod unsupported; + use unsupported as imp; + } else { + mod unix; + use unix as imp; + } +} + +pub use imp::{ExitStatus, ExitStatusError, Process}; + +pub use self::common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes}; +pub use crate::ffi::OsString as EnvKey; diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/process/unix/unix.rs index f19512233d8..191a09c8da9 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -10,12 +10,12 @@ use libc::{c_int, pid_t}; )))] use libc::{gid_t, uid_t}; +use super::common::*; use crate::io::{self, Error, ErrorKind}; use crate::num::NonZero; use crate::sys::cvt; #[cfg(target_os = "linux")] -use crate::sys::pal::unix::linux::pidfd::PidFd; -use crate::sys::process::process_common::*; +use crate::sys::pal::linux::pidfd::PidFd; use crate::{fmt, mem, sys}; cfg_if::cfg_if! { @@ -461,18 +461,20 @@ impl Command { if #[cfg(target_os = "linux")] { use crate::sys::weak::weak; - weak! { + weak!( fn pidfd_spawnp( - *mut libc::c_int, - *const libc::c_char, - *const libc::posix_spawn_file_actions_t, - *const libc::posix_spawnattr_t, - *const *mut libc::c_char, - *const *mut libc::c_char - ) -> libc::c_int - } + pidfd: *mut libc::c_int, + path: *const libc::c_char, + file_actions: *const libc::posix_spawn_file_actions_t, + attrp: *const libc::posix_spawnattr_t, + argv: *const *mut libc::c_char, + envp: *const *mut libc::c_char, + ) -> libc::c_int; + ); - weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int } + weak!( + fn pidfd_getpid(pidfd: libc::c_int) -> libc::c_int; + ); static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0); const UNKNOWN: u8 = 0; @@ -593,19 +595,19 @@ impl Command { // https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addchdir.html. // The _np version is more widely available, though, so try that first. - weak! { + weak!( fn posix_spawn_file_actions_addchdir_np( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int - } + file_actions: *mut libc::posix_spawn_file_actions_t, + path: *const libc::c_char, + ) -> libc::c_int; + ); - weak! { + weak!( fn posix_spawn_file_actions_addchdir( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int - } + file_actions: *mut libc::posix_spawn_file_actions_t, + path: *const libc::c_char, + ) -> libc::c_int; + ); posix_spawn_file_actions_addchdir_np .get() @@ -1051,7 +1053,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero::try_from(self.0) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), @@ -1232,10 +1234,9 @@ impl ExitStatusError { #[cfg(target_os = "linux")] mod linux_child_ext { - + use crate::io::ErrorKind; use crate::os::linux::process as os; - use crate::sys::pal::unix::ErrorKind; - use crate::sys::pal::unix::linux::pidfd as imp; + use crate::sys::pal::linux::pidfd as imp; use crate::sys_common::FromInner; use crate::{io, mem}; @@ -1261,10 +1262,9 @@ mod linux_child_ext { } #[cfg(test)] -#[path = "process_unix/tests.rs"] mod tests; -// See [`process_unsupported_wait_status::compare_with_linux`]; +// See [`unsupported_wait_status::compare_with_linux`]; #[cfg(all(test, target_os = "linux"))] -#[path = "process_unsupported/wait_status.rs"] -mod process_unsupported_wait_status; +#[path = "unsupported/wait_status.rs"] +mod unsupported_wait_status; diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs index f4d6ac6b4e3..f4d6ac6b4e3 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/process/unix/unix/tests.rs diff --git a/library/std/src/sys/pal/unix/process/process_unsupported.rs b/library/std/src/sys/process/unix/unsupported.rs index c58548835ff..78d270923cf 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported.rs +++ b/library/std/src/sys/process/unix/unsupported.rs @@ -1,9 +1,9 @@ use libc::{c_int, pid_t}; +use super::common::*; use crate::io; use crate::num::NonZero; -use crate::sys::pal::unix::unsupported::*; -use crate::sys::process::process_common::*; +use crate::sys::pal::unsupported::*; //////////////////////////////////////////////////////////////////////////////// // Command diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs b/library/std/src/sys/process/unix/unsupported/wait_status.rs index f04036bde49..f348d557e4b 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs +++ b/library/std/src/sys/process/unix/unsupported/wait_status.rs @@ -7,7 +7,7 @@ use crate::ffi::c_int; use crate::fmt; use crate::num::NonZero; -/// Emulated wait status for use by `process_unsupported.rs` +/// Emulated wait status for use by `unsupported.rs` /// /// Uses the "traditional unix" encoding. For use on platfors which are `#[cfg(unix)]` /// but do not actually support subprocesses at all. @@ -48,7 +48,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero::try_from(self.wait_status) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), @@ -79,5 +79,6 @@ impl ExitStatus { } #[cfg(test)] -#[path = "wait_status/tests.rs"] // needed because of strange layout of process_unsupported +#[path = "wait_status/tests.rs"] +// needed because this module is also imported through #[path] for testing purposes mod tests; diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs b/library/std/src/sys/process/unix/unsupported/wait_status/tests.rs index 5132eab10a1..0d9232fac5e 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs +++ b/library/std/src/sys/process/unix/unsupported/wait_status/tests.rs @@ -1,4 +1,4 @@ -// Note that tests in this file are run on Linux as well as on platforms using process_unsupported +// Note that tests in this file are run on Linux as well as on platforms using unsupported // Test that our emulation exactly matches Linux // diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index e2c1b6a0326..5f1727789a1 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -1,11 +1,11 @@ #![forbid(unsafe_op_in_unsafe_fn)] use libc::{self, RTP_ID, c_char, c_int}; +use super::common::*; use crate::io::{self, ErrorKind}; use crate::num::NonZero; use crate::sys::cvt; -use crate::sys::pal::unix::thread; -use crate::sys::process::process_common::*; +use crate::sys::pal::thread; use crate::{fmt, sys}; //////////////////////////////////////////////////////////////////////////////// @@ -200,7 +200,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero::try_from(self.0) { Ok(failure) => Err(ExitStatusError(failure)), Err(_) => Ok(()), diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/process/unsupported.rs index fee81744f09..fee81744f09 100644 --- a/library/std/src/sys/pal/unsupported/process.rs +++ b/library/std/src/sys/process/unsupported.rs diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/process/windows.rs index 50e4baba607..06c15e08f3f 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/process/windows.rs @@ -5,11 +5,10 @@ mod tests; use core::ffi::c_void; -use super::api::{self, WinError}; use crate::collections::BTreeMap; use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; -use crate::io::{self, Error, ErrorKind}; +use crate::io::{self, Error}; use crate::num::NonZero; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle}; @@ -20,6 +19,8 @@ use crate::sys::args::{self, Arg}; use crate::sys::c::{self, EXIT_FAILURE, EXIT_SUCCESS}; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; +use crate::sys::pal::api::{self, WinError}; +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; @@ -142,14 +143,6 @@ impl AsRef<OsStr> for EnvKey { } } -pub(crate) fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> io::Result<T> { - if s.as_ref().encode_wide().any(|b| b == 0) { - Err(io::const_error!(ErrorKind::InvalidInput, "nul byte found in provided data")) - } else { - Ok(s) - } -} - pub struct Command { program: OsString, args: Vec<Arg>, @@ -279,7 +272,7 @@ impl Command { let is_batch_file = if path::is_verbatim(&program) { has_bat_extension(&program[..program.len() - 1]) } else { - super::fill_utf16_buf( + fill_utf16_buf( |buffer, size| unsafe { // resolve the path so we can test the final file name. c::GetFullPathNameW(program.as_ptr(), size, buffer, ptr::null_mut()) @@ -521,7 +514,7 @@ where // 3 & 4. System paths // SAFETY: This uses `fill_utf16_buf` to safely call the OS functions. unsafe { - if let Ok(Some(path)) = super::fill_utf16_buf( + if let Ok(Some(path)) = fill_utf16_buf( |buf, size| c::GetSystemDirectoryW(buf, size), |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { @@ -529,7 +522,7 @@ where } #[cfg(not(target_vendor = "uwp"))] { - if let Ok(Some(path)) = super::fill_utf16_buf( + if let Ok(Some(path)) = fill_utf16_buf( |buf, size| c::GetWindowsDirectoryW(buf, size), |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { @@ -851,10 +844,8 @@ fn make_command_line(argv0: &OsStr, args: &[Arg], force_quotes: bool) -> io::Res // Get `cmd.exe` for use with bat scripts, encoded as a UTF-16 string. fn command_prompt() -> io::Result<Vec<u16>> { - let mut system: Vec<u16> = super::fill_utf16_buf( - |buf, size| unsafe { c::GetSystemDirectoryW(buf, size) }, - |buf| buf.into(), - )?; + let mut system: Vec<u16> = + fill_utf16_buf(|buf, size| unsafe { c::GetSystemDirectoryW(buf, size) }, |buf| buf.into())?; system.extend("\\cmd.exe".encode_utf16().chain([0])); Ok(system) } diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/process/windows/tests.rs index 1377e12162f..1377e12162f 100644 --- a/library/std/src/sys/pal/windows/process/tests.rs +++ b/library/std/src/sys/process/windows/tests.rs diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index e3cb79285cd..c0591ec0c15 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -73,13 +73,13 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { // A weak symbol allows interposition, e.g. for perf measurements that want to // disable randomness for consistency. Otherwise, we'll try a raw syscall. // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28) - syscall! { + syscall!( fn getrandom( buffer: *mut libc::c_void, length: libc::size_t, - flags: libc::c_uint - ) -> libc::ssize_t - } + flags: libc::c_uint, + ) -> libc::ssize_t; + ); static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true); static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true); diff --git a/library/std/src/sys/random/trusty.rs b/library/std/src/sys/random/trusty.rs index da6ca3eea24..e4db24695f8 100644 --- a/library/std/src/sys/random/trusty.rs +++ b/library/std/src/sys/random/trusty.rs @@ -1,4 +1,4 @@ -extern "C" { +unsafe extern "C" { fn trusty_rng_secure_rand(randomBuffer: *mut core::ffi::c_void, randomBufferLen: libc::size_t); } diff --git a/library/std/src/sys/stdio/sgx.rs b/library/std/src/sys/stdio/sgx.rs index 1894c098d18..2cf47f49192 100644 --- a/library/std/src/sys/stdio/sgx.rs +++ b/library/std/src/sys/stdio/sgx.rs @@ -3,9 +3,9 @@ use fortanix_sgx_abi as abi; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::sys::fd::FileDesc; -pub struct Stdin(()); -pub struct Stdout(()); -pub struct Stderr(()); +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R { let fd = FileDesc::new(fd); @@ -16,7 +16,7 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R { impl Stdin { pub const fn new() -> Stdin { - Stdin(()) + Stdin } } @@ -41,7 +41,7 @@ impl io::Read for Stdin { impl Stdout { pub const fn new() -> Stdout { - Stdout(()) + Stdout } } @@ -66,7 +66,7 @@ impl io::Write for Stdout { impl Stderr { pub const fn new() -> Stderr { - Stderr(()) + Stderr } } diff --git a/library/std/src/sys/stdio/solid.rs b/library/std/src/sys/stdio/solid.rs index a2ff4bb212f..55daf0b54b9 100644 --- a/library/std/src/sys/stdio/solid.rs +++ b/library/std/src/sys/stdio/solid.rs @@ -1,22 +1,13 @@ +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use crate::io; use crate::sys::pal::abi; -pub struct Stdin; +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; -pub struct Stderr; -struct PanicOutput; - -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} +pub type Stderr = Stdout; impl Stdout { pub const fn new() -> Stdout { @@ -35,46 +26,12 @@ impl io::Write for Stdout { } } -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl PanicOutput { - pub const fn new() -> PanicOutput { - PanicOutput - } -} - -impl io::Write for PanicOutput { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true } pub fn panic_output() -> Option<impl io::Write> { - Some(PanicOutput::new()) + Some(Stderr::new()) } diff --git a/library/std/src/sys/stdio/teeos.rs b/library/std/src/sys/stdio/teeos.rs index 67e251812da..27b3292bf8f 100644 --- a/library/std/src/sys/stdio/teeos.rs +++ b/library/std/src/sys/stdio/teeos.rs @@ -1,12 +1,16 @@ #![deny(unsafe_op_in_unsafe_fn)] +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use core::arch::asm; use crate::io; -pub struct Stdin; +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; -pub struct Stderr; +pub type Stderr = Stdout; const KCALL_DEBUG_CMD_PUT_BYTES: i64 = 2; @@ -25,27 +29,6 @@ unsafe fn debug_call(cap_ref: u64, call_no: i64, arg1: u64, arg2: u64) -> i32 { ret as i32 } -fn print_buf(s: &[u8]) -> io::Result<usize> { - // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. - const MAX_LEN: usize = 512; - let len = if s.len() > MAX_LEN { MAX_LEN } else { s.len() }; - let result = unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, s.as_ptr() as u64, len as u64) }; - - if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } -} - -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} - impl Stdout { pub const fn new() -> Stdout { Stdout @@ -54,23 +37,13 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - print_buf(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} + // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. + const MAX_LEN: usize = 512; + let len = buf.len().min(MAX_LEN); + let result = + unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, buf.as_ptr() as u64, len as u64) }; -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - print_buf(buf) + if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } } fn flush(&mut self) -> io::Result<()> { @@ -78,7 +51,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { err.raw_os_error() == Some(libc::EBADF as i32) diff --git a/library/std/src/sys/stdio/unix.rs b/library/std/src/sys/stdio/unix.rs index 08a06e0da9f..8535e3539e9 100644 --- a/library/std/src/sys/stdio/unix.rs +++ b/library/std/src/sys/stdio/unix.rs @@ -11,13 +11,13 @@ use crate::os::hermit::io::FromRawFd; use crate::os::unix::io::FromRawFd; use crate::sys::fd::FileDesc; -pub struct Stdin(()); -pub struct Stdout(()); -pub struct Stderr(()); +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; impl Stdin { pub const fn new() -> Stdin { - Stdin(()) + Stdin } } @@ -42,7 +42,7 @@ impl io::Read for Stdin { impl Stdout { pub const fn new() -> Stdout { - Stdout(()) + Stdout } } @@ -68,7 +68,7 @@ impl io::Write for Stdout { impl Stderr { pub const fn new() -> Stderr { - Stderr(()) + Stderr } } diff --git a/library/std/src/sys/stdio/unsupported.rs b/library/std/src/sys/stdio/unsupported.rs index b5e3f5be988..177264f5c10 100644 --- a/library/std/src/sys/stdio/unsupported.rs +++ b/library/std/src/sys/stdio/unsupported.rs @@ -1,8 +1,8 @@ -use crate::io; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; pub struct Stdin; pub struct Stdout; -pub struct Stderr; +pub type Stderr = Stdout; impl Stdin { pub const fn new() -> Stdin { @@ -11,9 +11,47 @@ impl Stdin { } impl io::Read for Stdin { + #[inline] fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } + + #[inline] + fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + // Do not force `Chain<Empty, T>` or `Chain<T, Empty>` to use vectored + // reads, unless the other reader is vectored. + false + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> { + Ok(0) + } } impl Stdout { @@ -23,26 +61,35 @@ impl Stdout { } impl io::Write for Stdout { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } - fn flush(&mut self) -> io::Result<()> { - Ok(()) + #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + let total_len = bufs.iter().map(|b| b.len()).sum(); + Ok(total_len) } -} -impl Stderr { - pub const fn new() -> Stderr { - Stderr + #[inline] + fn is_write_vectored(&self) -> bool { + true } -} -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - Ok(buf.len()) + #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) } + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + // Keep the default write_fmt so the `fmt::Arguments` are still evaluated. + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } diff --git a/library/std/src/sys/stdio/xous.rs b/library/std/src/sys/stdio/xous.rs index 71736145221..a92167642b7 100644 --- a/library/std/src/sys/stdio/xous.rs +++ b/library/std/src/sys/stdio/xous.rs @@ -1,27 +1,18 @@ -use crate::io; - -pub struct Stdin; -pub struct Stdout {} -pub struct Stderr; +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; +use crate::io; use crate::os::xous::ffi::{Connection, lend, try_lend, try_scalar}; use crate::os::xous::services::{LogLend, LogScalar, log_server, try_connect}; -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} +pub type Stdin = unsupported_stdio::Stdin; +pub struct Stdout; +pub struct Stderr; impl Stdout { pub const fn new() -> Stdout { - Stdout {} + Stdout } } @@ -73,7 +64,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true diff --git a/library/std/src/thread/spawnhook.rs b/library/std/src/thread/spawnhook.rs index 99b5ad9cb9f..98f471ad54b 100644 --- a/library/std/src/thread/spawnhook.rs +++ b/library/std/src/thread/spawnhook.rs @@ -113,18 +113,23 @@ where pub(super) fn run_spawn_hooks(thread: &Thread) -> ChildSpawnHooks { // Get a snapshot of the spawn hooks. // (Increments the refcount to the first node.) - let hooks = SPAWN_HOOKS.with(|hooks| { + if let Ok(hooks) = SPAWN_HOOKS.try_with(|hooks| { let snapshot = hooks.take(); hooks.set(snapshot.clone()); snapshot - }); - // Iterate over the hooks, run them, and collect the results in a vector. - let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref()) - .map(|hook| (hook.hook)(thread)) - .collect(); - // Pass on the snapshot of the hooks and the results to the new thread, - // which will then run SpawnHookResults::run(). - ChildSpawnHooks { hooks, to_run } + }) { + // Iterate over the hooks, run them, and collect the results in a vector. + let to_run: Vec<_> = iter::successors(hooks.first.as_deref(), |hook| hook.next.as_deref()) + .map(|hook| (hook.hook)(thread)) + .collect(); + // Pass on the snapshot of the hooks and the results to the new thread, + // which will then run SpawnHookResults::run(). + ChildSpawnHooks { hooks, to_run } + } else { + // TLS has been destroyed. Skip running the hooks. + // See https://github.com/rust-lang/rust/issues/138696 + ChildSpawnHooks::default() + } } /// The results of running the spawn hooks. diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 06c347af181..59ec48a57d1 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -108,6 +108,7 @@ fn test_is_finished() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_join_panic() { match thread::spawn(move || panic!()).join() { result::Result::Err(_) => (), @@ -210,6 +211,7 @@ fn test_simple_newsched_spawn() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_message_string_literal() { match thread::spawn(move || { panic!("static string"); @@ -226,6 +228,7 @@ fn test_try_panic_message_string_literal() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_owned_str() { match thread::spawn(move || { panic_any("owned string".to_string()); @@ -242,6 +245,7 @@ fn test_try_panic_any_message_owned_str() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_any() { match thread::spawn(move || { panic_any(Box::new(413u16) as Box<dyn Any + Send>); @@ -260,6 +264,7 @@ fn test_try_panic_any_message_any() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_unit_struct() { struct Juju; |
