diff options
Diffstat (limited to 'src/libstd/sys/windows/mod.rs')
| -rw-r--r-- | src/libstd/sys/windows/mod.rs | 111 |
1 files changed, 92 insertions, 19 deletions
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index e8b65c9b64e..8dd467eba9e 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -11,18 +11,14 @@ #![allow(missing_docs)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] -#![allow(unused_imports)] -#![allow(dead_code)] -#![allow(unused_unsafe)] -#![allow(unused_mut)] - -extern crate libc; use prelude::v1::*; -use num; +use ffi::OsStr; +use libc; use mem; use old_io::{self, IoResult, IoError}; +use os::windows::OsStrExt; use sync::{Once, ONCE_INIT}; macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( @@ -38,9 +34,10 @@ macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( pub mod backtrace; pub mod c; -pub mod ext; pub mod condvar; +pub mod ext; pub mod fs; +pub mod handle; pub mod helper_signal; pub mod mutex; pub mod os; @@ -48,12 +45,12 @@ pub mod os_str; pub mod pipe; pub mod process; pub mod rwlock; -pub mod sync; pub mod stack_overflow; +pub mod sync; pub mod tcp; -pub mod time; pub mod thread; pub mod thread_local; +pub mod time; pub mod timer; pub mod tty; pub mod udp; @@ -158,7 +155,7 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { pub fn wouldblock() -> bool { let err = os::errno(); - err == libc::WSAEWOULDBLOCK as uint + err == libc::WSAEWOULDBLOCK as i32 } pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { @@ -191,17 +188,93 @@ pub fn unimpl() -> IoError { } } -pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> { +fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> { match s { - Some(s) => Ok({ - let mut s = s.utf16_units().collect::<Vec<u16>>(); - s.push(0); - s - }), + Some(s) => Ok(to_utf16_os(OsStr::from_str(s))), None => Err(IoError { kind: old_io::InvalidInput, desc: "valid unicode input required", - detail: None - }) + detail: None, + }), + } +} + +fn to_utf16_os(s: &OsStr) -> Vec<u16> { + let mut v: Vec<_> = s.encode_wide().collect(); + v.push(0); + v +} + +// Many Windows APIs follow a pattern of where we hand the a buffer and then +// they will report back to us how large the buffer should be or how many bytes +// currently reside in the buffer. This function is an abstraction over these +// functions by making them easier to call. +// +// The first callback, `f1`, is yielded a (pointer, len) pair which can be +// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case). +// The closure is expected to return what the syscall returns which will be +// interpreted by this function to determine if the syscall needs to be invoked +// again (with more buffer space). +// +// Once the syscall has completed (errors bail out early) the second closure is +// yielded the data which has been read from the syscall. The return value +// from this closure is then the return value of the function. +fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> IoResult<T> + where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD, + F2: FnOnce(&[u16]) -> T +{ + // Start off with a stack buf but then spill over to the heap if we end up + // needing more space. + let mut stack_buf = [0u16; 512]; + let mut heap_buf = Vec::new(); + unsafe { + let mut n = stack_buf.len(); + loop { + let buf = if n <= stack_buf.len() { + &mut stack_buf[] + } else { + let extra = n - heap_buf.len(); + heap_buf.reserve(extra); + heap_buf.set_len(n); + &mut heap_buf[] + }; + + // This function is typically called on windows API functions which + // will return the correct length of the string, but these functions + // also return the `0` on error. In some cases, however, the + // returned "correct length" may actually be 0! + // + // To handle this case we call `SetLastError` to reset it to 0 and + // then check it again if we get the "0 error value". If the "last + // 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 libc::DWORD) { + 0 if libc::GetLastError() == 0 => 0, + 0 => return Err(IoError::last_error()), + n => n, + } as usize; + if k == n && libc::GetLastError() == + libc::ERROR_INSUFFICIENT_BUFFER as libc::DWORD { + n *= 2; + } else if k >= n { + n = k; + } else { + return Ok(f2(&buf[..k])) + } + } + } +} + +fn os2path(s: &[u16]) -> Path { + // FIXME: this should not be a panicking conversion (aka path reform) + Path::new(String::from_utf16(s).unwrap()) +} + +pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { + match v.iter().position(|c| *c == 0) { + // don't include the 0 + Some(i) => &v[..i], + None => v } } |
