diff options
| author | bors <bors@rust-lang.org> | 2015-02-03 03:44:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-02-03 03:44:05 +0000 |
| commit | 7858cb432d3f2efc0374424cb2b51518f697c172 (patch) | |
| tree | bccd460a861e61f758d2d459cb9da02b1ad8792b /src/libstd/sys/windows | |
| parent | eaf4c5c784637f3df8bdebc6ec21dbd4bc69420a (diff) | |
| parent | 9ece22ee00033cdf0b6b418c451112c92c8ad922 (diff) | |
| download | rust-7858cb432d3f2efc0374424cb2b51518f697c172.tar.gz rust-7858cb432d3f2efc0374424cb2b51518f697c172.zip | |
Auto merge of #21872 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/libstd/sys/windows')
| -rw-r--r-- | src/libstd/sys/windows/backtrace.rs | 34 | ||||
| -rw-r--r-- | src/libstd/sys/windows/c.rs | 190 | ||||
| -rw-r--r-- | src/libstd/sys/windows/fs.rs | 20 | ||||
| -rw-r--r-- | src/libstd/sys/windows/handle.rs | 31 | ||||
| -rw-r--r-- | src/libstd/sys/windows/mod.rs | 111 | ||||
| -rw-r--r-- | src/libstd/sys/windows/mutex.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/os.rs | 453 | ||||
| -rw-r--r-- | src/libstd/sys/windows/pipe.rs | 18 | ||||
| -rw-r--r-- | src/libstd/sys/windows/process.rs | 32 | ||||
| -rw-r--r-- | src/libstd/sys/windows/rwlock.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys/windows/stack_overflow.rs | 10 | ||||
| -rw-r--r-- | src/libstd/sys/windows/sync.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/tcp.rs | 9 | ||||
| -rw-r--r-- | src/libstd/sys/windows/thread.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/thread_local.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys/windows/timer.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/tty.rs | 5 |
17 files changed, 573 insertions, 354 deletions
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 1be1a412ffa..66712b9e3a1 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -7,29 +7,31 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. -/// As always, windows has something very different than unix, we mainly want -/// to avoid having to depend too much on libunwind for windows. -/// -/// If you google around, you'll find a fair bit of references to built-in -/// functions to get backtraces on windows. It turns out that most of these are -/// in an external library called dbghelp. I was unable to find this library -/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent -/// of it. -/// -/// You'll also find that there's a function called CaptureStackBackTrace -/// mentioned frequently (which is also easy to use), but sadly I didn't have a -/// copy of that function in my mingw install (maybe it was broken?). Instead, -/// this takes the route of using StackWalk64 in order to walk the stack. + +//! As always, windows has something very different than unix, we mainly want +//! to avoid having to depend too much on libunwind for windows. +//! +//! If you google around, you'll find a fair bit of references to built-in +//! functions to get backtraces on windows. It turns out that most of these are +//! in an external library called dbghelp. I was unable to find this library +//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent +//! of it. +//! +//! You'll also find that there's a function called CaptureStackBackTrace +//! mentioned frequently (which is also easy to use), but sadly I didn't have a +//! copy of that function in my mingw install (maybe it was broken?). Instead, +//! this takes the route of using StackWalk64 in order to walk the stack. + +#![allow(dead_code)] use dynamic_lib::DynamicLibrary; use ffi; -use core::ops::Index; use intrinsics; use old_io::{IoResult, Writer}; use libc; use mem; use ops::Drop; -use option::Option::{Some, None}; +use option::Option::{Some}; use path::Path; use ptr; use result::Result::{Ok, Err}; @@ -296,7 +298,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { // According to windows documentation, all dbghelp functions are // single-threaded. static LOCK: StaticMutex = MUTEX_INIT; - let _g = unsafe { LOCK.lock() }; + let _g = LOCK.lock(); // Open up dbghelp.dll, we don't link to it explicitly because it can't // always be found. Additionally, it's nice having fewer dependencies. diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index da3b7ee2f2f..0355565cf00 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -10,17 +10,21 @@ //! C definitions used by libnative that don't belong in liblibc -#![allow(overflowing_literals)] -#![allow(dead_code)] -#![allow(non_camel_case_types)] +#![allow(bad_style, dead_code, overflowing_literals)] use libc; -use prelude::v1::*; -pub const WSADESCRIPTION_LEN: uint = 256; -pub const WSASYS_STATUS_LEN: uint = 128; +pub use self::GET_FILEEX_INFO_LEVELS::*; +pub use self::FILE_INFO_BY_HANDLE_CLASS::*; +pub use libc::consts::os::extra::{ + FILE_ATTRIBUTE_READONLY, + FILE_ATTRIBUTE_DIRECTORY, +}; + +pub const WSADESCRIPTION_LEN: usize = 256; +pub const WSASYS_STATUS_LEN: usize = 128; pub const FIONBIO: libc::c_long = 0x8004667e; -pub const FD_SETSIZE: uint = 64; +pub const FD_SETSIZE: usize = 64; pub const MSG_DONTWAIT: libc::c_int = 0; pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582; pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4; @@ -32,12 +36,15 @@ pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40; pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT; pub const FD_ACCEPT: libc::c_long = 0x08; -pub const FD_MAX_EVENTS: uint = 10; +pub const FD_MAX_EVENTS: usize = 10; pub const WSA_INFINITE: libc::DWORD = libc::INFINITE; pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT; pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0; pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED; +pub const ERROR_NO_MORE_FILES: libc::DWORD = 18; +pub const TOKEN_READ: libc::DWORD = 0x20008; + #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { @@ -80,7 +87,7 @@ pub struct fd_set { } pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) { - set.fd_array[set.fd_count as uint] = s; + set.fd_array[set.fd_count as usize] = s; set.fd_count += 1; } @@ -110,6 +117,69 @@ pub struct CONSOLE_SCREEN_BUFFER_INFO { } pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO; +#[repr(C)] +pub struct WIN32_FILE_ATTRIBUTE_DATA { + pub dwFileAttributes: libc::DWORD, + pub ftCreationTime: libc::FILETIME, + pub ftLastAccessTime: libc::FILETIME, + pub ftLastWriteTime: libc::FILETIME, + pub nFileSizeHigh: libc::DWORD, + pub nFileSizeLow: libc::DWORD, +} + +#[repr(C)] +pub struct BY_HANDLE_FILE_INFORMATION { + pub dwFileAttributes: libc::DWORD, + pub ftCreationTime: libc::FILETIME, + pub ftLastAccessTime: libc::FILETIME, + pub ftLastWriteTime: libc::FILETIME, + pub dwVolumeSerialNumber: libc::DWORD, + pub nFileSizeHigh: libc::DWORD, + pub nFileSizeLow: libc::DWORD, + pub nNumberOfLinks: libc::DWORD, + pub nFileIndexHigh: libc::DWORD, + pub nFileIndexLow: libc::DWORD, +} + +pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; + +#[repr(C)] +pub enum GET_FILEEX_INFO_LEVELS { + GetFileExInfoStandard, + GetFileExMaxInfoLevel +} + +#[repr(C)] +pub enum FILE_INFO_BY_HANDLE_CLASS { + FileBasicInfo = 0, + FileStandardInfo = 1, + FileNameInfo = 2, + FileRenameInfo = 3, + FileDispositionInfo = 4, + FileAllocationInfo = 5, + FileEndOfFileInfo = 6, + FileStreamInfo = 7, + FileCompressionInfo = 8, + FileAttributeTagInfo = 9, + FileIdBothDirectoryInfo = 10, // 0xA + FileIdBothDirectoryRestartInfo = 11, // 0xB + FileIoPriorityHintInfo = 12, // 0xC + FileRemoteProtocolInfo = 13, // 0xD + FileFullDirectoryInfo = 14, // 0xE + FileFullDirectoryRestartInfo = 15, // 0xF + FileStorageInfo = 16, // 0x10 + FileAlignmentInfo = 17, // 0x11 + FileIdInfo = 18, // 0x12 + FileIdExtdDirectoryInfo = 19, // 0x13 + FileIdExtdDirectoryRestartInfo = 20, // 0x14 + MaximumFileInfoByHandlesClass +} + +#[repr(C)] +pub struct FILE_END_OF_FILE_INFO { + pub EndOfFile: libc::LARGE_INTEGER, +} + #[link(name = "ws2_32")] extern "system" { pub fn WSAStartup(wVersionRequested: libc::WORD, @@ -156,31 +226,29 @@ extern "system" { } pub mod compat { - use intrinsics::{atomic_store_relaxed, transmute}; - use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; use prelude::v1::*; + use ffi::CString; + use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; + use sync::atomic::{AtomicUsize, Ordering}; extern "system" { fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID; } - // store_func() is idempotent, so using relaxed ordering for the atomics - // should be enough. This way, calling a function in this compatibility - // layer (after it's loaded) shouldn't be any slower than a regular DLL - // call. - unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) { + fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str, + fallback: usize) -> usize { let mut module: Vec<u16> = module.utf16_units().collect(); module.push(0); let symbol = CString::from_slice(symbol.as_bytes()); - let handle = GetModuleHandleW(module.as_ptr()); - let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr())); - atomic_store_relaxed(ptr, if func == 0 { - fallback - } else { - func - }) + let func = unsafe { + let handle = GetModuleHandleW(module.as_ptr()); + GetProcAddress(handle, symbol.as_ptr()) as usize + }; + let value = if func == 0 {fallback} else {func}; + ptr.store(value, Ordering::SeqCst); + value } /// Macro for creating a compatibility fallback for a Windows function @@ -192,29 +260,36 @@ pub mod compat { /// }) /// ``` /// - /// Note that arguments unused by the fallback implementation should not be called `_` as - /// they are used to be passed to the real function if available. + /// Note that arguments unused by the fallback implementation should not be + /// called `_` as they are used to be passed to the real function if + /// available. macro_rules! compat_fn { ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty { $fallback:expr }) => ( #[inline(always)] pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype { - static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk; - - extern "system" fn thunk($($argname: $argtype),*) -> $rettype { - unsafe { - ::sys::c::compat::store_func(&mut ptr as *mut _ as *mut uint, - stringify!($module), - stringify!($symbol), - fallback as uint); - ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) - } + use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + use mem; + + static PTR: AtomicUsize = ATOMIC_USIZE_INIT; + + fn load() -> usize { + ::sys::c::compat::store_func(&PTR, + stringify!($module), + stringify!($symbol), + fallback as usize) } extern "system" fn fallback($($argname: $argtype),*) -> $rettype { $fallback } - ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*) + let addr = match PTR.load(Ordering::SeqCst) { + 0 => load(), + n => n, + }; + let f: extern "system" fn($($argtype),*) -> $rettype = + mem::transmute(addr); + f($($argname),*) } ) } @@ -229,10 +304,7 @@ pub mod compat { use libc::c_uint; use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE}; use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; - - extern "system" { - fn SetLastError(dwErrCode: DWORD); - } + use sys::c::SetLastError; compat_fn! { kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR, @@ -282,4 +354,42 @@ extern "system" { hConsoleOutput: libc::HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO, ) -> libc::BOOL; + + pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR, + fInfoLevelId: GET_FILEEX_INFO_LEVELS, + lpFileInformation: libc::LPVOID) -> libc::BOOL; + pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL; + pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR, + dwFileAttributes: libc::DWORD) -> libc::BOOL; + pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD; + pub fn GetFileInformationByHandle(hFile: libc::HANDLE, + lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) + -> libc::BOOL; + + pub fn SetLastError(dwErrCode: libc::DWORD); + pub fn GetCommandLineW() -> *mut libc::LPCWSTR; + pub fn LocalFree(ptr: *mut libc::c_void); + pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR, + pNumArgs: *mut libc::c_int) -> *mut *mut u16; + pub fn SetFileTime(hFile: libc::HANDLE, + lpCreationTime: *const libc::FILETIME, + lpLastAccessTime: *const libc::FILETIME, + lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL; + pub fn SetFileInformationByHandle(hFile: libc::HANDLE, + FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, + lpFileInformation: libc::LPVOID, + dwBufferSize: libc::DWORD) -> libc::BOOL; + pub fn GetTempPathW(nBufferLength: libc::DWORD, + lpBuffer: libc::LPCWSTR) -> libc::DWORD; + pub fn OpenProcessToken(ProcessHandle: libc::HANDLE, + DesiredAccess: libc::DWORD, + TokenHandle: *mut libc::HANDLE) -> libc::BOOL; + pub fn GetCurrentProcess() -> libc::HANDLE; +} + +#[link(name = "userenv")] +extern "system" { + pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE, + lpProfileDir: libc::LPCWSTR, + lpcchSize: *mut libc::DWORD) -> libc::BOOL; } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 80cdf9782f2..304d7e01532 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -10,20 +10,15 @@ //! Blocking Windows-based file I/O -use alloc::arc::Arc; use libc::{self, c_int}; use mem; -use sys::os::fill_utf16_buf_and_decode; -use path; use ptr; -use str; use old_io; use prelude::v1::*; use sys; -use sys::os; -use sys_common::{keep_going, eof, mkerr_libc}; +use sys_common::{mkerr_libc}; use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; use old_io::{IoResult, IoError, FileStat, SeekStyle}; @@ -262,7 +257,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> { let mut more_files = 1 as libc::BOOL; while more_files != 0 { { - let filename = os::truncate_utf16_at_nul(&wfd.cFileName); + let filename = super::truncate_utf16_at_nul(&wfd.cFileName); match String::from_utf16(filename) { Ok(filename) => paths.push(Path::new(filename)), Err(..) => { @@ -368,19 +363,12 @@ pub fn readlink(p: &Path) -> IoResult<Path> { } // Specify (sz - 1) because the documentation states that it's the size // without the null pointer - let ret = fill_utf16_buf_and_decode(|buf, sz| unsafe { + let ret = super::fill_utf16_buf(|buf, sz| unsafe { GetFinalPathNameByHandleW(handle, buf as *const u16, sz - 1, libc::VOLUME_NAME_DOS) - }); - let ret = match ret { - Some(ref s) if s.starts_with(r"\\?\") => { // " - Ok(Path::new(&s[4..])) - } - Some(s) => Ok(Path::new(s)), - None => Err(super::last_error()), - }; + }, super::os2path); assert!(unsafe { libc::CloseHandle(handle) } != 0); return ret; } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs new file mode 100644 index 00000000000..6737eeef125 --- /dev/null +++ b/src/libstd/sys/windows/handle.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use libc::{self, HANDLE}; + +pub struct Handle(HANDLE); + +unsafe impl Send for Handle {} +unsafe impl Sync for Handle {} + +impl Handle { + pub fn new(handle: HANDLE) -> Handle { + Handle(handle) + } +} + +impl Drop for Handle { + fn drop(&mut self) { + unsafe { let _ = libc::CloseHandle(self.0); } + } +} + 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 } } diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 828ad795ed3..75495efc7cb 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -38,8 +38,6 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK { impl Mutex { #[inline] - pub unsafe fn new() -> Mutex { MUTEX_INIT } - #[inline] pub unsafe fn lock(&self) { ffi::AcquireSRWLockExclusive(self.inner.get()) } diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index a82259ad5ec..c71e2d057c3 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -10,48 +10,32 @@ //! Implementation of `std::os` functionality for Windows -// FIXME: move various extern bindings from here into liblibc or -// something similar +#![allow(bad_style)] use prelude::v1::*; +use os::windows::*; +use error::Error as StdError; +use ffi::{OsString, OsStr, AsOsStr}; use fmt; -use old_io::{IoResult, IoError}; -use iter::repeat; -use libc::{c_int, c_void}; -use libc; -use os; -use path::BytesContainer; +use iter::Range; +use libc::types::os::arch::extra::LPWCH; +use libc::{self, c_int, c_void}; +use mem; +use old_io::{IoError, IoResult}; use ptr; use slice; +use sys::c; use sys::fs::FileDesc; +use sys::handle::Handle as RawHandle; -use os::TMPBUF_SZ; -use libc::types::os::arch::extra::DWORD; +use libc::funcs::extra::kernel32::{ + GetEnvironmentStringsW, + FreeEnvironmentStringsW +}; -const BUF_BYTES : uint = 2048u; - -/// Return a slice of `v` ending at (and not including) the first NUL -/// (0). -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 - } -} - -pub fn errno() -> uint { - use libc::types::os::arch::extra::DWORD; - - #[link_name = "kernel32"] - extern "system" { - fn GetLastError() -> DWORD; - } - - unsafe { - GetLastError() as uint - } +pub fn errno() -> i32 { + unsafe { libc::GetLastError() as i32 } } /// Get a detailed string description for the given error number @@ -80,7 +64,7 @@ pub fn error_string(errnum: i32) -> String { // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) let langId = 0x0800 as DWORD; - let mut buf = [0 as WCHAR; TMPBUF_SZ]; + let mut buf = [0 as WCHAR; 2048]; unsafe { let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | @@ -94,200 +78,170 @@ pub fn error_string(errnum: i32) -> String { if res == 0 { // Sometimes FormatMessageW can fail e.g. system doesn't like langId, let fm_err = errno(); - return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err); + return format!("OS Error {} (FormatMessageW() returned error {})", + errnum, fm_err); } - let msg = String::from_utf16(truncate_utf16_at_nul(&buf)); + let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len()); + let msg = String::from_utf16(&buf[..b]); match msg { - Ok(msg) => format!("OS Error {}: {}", errnum, msg), + Ok(msg) => msg, Err(..) => format!("OS Error {} (FormatMessageW() returned \ invalid UTF-16)", errnum), } } } -pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { - // Windows pipes work subtly differently than unix pipes, and their - // inheritance has to be handled in a different way that I do not - // fully understand. Here we explicitly make the pipe non-inheritable, - // which means to pass it to a subprocess they need to be duplicated - // first, as in std::run. - let mut fds = [0; 2]; - match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint, - (libc::O_BINARY | libc::O_NOINHERIT) as c_int) { - 0 => { - assert!(fds[0] != -1 && fds[0] != 0); - assert!(fds[1] != -1 && fds[1] != 0); - Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) - } - _ => Err(IoError::last_error()), - } +pub struct Env { + base: LPWCH, + cur: LPWCH, } -pub fn fill_utf16_buf_and_decode<F>(mut f: F) -> Option<String> where - F: FnMut(*mut u16, DWORD) -> DWORD, -{ - unsafe { - let mut n = TMPBUF_SZ as DWORD; - let mut res = None; - let mut done = false; - while !done { - let mut buf: Vec<u16> = repeat(0u16).take(n as uint).collect(); - let k = f(buf.as_mut_ptr(), n); - if k == (0 as DWORD) { - done = true; - } else if k == n && - libc::GetLastError() == - libc::ERROR_INSUFFICIENT_BUFFER as DWORD { - n *= 2 as DWORD; - } else if k >= n { - n = k; - } else { - done = true; - } - if k != 0 && done { - let sub = &buf[.. (k as uint)]; - // We want to explicitly catch the case when the - // closure returned invalid UTF-16, rather than - // set `res` to None and continue. - let s = String::from_utf16(sub).ok() - .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16"); - res = Some(s) +impl Iterator for Env { + type Item = (OsString, OsString); + + fn next(&mut self) -> Option<(OsString, OsString)> { + unsafe { + if *self.cur == 0 { return None } + let p = &*self.cur; + let mut len = 0; + while *(p as *const _).offset(len) != 0 { + len += 1; } + let p = p as *const u16; + let s = slice::from_raw_buf(&p, len as usize); + self.cur = self.cur.offset(len + 1); + + let (k, v) = match s.iter().position(|&b| b == '=' as u16) { + Some(n) => (&s[..n], &s[n+1..]), + None => (s, &[][]), + }; + Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v))) } - return res; } } -pub fn getcwd() -> IoResult<Path> { - use libc::DWORD; - use libc::GetCurrentDirectoryW; - use old_io::OtherIoError; +impl Drop for Env { + fn drop(&mut self) { + unsafe { FreeEnvironmentStringsW(self.base); } + } +} - let mut buf = [0 as u16; BUF_BYTES]; +pub fn env() -> Env { unsafe { - if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD { - return Err(IoError::last_error()); + let ch = GetEnvironmentStringsW(); + if ch as usize == 0 { + panic!("failure getting env string from OS: {}", + IoError::last_error()); } + Env { base: ch, cur: ch } } +} - match String::from_utf16(truncate_utf16_at_nul(&buf)) { - Ok(ref cwd) => Ok(Path::new(cwd)), - Err(..) => Err(IoError { - kind: OtherIoError, - desc: "GetCurrentDirectoryW returned invalid UTF-16", - detail: None, - }), - } +pub struct SplitPaths<'a> { + data: EncodeWide<'a>, + must_yield: bool, } -pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> { - use libc::funcs::extra::kernel32::{ - GetEnvironmentStringsW, - FreeEnvironmentStringsW - }; - let ch = GetEnvironmentStringsW(); - if ch as uint == 0 { - panic!("os::env() failure getting env string from OS: {}", - os::last_os_error()); +pub fn split_paths(unparsed: &OsStr) -> SplitPaths { + SplitPaths { + data: unparsed.encode_wide(), + must_yield: true, } - // Here, we lossily decode the string as UTF16. - // - // The docs suggest that the result should be in Unicode, but - // Windows doesn't guarantee it's actually UTF16 -- it doesn't - // validate the environment string passed to CreateProcess nor - // SetEnvironmentVariable. Yet, it's unlikely that returning a - // raw u16 buffer would be of practical use since the result would - // be inherently platform-dependent and introduce additional - // complexity to this code. - // - // Using the non-Unicode version of GetEnvironmentStrings is even - // worse since the result is in an OEM code page. Characters that - // can't be encoded in the code page would be turned into question - // marks. - let mut result = Vec::new(); - let mut i = 0; - while *ch.offset(i) != 0 { - let p = &*ch.offset(i); - let mut len = 0; - while *(p as *const _).offset(len) != 0 { - len += 1; - } - let p = p as *const u16; - let s = slice::from_raw_buf(&p, len as uint); - result.push(String::from_utf16_lossy(s).into_bytes()); - i += len as int + 1; - } - FreeEnvironmentStringsW(ch); - result } -pub fn split_paths(unparsed: &[u8]) -> Vec<Path> { - // On Windows, the PATH environment variable is semicolon separated. Double - // quotes are used as a way of introducing literal semicolons (since - // c:\some;dir is a valid Windows path). Double quotes are not themselves - // permitted in path names, so there is no way to escape a double quote. - // Quoted regions can appear in arbitrary locations, so - // - // c:\foo;c:\som"e;di"r;c:\bar - // - // Should parse as [c:\foo, c:\some;dir, c:\bar]. - // - // (The above is based on testing; there is no clear reference available - // for the grammar.) - - let mut parsed = Vec::new(); - let mut in_progress = Vec::new(); - let mut in_quote = false; - - for b in unparsed.iter() { - match *b { - b';' if !in_quote => { - parsed.push(Path::new(in_progress.as_slice())); - in_progress.truncate(0) - } - b'"' => { +impl<'a> Iterator for SplitPaths<'a> { + type Item = Path; + fn next(&mut self) -> Option<Path> { + // On Windows, the PATH environment variable is semicolon separated. + // Double quotes are used as a way of introducing literal semicolons + // (since c:\some;dir is a valid Windows path). Double quotes are not + // themselves permitted in path names, so there is no way to escape a + // double quote. Quoted regions can appear in arbitrary locations, so + // + // c:\foo;c:\som"e;di"r;c:\bar + // + // Should parse as [c:\foo, c:\some;dir, c:\bar]. + // + // (The above is based on testing; there is no clear reference available + // for the grammar.) + + + let must_yield = self.must_yield; + self.must_yield = false; + + let mut in_progress = Vec::new(); + let mut in_quote = false; + for b in self.data.by_ref() { + if b == '"' as u16 { in_quote = !in_quote; + } else if b == ';' as u16 && !in_quote { + self.must_yield = true; + break + } else { + in_progress.push(b) } - _ => { - in_progress.push(*b); - } + } + + if !must_yield && in_progress.is_empty() { + None + } else { + Some(super::os2path(&in_progress[])) } } - parsed.push(Path::new(in_progress)); - parsed } -pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> { +#[derive(Show)] +pub struct JoinPathsError; + +pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError> + where I: Iterator<Item=T>, T: AsOsStr +{ let mut joined = Vec::new(); - let sep = b';'; + let sep = b';' as u16; - for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() { + for (i, path) in paths.enumerate() { + let path = path.as_os_str(); if i > 0 { joined.push(sep) } - if path.contains(&b'"') { - return Err("path segment contains `\"`"); - } else if path.contains(&sep) { - joined.push(b'"'); - joined.push_all(path); - joined.push(b'"'); + let v = path.encode_wide().collect::<Vec<u16>>(); + if v.contains(&(b'"' as u16)) { + return Err(JoinPathsError) + } else if v.contains(&sep) { + joined.push(b'"' as u16); + joined.push_all(&v[]); + joined.push(b'"' as u16); } else { - joined.push_all(path); + joined.push_all(&v[]); } } - Ok(joined) + Ok(OsStringExt::from_wide(&joined[])) } -pub fn load_self() -> Option<Vec<u8>> { - unsafe { - fill_utf16_buf_and_decode(|buf, sz| { - libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) - }).map(|s| s.to_string().into_bytes()) +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "path segment contains `\"`".fmt(f) } } +impl StdError for JoinPathsError { + fn description(&self) -> &str { "failed to join paths" } +} + +pub fn current_exe() -> IoResult<Path> { + super::fill_utf16_buf(|buf, sz| unsafe { + libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) + }, super::os2path) +} + +pub fn getcwd() -> IoResult<Path> { + super::fill_utf16_buf(|buf, sz| unsafe { + libc::GetCurrentDirectoryW(sz, buf) + }, super::os2path) +} + pub fn chdir(p: &Path) -> IoResult<()> { - let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>(); + let mut p = p.as_os_str().encode_wide().collect::<Vec<_>>(); p.push(0); unsafe { @@ -298,39 +252,124 @@ pub fn chdir(p: &Path) -> IoResult<()> { } } -pub fn page_size() -> uint { - use mem; +pub fn getenv(k: &OsStr) -> Option<OsString> { + let k = super::to_utf16_os(k); + super::fill_utf16_buf(|buf, sz| unsafe { + libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz) + }, |buf| { + OsStringExt::from_wide(buf) + }).ok() +} + +pub fn setenv(k: &OsStr, v: &OsStr) { + let k = super::to_utf16_os(k); + let v = super::to_utf16_os(v); + unsafe { - let mut info = mem::zeroed(); - libc::GetSystemInfo(&mut info); + if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 { + panic!("failed to set env: {}", IoError::last_error()); + } + } +} - return info.dwPageSize as uint; +pub fn unsetenv(n: &OsStr) { + let v = super::to_utf16_os(n); + unsafe { + if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 { + panic!("failed to unset env: {}", IoError::last_error()); + } } } -#[cfg(test)] -mod tests { - use super::truncate_utf16_at_nul; +pub struct Args { + range: Range<isize>, + cur: *mut *mut u16, +} - #[test] - fn test_truncate_utf16_at_nul() { - let v = []; - let b: &[u16] = &[]; - assert_eq!(truncate_utf16_at_nul(&v), b); +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option<OsString> { + self.range.next().map(|i| unsafe { + let ptr = *self.cur.offset(i); + let mut len = 0; + while *ptr.offset(len) != 0 { len += 1; } + + // Push it onto the list. + let ptr = ptr as *const u16; + let buf = slice::from_raw_buf(&ptr, len as usize); + OsStringExt::from_wide(buf) + }) + } + fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() } +} - let v = [0, 2, 3]; - assert_eq!(truncate_utf16_at_nul(&v), b); +impl Drop for Args { + fn drop(&mut self) { + unsafe { c::LocalFree(self.cur as *mut c_void); } + } +} - let v = [1, 0, 3]; - let b: &[u16] = &[1]; - assert_eq!(truncate_utf16_at_nul(&v), b); +pub fn args() -> Args { + unsafe { + let mut nArgs: c_int = 0; + let lpCmdLine = c::GetCommandLineW(); + let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs); - let v = [1, 2, 0]; - let b: &[u16] = &[1, 2]; - assert_eq!(truncate_utf16_at_nul(&v), b); + Args { cur: szArgList, range: range(0, nArgs as isize) } + } +} - let v = [1, 2, 3]; - let b: &[u16] = &[1, 2, 3]; - assert_eq!(truncate_utf16_at_nul(&v), b); +pub fn page_size() -> usize { + unsafe { + let mut info = mem::zeroed(); + libc::GetSystemInfo(&mut info); + return info.dwPageSize as usize; + } +} + +pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { + // Windows pipes work subtly differently than unix pipes, and their + // inheritance has to be handled in a different way that I do not + // fully understand. Here we explicitly make the pipe non-inheritable, + // which means to pass it to a subprocess they need to be duplicated + // first, as in std::run. + let mut fds = [0; 2]; + match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint, + (libc::O_BINARY | libc::O_NOINHERIT) as c_int) { + 0 => { + assert!(fds[0] != -1 && fds[0] != 0); + assert!(fds[1] != -1 && fds[1] != 0); + Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) + } + _ => Err(IoError::last_error()), } } + +pub fn temp_dir() -> Path { + super::fill_utf16_buf(|buf, sz| unsafe { + c::GetTempPathW(sz, buf) + }, super::os2path).unwrap() +} + +pub fn home_dir() -> Option<Path> { + getenv("HOME".as_os_str()).or_else(|| { + getenv("USERPROFILE".as_os_str()) + }).map(|os| { + // FIXME: OsString => Path + Path::new(os.to_str().unwrap()) + }).or_else(|| unsafe { + let me = c::GetCurrentProcess(); + let mut token = ptr::null_mut(); + if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { + return None + } + let _handle = RawHandle::new(token); + super::fill_utf16_buf(|buf, mut sz| { + match c::GetUserProfileDirectoryW(token, buf, &mut sz) { + 0 if libc::GetLastError() != 0 => 0, + 0 => sz, + n => n as libc::DWORD, + } + }, super::os2path).ok() + }) +} diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 0bc2a827272..1f228b7d32e 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -352,7 +352,7 @@ impl UnixStream { fn cancel_io(&self) -> IoResult<()> { match unsafe { c::CancelIoEx(self.handle(), ptr::null_mut()) } { - 0 if os::errno() == libc::ERROR_NOT_FOUND as uint => { + 0 if os::errno() == libc::ERROR_NOT_FOUND as i32 => { Ok(()) } 0 => Err(super::last_error()), @@ -374,7 +374,7 @@ impl UnixStream { // acquire the lock. // // See comments in close_read() about why this lock is necessary. - let guard = unsafe { self.inner.lock.lock() }; + let guard = self.inner.lock.lock(); if self.read_closed() { return Err(eof()) } @@ -392,7 +392,7 @@ impl UnixStream { // If our errno doesn't say that the I/O is pending, then we hit some // legitimate error and return immediately. - if os::errno() != libc::ERROR_IO_PENDING as uint { + if os::errno() != libc::ERROR_IO_PENDING as i32 { return Err(super::last_error()) } @@ -417,7 +417,7 @@ impl UnixStream { // If we succeeded, or we failed for some reason other than // CancelIoEx, return immediately if ret != 0 { return Ok(bytes_read as uint) } - if os::errno() != libc::ERROR_OPERATION_ABORTED as uint { + if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 { return Err(super::last_error()) } @@ -450,7 +450,7 @@ impl UnixStream { // going after we woke up. // // See comments in close_read() about why this lock is necessary. - let guard = unsafe { self.inner.lock.lock() }; + let guard = self.inner.lock.lock(); if self.write_closed() { return Err(epipe()) } @@ -465,7 +465,7 @@ impl UnixStream { drop(guard); if ret == 0 { - if err != libc::ERROR_IO_PENDING as uint { + if err != libc::ERROR_IO_PENDING as i32 { return Err(decode_error_detailed(err as i32)) } // Process a timeout if one is pending @@ -481,7 +481,7 @@ impl UnixStream { // aborted, then check to see if the write half was actually // closed or whether we woke up from the read half closing. if ret == 0 { - if os::errno() != libc::ERROR_OPERATION_ABORTED as uint { + if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 { return Err(super::last_error()) } if !wait_succeeded.is_ok() { @@ -525,14 +525,14 @@ impl UnixStream { // close_read() between steps 1 and 2. By atomically executing steps 1 // and 2 with a lock with respect to close_read(), we're guaranteed that // no thread will erroneously sit in a read forever. - let _guard = unsafe { self.inner.lock.lock() }; + let _guard = self.inner.lock.lock(); self.inner.read_closed.store(true, Ordering::SeqCst); self.cancel_io() } pub fn close_write(&mut self) -> IoResult<()> { // see comments in close_read() for why this lock is necessary - let _guard = unsafe { self.inner.lock.lock() }; + let _guard = self.inner.lock.lock(); self.inner.write_closed.store(true, Ordering::SeqCst); self.cancel_io() } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 3d66718d00b..3ca735f7fdf 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,28 +10,27 @@ use prelude::v1::*; +use collections::hash_map::Hasher; use collections; +use env; use ffi::CString; use hash::Hash; -use collections::hash_map::Hasher; +use libc::{pid_t, c_void}; +use libc; +use mem; use old_io::fs::PathExtensions; -use old_io::process::{ProcessExit, ExitStatus, ExitSignal}; +use old_io::process::{ProcessExit, ExitStatus}; use old_io::{IoResult, IoError}; use old_io; -use libc::{pid_t, c_void, c_int}; -use libc; -use mem; use os; use path::BytesContainer; use ptr; use str; -use sys::fs::FileDesc; use sync::{StaticMutex, MUTEX_INIT}; +use sys::fs::FileDesc; -use sys::fs; -use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer}; -use sys_common::helper_thread::Helper; -use sys_common::{AsInner, mkerr_libc, timeout}; +use sys::timer; +use sys_common::{AsInner, timeout}; pub use sys_common::ProcessConfig; @@ -106,6 +105,7 @@ impl Process { return ret; } + #[allow(deprecated)] pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>, out_fd: Option<P>, err_fd: Option<P>) -> IoResult<Process> @@ -128,7 +128,7 @@ impl Process { use libc::funcs::extra::msvcrt::get_osfhandle; use mem; - use iter::{Iterator, IteratorExt}; + use iter::IteratorExt; use str::StrExt; if cfg.gid().is_some() || cfg.uid().is_some() { @@ -142,14 +142,14 @@ impl Process { // To have the spawning semantics of unix/windows stay the same, we need to // read the *child's* PATH if one is provided. See #15149 for more details. let program = cfg.env().and_then(|env| { - for (key, v) in env.iter() { + for (key, v) in env { if b"PATH" != key.container_as_bytes() { continue } // Split the value and test each path to see if the // program exists. - for path in os::split_paths(v.container_as_bytes()).into_iter() { + for path in os::split_paths(v.container_as_bytes()) { let path = path.join(cfg.program().as_bytes()) - .with_extension(os::consts::EXE_EXTENSION); + .with_extension(env::consts::EXE_EXTENSION); if path.exists() { return Some(CString::from_slice(path.as_vec())) } @@ -372,7 +372,7 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String { let mut cmd = String::new(); append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok() .expect("expected program name to be utf-8 encoded")); - for arg in args.iter() { + for arg in args { cmd.push(' '); append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok() .expect("expected argument to be utf-8 encoded")); @@ -437,7 +437,7 @@ fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T Some(env) => { let mut blk = Vec::new(); - for pair in env.iter() { + for pair in env { let kv = format!("{}={}", pair.0.container_as_str().unwrap(), pair.1.container_as_str().unwrap()); diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs index 88ce85c39f6..76fe352ed77 100644 --- a/src/libstd/sys/windows/rwlock.rs +++ b/src/libstd/sys/windows/rwlock.rs @@ -19,9 +19,6 @@ pub const RWLOCK_INIT: RWLock = RWLock { impl RWLock { #[inline] - pub unsafe fn new() -> RWLock { RWLOCK_INIT } - - #[inline] pub unsafe fn read(&self) { ffi::AcquireSRWLockShared(self.inner.get()) } diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs index 0cb4c573ae3..b0410701ee1 100644 --- a/src/libstd/sys/windows/stack_overflow.rs +++ b/src/libstd/sys/windows/stack_overflow.rs @@ -14,7 +14,7 @@ use ptr; use mem; use libc; use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL}; -use sys_common::{stack, thread_info}; +use sys_common::stack; pub struct Handler { _data: *mut libc::c_void @@ -30,14 +30,6 @@ impl Drop for Handler { fn drop(&mut self) {} } -// get_task_info is called from an exception / signal handler. -// It returns the guard page of the current task or 0 if that -// guard page doesn't exist. None is returned if there's currently -// no local task. -unsafe fn get_task_guard_page() -> uint { - thread_info::stack_guard() -} - // This is initialized in init() and only read from after static mut PAGE_SIZE: uint = 0; diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs index d60646b7db9..7614104c98b 100644 --- a/src/libstd/sys/windows/sync.rs +++ b/src/libstd/sys/windows/sync.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc::{BOOL, DWORD, c_void, LPVOID, c_ulong}; +use libc::{BOOL, DWORD, LPVOID, c_ulong}; use libc::types::os::arch::extra::BOOLEAN; pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE; diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs index 64e440331c1..4804ca510cb 100644 --- a/src/libstd/sys/windows/tcp.rs +++ b/src/libstd/sys/windows/tcp.rs @@ -14,12 +14,11 @@ use libc; use mem; use ptr; use prelude::v1::*; -use super::{last_error, last_net_error, retry, sock_t}; +use super::{last_error, last_net_error, sock_t}; use sync::Arc; use sync::atomic::{AtomicBool, Ordering}; -use sys::fs::FileDesc; use sys::{self, c, set_nonblocking, wouldblock, timer}; -use sys_common::{self, timeout, eof, net}; +use sys_common::{timeout, eof, net}; pub use sys_common::net::TcpStream; @@ -202,10 +201,6 @@ impl TcpAcceptor { Err(eof()) } - pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> { - net::sockname(self.socket(), libc::getsockname) - } - pub fn set_timeout(&mut self, timeout: Option<u64>) { self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0); } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index a94adcb3bc7..a38dc9b2d34 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::prelude::*; - use boxed::Box; use cmp; use mem; diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index 0f8ceed39a6..54a32e43daf 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -233,6 +233,7 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID, } } +#[allow(dead_code)] // actually called above unsafe fn run_dtors() { let mut any_run = true; for _ in 0..5 { @@ -248,7 +249,7 @@ unsafe fn run_dtors() { DTOR_LOCK.unlock(); ret }; - for &(key, dtor) in dtors.iter() { + for &(key, dtor) in &dtors { let ptr = TlsGetValue(key); if !ptr.is_null() { TlsSetValue(key, ptr::null_mut()); diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index 34f3c418c55..d156dd801f9 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -28,8 +28,6 @@ use ptr; use old_io::IoResult; use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; -use sys::c; -use sys::fs::FileDesc; use sys_common::helper_thread::Helper; helper_init! { static HELPER: Helper<Req> } diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 6ecabfa9853..f02c8e49f41 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -38,7 +38,7 @@ use str::from_utf8; use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; -use super::c::{ERROR_ILLEGAL_CHARACTER, CONSOLE_SCREEN_BUFFER_INFO}; +use super::c::{CONSOLE_SCREEN_BUFFER_INFO}; use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; use super::c::{GetConsoleScreenBufferInfo}; @@ -155,9 +155,6 @@ impl TTY { (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)), } } - - // Let us magically declare this as a TTY - pub fn isatty(&self) -> bool { true } } impl Drop for TTY { |
