#![allow(missing_docs, nonstandard_style)]
-use crate::ffi::{OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
use crate::io::ErrorKind;
+use crate::mem::MaybeUninit;
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
use crate::path::PathBuf;
use crate::time::Duration;
pub mod pipe;
pub mod process;
pub mod rand;
+pub mod stdio;
pub mod thread;
pub mod thread_local_dtor;
pub mod thread_local_key;
-pub mod thread_parker;
+pub mod thread_parking;
pub mod time;
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "uwp"))] {
- pub mod stdio;
pub mod stack_overflow;
} else {
- pub mod stdio_uwp;
pub mod stack_overflow_uwp;
- pub use self::stdio_uwp as stdio;
pub use self::stack_overflow_uwp as stack_overflow;
}
}
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {
stack_overflow::init();
+
+ // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already
+ // exists, we have to call it ourselves.
+ thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0"));
}
// SAFETY: must be called only once during runtime cleanup.
net::cleanup();
}
+#[inline]
+pub fn is_interrupted(_errno: i32) -> bool {
+ false
+}
+
pub fn decode_error_kind(errno: i32) -> ErrorKind {
use ErrorKind::*;
c::ERROR_ALREADY_EXISTS => return AlreadyExists,
c::ERROR_FILE_EXISTS => return AlreadyExists,
c::ERROR_BROKEN_PIPE => return BrokenPipe,
- c::ERROR_FILE_NOT_FOUND => return NotFound,
- c::ERROR_PATH_NOT_FOUND => return NotFound,
+ c::ERROR_FILE_NOT_FOUND
+ | c::ERROR_PATH_NOT_FOUND
+ | c::ERROR_INVALID_DRIVE
+ | c::ERROR_BAD_NETPATH
+ | c::ERROR_BAD_NET_NAME => return NotFound,
c::ERROR_NO_DATA => return BrokenPipe,
- c::ERROR_INVALID_NAME => return InvalidFilename,
+ c::ERROR_INVALID_NAME | c::ERROR_BAD_PATHNAME => return InvalidFilename,
c::ERROR_INVALID_PARAMETER => return InvalidInput,
c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory,
c::ERROR_SEM_TIMEOUT
// This initial size also works around `GetFullPathNameW` returning
// incorrect size hints for some short paths:
// https://github.com/dylni/normpath/issues/5
- let mut stack_buf = [0u16; 512];
- let mut heap_buf = Vec::new();
+ let mut stack_buf: [MaybeUninit<u16>; 512] = MaybeUninit::uninit_array();
+ let mut heap_buf: Vec<MaybeUninit<u16>> = Vec::new();
unsafe {
let mut n = stack_buf.len();
loop {
} else {
let extra = n - heap_buf.len();
heap_buf.reserve(extra);
+ // We used `reserve` and not `reserve_exact`, so in theory we
+ // may have gotten more than requested. If so, we'd like to use
+ // it... so long as we won't cause overflow.
+ n = heap_buf.capacity().min(c::DWORD::MAX as usize);
+ // Safety: MaybeUninit<u16> does not need initialization
heap_buf.set_len(n);
&mut heap_buf[..]
};
// error" is still 0 then we interpret it as a 0 length buffer and
// not an actual error.
c::SetLastError(0);
- let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
+ let k = match f1(buf.as_mut_ptr().cast::<u16>(), n as c::DWORD) {
0 if c::GetLastError() == 0 => 0,
0 => return Err(crate::io::Error::last_os_error()),
n => n,
} as usize;
if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
- n *= 2;
+ n = n.saturating_mul(2).min(c::DWORD::MAX as usize);
} else if k > n {
n = k;
} else if k == n {
// Therefore k never equals n.
unreachable!();
} else {
- return Ok(f2(&buf[..k]));
+ // Safety: First `k` values are initialized.
+ let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
+ return Ok(f2(slice));
}
}
}
}
crate::intrinsics::abort();
}
+
+/// Align the inner value to 8 bytes.
+///
+/// This is enough for almost all of the buffers we're likely to work with in
+/// the Windows APIs we use.
+#[repr(C, align(8))]
+#[derive(Copy, Clone)]
+pub(crate) struct Align8<T: ?Sized>(pub T);