summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:19 +0000
commita0b8f38ab54ac451646aa00cd5e91b6c76f22a84 (patch)
treefc451898ccaf445814e26b46664d78702178101d /library/std/src/sys
parentAdding debian version 1.71.1+dfsg1-2. (diff)
downloadrustc-a0b8f38ab54ac451646aa00cd5e91b6c76f22a84.tar.xz
rustc-a0b8f38ab54ac451646aa00cd5e91b6c76f22a84.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/common/small_c_string.rs2
-rw-r--r--library/std/src/sys/common/tests.rs4
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs22
-rw-r--r--library/std/src/sys/common/thread_local/mod.rs21
-rw-r--r--library/std/src/sys/unix/args.rs4
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs17
-rw-r--r--library/std/src/sys/unix/fs.rs75
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs4
-rw-r--r--library/std/src/sys/unix/l4re.rs6
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs3
-rw-r--r--library/std/src/sys/unix/mod.rs15
-rw-r--r--library/std/src/sys/unix/net.rs8
-rw-r--r--library/std/src/sys/unix/os.rs12
-rw-r--r--library/std/src/sys/unix/os_str.rs13
-rw-r--r--library/std/src/sys/unix/os_str/tests.rs9
-rw-r--r--library/std/src/sys/unix/path.rs2
-rw-r--r--library/std/src/sys/unix/process/process_common.rs4
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs152
-rw-r--r--library/std/src/sys/unix/process/process_vxworks.rs7
-rw-r--r--library/std/src/sys/unix/rand.rs3
-rw-r--r--library/std/src/sys/unix/thread.rs34
-rw-r--r--library/std/src/sys/unix/thread_parking/pthread.rs6
-rw-r--r--library/std/src/sys/unix/time.rs6
-rw-r--r--library/std/src/sys/unix/weak.rs4
-rw-r--r--library/std/src/sys/wasi/fd.rs6
-rw-r--r--library/std/src/sys/wasi/fs.rs4
-rw-r--r--library/std/src/sys/windows/args.rs6
-rw-r--r--library/std/src/sys/windows/c.rs100
-rw-r--r--library/std/src/sys/windows/c/windows_sys.lst5
-rw-r--r--library/std/src/sys/windows/c/windows_sys.rs26
-rw-r--r--library/std/src/sys/windows/net.rs2
-rw-r--r--library/std/src/sys/windows/os_str.rs12
-rw-r--r--library/std/src/sys/windows/path.rs42
-rw-r--r--library/std/src/sys/windows/process.rs15
-rw-r--r--library/std/src/sys/windows/rand.rs5
-rw-r--r--library/std/src/sys/windows/stdio.rs7
-rw-r--r--library/std/src/sys/windows/stdio/tests.rs6
38 files changed, 518 insertions, 162 deletions
diff --git a/library/std/src/sys/common/small_c_string.rs b/library/std/src/sys/common/small_c_string.rs
index 01acd5191..963d17a47 100644
--- a/library/std/src/sys/common/small_c_string.rs
+++ b/library/std/src/sys/common/small_c_string.rs
@@ -19,7 +19,7 @@ pub fn run_path_with_cstr<T, F>(path: &Path, f: F) -> io::Result<T>
where
F: FnOnce(&CStr) -> io::Result<T>,
{
- run_with_cstr(path.as_os_str().bytes(), f)
+ run_with_cstr(path.as_os_str().as_os_str_bytes(), f)
}
#[inline]
diff --git a/library/std/src/sys/common/tests.rs b/library/std/src/sys/common/tests.rs
index fb6f5d6af..0a1cbcbe8 100644
--- a/library/std/src/sys/common/tests.rs
+++ b/library/std/src/sys/common/tests.rs
@@ -8,7 +8,7 @@ use core::iter::repeat;
fn stack_allocation_works() {
let path = Path::new("abc");
let result = run_path_with_cstr(path, |p| {
- assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap());
+ assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap());
Ok(42)
});
assert_eq!(result.unwrap(), 42);
@@ -25,7 +25,7 @@ fn heap_allocation_works() {
let path = repeat("a").take(384).collect::<String>();
let path = Path::new(&path);
let result = run_path_with_cstr(path, |p| {
- assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap());
+ assert_eq!(p, &*CString::new(path.as_os_str().as_os_str_bytes()).unwrap());
Ok(42)
});
assert_eq!(result.unwrap(), 42);
diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs
index 447044a79..bc5da1a18 100644
--- a/library/std/src/sys/common/thread_local/fast_local.rs
+++ b/library/std/src/sys/common/thread_local/fast_local.rs
@@ -33,20 +33,21 @@ pub macro thread_local_inner {
// 1 == dtor registered, dtor not run
// 2 == dtor registered and is running or has run
#[thread_local]
- static mut STATE: $crate::primitive::u8 = 0;
+ static STATE: $crate::cell::Cell<$crate::primitive::u8> = $crate::cell::Cell::new(0);
+ // Safety: Performs `drop_in_place(ptr as *mut $t)`, and requires
+ // all that comes with it.
unsafe extern "C" fn destroy(ptr: *mut $crate::primitive::u8) {
- let ptr = ptr as *mut $t;
-
- unsafe {
- $crate::debug_assert_eq!(STATE, 1);
- STATE = 2;
- $crate::ptr::drop_in_place(ptr);
- }
+ $crate::thread::local_impl::abort_on_dtor_unwind(|| {
+ let old_state = STATE.replace(2);
+ $crate::debug_assert_eq!(old_state, 1);
+ // Safety: safety requirement is passed on to caller.
+ unsafe { $crate::ptr::drop_in_place(ptr.cast::<$t>()); }
+ });
}
unsafe {
- match STATE {
+ match STATE.get() {
// 0 == we haven't registered a destructor, so do
// so now.
0 => {
@@ -54,7 +55,7 @@ pub macro thread_local_inner {
$crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
destroy,
);
- STATE = 1;
+ STATE.set(1);
$crate::option::Option::Some(&VAL)
}
// 1 == the destructor is registered and the value
@@ -148,7 +149,6 @@ impl<T> fmt::Debug for Key<T> {
f.debug_struct("Key").finish_non_exhaustive()
}
}
-
impl<T> Key<T> {
pub const fn new() -> Key<T> {
Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) }
diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs
index 77f645883..975509bd4 100644
--- a/library/std/src/sys/common/thread_local/mod.rs
+++ b/library/std/src/sys/common/thread_local/mod.rs
@@ -101,3 +101,24 @@ mod lazy {
}
}
}
+
+/// Run a callback in a scenario which must not unwind (such as a `extern "C"
+/// fn` declared in a user crate). If the callback unwinds anyway, then
+/// `rtabort` with a message about thread local panicking on drop.
+#[inline]
+pub fn abort_on_dtor_unwind(f: impl FnOnce()) {
+ // Using a guard like this is lower cost.
+ let guard = DtorUnwindGuard;
+ f();
+ core::mem::forget(guard);
+
+ struct DtorUnwindGuard;
+ impl Drop for DtorUnwindGuard {
+ #[inline]
+ fn drop(&mut self) {
+ // This is not terribly descriptive, but it doesn't need to be as we'll
+ // already have printed a panic message at this point.
+ rtabort!("thread local panicked on drop");
+ }
+ }
+}
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 9ed4d9c1e..eafd6821f 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -168,7 +168,7 @@ mod imp {
}
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
mod imp {
use super::Args;
use crate::ffi::CStr;
@@ -209,7 +209,7 @@ mod imp {
// for i in (0..[args count])
// res.push([args objectAtIndex:i])
// res
- #[cfg(any(target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn args() -> Args {
use crate::ffi::OsString;
use crate::mem;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 8c3ef88d8..929e9dae7 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -31,6 +31,17 @@ pub mod os {
pub const EXE_EXTENSION: &str = "";
}
+#[cfg(target_os = "tvos")]
+pub mod os {
+ pub const FAMILY: &str = "unix";
+ pub const OS: &str = "tvos";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".dylib";
+ pub const DLL_EXTENSION: &str = "dylib";
+ pub const EXE_SUFFIX: &str = "";
+ pub const EXE_EXTENSION: &str = "";
+}
+
#[cfg(target_os = "watchos")]
pub mod os {
pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index cb630eede..85e020ae4 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -44,6 +44,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
+ target_os = "tvos",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
@@ -69,6 +70,7 @@ const fn max_iov() -> usize {
target_os = "emscripten",
target_os = "freebsd",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -181,6 +183,7 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -222,6 +225,7 @@ impl FileDesc {
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios",
+ target_os = "tvos",
target_os = "macos",
))]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
@@ -320,6 +324,7 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -361,6 +366,7 @@ impl FileDesc {
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios",
+ target_os = "tvos",
target_os = "macos",
))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
@@ -402,7 +408,10 @@ impl FileDesc {
}
}
#[cfg(any(
- all(target_env = "newlib", not(any(target_os = "espidf", target_os = "horizon"))),
+ all(
+ target_env = "newlib",
+ not(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))
+ ),
target_os = "solaris",
target_os = "illumos",
target_os = "emscripten",
@@ -424,10 +433,10 @@ impl FileDesc {
Ok(())
}
}
- #[cfg(any(target_os = "espidf", target_os = "horizon"))]
+ #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
pub fn set_cloexec(&self) -> io::Result<()> {
- // FD_CLOEXEC is not supported in ESP-IDF and Horizon OS but there's no need to,
- // because neither supports spawning processes.
+ // FD_CLOEXEC is not supported in ESP-IDF, Horizon OS and Vita but there's no need to,
+ // because none of them supports spawning processes.
Ok(())
}
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 09e9ae272..fbc7f04ce 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -15,6 +15,7 @@ use crate::mem;
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
))]
use crate::mem::MaybeUninit;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
@@ -31,6 +32,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
all(target_os = "linux", target_env = "gnu"),
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
))]
use crate::sys::weak::syscall;
@@ -42,6 +44,7 @@ use libc::{c_int, mode_t};
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "solaris",
all(target_os = "linux", target_env = "gnu")
@@ -58,6 +61,7 @@ use libc::fstatat64;
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
))]
use libc::readdir as readdir64;
#[cfg(target_os = "linux")]
@@ -74,6 +78,7 @@ use libc::readdir64_r;
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
)))]
use libc::readdir_r as readdir64_r;
#[cfg(target_os = "android")]
@@ -283,6 +288,7 @@ unsafe impl Sync for Dir {}
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita"
))]
pub struct DirEntry {
dir: Arc<InnerReadDir>,
@@ -304,10 +310,16 @@ pub struct DirEntry {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
))]
struct dirent64_min {
d_ino: u64,
- #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))]
+ #[cfg(not(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "nto",
+ target_os = "vita"
+ )))]
d_type: u8,
}
@@ -319,6 +331,7 @@ struct dirent64_min {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
)))]
pub struct DirEntry {
dir: Arc<InnerReadDir>,
@@ -349,7 +362,7 @@ pub struct FilePermissions {
pub struct FileTimes {
accessed: Option<SystemTime>,
modified: Option<SystemTime>,
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
created: Option<SystemTime>,
}
@@ -508,6 +521,7 @@ impl FileAttr {
target_os = "openbsd",
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
))]
pub fn created(&self) -> io::Result<SystemTime> {
@@ -519,7 +533,9 @@ impl FileAttr {
target_os = "openbsd",
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
+ target_os = "vita",
)))]
pub fn created(&self) -> io::Result<SystemTime> {
cfg_has_statx! {
@@ -541,6 +557,11 @@ impl FileAttr {
currently",
))
}
+
+ #[cfg(target_os = "vita")]
+ pub fn created(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::new(self.stat.st_ctime as i64, 0))
+ }
}
#[cfg(target_os = "nto")]
@@ -594,7 +615,7 @@ impl FileTimes {
self.modified = Some(t);
}
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
pub fn set_created(&mut self, t: SystemTime) {
self.created = Some(t);
}
@@ -645,6 +666,7 @@ impl Iterator for ReadDir {
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
@@ -725,6 +747,7 @@ impl Iterator for ReadDir {
continue;
}
+ #[cfg(not(target_os = "vita"))]
let entry = dirent64_min {
d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
#[cfg(not(any(
@@ -735,6 +758,9 @@ impl Iterator for ReadDir {
d_type: *offset_ptr!(entry_ptr, d_type) as u8,
};
+ #[cfg(target_os = "vita")]
+ let entry = dirent64_min { d_ino: 0u64 };
+
return Some(Ok(DirEntry {
entry,
name: name.to_owned(),
@@ -752,6 +778,7 @@ impl Iterator for ReadDir {
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
)))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
@@ -842,6 +869,7 @@ impl DirEntry {
target_os = "haiku",
target_os = "vxworks",
target_os = "nto",
+ target_os = "vita",
))]
pub fn file_type(&self) -> io::Result<FileType> {
self.metadata().map(|m| m.file_type())
@@ -853,6 +881,7 @@ impl DirEntry {
target_os = "haiku",
target_os = "vxworks",
target_os = "nto",
+ target_os = "vita",
)))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
@@ -870,6 +899,7 @@ impl DirEntry {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "linux",
target_os = "emscripten",
@@ -903,6 +933,7 @@ impl DirEntry {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "netbsd",
target_os = "openbsd",
@@ -921,6 +952,7 @@ impl DirEntry {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "netbsd",
target_os = "openbsd",
@@ -939,6 +971,7 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
)))]
fn name_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
@@ -951,6 +984,7 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
))]
fn name_cstr(&self) -> &CStr {
&self.name
@@ -1080,11 +1114,21 @@ impl File {
cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?;
return Ok(());
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+ ))]
unsafe fn os_fsync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
- #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
+ #[cfg(not(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+ )))]
unsafe fn os_fsync(fd: c_int) -> c_int {
libc::fsync(fd)
}
@@ -1094,7 +1138,12 @@ impl File {
cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?;
return Ok(());
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+ ))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
@@ -1113,6 +1162,7 @@ impl File {
target_os = "android",
target_os = "freebsd",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -1222,7 +1272,7 @@ impl File {
io::ErrorKind::Unsupported,
"setting file times not supported",
))
- } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+ } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
let mut num_times = 0;
let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
@@ -1543,7 +1593,7 @@ 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"))] {
+ if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] {
// 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.
@@ -1666,6 +1716,8 @@ fn open_to_and_set_permissions(
.truncate(true)
.open(to)?;
let writer_metadata = writer.metadata()?;
+ // fchmod is broken on vita
+ #[cfg(not(target_os = "vita"))]
if writer_metadata.is_file() {
// Set the correct file permissions, in case the file already existed.
// Don't set the permissions on already existing non-files like
@@ -1680,6 +1732,7 @@ fn open_to_and_set_permissions(
target_os = "android",
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
)))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
@@ -1707,7 +1760,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
}
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
use crate::sync::atomic::{AtomicBool, Ordering};
@@ -1844,11 +1897,12 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
pub use remove_dir_impl::remove_dir_all;
-// Fallback for REDOX, ESP-ID, Horizon, and Miri
+// Fallback for REDOX, ESP-ID, Horizon, Vita and Miri
#[cfg(any(
target_os = "redox",
target_os = "espidf",
target_os = "horizon",
+ target_os = "vita",
target_os = "nto",
miri
))]
@@ -1861,6 +1915,7 @@ mod remove_dir_impl {
target_os = "redox",
target_os = "espidf",
target_os = "horizon",
+ target_os = "vita",
target_os = "nto",
miri
)))]
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index 16c8e0c0e..7d49bbdcb 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -466,7 +466,7 @@ impl<T: CopyRead> CopyRead for Take<T> {
}
}
-impl<T: CopyRead> CopyRead for BufReader<T> {
+impl<T: ?Sized + CopyRead> CopyRead for BufReader<T> {
fn drain_to<W: Write>(&mut self, writer: &mut W, outer_limit: u64) -> Result<u64> {
let buf = self.buffer();
let buf = &buf[0..min(buf.len(), outer_limit.try_into().unwrap_or(usize::MAX))];
@@ -495,7 +495,7 @@ impl<T: CopyRead> CopyRead for BufReader<T> {
}
}
-impl<T: CopyWrite> CopyWrite for BufWriter<T> {
+impl<T: ?Sized + CopyWrite> CopyWrite for BufWriter<T> {
fn properties(&self) -> CopyParams {
self.get_ref().properties()
}
diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs
index ee016887e..fe9559f2a 100644
--- a/library/std/src/sys/unix/l4re.rs
+++ b/library/std/src/sys/unix/l4re.rs
@@ -10,7 +10,7 @@ macro_rules! unimpl {
pub mod net {
#![allow(warnings)]
use crate::fmt;
- use crate::io::{self, IoSlice, IoSliceMut};
+ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc;
@@ -218,6 +218,10 @@ pub mod net {
unimpl!();
}
+ pub fn read_buf(&self, _: BorrowedCursor<'_>) -> io::Result<()> {
+ unimpl!();
+ }
+
pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
unimpl!();
}
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 192fa216d..2dc1b0c60 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -32,6 +32,7 @@ impl LazyInit for AllocatedCondvar {
if #[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "l4re",
target_os = "android",
@@ -124,6 +125,7 @@ impl Condvar {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "android",
target_os = "espidf",
@@ -158,6 +160,7 @@ impl Condvar {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "android",
target_os = "espidf",
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index bb9e65e68..326f1481e 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -88,6 +88,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// The poll on Darwin doesn't set POLLNVAL for closed fds.
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "redox",
target_os = "l4re",
@@ -164,12 +165,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}
unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
- #[cfg(not(any(
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "horizon",
- target_os = "vita"
- )))]
+ #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
{
// We don't want to add this as a public type to std, nor do we
// want to `include!` a file from the compiler (which would break
@@ -207,7 +203,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
- target_os = "vita"
)))]
static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
crate::sync::atomic::AtomicBool::new(false);
@@ -217,7 +212,6 @@ static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
- target_os = "vita",
)))]
pub(crate) fn unix_sigpipe_attr_specified() -> bool {
UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed)
@@ -395,7 +389,7 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "macos")] {
#[link(name = "System")]
extern "C" {}
- } else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
+ } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
#[link(name = "System")]
#[link(name = "objc")]
#[link(name = "Security", kind = "framework")]
@@ -408,6 +402,9 @@ cfg_if::cfg_if! {
} else if #[cfg(all(target_os = "linux", target_env = "uclibc"))] {
#[link(name = "dl")]
extern "C" {}
+ } else if #[cfg(target_os = "vita")] {
+ #[link(name = "pthread", kind = "static", modifiers = "-bundle")]
+ extern "C" {}
}
}
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 39edb136c..7258c222a 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -454,12 +454,18 @@ impl Socket {
Ok(passcred != 0)
}
- #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+ #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "vita")))]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as libc::c_int;
cvt(unsafe { libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &mut nonblocking) }).map(drop)
}
+ #[cfg(target_os = "vita")]
+ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ let option = nonblocking as libc::c_int;
+ setsockopt(self, libc::SOL_SOCKET, libc::SO_NONBLOCK, option)
+ }
+
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
// FIONBIO is inadequate for sockets on illumos/Solaris, so use the
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 8edfd3313..a68c14758 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -63,7 +63,13 @@ extern "C" {
#[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
#[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(
- any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
+ any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "freebsd",
+ target_os = "watchos"
+ ),
link_name = "__error"
)]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
@@ -375,7 +381,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
Ok(PathBuf::from(OsString::from_vec(e)))
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
let mut sz: u32 = 0;
@@ -609,6 +615,7 @@ pub fn home_dir() -> Option<PathBuf> {
#[cfg(any(
target_os = "android",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "emscripten",
target_os = "redox",
@@ -623,6 +630,7 @@ pub fn home_dir() -> Option<PathBuf> {
#[cfg(not(any(
target_os = "android",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "emscripten",
target_os = "redox",
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index 488217f39..f7333fd5a 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -193,17 +193,22 @@ impl Buf {
impl Slice {
#[inline]
- fn from_u8_slice(s: &[u8]) -> &Slice {
+ pub fn as_os_str_bytes(&self) -> &[u8] {
+ &self.inner
+ }
+
+ #[inline]
+ pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice {
unsafe { mem::transmute(s) }
}
#[inline]
pub fn from_str(s: &str) -> &Slice {
- Slice::from_u8_slice(s.as_bytes())
+ unsafe { Slice::from_os_str_bytes_unchecked(s.as_bytes()) }
}
- pub fn to_str(&self) -> Option<&str> {
- str::from_utf8(&self.inner).ok()
+ pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
+ str::from_utf8(&self.inner)
}
pub fn to_string_lossy(&self) -> Cow<'_, str> {
diff --git a/library/std/src/sys/unix/os_str/tests.rs b/library/std/src/sys/unix/os_str/tests.rs
index 22ba0c923..91bc0e61a 100644
--- a/library/std/src/sys/unix/os_str/tests.rs
+++ b/library/std/src/sys/unix/os_str/tests.rs
@@ -2,7 +2,7 @@ use super::*;
#[test]
fn slice_debug_output() {
- let input = Slice::from_u8_slice(b"\xF0hello,\tworld");
+ let input = unsafe { Slice::from_os_str_bytes_unchecked(b"\xF0hello,\tworld") };
let expected = r#""\xF0hello,\tworld""#;
let output = format!("{input:?}");
@@ -11,8 +11,7 @@ fn slice_debug_output() {
#[test]
fn display() {
- assert_eq!(
- "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye",
- Slice::from_u8_slice(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string(),
- );
+ assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe {
+ Slice::from_os_str_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()
+ },);
}
diff --git a/library/std/src/sys/unix/path.rs b/library/std/src/sys/unix/path.rs
index a98a69e2d..935245f63 100644
--- a/library/std/src/sys/unix/path.rs
+++ b/library/std/src/sys/unix/path.rs
@@ -30,7 +30,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
// Get the components, skipping the redundant leading "." component if it exists.
let mut components = path.strip_prefix(".").unwrap_or(path).components();
- let path_os = path.as_os_str().bytes();
+ let path_os = path.as_os_str().as_os_str_bytes();
let mut normalized = if path.is_absolute() {
// "If a pathname begins with two successive <slash> characters, the
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index afd03d79c..640648e87 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -164,9 +164,9 @@ pub enum ProgramKind {
impl ProgramKind {
fn new(program: &OsStr) -> Self {
- if program.bytes().starts_with(b"/") {
+ if program.as_os_str_bytes().starts_with(b"/") {
Self::Absolute
- } else if program.bytes().contains(&b'/') {
+ } else if program.as_os_str_bytes().contains(&b'/') {
// If the program has more than one component in it, it is a relative path.
Self::Relative
} else {
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 612d43fe2..0ce93af66 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall;
#[cfg(any(
target_os = "macos",
+ target_os = "watchos",
+ target_os = "tvos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@@ -28,15 +30,38 @@ use libc::RTP_ID as pid_t;
#[cfg(not(target_os = "vxworks"))]
use libc::{c_int, pid_t};
-#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
+#[cfg(not(any(
+ target_os = "vxworks",
+ target_os = "l4re",
+ target_os = "tvos",
+ target_os = "watchos",
+)))]
use libc::{gid_t, uid_t};
cfg_if::cfg_if! {
if #[cfg(all(target_os = "nto", target_env = "nto71"))] {
use crate::thread;
use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t};
- // arbitrary number of tries:
- const MAX_FORKSPAWN_TRIES: u32 = 4;
+ use crate::time::Duration;
+ use crate::sync::LazyLock;
+ // Get smallest amount of time we can sleep.
+ // Return a common value if it cannot be determined.
+ fn get_clock_resolution() -> Duration {
+ static MIN_DELAY: LazyLock<Duration, fn() -> Duration> = LazyLock::new(|| {
+ let mut mindelay = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+ if unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut mindelay) } == 0
+ {
+ Duration::from_nanos(mindelay.tv_nsec as u64)
+ } else {
+ Duration::from_millis(1)
+ }
+ });
+ *MIN_DELAY
+ }
+ // Arbitrary minimum sleep duration for retrying fork/spawn
+ const MIN_FORKSPAWN_SLEEP: Duration = Duration::from_nanos(1);
+ // Maximum duration of sleeping before giving up and returning an error
+ const MAX_FORKSPAWN_SLEEP: Duration = Duration::from_millis(1000);
}
}
@@ -66,7 +91,6 @@ impl Command {
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
return Ok((ret, ours));
}
-
let (input, output) = sys::pipe::anon_pipe()?;
// Whatever happens after the fork is almost for sure going to touch or
@@ -148,9 +172,31 @@ impl Command {
crate::sys_common::process::wait_with_output(proc, pipes)
}
+ // WatchOS and TVOS headers mark the `fork`/`exec*` functions with
+ // `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the
+ // `posix_spawn*` functions should be used instead. It isn't entirely clear
+ // what `PROHIBITED` means here (e.g. if calls to these functions are
+ // allowed to exist in dead code), but it sounds bad, so we go out of our
+ // way to avoid that all-together.
+ #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+ const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!(
+ ErrorKind::Unsupported,
+ "`fork`+`exec`-based process spawning is not supported on this target",
+ );
+
+ #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+ unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+ return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
+ }
+
// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, -1)) in the parent.
- #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
+ #[cfg(not(any(
+ target_os = "linux",
+ target_os = "watchos",
+ target_os = "tvos",
+ all(target_os = "nto", target_env = "nto71"),
+ )))]
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
cvt(libc::fork()).map(|res| (res, -1))
}
@@ -163,12 +209,25 @@ impl Command {
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
use crate::sys::os::errno;
- let mut tries_left = MAX_FORKSPAWN_TRIES;
+ let mut delay = MIN_FORKSPAWN_SLEEP;
+
loop {
let r = libc::fork();
- if r == -1 as libc::pid_t && tries_left > 0 && errno() as libc::c_int == libc::EBADF {
- thread::yield_now();
- tries_left -= 1;
+ if r == -1 as libc::pid_t && errno() as libc::c_int == libc::EBADF {
+ if delay < get_clock_resolution() {
+ // We cannot sleep this short (it would be longer).
+ // Yield instead.
+ thread::yield_now();
+ } else if delay < MAX_FORKSPAWN_SLEEP {
+ thread::sleep(delay);
+ } else {
+ return Err(io::const_io_error!(
+ ErrorKind::WouldBlock,
+ "forking returned EBADF too often",
+ ));
+ }
+ delay *= 2;
+ continue;
} else {
return cvt(r).map(|res| (res, -1));
}
@@ -308,6 +367,7 @@ impl Command {
// allocation). Instead we just close it manually. This will never
// have the drop glue anyway because this code never returns (the
// child will either exec() or invoke libc::exit)
+ #[cfg(not(any(target_os = "tvos", target_os = "watchos")))]
unsafe fn do_exec(
&mut self,
stdio: ChildPipes,
@@ -414,8 +474,19 @@ impl Command {
Err(io::Error::last_os_error())
}
+ #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+ unsafe fn do_exec(
+ &mut self,
+ _stdio: ChildPipes,
+ _maybe_envp: Option<&CStringArray>,
+ ) -> Result<!, io::Error> {
+ return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
+ }
+
#[cfg(not(any(
target_os = "macos",
+ target_os = "tvos",
+ target_os = "watchos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@@ -433,6 +504,9 @@ impl Command {
// directly.
#[cfg(any(
target_os = "macos",
+ // FIXME: `target_os = "ios"`?
+ target_os = "tvos",
+ target_os = "watchos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@@ -480,17 +554,28 @@ impl Command {
attrp: *const posix_spawnattr_t,
argv: *const *mut c_char,
envp: *const *mut c_char,
- ) -> i32 {
- let mut tries_left = MAX_FORKSPAWN_TRIES;
+ ) -> io::Result<i32> {
+ let mut delay = MIN_FORKSPAWN_SLEEP;
loop {
match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
- libc::EBADF if tries_left > 0 => {
- thread::yield_now();
- tries_left -= 1;
+ libc::EBADF => {
+ if delay < get_clock_resolution() {
+ // We cannot sleep this short (it would be longer).
+ // Yield instead.
+ thread::yield_now();
+ } else if delay < MAX_FORKSPAWN_SLEEP {
+ thread::sleep(delay);
+ } else {
+ return Err(io::const_io_error!(
+ ErrorKind::WouldBlock,
+ "posix_spawnp returned EBADF too often",
+ ));
+ }
+ delay *= 2;
continue;
}
r => {
- return r;
+ return Ok(r);
}
}
}
@@ -508,7 +593,7 @@ impl Command {
}
let addchdir = match self.get_cwd() {
Some(cwd) => {
- if cfg!(target_os = "macos") {
+ if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) {
// There is a bug in macOS where a relative executable
// path like "../myprogram" will cause `posix_spawn` to
// successfully launch the program, but erroneously return
@@ -620,14 +705,20 @@ impl Command {
let spawn_fn = libc::posix_spawnp;
#[cfg(target_os = "nto")]
let spawn_fn = retrying_libc_posix_spawnp;
- cvt_nz(spawn_fn(
+
+ let spawn_res = spawn_fn(
&mut p.pid,
self.get_program_cstr().as_ptr(),
file_actions.0.as_ptr(),
attrs.0.as_ptr(),
self.get_argv().as_ptr() as *const _,
envp as *const _,
- ))?;
+ );
+
+ #[cfg(target_os = "nto")]
+ let spawn_res = spawn_res?;
+
+ cvt_nz(spawn_res)?;
Ok(Some(p))
}
}
@@ -671,12 +762,9 @@ impl Process {
pub fn kill(&mut self) -> io::Result<()> {
// If we've already waited on this process then the pid can be recycled
// and used for another process, and we probably shouldn't be killing
- // random processes, so just return an error.
+ // random processes, so return Ok because the process has exited already.
if self.status.is_some() {
- Err(io::const_io_error!(
- ErrorKind::InvalidInput,
- "invalid argument: can't kill an exited process",
- ))
+ Ok(())
} else {
cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
}
@@ -788,31 +876,47 @@ fn signal_string(signal: i32) -> &'static str {
libc::SIGILL => " (SIGILL)",
libc::SIGTRAP => " (SIGTRAP)",
libc::SIGABRT => " (SIGABRT)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGBUS => " (SIGBUS)",
libc::SIGFPE => " (SIGFPE)",
libc::SIGKILL => " (SIGKILL)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGUSR1 => " (SIGUSR1)",
libc::SIGSEGV => " (SIGSEGV)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGUSR2 => " (SIGUSR2)",
libc::SIGPIPE => " (SIGPIPE)",
libc::SIGALRM => " (SIGALRM)",
libc::SIGTERM => " (SIGTERM)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGCHLD => " (SIGCHLD)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGCONT => " (SIGCONT)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGSTOP => " (SIGSTOP)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGTSTP => " (SIGTSTP)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGTTIN => " (SIGTTIN)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGTTOU => " (SIGTTOU)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGURG => " (SIGURG)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGXCPU => " (SIGXCPU)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGXFSZ => " (SIGXFSZ)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGVTALRM => " (SIGVTALRM)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGPROF => " (SIGPROF)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGWINCH => " (SIGWINCH)",
- #[cfg(not(target_os = "haiku"))]
+ #[cfg(not(any(target_os = "haiku", target_os = "l4re")))]
libc::SIGIO => " (SIGIO)",
#[cfg(target_os = "haiku")]
libc::SIGPOLL => " (SIGPOLL)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGSYS => " (SIGSYS)",
// For information on Linux signals, run `man 7 signal`
#[cfg(all(
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index c40e7ada0..f70d3cb39 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -144,12 +144,9 @@ impl Process {
pub fn kill(&mut self) -> io::Result<()> {
// If we've already waited on this process then the pid can be recycled
// and used for another process, and we probably shouldn't be killing
- // random processes, so just return an error.
+ // random processes, so return Ok because the process has exited already.
if self.status.is_some() {
- Err(io::const_io_error!(
- ErrorKind::InvalidInput,
- "invalid argument: can't kill an exited process",
- ))
+ Ok(())
} else {
cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
}
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index d8b63546b..d471be33e 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -14,6 +14,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
unix,
not(target_os = "macos"),
not(target_os = "ios"),
+ not(target_os = "tvos"),
not(target_os = "watchos"),
not(target_os = "openbsd"),
not(target_os = "freebsd"),
@@ -198,7 +199,7 @@ mod imp {
// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
// only used on iOS where direct access to `/dev/urandom` is blocked by the
// sandbox.
-#[cfg(any(target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
mod imp {
use crate::io;
use crate::ptr;
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 7307d9b2c..4f2d9cf36 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -150,7 +150,7 @@ impl Thread {
}
}
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn set_name(name: &CStr) {
unsafe {
let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
@@ -284,7 +284,13 @@ impl Drop for Thread {
}
}
-#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+))]
fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
let mut result = [0; MAX_WITH_NUL];
for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
@@ -300,6 +306,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "solaris",
@@ -345,6 +352,29 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
}
}
+ #[cfg(target_os = "netbsd")]
+ {
+ unsafe {
+ let set = libc::_cpuset_create();
+ if !set.is_null() {
+ let mut count: usize = 0;
+ if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
+ for i in 0..u64::MAX {
+ match libc::_cpuset_isset(i, set) {
+ -1 => break,
+ 0 => continue,
+ _ => count = count + 1,
+ }
+ }
+ }
+ libc::_cpuset_destroy(set);
+ if let Some(count) = NonZeroUsize::new(count) {
+ return Ok(count);
+ }
+ }
+ }
+ }
+
let mut cpus: libc::c_uint = 0;
let mut cpus_size = crate::mem::size_of_val(&cpus);
diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs
index 43046ed07..ae805d843 100644
--- a/library/std/src/sys/unix/thread_parking/pthread.rs
+++ b/library/std/src/sys/unix/thread_parking/pthread.rs
@@ -46,6 +46,7 @@ unsafe fn wait_timeout(
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "horizon",
@@ -73,6 +74,7 @@ unsafe fn wait_timeout(
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "horizon",
@@ -120,10 +122,12 @@ impl Parker {
if #[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "l4re",
target_os = "android",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "vita",
))] {
addr_of_mut!((*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER));
} else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index a9fbc7ab1..17b4130c2 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -219,7 +219,8 @@ impl From<__timespec64> for Timespec {
#[cfg(any(
all(target_os = "macos", any(not(target_arch = "aarch64"))),
target_os = "ios",
- target_os = "watchos"
+ target_os = "watchos",
+ target_os = "tvos"
))]
mod inner {
use crate::sync::atomic::{AtomicU64, Ordering};
@@ -339,7 +340,8 @@ mod inner {
#[cfg(not(any(
all(target_os = "macos", any(not(target_arch = "aarch64"))),
target_os = "ios",
- target_os = "watchos"
+ target_os = "watchos",
+ target_os = "tvos"
)))]
mod inner {
use crate::fmt;
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index 62ffee70b..61088ff16 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -28,7 +28,7 @@ use crate::ptr;
use crate::sync::atomic::{self, AtomicPtr, Ordering};
// We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
@@ -43,7 +43,7 @@ pub(crate) macro weak {
}
// On non-ELF targets, use the dlsym approximation of weak linkage.
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
pub(crate) use self::dlsym as weak;
pub(crate) struct ExternWeak<F: Copy> {
diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs
index 9a8b2a0be..1b50c2ea6 100644
--- a/library/std/src/sys/wasi/fd.rs
+++ b/library/std/src/sys/wasi/fd.rs
@@ -96,7 +96,7 @@ impl WasiFd {
unsafe { wasi::fd_sync(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
}
- pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
+ pub(crate) fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
unsafe {
wasi::fd_advise(self.as_raw_fd() as wasi::Fd, offset, len, advice).map_err(err2io)
}
@@ -179,7 +179,7 @@ impl WasiFd {
}
}
- pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
+ pub(crate) fn filestat_get(&self) -> io::Result<wasi::Filestat> {
unsafe { wasi::fd_filestat_get(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
}
@@ -199,7 +199,7 @@ impl WasiFd {
unsafe { wasi::fd_filestat_set_size(self.as_raw_fd() as wasi::Fd, size).map_err(err2io) }
}
- pub fn path_filestat_get(
+ pub(crate) fn path_filestat_get(
&self,
flags: wasi::Lookupflags,
path: &str,
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 8d1dbf591..437aae3ae 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -104,7 +104,7 @@ impl FileAttr {
Ok(SystemTime::from_wasi_timestamp(self.meta.ctim))
}
- pub fn as_wasi(&self) -> &wasi::Filestat {
+ pub(crate) fn as_wasi(&self) -> &wasi::Filestat {
&self.meta
}
}
@@ -142,7 +142,7 @@ impl FileType {
self.bits == wasi::FILETYPE_SYMBOLIC_LINK
}
- pub fn bits(&self) -> wasi::Filetype {
+ pub(crate) fn bits(&self) -> wasi::Filetype {
self.bits
}
}
diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs
index 5bfd8b52e..6b597f499 100644
--- a/library/std/src/sys/windows/args.rs
+++ b/library/std/src/sys/windows/args.rs
@@ -226,7 +226,7 @@ pub(crate) fn append_arg(cmd: &mut Vec<u16>, arg: &Arg, force_quotes: bool) -> i
// that it actually gets passed through on the command line or otherwise
// it will be dropped entirely when parsed on the other end.
ensure_no_nuls(arg)?;
- let arg_bytes = arg.bytes();
+ let arg_bytes = arg.as_os_str_bytes();
let (quote, escape) = match quote {
Quote::Always => (true, true),
Quote::Auto => {
@@ -297,7 +297,9 @@ pub(crate) fn make_bat_command_line(
// * `|<>` pipe/redirect characters.
const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>";
let force_quotes = match arg {
- Arg::Regular(arg) if !force_quotes => arg.bytes().iter().any(|c| SPECIAL.contains(c)),
+ Arg::Regular(arg) if !force_quotes => {
+ arg.as_os_str_bytes().iter().any(|c| SPECIAL.contains(c))
+ }
_ => force_quotes,
};
append_arg(&mut cmd, arg, force_quotes)?;
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 2bc40c474..d9ccba0e9 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -12,13 +12,13 @@ use crate::os::windows::io::{AsRawHandle, BorrowedHandle};
use crate::ptr;
use core::ffi::NonZero_c_ulong;
-#[path = "c/windows_sys.rs"] // c.rs is included from two places so we need to specify this
mod windows_sys;
pub use windows_sys::*;
pub type DWORD = c_ulong;
pub type NonZeroDWORD = NonZero_c_ulong;
pub type LARGE_INTEGER = c_longlong;
+#[cfg_attr(target_vendor = "uwp", allow(unused))]
pub type LONG = c_long;
pub type UINT = c_uint;
pub type WCHAR = u16;
@@ -267,6 +267,8 @@ pub unsafe fn getaddrinfo(
windows_sys::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res)
}
+cfg_if::cfg_if! {
+if #[cfg(not(target_vendor = "uwp"))] {
pub unsafe fn NtReadFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
@@ -313,6 +315,8 @@ pub unsafe fn NtWriteFile(
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
)
}
+}
+}
// Functions that aren't available on every version of Windows that we support,
// but we still use them and just provide some form of a fallback implementation.
@@ -376,4 +380,98 @@ compat_fn_with_fallback! {
) -> NTSTATUS {
panic!("keyed events not available")
}
+
+ // These functions are available on UWP when lazily loaded. They will fail WACK if loaded statically.
+ #[cfg(target_vendor = "uwp")]
+ pub fn NtCreateFile(
+ filehandle: *mut HANDLE,
+ desiredaccess: FILE_ACCESS_RIGHTS,
+ objectattributes: *const OBJECT_ATTRIBUTES,
+ iostatusblock: *mut IO_STATUS_BLOCK,
+ allocationsize: *const i64,
+ fileattributes: FILE_FLAGS_AND_ATTRIBUTES,
+ shareaccess: FILE_SHARE_MODE,
+ createdisposition: NTCREATEFILE_CREATE_DISPOSITION,
+ createoptions: NTCREATEFILE_CREATE_OPTIONS,
+ eabuffer: *const ::core::ffi::c_void,
+ ealength: u32
+ ) -> NTSTATUS {
+ STATUS_NOT_IMPLEMENTED
+ }
+ #[cfg(target_vendor = "uwp")]
+ pub fn NtReadFile(
+ filehandle: BorrowedHandle<'_>,
+ event: HANDLE,
+ apcroutine: PIO_APC_ROUTINE,
+ apccontext: *mut c_void,
+ iostatusblock: &mut IO_STATUS_BLOCK,
+ buffer: *mut crate::mem::MaybeUninit<u8>,
+ length: ULONG,
+ byteoffset: Option<&LARGE_INTEGER>,
+ key: Option<&ULONG>
+ ) -> NTSTATUS {
+ STATUS_NOT_IMPLEMENTED
+ }
+ #[cfg(target_vendor = "uwp")]
+ pub fn NtWriteFile(
+ filehandle: BorrowedHandle<'_>,
+ event: HANDLE,
+ apcroutine: PIO_APC_ROUTINE,
+ apccontext: *mut c_void,
+ iostatusblock: &mut IO_STATUS_BLOCK,
+ buffer: *const u8,
+ length: ULONG,
+ byteoffset: Option<&LARGE_INTEGER>,
+ key: Option<&ULONG>
+ ) -> NTSTATUS {
+ STATUS_NOT_IMPLEMENTED
+ }
+ #[cfg(target_vendor = "uwp")]
+ pub fn RtlNtStatusToDosError(Status: NTSTATUS) -> u32 {
+ Status as u32
+ }
+}
+
+// # Arm32 shim
+//
+// AddVectoredExceptionHandler and WSAStartup use platform-specific types.
+// However, Microsoft no longer supports thumbv7a so definitions for those targets
+// are not included in the win32 metadata. We work around that by defining them here.
+//
+// Where possible, these definitions should be kept in sync with https://docs.rs/windows-sys
+cfg_if::cfg_if! {
+if #[cfg(not(target_vendor = "uwp"))] {
+ #[link(name = "kernel32")]
+ extern "system" {
+ pub fn AddVectoredExceptionHandler(
+ first: u32,
+ handler: PVECTORED_EXCEPTION_HANDLER,
+ ) -> *mut c_void;
+ }
+ pub type PVECTORED_EXCEPTION_HANDLER = Option<
+ unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32,
+ >;
+ #[repr(C)]
+ pub struct EXCEPTION_POINTERS {
+ pub ExceptionRecord: *mut EXCEPTION_RECORD,
+ pub ContextRecord: *mut CONTEXT,
+ }
+ #[cfg(target_arch = "arm")]
+ pub enum CONTEXT {}
+}}
+
+#[link(name = "ws2_32")]
+extern "system" {
+ pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32;
+}
+#[cfg(target_arch = "arm")]
+#[repr(C)]
+pub struct WSADATA {
+ pub wVersion: u16,
+ pub wHighVersion: u16,
+ pub szDescription: [u8; 257],
+ pub szSystemStatus: [u8; 129],
+ pub iMaxSockets: u16,
+ pub iMaxUdpDg: u16,
+ pub lpVendorInfo: PSTR,
}
diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst
index 3e454199f..631aedd26 100644
--- a/library/std/src/sys/windows/c/windows_sys.lst
+++ b/library/std/src/sys/windows/c/windows_sys.lst
@@ -1930,6 +1930,7 @@ Windows.Win32.Foundation.SetLastError
Windows.Win32.Foundation.STATUS_DELETE_PENDING
Windows.Win32.Foundation.STATUS_END_OF_FILE
Windows.Win32.Foundation.STATUS_INVALID_PARAMETER
+Windows.Win32.Foundation.STATUS_NOT_IMPLEMENTED
Windows.Win32.Foundation.STATUS_PENDING
Windows.Win32.Foundation.STATUS_SUCCESS
Windows.Win32.Foundation.TRUE
@@ -2170,7 +2171,6 @@ Windows.Win32.Networking.WinSock.WSARecv
Windows.Win32.Networking.WinSock.WSASend
Windows.Win32.Networking.WinSock.WSASERVICE_NOT_FOUND
Windows.Win32.Networking.WinSock.WSASocketW
-Windows.Win32.Networking.WinSock.WSAStartup
Windows.Win32.Networking.WinSock.WSASYSCALLFAILURE
Windows.Win32.Networking.WinSock.WSASYSNOTREADY
Windows.Win32.Networking.WinSock.WSATRY_AGAIN
@@ -2418,12 +2418,10 @@ Windows.Win32.System.Console.STD_HANDLE
Windows.Win32.System.Console.STD_INPUT_HANDLE
Windows.Win32.System.Console.STD_OUTPUT_HANDLE
Windows.Win32.System.Console.WriteConsoleW
-Windows.Win32.System.Diagnostics.Debug.AddVectoredExceptionHandler
Windows.Win32.System.Diagnostics.Debug.ARM64_NT_NEON128
Windows.Win32.System.Diagnostics.Debug.CONTEXT
Windows.Win32.System.Diagnostics.Debug.CONTEXT
Windows.Win32.System.Diagnostics.Debug.CONTEXT
-Windows.Win32.System.Diagnostics.Debug.EXCEPTION_POINTERS
Windows.Win32.System.Diagnostics.Debug.EXCEPTION_RECORD
Windows.Win32.System.Diagnostics.Debug.FACILITY_CODE
Windows.Win32.System.Diagnostics.Debug.FACILITY_NT_BIT
@@ -2436,7 +2434,6 @@ Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_IGNORE_INSERTS
Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_OPTIONS
Windows.Win32.System.Diagnostics.Debug.FormatMessageW
Windows.Win32.System.Diagnostics.Debug.M128A
-Windows.Win32.System.Diagnostics.Debug.PVECTORED_EXCEPTION_HANDLER
Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT
Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT
Windows.Win32.System.Environment.FreeEnvironmentStringsW
diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs
index 36a30f6ba..023770871 100644
--- a/library/std/src/sys/windows/c/windows_sys.rs
+++ b/library/std/src/sys/windows/c/windows_sys.rs
@@ -40,13 +40,6 @@ extern "system" {
}
#[link(name = "kernel32")]
extern "system" {
- pub fn AddVectoredExceptionHandler(
- first: u32,
- handler: PVECTORED_EXCEPTION_HANDLER,
- ) -> *mut ::core::ffi::c_void;
-}
-#[link(name = "kernel32")]
-extern "system" {
pub fn CancelIo(hfile: HANDLE) -> BOOL;
}
#[link(name = "kernel32")]
@@ -712,10 +705,6 @@ extern "system" {
}
#[link(name = "ws2_32")]
extern "system" {
- pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32;
-}
-#[link(name = "ws2_32")]
-extern "system" {
pub fn accept(s: SOCKET, addr: *mut SOCKADDR, addrlen: *mut i32) -> SOCKET;
}
#[link(name = "ws2_32")]
@@ -3029,17 +3018,6 @@ pub const ERROR_XML_PARSE_ERROR: WIN32_ERROR = 1465u32;
pub type EXCEPTION_DISPOSITION = i32;
pub const EXCEPTION_MAXIMUM_PARAMETERS: u32 = 15u32;
#[repr(C)]
-pub struct EXCEPTION_POINTERS {
- pub ExceptionRecord: *mut EXCEPTION_RECORD,
- pub ContextRecord: *mut CONTEXT,
-}
-impl ::core::marker::Copy for EXCEPTION_POINTERS {}
-impl ::core::clone::Clone for EXCEPTION_POINTERS {
- fn clone(&self) -> Self {
- *self
- }
-}
-#[repr(C)]
pub struct EXCEPTION_RECORD {
pub ExceptionCode: NTSTATUS,
pub ExceptionFlags: u32,
@@ -3748,9 +3726,6 @@ pub const PROFILE_SERVER: PROCESS_CREATION_FLAGS = 1073741824u32;
pub const PROFILE_USER: PROCESS_CREATION_FLAGS = 268435456u32;
pub const PROGRESS_CONTINUE: u32 = 0u32;
pub type PSTR = *mut u8;
-pub type PVECTORED_EXCEPTION_HANDLER = ::core::option::Option<
- unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32,
->;
pub type PWSTR = *mut u16;
pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32;
pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32;
@@ -3888,6 +3863,7 @@ pub type STARTUPINFOW_FLAGS = u32;
pub const STATUS_DELETE_PENDING: NTSTATUS = -1073741738i32;
pub const STATUS_END_OF_FILE: NTSTATUS = -1073741807i32;
pub const STATUS_INVALID_PARAMETER: NTSTATUS = -1073741811i32;
+pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = -1073741822i32;
pub const STATUS_PENDING: NTSTATUS = 259i32;
pub const STATUS_SUCCESS: NTSTATUS = 0i32;
pub const STD_ERROR_HANDLE: STD_HANDLE = 4294967284u32;
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index 2404bbe2b..1ae42cb7e 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -159,7 +159,7 @@ impl Socket {
}
let mut timeout = c::timeval {
- tv_sec: timeout.as_secs() as c_long,
+ tv_sec: cmp::min(timeout.as_secs(), c_long::MAX as u64) as c_long,
tv_usec: (timeout.subsec_nanos() / 1000) as c_long,
};
diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs
index 2f2b0e56e..16c4f55c6 100644
--- a/library/std/src/sys/windows/os_str.rs
+++ b/library/std/src/sys/windows/os_str.rs
@@ -152,11 +152,21 @@ impl Buf {
impl Slice {
#[inline]
+ pub fn as_os_str_bytes(&self) -> &[u8] {
+ self.inner.as_bytes()
+ }
+
+ #[inline]
+ pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice {
+ mem::transmute(Wtf8::from_bytes_unchecked(s))
+ }
+
+ #[inline]
pub fn from_str(s: &str) -> &Slice {
unsafe { mem::transmute(Wtf8::from_str(s)) }
}
- pub fn to_str(&self) -> Option<&str> {
+ pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
self.inner.as_str()
}
diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs
index c3573d14c..c9c2d10e6 100644
--- a/library/std/src/sys/windows/path.rs
+++ b/library/std/src/sys/windows/path.rs
@@ -1,7 +1,6 @@
use super::{c, fill_utf16_buf, to_u16s};
use crate::ffi::{OsStr, OsString};
use crate::io;
-use crate::mem;
use crate::path::{Path, PathBuf, Prefix};
use crate::ptr;
@@ -11,16 +10,6 @@ mod tests;
pub const MAIN_SEP_STR: &str = "\\";
pub const MAIN_SEP: char = '\\';
-/// # Safety
-///
-/// `bytes` must be a valid wtf8 encoded slice
-#[inline]
-unsafe fn bytes_as_os_str(bytes: &[u8]) -> &OsStr {
- // &OsStr is layout compatible with &Slice, which is compatible with &Wtf8,
- // which is compatible with &[u8].
- mem::transmute(bytes)
-}
-
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/' || b == b'\\'
@@ -33,12 +22,12 @@ pub fn is_verbatim_sep(b: u8) -> bool {
/// Returns true if `path` looks like a lone filename.
pub(crate) fn is_file_name(path: &OsStr) -> bool {
- !path.bytes().iter().copied().any(is_sep_byte)
+ !path.as_os_str_bytes().iter().copied().any(is_sep_byte)
}
pub(crate) fn has_trailing_slash(path: &OsStr) -> bool {
- let is_verbatim = path.bytes().starts_with(br"\\?\");
+ let is_verbatim = path.as_os_str_bytes().starts_with(br"\\?\");
let is_separator = if is_verbatim { is_verbatim_sep } else { is_sep_byte };
- if let Some(&c) = path.bytes().last() { is_separator(c) } else { false }
+ if let Some(&c) = path.as_os_str_bytes().last() { is_separator(c) } else { false }
}
/// Appends a suffix to a path.
@@ -60,7 +49,7 @@ impl<'a, const LEN: usize> PrefixParser<'a, LEN> {
fn get_prefix(path: &OsStr) -> [u8; LEN] {
let mut prefix = [0; LEN];
// SAFETY: Only ASCII characters are modified.
- for (i, &ch) in path.bytes().iter().take(LEN).enumerate() {
+ for (i, &ch) in path.as_os_str_bytes().iter().take(LEN).enumerate() {
prefix[i] = if ch == b'/' { b'\\' } else { ch };
}
prefix
@@ -93,7 +82,7 @@ impl<'a> PrefixParserSlice<'a, '_> {
}
fn prefix_bytes(&self) -> &'a [u8] {
- &self.path.bytes()[..self.index]
+ &self.path.as_os_str_bytes()[..self.index]
}
fn finish(self) -> &'a OsStr {
@@ -101,7 +90,7 @@ impl<'a> PrefixParserSlice<'a, '_> {
// &[u8] and back. This is safe to do because (1) we only look at ASCII
// contents of the encoding and (2) new &OsStr values are produced only
// from ASCII-bounded slices of existing &OsStr values.
- unsafe { bytes_as_os_str(&self.path.bytes()[self.index..]) }
+ unsafe { OsStr::from_os_str_bytes_unchecked(&self.path.as_os_str_bytes()[self.index..]) }
}
}
@@ -173,7 +162,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> {
drive.is_ascii_alphabetic()
}
- match path.bytes() {
+ match path.as_os_str_bytes() {
[drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()),
_ => None,
}
@@ -182,7 +171,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> {
// Parses a drive prefix exactly, e.g. "C:"
fn parse_drive_exact(path: &OsStr) -> Option<u8> {
// only parse two bytes: the drive letter and the drive separator
- if path.bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
+ if path.as_os_str_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
parse_drive(path)
} else {
None
@@ -196,21 +185,26 @@ fn parse_drive_exact(path: &OsStr) -> Option<u8> {
fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) {
let separator = if verbatim { is_verbatim_sep } else { is_sep_byte };
- match path.bytes().iter().position(|&x| separator(x)) {
+ match path.as_os_str_bytes().iter().position(|&x| separator(x)) {
Some(separator_start) => {
let separator_end = separator_start + 1;
- let component = &path.bytes()[..separator_start];
+ let component = &path.as_os_str_bytes()[..separator_start];
// Panic safe
// The max `separator_end` is `bytes.len()` and `bytes[bytes.len()..]` is a valid index.
- let path = &path.bytes()[separator_end..];
+ let path = &path.as_os_str_bytes()[separator_end..];
// SAFETY: `path` is a valid wtf8 encoded slice and each of the separators ('/', '\')
// is encoded in a single byte, therefore `bytes[separator_start]` and
// `bytes[separator_end]` must be code point boundaries and thus
// `bytes[..separator_start]` and `bytes[separator_end..]` are valid wtf8 slices.
- unsafe { (bytes_as_os_str(component), bytes_as_os_str(path)) }
+ unsafe {
+ (
+ OsStr::from_os_str_bytes_unchecked(component),
+ OsStr::from_os_str_bytes_unchecked(path),
+ )
+ }
}
None => (path, OsStr::new("")),
}
@@ -329,7 +323,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
// Verbatim paths should not be modified.
if prefix.map(|x| x.is_verbatim()).unwrap_or(false) {
// NULs in verbatim paths are rejected for consistency.
- if path.bytes().contains(&0) {
+ if path.as_os_str_bytes().contains(&0) {
return Err(io::const_io_error!(
io::ErrorKind::InvalidInput,
"strings passed to WinAPI cannot contain NULs",
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index df3667c0f..e3493cbb8 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -395,7 +395,7 @@ fn resolve_exe<'a>(
// Test if the file name has the `exe` extension.
// This does a case-insensitive `ends_with`.
let has_exe_suffix = if exe_path.len() >= EXE_SUFFIX.len() {
- exe_path.bytes()[exe_path.len() - EXE_SUFFIX.len()..]
+ exe_path.as_os_str_bytes()[exe_path.len() - EXE_SUFFIX.len()..]
.eq_ignore_ascii_case(EXE_SUFFIX.as_bytes())
} else {
false
@@ -425,7 +425,7 @@ fn resolve_exe<'a>(
// From the `CreateProcessW` docs:
// > If the file name does not contain an extension, .exe is appended.
// Note that this rule only applies when searching paths.
- let has_extension = exe_path.bytes().contains(&b'.');
+ let has_extension = exe_path.as_os_str_bytes().contains(&b'.');
// Search the directories given by `search_paths`.
let result = search_paths(parent_paths, child_paths, |mut path| {
@@ -595,7 +595,16 @@ pub struct Process {
impl Process {
pub fn kill(&mut self) -> io::Result<()> {
- cvt(unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) })?;
+ let result = unsafe { c::TerminateProcess(self.handle.as_raw_handle(), 1) };
+ if result == c::FALSE {
+ let error = unsafe { c::GetLastError() };
+ // TerminateProcess returns ERROR_ACCESS_DENIED if the process has already been
+ // terminated (by us, or for any other reason). So check if the process was actually
+ // terminated, and if so, do not return an error.
+ if error != c::ERROR_ACCESS_DENIED || self.try_wait().is_err() {
+ return Err(crate::io::Error::from_raw_os_error(error as i32));
+ }
+ }
Ok(())
}
diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs
index bca4e38d9..5d8fd1378 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -1,5 +1,3 @@
-use crate::ffi::c_void;
-use crate::io;
use crate::mem;
use crate::ptr;
use crate::sys::c;
@@ -25,6 +23,9 @@ pub fn hashmap_random_keys() -> (u64, u64) {
#[cfg(not(target_vendor = "uwp"))]
#[inline(never)]
fn fallback_rng() -> (u64, u64) {
+ use crate::ffi::c_void;
+ use crate::io;
+
let mut v = (0, 0);
let ret = unsafe {
c::RtlGenRandom(&mut v as *mut _ as *mut c_void, mem::size_of_val(&v) as c::ULONG)
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index 2e3e0859d..3fcaaa508 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -11,6 +11,9 @@ use crate::sys::cvt;
use crate::sys::handle::Handle;
use core::str::utf8_char_width;
+#[cfg(test)]
+mod tests;
+
// Don't cache handles but get them fresh for every read/write. This allows us to track changes to
// the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
pub struct Stdin {
@@ -383,6 +386,10 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
debug_assert!(utf16.len() <= c::c_int::MAX as usize);
debug_assert!(utf8.len() <= c::c_int::MAX as usize);
+ if utf16.is_empty() {
+ return Ok(0);
+ }
+
let result = unsafe {
c::WideCharToMultiByte(
c::CP_UTF8, // CodePage
diff --git a/library/std/src/sys/windows/stdio/tests.rs b/library/std/src/sys/windows/stdio/tests.rs
new file mode 100644
index 000000000..1e53e0bee
--- /dev/null
+++ b/library/std/src/sys/windows/stdio/tests.rs
@@ -0,0 +1,6 @@
+use super::utf16_to_utf8;
+
+#[test]
+fn zero_size_read() {
+ assert_eq!(utf16_to_utf8(&[], &mut []).unwrap(), 0);
+}