2019-02-09 22:16:58 +00:00
|
|
|
//! Implementation of `std::os` functionality for Windows.
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2018-08-29 08:21:01 -05:00
|
|
|
#![allow(nonstandard_style)]
|
2014-09-30 17:03:56 -07:00
|
|
|
|
std: Stabilize portions of `std::os::$platform`
This commit starts to organize the `std::os::$platform` modules and in the
process stabilizes some of the functionality contained within. The organization
of these modules will reflect the organization of the standard library itself
with extension traits for primitives in the same corresponding module.
The OS-specific modules will grow more functionality over time including
concrete types that are not extending functionality of other structures, and
these will either go into the closest module in `std::os::$platform` or they
will grow a new module in the hierarchy.
The following items are now stable:
* `os::{unix, windows}`
* `unix::ffi`
* `unix::ffi::OsStrExt`
* `unix::ffi::OsStrExt::{from_bytes, as_bytes, to_cstring}`
* `unix::ffi::OsString`
* `unix::ffi::OsStringExt::{from_vec, into_vec}`
* `unix::process`
* `unix::process::CommandExt`
* `unix::process::CommandExt::{uid, gid}`
* `unix::process::ExitStatusExt`
* `unix::process::ExitStatusExt::signal`
* `unix::prelude`
* `windows::ffi`
* `windows::ffi::OsStringExt`
* `windows::ffi::OsStringExt::from_wide`
* `windows::ffi::OsStrExt`
* `windows::ffi::OsStrExt::encode_wide`
* `windows::prelude`
The following items remain unstable:
* `unix::io`
* `unix::io::{Fd, AsRawFd}`
* `unix::fs::{PermissionsExt, OpenOptionsExt}`
* `windows::io`
* `windows::io::{Handle, AsRawHandle}`
* `windows::io::{Socket, AsRawSocket}`
* `windows::fs`
* `windows::fs::OpenOptionsExt`
Due to the reorgnization of the platform extension modules, this commit is a
breaking change. Most imports can be fixed by adding the relevant libstd module
in the `use` path (such as `ffi` or `fs`).
[breaking-change]
2015-03-13 17:12:38 -07:00
|
|
|
use os::windows::prelude::*;
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
use error::Error as StdError;
|
2015-03-30 11:00:05 -07:00
|
|
|
use ffi::{OsString, OsStr};
|
2014-12-31 10:20:31 -08:00
|
|
|
use fmt;
|
2015-02-23 10:59:17 -08:00
|
|
|
use io;
|
std: Stabilize portions of `std::os::$platform`
This commit starts to organize the `std::os::$platform` modules and in the
process stabilizes some of the functionality contained within. The organization
of these modules will reflect the organization of the standard library itself
with extension traits for primitives in the same corresponding module.
The OS-specific modules will grow more functionality over time including
concrete types that are not extending functionality of other structures, and
these will either go into the closest module in `std::os::$platform` or they
will grow a new module in the hierarchy.
The following items are now stable:
* `os::{unix, windows}`
* `unix::ffi`
* `unix::ffi::OsStrExt`
* `unix::ffi::OsStrExt::{from_bytes, as_bytes, to_cstring}`
* `unix::ffi::OsString`
* `unix::ffi::OsStringExt::{from_vec, into_vec}`
* `unix::process`
* `unix::process::CommandExt`
* `unix::process::CommandExt::{uid, gid}`
* `unix::process::ExitStatusExt`
* `unix::process::ExitStatusExt::signal`
* `unix::prelude`
* `windows::ffi`
* `windows::ffi::OsStringExt`
* `windows::ffi::OsStringExt::from_wide`
* `windows::ffi::OsStrExt`
* `windows::ffi::OsStrExt::encode_wide`
* `windows::prelude`
The following items remain unstable:
* `unix::io`
* `unix::io::{Fd, AsRawFd}`
* `unix::fs::{PermissionsExt, OpenOptionsExt}`
* `windows::io`
* `windows::io::{Handle, AsRawHandle}`
* `windows::io::{Socket, AsRawSocket}`
* `windows::fs`
* `windows::fs::OpenOptionsExt`
Due to the reorgnization of the platform extension modules, this commit is a
breaking change. Most imports can be fixed by adding the relevant libstd module
in the `use` path (such as `ffi` or `fs`).
[breaking-change]
2015-03-13 17:12:38 -07:00
|
|
|
use os::windows::ffi::EncodeWide;
|
2015-02-23 10:59:17 -08:00
|
|
|
use path::{self, PathBuf};
|
2014-12-15 06:03:00 +02:00
|
|
|
use ptr;
|
2014-12-14 00:05:32 -08:00
|
|
|
use slice;
|
2015-10-25 10:19:35 -07:00
|
|
|
use sys::{c, cvt};
|
std: Stabilize parts of std::os::platform::io
This commit stabilizes the platform-specific `io` modules, specifically around
the traits having to do with the raw representation of each object on each
platform.
Specifically, the following material was stabilized:
* `AsRaw{Fd,Socket,Handle}`
* `RawFd` (renamed from `Fd`)
* `RawHandle` (renamed from `Handle`)
* `RawSocket` (renamed from `Socket`)
* `AsRaw{Fd,Socket,Handle}` implementations
* `std::os::{unix, windows}::io`
The following material was added as `#[unstable]`:
* `FromRaw{Fd,Socket,Handle}`
* Implementations for various primitives
There are a number of future improvements that are possible to make to this
module, but this should cover a good bit of functionality desired from these
modules for now. Some specific future additions may include:
* `IntoRawXXX` traits to consume the raw representation and cancel the
auto-destructor.
* `Fd`, `Socket`, and `Handle` abstractions that behave like Rust objects and
have nice methods for various syscalls.
At this time though, these are considered backwards-compatible extensions and
will not be stabilized at this time.
This commit is a breaking change due to the addition of `Raw` in from of the
type aliases in each of the platform-specific modules.
[breaking-change]
2015-03-26 16:18:29 -07:00
|
|
|
use sys::handle::Handle;
|
2014-09-30 17:03:56 -07:00
|
|
|
|
2015-11-19 18:01:11 +00:00
|
|
|
use super::to_u16s;
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
pub fn errno() -> i32 {
|
2015-11-02 16:23:22 -08:00
|
|
|
unsafe { c::GetLastError() as i32 }
|
2014-09-30 17:03:56 -07:00
|
|
|
}
|
|
|
|
|
|
2015-04-13 10:21:32 -04:00
|
|
|
/// Gets a detailed string description for the given error number.
|
2017-05-03 10:19:23 -07:00
|
|
|
pub fn error_string(mut errnum: i32) -> String {
|
2014-09-30 17:03:56 -07:00
|
|
|
// This value is calculated from the macro
|
|
|
|
|
// MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
|
2015-11-02 16:23:22 -08:00
|
|
|
let langId = 0x0800 as c::DWORD;
|
2014-09-30 17:03:56 -07:00
|
|
|
|
2015-11-02 16:23:22 -08:00
|
|
|
let mut buf = [0 as c::WCHAR; 2048];
|
2014-09-30 17:03:56 -07:00
|
|
|
|
|
|
|
|
unsafe {
|
2017-05-03 10:19:23 -07:00
|
|
|
let mut module = ptr::null_mut();
|
|
|
|
|
let mut flags = 0;
|
|
|
|
|
|
|
|
|
|
// NTSTATUS errors may be encoded as HRESULT, which may returned from
|
|
|
|
|
// GetLastError. For more information about Windows error codes, see
|
|
|
|
|
// `[MS-ERREF]`: https://msdn.microsoft.com/en-us/library/cc231198.aspx
|
|
|
|
|
if (errnum & c::FACILITY_NT_BIT as i32) != 0 {
|
|
|
|
|
// format according to https://support.microsoft.com/en-us/help/259693
|
2018-12-04 10:21:42 +01:00
|
|
|
const NTDLL_DLL: &[u16] = &['N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _,
|
|
|
|
|
'.' as _, 'D' as _, 'L' as _, 'L' as _, 0];
|
2017-05-03 10:19:23 -07:00
|
|
|
module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
|
|
|
|
|
|
|
|
|
|
if module != ptr::null_mut() {
|
|
|
|
|
errnum ^= c::FACILITY_NT_BIT as i32;
|
|
|
|
|
flags = c::FORMAT_MESSAGE_FROM_HMODULE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let res = c::FormatMessageW(flags | c::FORMAT_MESSAGE_FROM_SYSTEM |
|
2015-11-02 16:23:22 -08:00
|
|
|
c::FORMAT_MESSAGE_IGNORE_INSERTS,
|
2017-05-03 10:19:23 -07:00
|
|
|
module,
|
2015-11-02 16:23:22 -08:00
|
|
|
errnum as c::DWORD,
|
|
|
|
|
langId,
|
|
|
|
|
buf.as_mut_ptr(),
|
|
|
|
|
buf.len() as c::DWORD,
|
|
|
|
|
ptr::null()) as usize;
|
2014-09-30 17:03:56 -07:00
|
|
|
if res == 0 {
|
2018-11-27 02:59:49 +00:00
|
|
|
// Sometimes FormatMessageW can fail e.g., system doesn't like langId,
|
2014-09-30 17:03:56 -07:00
|
|
|
let fm_err = errno();
|
2015-01-27 12:20:58 -08:00
|
|
|
return format!("OS Error {} (FormatMessageW() returned error {})",
|
|
|
|
|
errnum, fm_err);
|
2014-09-30 17:03:56 -07:00
|
|
|
}
|
|
|
|
|
|
2015-08-25 18:26:29 +03:00
|
|
|
match String::from_utf16(&buf[..res]) {
|
2015-08-06 22:44:50 +02:00
|
|
|
Ok(mut msg) => {
|
|
|
|
|
// Trim trailing CRLF inserted by FormatMessageW
|
2018-12-05 06:42:56 -08:00
|
|
|
let len = msg.trim_end().len();
|
2015-08-06 22:44:50 +02:00
|
|
|
msg.truncate(len);
|
|
|
|
|
msg
|
|
|
|
|
},
|
2014-12-29 16:38:07 -08:00
|
|
|
Err(..) => format!("OS Error {} (FormatMessageW() returned \
|
|
|
|
|
invalid UTF-16)", errnum),
|
2014-09-30 17:03:56 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
pub struct Env {
|
2015-11-02 16:23:22 -08:00
|
|
|
base: c::LPWCH,
|
|
|
|
|
cur: c::LPWCH,
|
2014-09-30 17:03:56 -07:00
|
|
|
}
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
impl Iterator for Env {
|
|
|
|
|
type Item = (OsString, OsString);
|
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<(OsString, OsString)> {
|
2015-11-17 23:33:34 +00:00
|
|
|
loop {
|
|
|
|
|
unsafe {
|
|
|
|
|
if *self.cur == 0 { return None }
|
|
|
|
|
let p = &*self.cur as *const u16;
|
|
|
|
|
let mut len = 0;
|
|
|
|
|
while *p.offset(len) != 0 {
|
|
|
|
|
len += 1;
|
|
|
|
|
}
|
|
|
|
|
let s = slice::from_raw_parts(p, len as usize);
|
|
|
|
|
self.cur = self.cur.offset(len + 1);
|
|
|
|
|
|
|
|
|
|
// Windows allows environment variables to start with an equals
|
|
|
|
|
// symbol (in any other position, this is the separator between
|
|
|
|
|
// variable name and value). Since`s` has at least length 1 at
|
|
|
|
|
// this point (because the empty string terminates the array of
|
|
|
|
|
// environment variables), we can safely slice.
|
|
|
|
|
let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) {
|
|
|
|
|
Some(p) => p,
|
|
|
|
|
None => continue,
|
2015-11-19 19:07:27 +00:00
|
|
|
};
|
2015-11-17 23:33:34 +00:00
|
|
|
return Some((
|
|
|
|
|
OsStringExt::from_wide(&s[..pos]),
|
|
|
|
|
OsStringExt::from_wide(&s[pos+1..]),
|
|
|
|
|
))
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
impl Drop for Env {
|
|
|
|
|
fn drop(&mut self) {
|
2015-11-02 16:23:22 -08:00
|
|
|
unsafe { c::FreeEnvironmentStringsW(self.base); }
|
2015-01-27 12:20:58 -08:00
|
|
|
}
|
|
|
|
|
}
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
pub fn env() -> Env {
|
2014-11-24 16:21:39 -08:00
|
|
|
unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
let ch = c::GetEnvironmentStringsW();
|
2015-01-27 12:20:58 -08:00
|
|
|
if ch as usize == 0 {
|
|
|
|
|
panic!("failure getting env string from OS: {}",
|
2015-03-11 15:24:14 -07:00
|
|
|
io::Error::last_os_error());
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
2015-01-27 12:20:58 -08:00
|
|
|
Env { base: ch, cur: ch }
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
2015-01-27 12:20:58 -08:00
|
|
|
}
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
pub struct SplitPaths<'a> {
|
|
|
|
|
data: EncodeWide<'a>,
|
|
|
|
|
must_yield: bool,
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
|
|
|
|
|
SplitPaths {
|
|
|
|
|
data: unparsed.encode_wide(),
|
|
|
|
|
must_yield: true,
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
impl<'a> Iterator for SplitPaths<'a> {
|
2015-02-23 10:59:17 -08:00
|
|
|
type Item = PathBuf;
|
|
|
|
|
fn next(&mut self) -> Option<PathBuf> {
|
2015-01-27 12:20:58 -08:00
|
|
|
// 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 {
|
2014-11-24 16:21:39 -08:00
|
|
|
in_quote = !in_quote;
|
2015-01-27 12:20:58 -08:00
|
|
|
} else if b == ';' as u16 && !in_quote {
|
|
|
|
|
self.must_yield = true;
|
|
|
|
|
break
|
|
|
|
|
} else {
|
|
|
|
|
in_progress.push(b)
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
2015-01-27 12:20:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !must_yield && in_progress.is_empty() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
2015-02-23 10:59:17 -08:00
|
|
|
Some(super::os2path(&in_progress))
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-02 21:39:14 -08:00
|
|
|
#[derive(Debug)]
|
2015-01-27 12:20:58 -08:00
|
|
|
pub struct JoinPathsError;
|
|
|
|
|
|
|
|
|
|
pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
|
2015-03-30 11:00:05 -07:00
|
|
|
where I: Iterator<Item=T>, T: AsRef<OsStr>
|
2015-01-27 12:20:58 -08:00
|
|
|
{
|
2014-11-24 16:21:39 -08:00
|
|
|
let mut joined = Vec::new();
|
2015-01-27 12:20:58 -08:00
|
|
|
let sep = b';' as u16;
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
for (i, path) in paths.enumerate() {
|
2015-03-30 11:00:05 -07:00
|
|
|
let path = path.as_ref();
|
2014-11-24 16:21:39 -08:00
|
|
|
if i > 0 { joined.push(sep) }
|
2015-01-27 12:20:58 -08:00
|
|
|
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);
|
2015-12-02 17:31:49 -08:00
|
|
|
joined.extend_from_slice(&v[..]);
|
2015-01-27 12:20:58 -08:00
|
|
|
joined.push(b'"' as u16);
|
2014-11-24 16:21:39 -08:00
|
|
|
} else {
|
2015-12-02 17:31:49 -08:00
|
|
|
joined.extend_from_slice(&v[..]);
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 14:48:57 -05:00
|
|
|
Ok(OsStringExt::from_wide(&joined[..]))
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
impl fmt::Display for JoinPathsError {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
"path segment contains `\"`".fmt(f)
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-27 12:20:58 -08:00
|
|
|
impl StdError for JoinPathsError {
|
|
|
|
|
fn description(&self) -> &str { "failed to join paths" }
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:59:17 -08:00
|
|
|
pub fn current_exe() -> io::Result<PathBuf> {
|
2015-04-09 17:42:22 -07:00
|
|
|
super::fill_utf16_buf(|buf, sz| unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::GetModuleFileNameW(ptr::null_mut(), buf, sz)
|
2015-01-27 12:20:58 -08:00
|
|
|
}, super::os2path)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:59:17 -08:00
|
|
|
pub fn getcwd() -> io::Result<PathBuf> {
|
2015-04-09 17:42:22 -07:00
|
|
|
super::fill_utf16_buf(|buf, sz| unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::GetCurrentDirectoryW(sz, buf)
|
2015-01-27 12:20:58 -08:00
|
|
|
}, super::os2path)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:59:17 -08:00
|
|
|
pub fn chdir(p: &path::Path) -> io::Result<()> {
|
2015-03-30 11:00:05 -07:00
|
|
|
let p: &OsStr = p.as_ref();
|
|
|
|
|
let mut p = p.encode_wide().collect::<Vec<_>>();
|
2014-11-24 16:21:39 -08:00
|
|
|
p.push(0);
|
|
|
|
|
|
2015-10-25 10:19:35 -07:00
|
|
|
cvt(unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetCurrentDirectoryW(p.as_ptr())
|
2015-10-25 10:19:35 -07:00
|
|
|
}).map(|_| ())
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
|
|
|
|
|
2015-10-25 10:19:35 -07:00
|
|
|
pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
|
2016-03-22 22:01:37 -05:00
|
|
|
let k = to_u16s(k)?;
|
2015-10-25 10:19:35 -07:00
|
|
|
let res = super::fill_utf16_buf(|buf, sz| unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
|
2015-01-27 12:20:58 -08:00
|
|
|
}, |buf| {
|
|
|
|
|
OsStringExt::from_wide(buf)
|
2015-10-25 10:19:35 -07:00
|
|
|
});
|
|
|
|
|
match res {
|
|
|
|
|
Ok(value) => Ok(Some(value)),
|
2015-11-02 16:23:22 -08:00
|
|
|
Err(e) => {
|
|
|
|
|
if e.raw_os_error() == Some(c::ERROR_ENVVAR_NOT_FOUND as i32) {
|
|
|
|
|
Ok(None)
|
|
|
|
|
} else {
|
|
|
|
|
Err(e)
|
|
|
|
|
}
|
2015-10-25 10:19:35 -07:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-27 12:20:58 -08:00
|
|
|
}
|
|
|
|
|
|
2015-10-25 10:19:35 -07:00
|
|
|
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
2016-03-22 22:01:37 -05:00
|
|
|
let k = to_u16s(k)?;
|
|
|
|
|
let v = to_u16s(v)?;
|
2015-01-27 12:20:58 -08:00
|
|
|
|
2015-10-25 10:19:35 -07:00
|
|
|
cvt(unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())
|
2015-10-25 10:19:35 -07:00
|
|
|
}).map(|_| ())
|
2015-01-27 12:20:58 -08:00
|
|
|
}
|
2014-11-24 16:21:39 -08:00
|
|
|
|
2015-10-25 10:19:35 -07:00
|
|
|
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
|
2016-03-22 22:01:37 -05:00
|
|
|
let v = to_u16s(n)?;
|
2015-10-25 10:19:35 -07:00
|
|
|
cvt(unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())
|
2015-10-25 10:19:35 -07:00
|
|
|
}).map(|_| ())
|
2014-11-24 16:21:39 -08:00
|
|
|
}
|
std: Stabilize the std::str module
This commit starts out by consolidating all `str` extension traits into one
`StrExt` trait to be included in the prelude. This means that
`UnicodeStrPrelude`, `StrPrelude`, and `StrAllocating` have all been merged into
one `StrExt` exported by the standard library. Some functionality is currently
duplicated with the `StrExt` present in libcore.
This commit also currently avoids any methods which require any form of pattern
to operate. These functions will be stabilized via a separate RFC.
Next, stability of methods and structures are as follows:
Stable
* from_utf8_unchecked
* CowString - after moving to std::string
* StrExt::as_bytes
* StrExt::as_ptr
* StrExt::bytes/Bytes - also made a struct instead of a typedef
* StrExt::char_indices/CharIndices - CharOffsets was renamed
* StrExt::chars/Chars
* StrExt::is_empty
* StrExt::len
* StrExt::lines/Lines
* StrExt::lines_any/LinesAny
* StrExt::slice_unchecked
* StrExt::trim
* StrExt::trim_left
* StrExt::trim_right
* StrExt::words/Words - also made a struct instead of a typedef
Unstable
* from_utf8 - the error type was changed to a `Result`, but the error type has
yet to prove itself
* from_c_str - this function will be handled by the c_str RFC
* FromStr - this trait will have an associated error type eventually
* StrExt::escape_default - needs iterators at least, unsure if it should make
the cut
* StrExt::escape_unicode - needs iterators at least, unsure if it should make
the cut
* StrExt::slice_chars - this function has yet to prove itself
* StrExt::slice_shift_char - awaiting conventions about slicing and shifting
* StrExt::graphemes/Graphemes - this functionality may only be in libunicode
* StrExt::grapheme_indices/GraphemeIndices - this functionality may only be in
libunicode
* StrExt::width - this functionality may only be in libunicode
* StrExt::utf16_units - this functionality may only be in libunicode
* StrExt::nfd_chars - this functionality may only be in libunicode
* StrExt::nfkd_chars - this functionality may only be in libunicode
* StrExt::nfc_chars - this functionality may only be in libunicode
* StrExt::nfkc_chars - this functionality may only be in libunicode
* StrExt::is_char_boundary - naming is uncertain with container conventions
* StrExt::char_range_at - naming is uncertain with container conventions
* StrExt::char_range_at_reverse - naming is uncertain with container conventions
* StrExt::char_at - naming is uncertain with container conventions
* StrExt::char_at_reverse - naming is uncertain with container conventions
* StrVector::concat - this functionality may be replaced with iterators, but
it's not certain at this time
* StrVector::connect - as with concat, may be deprecated in favor of iterators
Deprecated
* StrAllocating and UnicodeStrPrelude have been merged into StrExit
* eq_slice - compiler implementation detail
* from_str - use the inherent parse() method
* is_utf8 - call from_utf8 instead
* replace - call the method instead
* truncate_utf16_at_nul - this is an implementation detail of windows and does
not need to be exposed.
* utf8_char_width - moved to libunicode
* utf16_items - moved to libunicode
* is_utf16 - moved to libunicode
* Utf16Items - moved to libunicode
* Utf16Item - moved to libunicode
* Utf16Encoder - moved to libunicode
* AnyLines - renamed to LinesAny and made a struct
* SendStr - use CowString<'static> instead
* str::raw - all functionality is deprecated
* StrExt::into_string - call to_string() instead
* StrExt::repeat - use iterators instead
* StrExt::char_len - use .chars().count() instead
* StrExt::is_alphanumeric - use .chars().all(..)
* StrExt::is_whitespace - use .chars().all(..)
Pending deprecation -- while slicing syntax is being worked out, these methods
are all #[unstable]
* Str - while currently used for generic programming, this trait will be
replaced with one of [], deref coercions, or a generic conversion trait.
* StrExt::slice - use slicing syntax instead
* StrExt::slice_to - use slicing syntax instead
* StrExt::slice_from - use slicing syntax instead
* StrExt::lev_distance - deprecated with no replacement
Awaiting stabilization due to patterns and/or matching
* StrExt::contains
* StrExt::contains_char
* StrExt::split
* StrExt::splitn
* StrExt::split_terminator
* StrExt::rsplitn
* StrExt::match_indices
* StrExt::split_str
* StrExt::starts_with
* StrExt::ends_with
* StrExt::trim_chars
* StrExt::trim_left_chars
* StrExt::trim_right_chars
* StrExt::find
* StrExt::rfind
* StrExt::find_str
* StrExt::subslice_offset
2014-12-10 09:02:31 -08:00
|
|
|
|
2015-02-23 10:59:17 -08:00
|
|
|
pub fn temp_dir() -> PathBuf {
|
2015-04-09 17:42:22 -07:00
|
|
|
super::fill_utf16_buf(|buf, sz| unsafe {
|
2015-01-27 12:20:58 -08:00
|
|
|
c::GetTempPathW(sz, buf)
|
|
|
|
|
}, super::os2path).unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:59:17 -08:00
|
|
|
pub fn home_dir() -> Option<PathBuf> {
|
2015-10-25 10:19:35 -07:00
|
|
|
::env::var_os("HOME").or_else(|| {
|
|
|
|
|
::env::var_os("USERPROFILE")
|
2015-03-23 15:54:39 -07:00
|
|
|
}).map(PathBuf::from).or_else(|| unsafe {
|
2015-01-27 12:20:58 -08:00
|
|
|
let me = c::GetCurrentProcess();
|
|
|
|
|
let mut token = ptr::null_mut();
|
|
|
|
|
if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
|
|
|
|
|
return None
|
|
|
|
|
}
|
std: Stabilize parts of std::os::platform::io
This commit stabilizes the platform-specific `io` modules, specifically around
the traits having to do with the raw representation of each object on each
platform.
Specifically, the following material was stabilized:
* `AsRaw{Fd,Socket,Handle}`
* `RawFd` (renamed from `Fd`)
* `RawHandle` (renamed from `Handle`)
* `RawSocket` (renamed from `Socket`)
* `AsRaw{Fd,Socket,Handle}` implementations
* `std::os::{unix, windows}::io`
The following material was added as `#[unstable]`:
* `FromRaw{Fd,Socket,Handle}`
* Implementations for various primitives
There are a number of future improvements that are possible to make to this
module, but this should cover a good bit of functionality desired from these
modules for now. Some specific future additions may include:
* `IntoRawXXX` traits to consume the raw representation and cancel the
auto-destructor.
* `Fd`, `Socket`, and `Handle` abstractions that behave like Rust objects and
have nice methods for various syscalls.
At this time though, these are considered backwards-compatible extensions and
will not be stabilized at this time.
This commit is a breaking change due to the addition of `Raw` in from of the
type aliases in each of the platform-specific modules.
[breaking-change]
2015-03-26 16:18:29 -07:00
|
|
|
let _handle = Handle::new(token);
|
2015-04-09 17:42:22 -07:00
|
|
|
super::fill_utf16_buf(|buf, mut sz| {
|
2015-01-27 12:20:58 -08:00
|
|
|
match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
|
2016-02-11 13:12:56 -05:00
|
|
|
0 if c::GetLastError() != c::ERROR_INSUFFICIENT_BUFFER => 0,
|
2015-01-27 12:20:58 -08:00
|
|
|
0 => sz,
|
2016-02-11 13:12:56 -05:00
|
|
|
_ => sz - 1, // sz includes the null terminator
|
2015-01-27 12:20:58 -08:00
|
|
|
}
|
|
|
|
|
}, super::os2path).ok()
|
|
|
|
|
})
|
|
|
|
|
}
|
2015-03-31 14:41:59 -07:00
|
|
|
|
|
|
|
|
pub fn exit(code: i32) -> ! {
|
2015-11-02 16:23:22 -08:00
|
|
|
unsafe { c::ExitProcess(code as c::UINT) }
|
2015-03-31 14:41:59 -07:00
|
|
|
}
|
2017-05-03 10:24:49 -07:00
|
|
|
|
2017-10-05 23:49:36 -06:00
|
|
|
pub fn getpid() -> u32 {
|
|
|
|
|
unsafe { c::GetCurrentProcessId() as u32 }
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-03 10:24:49 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use io::Error;
|
|
|
|
|
use sys::c;
|
|
|
|
|
|
|
|
|
|
// tests `error_string` above
|
|
|
|
|
#[test]
|
|
|
|
|
fn ntstatus_error() {
|
|
|
|
|
const STATUS_UNSUCCESSFUL: u32 = 0xc000_0001;
|
|
|
|
|
assert!(!Error::from_raw_os_error((STATUS_UNSUCCESSFUL | c::FACILITY_NT_BIT) as _)
|
|
|
|
|
.to_string().contains("FormatMessageW() returned error"));
|
|
|
|
|
}
|
|
|
|
|
}
|