std: Add a new env
module
This is an implementation of [RFC 578][rfc] which adds a new `std::env` module to replace most of the functionality in the current `std::os` module. More details can be found in the RFC itself, but as a summary the following methods have all been deprecated: [rfc]: https://github.com/rust-lang/rfcs/pull/578 * `os::args_as_bytes` => `env::args` * `os::args` => `env::args` * `os::consts` => `env::consts` * `os::dll_filename` => no replacement, use `env::consts` directly * `os::page_size` => `env::page_size` * `os::make_absolute` => use `env::current_dir` + `join` instead * `os::getcwd` => `env::current_dir` * `os::change_dir` => `env::set_current_dir` * `os::homedir` => `env::home_dir` * `os::tmpdir` => `env::temp_dir` * `os::join_paths` => `env::join_paths` * `os::split_paths` => `env::split_paths` * `os::self_exe_name` => `env::current_exe` * `os::self_exe_path` => use `env::current_exe` + `pop` * `os::set_exit_status` => `env::set_exit_status` * `os::get_exit_status` => `env::get_exit_status` * `os::env` => `env::vars` * `os::env_as_bytes` => `env::vars` * `os::getenv` => `env::var` or `env::var_string` * `os::getenv_as_bytes` => `env::var` * `os::setenv` => `env::set_var` * `os::unsetenv` => `env::remove_var` Many function signatures have also been tweaked for various purposes, but the main changes were: * `Vec`-returning APIs now all return iterators instead * All APIs are now centered around `OsString` instead of `Vec<u8>` or `String`. There is currently on convenience API, `env::var_string`, which can be used to get the value of an environment variable as a unicode `String`. All old APIs are `#[deprecated]` in-place and will remain for some time to allow for migrations. The semantics of the APIs have been tweaked slightly with regard to dealing with invalid unicode (panic instead of replacement). The new `std::env` module is all contained within the `env` feature, so crates must add the following to access the new APIs: #![feature(env)] [breaking-change]
This commit is contained in:
parent
f1398d2736
commit
70ed3a48df
66 changed files with 2262 additions and 869 deletions
|
@ -22,6 +22,7 @@
|
|||
#![feature(std_misc)]
|
||||
#![feature(test)]
|
||||
#![feature(unicode)]
|
||||
#![feature(env)]
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
|
@ -31,7 +32,7 @@ extern crate getopts;
|
|||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::old_io;
|
||||
use std::old_io::fs;
|
||||
use std::thunk::Thunk;
|
||||
|
@ -48,7 +49,7 @@ pub mod common;
|
|||
pub mod errors;
|
||||
|
||||
pub fn main() {
|
||||
let args = os::args();
|
||||
let args = env::args().map(|s| s.into_string().unwrap()).collect();;
|
||||
let config = parse_config(args);
|
||||
|
||||
if config.valgrind_path.is_none() && config.force_valgrind {
|
||||
|
@ -224,7 +225,7 @@ pub fn run_tests(config: &Config) {
|
|||
//arm-linux-androideabi debug-info test uses remote debugger
|
||||
//so, we test 1 task at once.
|
||||
// also trying to isolate problems with adb_run_wrapper.sh ilooping
|
||||
os::setenv("RUST_TEST_TASKS","1");
|
||||
env::set_var("RUST_TEST_TASKS","1");
|
||||
}
|
||||
|
||||
match config.mode {
|
||||
|
@ -232,7 +233,7 @@ pub fn run_tests(config: &Config) {
|
|||
// Some older versions of LLDB seem to have problems with multiple
|
||||
// instances running in parallel, so only run one test task at a
|
||||
// time.
|
||||
os::setenv("RUST_TEST_TASKS", "1");
|
||||
env::set_var("RUST_TEST_TASKS", "1");
|
||||
}
|
||||
_ => { /* proceed */ }
|
||||
}
|
||||
|
@ -245,7 +246,7 @@ pub fn run_tests(config: &Config) {
|
|||
old_io::test::raise_fd_limit();
|
||||
// Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
|
||||
// If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
|
||||
os::setenv("__COMPAT_LAYER", "RunAsInvoker");
|
||||
env::set_var("__COMPAT_LAYER", "RunAsInvoker");
|
||||
let res = test::run_tests_console(&opts, tests.into_iter().collect());
|
||||
match res {
|
||||
Ok(true) => {}
|
||||
|
|
|
@ -31,7 +31,7 @@ use std::old_io::process::ProcessExit;
|
|||
use std::old_io::process;
|
||||
use std::old_io::timer;
|
||||
use std::old_io;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::iter::repeat;
|
||||
use std::str;
|
||||
use std::string::String;
|
||||
|
@ -1298,9 +1298,9 @@ fn make_lib_name(config: &Config, auxfile: &Path, testfile: &Path) -> Path {
|
|||
|
||||
fn make_exe_name(config: &Config, testfile: &Path) -> Path {
|
||||
let mut f = output_base_name(config, testfile);
|
||||
if !os::consts::EXE_SUFFIX.is_empty() {
|
||||
if !env::consts::EXE_SUFFIX.is_empty() {
|
||||
let mut fname = f.filename().unwrap().to_vec();
|
||||
fname.extend(os::consts::EXE_SUFFIX.bytes());
|
||||
fname.extend(env::consts::EXE_SUFFIX.bytes());
|
||||
f.set_filename(fname);
|
||||
}
|
||||
f
|
||||
|
|
|
@ -87,6 +87,7 @@ def make_win_dist(rust_root, gcc_root, target_triple):
|
|||
"libsetupapi.a",
|
||||
"libshell32.a",
|
||||
"libuser32.a",
|
||||
"libuserenv.a",
|
||||
"libuuid.a",
|
||||
"libwinhttp.a",
|
||||
"libwinmm.a",
|
||||
|
|
|
@ -173,15 +173,15 @@
|
|||
#![feature(int_uint)]
|
||||
#![feature(core)]
|
||||
#![feature(io)]
|
||||
#![feature(os)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(env)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::old_io::LineBufferedWriter;
|
||||
use std::old_io;
|
||||
use std::mem;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::ptr;
|
||||
use std::rt;
|
||||
use std::slice;
|
||||
|
@ -397,9 +397,9 @@ fn enabled(level: u32,
|
|||
/// This is not threadsafe at all, so initialization is performed through a
|
||||
/// `Once` primitive (and this function is called from that primitive).
|
||||
fn init() {
|
||||
let (mut directives, filter) = match os::getenv("RUST_LOG") {
|
||||
Some(spec) => directive::parse_logging_spec(&spec[]),
|
||||
None => (Vec::new(), None),
|
||||
let (mut directives, filter) = match env::var_string("RUST_LOG") {
|
||||
Ok(spec) => directive::parse_logging_spec(&spec[]),
|
||||
Err(..) => (Vec::new(), None),
|
||||
};
|
||||
|
||||
// Sort the provided directives by length of their name, this allows a
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(libc)]
|
||||
#![feature(os)]
|
||||
#![feature(env)]
|
||||
#![feature(path)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
pub use self::FileMatch::*;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::old_io::fs::PathExtensions;
|
||||
use std::old_io::fs;
|
||||
use std::os;
|
||||
|
||||
use util::fs as myfs;
|
||||
use session::search_paths::{SearchPaths, PathKind};
|
||||
|
@ -194,7 +194,7 @@ pub fn get_or_default_sysroot() -> Path {
|
|||
})
|
||||
}
|
||||
|
||||
match canonicalize(os::self_exe_name()) {
|
||||
match canonicalize(env::current_exe().ok()) {
|
||||
Some(mut p) => { p.pop(); p.pop(); p }
|
||||
None => panic!("can't determine value for sysroot")
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ static PATH_ENTRY_SEPARATOR: &'static str = ":";
|
|||
|
||||
/// Returns RUST_PATH as a string, without default paths added
|
||||
pub fn get_rust_path() -> Option<String> {
|
||||
os::getenv("RUST_PATH").map(|x| x.to_string())
|
||||
env::var_string("RUST_PATH").ok()
|
||||
}
|
||||
|
||||
/// Returns the value of RUST_PATH, as a list
|
||||
|
@ -224,7 +224,7 @@ pub fn rust_path() -> Vec<Path> {
|
|||
}
|
||||
None => Vec::new()
|
||||
};
|
||||
let mut cwd = os::getcwd().unwrap();
|
||||
let mut cwd = env::current_dir().unwrap();
|
||||
// now add in default entries
|
||||
let cwd_dot_rust = cwd.join(".rust");
|
||||
if !env_rust_path.contains(&cwd_dot_rust) {
|
||||
|
@ -243,7 +243,7 @@ pub fn rust_path() -> Vec<Path> {
|
|||
}
|
||||
cwd.pop();
|
||||
}
|
||||
let h = os::homedir();
|
||||
let h = env::home_dir();
|
||||
for h in h.iter() {
|
||||
let p = h.join(".rust");
|
||||
if !env_rust_path.contains(&p) && p.exists() {
|
||||
|
|
|
@ -27,7 +27,7 @@ use util::ppaux::Repr;
|
|||
|
||||
use std::collections::hash_map::Entry::Vacant;
|
||||
use std::old_io::{self, File};
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
|
||||
use syntax::ast;
|
||||
|
||||
|
@ -59,13 +59,13 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
|
|||
}
|
||||
|
||||
let requested_node : Option<ast::NodeId> =
|
||||
os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s| s.parse().ok());
|
||||
env::var_string("RUST_REGION_GRAPH_NODE").ok().and_then(|s| s.parse().ok());
|
||||
|
||||
if requested_node.is_some() && requested_node != Some(subject_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
let requested_output = os::getenv("RUST_REGION_GRAPH");
|
||||
let requested_output = env::var_string("RUST_REGION_GRAPH").ok();
|
||||
debug!("requested_output: {:?} requested_node: {:?}",
|
||||
requested_output, requested_node);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use metadata::creader::{CrateOrString, CrateReader};
|
|||
use plugin::registry::Registry;
|
||||
|
||||
use std::mem;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::collections::HashSet;
|
||||
use syntax::ast;
|
||||
|
@ -233,7 +233,7 @@ impl<'a> PluginLoader<'a> {
|
|||
path: Path,
|
||||
symbol: String) -> PluginRegistrarFun {
|
||||
// Make sure the path contains a / or the linker will search for it.
|
||||
let path = os::make_absolute(&path).unwrap();
|
||||
let path = env::current_dir().unwrap().join(&path);
|
||||
|
||||
let lib = match DynamicLibrary::open(Some(&path)) {
|
||||
Ok(lib) => lib,
|
||||
|
|
|
@ -27,7 +27,7 @@ use syntax::{ast, codemap};
|
|||
|
||||
use rustc_back::target::Target;
|
||||
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
pub mod config;
|
||||
|
@ -347,7 +347,7 @@ pub fn build_session_(sopts: config::Options,
|
|||
if path.is_absolute() {
|
||||
path.clone()
|
||||
} else {
|
||||
os::getcwd().unwrap().join(&path)
|
||||
env::current_dir().unwrap().join(&path)
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -370,7 +370,7 @@ pub fn build_session_(sopts: config::Options,
|
|||
plugin_registrar_fn: Cell::new(None),
|
||||
default_sysroot: default_sysroot,
|
||||
local_crate_source_file: local_crate_source_file,
|
||||
working_dir: os::getcwd().unwrap(),
|
||||
working_dir: env::current_dir().unwrap(),
|
||||
lint_store: RefCell::new(lint::LintStore::new()),
|
||||
lints: RefCell::new(NodeMap()),
|
||||
crate_types: RefCell::new(Vec::new()),
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::old_io::fs::PathExtensions;
|
|||
use std::old_io::process::{Command, ProcessOutput};
|
||||
use std::old_io::{fs, TempDir};
|
||||
use std::old_io;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::str;
|
||||
use syntax::diagnostic::Handler as ErrorHandler;
|
||||
|
||||
|
@ -224,7 +224,7 @@ impl<'a> ArchiveBuilder<'a> {
|
|||
pub fn build(self) -> Archive<'a> {
|
||||
// Get an absolute path to the destination, so `ar` will work even
|
||||
// though we run it from `self.work_dir`.
|
||||
let abs_dst = os::getcwd().unwrap().join(&self.archive.dst);
|
||||
let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
|
||||
assert!(!abs_dst.is_relative());
|
||||
let mut args = vec![&abs_dst];
|
||||
let mut total_len = abs_dst.as_vec().len();
|
||||
|
@ -283,7 +283,7 @@ impl<'a> ArchiveBuilder<'a> {
|
|||
// First, extract the contents of the archive to a temporary directory.
|
||||
// We don't unpack directly into `self.work_dir` due to the possibility
|
||||
// of filename collisions.
|
||||
let archive = os::make_absolute(archive).unwrap();
|
||||
let archive = env::current_dir().unwrap().join(archive);
|
||||
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
|
||||
"x", Some(loc.path()), &[&archive]);
|
||||
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
|
||||
use std::old_io;
|
||||
use std::old_io::fs;
|
||||
use std::os;
|
||||
use std::env;
|
||||
|
||||
/// Returns an absolute path in the filesystem that `path` points to. The
|
||||
/// returned path does not contain any symlinks in its hierarchy.
|
||||
pub fn realpath(original: &Path) -> old_io::IoResult<Path> {
|
||||
static MAX_LINKS_FOLLOWED: uint = 256;
|
||||
let original = os::make_absolute(original).unwrap();
|
||||
let original = try!(env::current_dir()).join(original);
|
||||
|
||||
// Right now lstat on windows doesn't work quite well
|
||||
if cfg!(windows) {
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#![feature(path)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(env)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate serialize;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::old_io::IoError;
|
||||
use syntax::ast;
|
||||
|
||||
|
@ -105,8 +105,6 @@ fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path
|
|||
F: FnOnce() -> Path,
|
||||
G: FnMut(&Path) -> Result<Path, IoError>,
|
||||
{
|
||||
use std::os;
|
||||
|
||||
// Mac doesn't appear to support $ORIGIN
|
||||
let prefix = if config.is_like_osx {
|
||||
"@loader_path"
|
||||
|
@ -114,9 +112,10 @@ fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path
|
|||
"$ORIGIN"
|
||||
};
|
||||
|
||||
let mut lib = (config.realpath)(&os::make_absolute(lib).unwrap()).unwrap();
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
|
||||
lib.pop();
|
||||
let mut output = (config.realpath)(&os::make_absolute(&config.out_filename).unwrap()).unwrap();
|
||||
let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
|
||||
output.pop();
|
||||
let relative = lib.path_relative_from(&output);
|
||||
let relative = relative.expect("could not create rpath relative to output");
|
||||
|
@ -131,7 +130,7 @@ fn get_install_prefix_rpath<F, G>(config: RPathConfig<F, G>) -> String where
|
|||
G: FnMut(&Path) -> Result<Path, IoError>,
|
||||
{
|
||||
let path = (config.get_install_prefix_lib_path)();
|
||||
let path = os::make_absolute(&path).unwrap();
|
||||
let path = env::current_dir().unwrap().join(&path);
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
path.as_str().expect("non-utf8 component in rpath").to_string()
|
||||
}
|
||||
|
|
|
@ -301,7 +301,8 @@ impl Target {
|
|||
/// The error string could come from any of the APIs called, including filesystem access and
|
||||
/// JSON decoding.
|
||||
pub fn search(target: &str) -> Result<Target, String> {
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::old_io::File;
|
||||
use std::path::Path;
|
||||
use serialize::json;
|
||||
|
@ -379,12 +380,12 @@ impl Target {
|
|||
Path::new(target)
|
||||
};
|
||||
|
||||
let target_path = os::getenv("RUST_TARGET_PATH").unwrap_or(String::new());
|
||||
let target_path = env::var("RUST_TARGET_PATH")
|
||||
.unwrap_or(OsString::from_str(""));
|
||||
|
||||
let paths = os::split_paths(&target_path[]);
|
||||
// FIXME 16351: add a sane default search path?
|
||||
|
||||
for dir in paths.iter() {
|
||||
for dir in env::split_paths(&target_path) {
|
||||
let p = dir.join(path.clone());
|
||||
if p.is_file() {
|
||||
return load_file(&p);
|
||||
|
|
|
@ -30,9 +30,10 @@ use rustc_privacy;
|
|||
|
||||
use serialize::json;
|
||||
|
||||
use std::old_io;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::old_io::fs;
|
||||
use std::os;
|
||||
use std::old_io;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
use syntax::attr;
|
||||
|
@ -460,12 +461,12 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||
// dependent dlls. Note that this uses cfg!(windows) as opposed to
|
||||
// targ_cfg because syntax extensions are always loaded for the host
|
||||
// compiler, not for the target.
|
||||
let mut _old_path = String::new();
|
||||
let mut _old_path = OsString::from_str("");
|
||||
if cfg!(windows) {
|
||||
_old_path = os::getenv("PATH").unwrap_or(_old_path);
|
||||
_old_path = env::var("PATH").unwrap_or(_old_path);
|
||||
let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
|
||||
new_path.extend(os::split_paths(&_old_path[]).into_iter());
|
||||
os::setenv("PATH", os::join_paths(&new_path[]).unwrap());
|
||||
new_path.extend(env::split_paths(&_old_path));
|
||||
env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
|
||||
}
|
||||
let cfg = syntax::ext::expand::ExpansionConfig {
|
||||
crate_name: crate_name.to_string(),
|
||||
|
@ -478,7 +479,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||
syntax_exts,
|
||||
krate);
|
||||
if cfg!(windows) {
|
||||
os::setenv("PATH", _old_path);
|
||||
env::set_var("PATH", &_old_path);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
@ -734,10 +735,10 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
|
|||
pub fn phase_6_link_output(sess: &Session,
|
||||
trans: &trans::CrateTranslation,
|
||||
outputs: &OutputFilenames) {
|
||||
let old_path = os::getenv("PATH").unwrap_or_else(||String::new());
|
||||
let old_path = env::var("PATH").unwrap_or(OsString::from_str(""));
|
||||
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
|
||||
new_path.extend(os::split_paths(&old_path[]).into_iter());
|
||||
os::setenv("PATH", os::join_paths(&new_path[]).unwrap());
|
||||
new_path.extend(env::split_paths(&old_path));
|
||||
env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
|
||||
|
||||
time(sess.time_passes(), "linking", (), |_|
|
||||
link::link_binary(sess,
|
||||
|
@ -745,7 +746,7 @@ pub fn phase_6_link_output(sess: &Session,
|
|||
outputs,
|
||||
&trans.link.crate_name[]));
|
||||
|
||||
os::setenv("PATH", old_path);
|
||||
env::set_var("PATH", &old_path);
|
||||
}
|
||||
|
||||
fn escape_dep_filename(filename: &str) -> String {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(env)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(libc)]
|
||||
|
@ -74,7 +75,7 @@ use rustc::util::common::time;
|
|||
use std::cmp::Ordering::Equal;
|
||||
use std::old_io;
|
||||
use std::iter::repeat;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
|
@ -252,7 +253,7 @@ pub fn get_unstable_features_setting() -> UnstableFeatures {
|
|||
// subverting the unstable features lints
|
||||
let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY");
|
||||
// The matching key to the above, only known by the build system
|
||||
let bootstrap_provided_key = os::getenv("RUSTC_BOOTSTRAP_KEY");
|
||||
let bootstrap_provided_key = env::var_string("RUSTC_BOOTSTRAP_KEY").ok();
|
||||
match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) {
|
||||
(_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat,
|
||||
(true, _, _) => UnstableFeatures::Disallow,
|
||||
|
@ -618,7 +619,7 @@ pub fn monitor<F:FnOnce()+Send>(f: F) {
|
|||
|
||||
// FIXME: Hacks on hacks. If the env is trying to override the stack size
|
||||
// then *don't* set it explicitly.
|
||||
if os::getenv("RUST_MIN_STACK").is_none() {
|
||||
if env::var("RUST_MIN_STACK").is_none() {
|
||||
cfg = cfg.stack_size(STACK_SIZE);
|
||||
}
|
||||
|
||||
|
@ -682,8 +683,8 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry {
|
|||
}
|
||||
|
||||
pub fn main() {
|
||||
let args = std::os::args();
|
||||
let result = run(args);
|
||||
std::os::set_exit_status(result);
|
||||
let args = env::args().map(|s| s.into_string().unwrap());
|
||||
let result = run(args.collect());
|
||||
std::env::set_exit_status(result as i32);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
#![feature(hash)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(env)]
|
||||
#![feature(libc)]
|
||||
#![feature(os)]
|
||||
#![feature(path)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
|
|
|
@ -34,7 +34,7 @@ use middle::ty::{self, Ty};
|
|||
|
||||
use std::cell::Cell;
|
||||
use std::old_io::{self, File, fs};
|
||||
use std::os;
|
||||
use std::env;
|
||||
|
||||
use syntax::ast_util::{self, PostExpansionMethod};
|
||||
use syntax::ast::{self, NodeId, DefId};
|
||||
|
@ -1551,9 +1551,9 @@ pub fn process_crate(sess: &Session,
|
|||
info!("Dumping crate {}", cratename);
|
||||
|
||||
// find a path to dump our data to
|
||||
let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") {
|
||||
Some(val) => Path::new(val),
|
||||
None => match odir {
|
||||
let mut root_path = match env::var_string("DXR_RUST_TEMP_FOLDER") {
|
||||
Ok(val) => Path::new(val),
|
||||
Err(..) => match odir {
|
||||
Some(val) => val.join("dxr"),
|
||||
None => Path::new("dxr-temp"),
|
||||
},
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(env)]
|
||||
#![feature(hash)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
|
@ -50,6 +51,7 @@ extern crate "serialize" as rustc_serialize; // used by deriving
|
|||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::old_io::File;
|
||||
use std::old_io;
|
||||
use std::rc::Rc;
|
||||
|
@ -121,9 +123,10 @@ struct Output {
|
|||
pub fn main() {
|
||||
static STACK_SIZE: uint = 32000000; // 32MB
|
||||
let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || {
|
||||
main_args(std::os::args().as_slice())
|
||||
let s = env::args().map(|s| s.into_string().unwrap());
|
||||
main_args(&s.collect::<Vec<_>>())
|
||||
}).join();
|
||||
std::os::set_exit_status(res.ok().unwrap());
|
||||
env::set_exit_status(res.ok().unwrap() as i32);
|
||||
}
|
||||
|
||||
pub fn opts() -> Vec<getopts::OptGroup> {
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::sync::mpsc::channel;
|
|||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::old_io::{Command, TempDir};
|
||||
use std::old_io;
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::str;
|
||||
use std::thread::Thread;
|
||||
use std::thunk::Thunk;
|
||||
|
@ -49,7 +49,7 @@ pub fn run(input: &str,
|
|||
let input = config::Input::File(input_path.clone());
|
||||
|
||||
let sessopts = config::Options {
|
||||
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
||||
maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
|
||||
search_paths: libs.clone(),
|
||||
crate_types: vec!(config::CrateTypeDylib),
|
||||
externs: externs.clone(),
|
||||
|
@ -119,7 +119,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
|||
let input = config::Input::Str(test.to_string());
|
||||
|
||||
let sessopts = config::Options {
|
||||
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
|
||||
maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
|
||||
search_paths: libs,
|
||||
crate_types: vec!(config::CrateTypeExecutable),
|
||||
output_types: vec!(config::OutputTypeExe),
|
||||
|
|
|
@ -19,7 +19,7 @@ use prelude::v1::*;
|
|||
|
||||
use ffi::CString;
|
||||
use mem;
|
||||
use os;
|
||||
use env;
|
||||
use str;
|
||||
|
||||
#[allow(missing_copy_implementations)]
|
||||
|
@ -68,7 +68,7 @@ impl DynamicLibrary {
|
|||
let mut search_path = DynamicLibrary::search_path();
|
||||
search_path.insert(0, path.clone());
|
||||
let newval = DynamicLibrary::create_path(search_path.as_slice());
|
||||
os::setenv(DynamicLibrary::envvar(),
|
||||
env::set_var(DynamicLibrary::envvar(),
|
||||
str::from_utf8(newval.as_slice()).unwrap());
|
||||
}
|
||||
|
||||
|
@ -102,19 +102,11 @@ impl DynamicLibrary {
|
|||
/// Returns the current search path for dynamic libraries being used by this
|
||||
/// process
|
||||
pub fn search_path() -> Vec<Path> {
|
||||
let mut ret = Vec::new();
|
||||
match os::getenv_as_bytes(DynamicLibrary::envvar()) {
|
||||
Some(env) => {
|
||||
for portion in
|
||||
env.as_slice()
|
||||
.split(|a| *a == DynamicLibrary::separator()) {
|
||||
ret.push(Path::new(portion));
|
||||
match env::var(DynamicLibrary::envvar()) {
|
||||
Some(var) => env::split_paths(&var).collect(),
|
||||
None => Vec::new(),
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Access the value at the symbol of the dynamic library
|
||||
pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
|
||||
|
|
833
src/libstd/env.rs
Normal file
833
src/libstd/env.rs
Normal file
|
@ -0,0 +1,833 @@
|
|||
// Copyright 2012-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.
|
||||
|
||||
//! Inspection and manipulation of the process's environment.
|
||||
//!
|
||||
//! This module contains methods to inspect various aspects such as
|
||||
//! environment varibles, process arguments, the current directory, and various
|
||||
//! other important directories.
|
||||
|
||||
#![unstable(feature = "env", reason = "recently added via RFC 578")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use error::Error;
|
||||
use ffi::{OsString, AsOsStr};
|
||||
use fmt;
|
||||
use old_io::IoResult;
|
||||
use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
|
||||
use sync::{StaticMutex, MUTEX_INIT};
|
||||
use sys::os as os_imp;
|
||||
|
||||
/// Returns the current working directory as a `Path`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an `Err` if the current working directory value is invalid.
|
||||
/// Possible cases:
|
||||
///
|
||||
/// * Current directory does not exist.
|
||||
/// * There are insufficient permissions to access the current directory.
|
||||
/// * The internal buffer is not large enough to hold the path.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// // We assume that we are in a valid directory.
|
||||
/// let p = env::current_dir().unwrap();
|
||||
/// println!("The current directory is {}", p.display());
|
||||
/// ```
|
||||
pub fn current_dir() -> IoResult<Path> {
|
||||
os_imp::getcwd()
|
||||
}
|
||||
|
||||
/// Changes the current working directory to the specified path, returning
|
||||
/// whether the change was completed successfully or not.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// let root = Path::new("/");
|
||||
/// assert!(env::set_current_dir(&root).is_ok());
|
||||
/// println!("Successfully changed working directory to {}!", root.display());
|
||||
/// ```
|
||||
pub fn set_current_dir(p: &Path) -> IoResult<()> {
|
||||
os_imp::chdir(p)
|
||||
}
|
||||
|
||||
static ENV_LOCK: StaticMutex = MUTEX_INIT;
|
||||
|
||||
/// An iterator over a snapshot of the environment variables of this process.
|
||||
///
|
||||
/// This iterator is created through `std::env::vars()` and yields `(OsString,
|
||||
/// OsString)` pairs.
|
||||
pub struct Vars { inner: os_imp::Env }
|
||||
|
||||
/// Returns an iterator of (variable, value) pairs, for all the environment
|
||||
/// variables of the current process.
|
||||
///
|
||||
/// The returned iterator contains a snapshot of the process's environment
|
||||
/// variables at the time of this invocation, modifications to environment
|
||||
/// variables afterwards will not be reflected in the returned iterator.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// // We will iterate through the references to the element returned by
|
||||
/// // env::vars();
|
||||
/// for (key, value) in env::vars() {
|
||||
/// println!("{:?}: {:?}", key, value);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn vars() -> Vars {
|
||||
let _g = ENV_LOCK.lock();
|
||||
Vars { inner: os_imp::env() }
|
||||
}
|
||||
|
||||
impl Iterator for Vars {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
/// Fetches the environment variable `key` from the current process, returning
|
||||
/// None if the variable isn't set.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// let key = "HOME";
|
||||
/// match env::var(key) {
|
||||
/// Some(val) => println!("{}: {:?}", key, val),
|
||||
/// None => println!("{} is not defined in the environment.", key)
|
||||
/// }
|
||||
/// ```
|
||||
pub fn var<K: ?Sized>(key: &K) -> Option<OsString> where K: AsOsStr {
|
||||
let _g = ENV_LOCK.lock();
|
||||
os_imp::getenv(key.as_os_str())
|
||||
}
|
||||
|
||||
/// Fetches the environment variable `key` from the current process.
|
||||
///
|
||||
/// The returned result is `Ok(s)` if the environment variable is present and is
|
||||
/// valid unicode. If the environment variable is not present, or it is not
|
||||
/// valid unicode, then `Err` will be returned.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// let key = "HOME";
|
||||
/// match env::var_string(key) {
|
||||
/// Ok(val) => println!("{}: {:?}", key, val),
|
||||
/// Err(e) => println!("couldn't interpret {}: {}", key, e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn var_string<K: ?Sized>(key: &K) -> Result<String, VarError> where K: AsOsStr {
|
||||
match var(key) {
|
||||
Some(s) => s.into_string().map_err(VarError::NotUnicode),
|
||||
None => Err(VarError::NotPresent)
|
||||
}
|
||||
}
|
||||
|
||||
/// Possible errors from the `env::var` method.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum VarError {
|
||||
/// The specified environment variable was not present in the current
|
||||
/// process's environment.
|
||||
NotPresent,
|
||||
|
||||
/// The specified environment variable was found, but it did not contain
|
||||
/// valid unicode data. The found data is returned as a payload of this
|
||||
/// variant.
|
||||
NotUnicode(OsString),
|
||||
}
|
||||
|
||||
impl fmt::Display for VarError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
VarError::NotPresent => write!(f, "environment variable not found"),
|
||||
VarError::NotUnicode(ref s) => {
|
||||
write!(f, "environment variable was not valid unicode: {:?}", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for VarError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
VarError::NotPresent => "environment variable not found",
|
||||
VarError::NotUnicode(..) => "environment variable was not valid unicode",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the environment variable `k` to the value `v` for the currently running
|
||||
/// process.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// let key = "KEY";
|
||||
/// env::set_var(key, "VALUE");
|
||||
/// assert_eq!(env::var_string(key), Ok("VALUE".to_string()));
|
||||
/// ```
|
||||
pub fn set_var<K: ?Sized, V: ?Sized>(k: &K, v: &V)
|
||||
where K: AsOsStr, V: AsOsStr
|
||||
{
|
||||
let _g = ENV_LOCK.lock();
|
||||
os_imp::setenv(k.as_os_str(), v.as_os_str())
|
||||
}
|
||||
|
||||
/// Remove a variable from the environment entirely.
|
||||
pub fn remove_var<K: ?Sized>(k: &K) where K: AsOsStr {
|
||||
let _g = ENV_LOCK.lock();
|
||||
os_imp::unsetenv(k.as_os_str())
|
||||
}
|
||||
|
||||
/// An iterator over `Path` instances for parsing an environment variable
|
||||
/// according to platform-specific conventions.
|
||||
///
|
||||
/// This structure is returned from `std::env::split_paths`.
|
||||
pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
|
||||
|
||||
/// Parses input according to platform conventions for the `PATH`
|
||||
/// environment variable.
|
||||
///
|
||||
/// Returns an iterator over the paths contained in `unparsed`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// let key = "PATH";
|
||||
/// match env::var(key) {
|
||||
/// Some(paths) => {
|
||||
/// for path in env::split_paths(&paths) {
|
||||
/// println!("'{}'", path.display());
|
||||
/// }
|
||||
/// }
|
||||
/// None => println!("{} is not defined in the environment.", key)
|
||||
/// }
|
||||
/// ```
|
||||
pub fn split_paths<T: AsOsStr + ?Sized>(unparsed: &T) -> SplitPaths {
|
||||
SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) }
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SplitPaths<'a> {
|
||||
type Item = Path;
|
||||
fn next(&mut self) -> Option<Path> { self.inner.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
/// Error type returned from `std::env::join_paths` when paths fail to be
|
||||
/// joined.
|
||||
#[derive(Debug)]
|
||||
pub struct JoinPathsError {
|
||||
inner: os_imp::JoinPathsError
|
||||
}
|
||||
|
||||
/// Joins a collection of `Path`s appropriately for the `PATH`
|
||||
/// environment variable.
|
||||
///
|
||||
/// Returns an `OsString` on success.
|
||||
///
|
||||
/// Returns an `Err` (containing an error message) if one of the input
|
||||
/// `Path`s contains an invalid character for constructing the `PATH`
|
||||
/// variable (a double quote on Windows or a colon on Unix).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// if let Some(path) = env::var("PATH") {
|
||||
/// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
|
||||
/// paths.push(Path::new("/home/xyz/bin"));
|
||||
/// let new_path = env::join_paths(paths.iter()).unwrap();
|
||||
/// env::set_var("PATH", &new_path);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
|
||||
where I: Iterator<Item=T>, T: AsOsStr
|
||||
{
|
||||
os_imp::join_paths(paths).map_err(|e| {
|
||||
JoinPathsError { inner: e }
|
||||
})
|
||||
}
|
||||
|
||||
impl fmt::Display for JoinPathsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for JoinPathsError {
|
||||
fn description(&self) -> &str { self.inner.description() }
|
||||
}
|
||||
|
||||
/// Optionally returns the path to the current user's home directory if known.
|
||||
///
|
||||
/// # Unix
|
||||
///
|
||||
/// Returns the value of the 'HOME' environment variable if it is set
|
||||
/// and not equal to the empty string.
|
||||
///
|
||||
/// # Windows
|
||||
///
|
||||
/// Returns the value of the 'HOME' environment variable if it is
|
||||
/// set and not equal to the empty string. Otherwise, returns the value of the
|
||||
/// 'USERPROFILE' environment variable if it is set and not equal to the empty
|
||||
/// string.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// match env::home_dir() {
|
||||
/// Some(ref p) => println!("{}", p.display()),
|
||||
/// None => println!("Impossible to get your home dir!")
|
||||
/// }
|
||||
/// ```
|
||||
pub fn home_dir() -> Option<Path> {
|
||||
os_imp::home_dir()
|
||||
}
|
||||
|
||||
/// Returns the path to a temporary directory.
|
||||
///
|
||||
/// On Unix, returns the value of the 'TMPDIR' environment variable if it is
|
||||
/// set, otherwise for non-Android it returns '/tmp'. If Android, since there
|
||||
/// is no global temporary folder (it is usually allocated per-app), we return
|
||||
/// '/data/local/tmp'.
|
||||
///
|
||||
/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
|
||||
/// 'USERPROFILE' environment variable if any are set and not the empty
|
||||
/// string. Otherwise, tmpdir returns the path to the Windows directory.
|
||||
pub fn temp_dir() -> Path {
|
||||
os_imp::temp_dir()
|
||||
}
|
||||
|
||||
/// Optionally returns the filesystem path to the current executable which is
|
||||
/// running but with the executable name.
|
||||
///
|
||||
/// The path returned is not necessarily a "real path" to the executable as
|
||||
/// there may be intermediate symlinks.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Acquring the path to the current executable is a platform-specific operation
|
||||
/// that can fail for a good number of reasons. Some errors can include, but not
|
||||
/// be limited to filesystem operations failing or general syscall failures.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// match env::current_exe() {
|
||||
/// Ok(exe_path) => println!("Path of this executable is: {}",
|
||||
/// exe_path.display()),
|
||||
/// Err(e) => println!("failed to get current exe path: {}", e),
|
||||
/// };
|
||||
/// ```
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
os_imp::current_exe()
|
||||
}
|
||||
|
||||
static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
|
||||
|
||||
/// Sets the process exit code
|
||||
///
|
||||
/// Sets the exit code returned by the process if all supervised tasks
|
||||
/// terminate successfully (without panicking). If the current root task panics
|
||||
/// and is supervised by the scheduler then any user-specified exit status is
|
||||
/// ignored and the process exits with the default panic status.
|
||||
///
|
||||
/// Note that this is not synchronized against modifications of other threads.
|
||||
pub fn set_exit_status(code: i32) {
|
||||
EXIT_STATUS.store(code as isize, Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// Fetches the process's current exit code. This defaults to 0 and can change
|
||||
/// by calling `set_exit_status`.
|
||||
pub fn get_exit_status() -> i32 {
|
||||
EXIT_STATUS.load(Ordering::SeqCst) as i32
|
||||
}
|
||||
|
||||
/// An iterator over the arguments of a process, yielding an `OsString` value
|
||||
/// for each argument.
|
||||
///
|
||||
/// This structure is created through the `std::env::args` method.
|
||||
pub struct Args { inner: os_imp::Args }
|
||||
|
||||
/// Returns the arguments which this program was started with (normally passed
|
||||
/// via the command line).
|
||||
///
|
||||
/// The first element is traditionally the path to the executable, but it can be
|
||||
/// set to arbitrary text, and it may not even exist, so this property should
|
||||
/// not be relied upon for security purposes.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
///
|
||||
/// // Prints each argument on a separate line
|
||||
/// for argument in env::args() {
|
||||
/// println!("{:?}", argument);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn args() -> Args {
|
||||
Args { inner: os_imp::args() }
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.inner.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
/// Returns the page size of the current architecture in bytes.
|
||||
pub fn page_size() -> usize {
|
||||
os_imp::page_size()
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "unix";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `linux`.
|
||||
pub const OS: &'static str = "linux";
|
||||
|
||||
/// Specifies the filename prefix used for shared libraries on this
|
||||
/// platform: in this case, `lib`.
|
||||
pub const DLL_PREFIX: &'static str = "lib";
|
||||
|
||||
/// Specifies the filename suffix used for shared libraries on this
|
||||
/// platform: in this case, `.so`.
|
||||
pub const DLL_SUFFIX: &'static str = ".so";
|
||||
|
||||
/// Specifies the file extension used for shared libraries on this
|
||||
/// platform that goes after the dot: in this case, `so`.
|
||||
pub const DLL_EXTENSION: &'static str = "so";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const EXE_SUFFIX: &'static str = "";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, the empty string.
|
||||
pub const EXE_EXTENSION: &'static str = "";
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "unix";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `macos`.
|
||||
pub const OS: &'static str = "macos";
|
||||
|
||||
/// Specifies the filename prefix used for shared libraries on this
|
||||
/// platform: in this case, `lib`.
|
||||
pub const DLL_PREFIX: &'static str = "lib";
|
||||
|
||||
/// Specifies the filename suffix used for shared libraries on this
|
||||
/// platform: in this case, `.dylib`.
|
||||
pub const DLL_SUFFIX: &'static str = ".dylib";
|
||||
|
||||
/// Specifies the file extension used for shared libraries on this
|
||||
/// platform that goes after the dot: in this case, `dylib`.
|
||||
pub const DLL_EXTENSION: &'static str = "dylib";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const EXE_SUFFIX: &'static str = "";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, the empty string.
|
||||
pub const EXE_EXTENSION: &'static str = "";
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "ios")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "unix";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `ios`.
|
||||
pub const OS: &'static str = "ios";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const EXE_SUFFIX: &'static str = "";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, the empty string.
|
||||
pub const EXE_EXTENSION: &'static str = "";
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "unix";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `freebsd`.
|
||||
pub const OS: &'static str = "freebsd";
|
||||
|
||||
/// Specifies the filename prefix used for shared libraries on this
|
||||
/// platform: in this case, `lib`.
|
||||
pub const DLL_PREFIX: &'static str = "lib";
|
||||
|
||||
/// Specifies the filename suffix used for shared libraries on this
|
||||
/// platform: in this case, `.so`.
|
||||
pub const DLL_SUFFIX: &'static str = ".so";
|
||||
|
||||
/// Specifies the file extension used for shared libraries on this
|
||||
/// platform that goes after the dot: in this case, `so`.
|
||||
pub const DLL_EXTENSION: &'static str = "so";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const EXE_SUFFIX: &'static str = "";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, the empty string.
|
||||
pub const EXE_EXTENSION: &'static str = "";
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "unix";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `dragonfly`.
|
||||
pub const OS: &'static str = "dragonfly";
|
||||
|
||||
/// Specifies the filename prefix used for shared libraries on this
|
||||
/// platform: in this case, `lib`.
|
||||
pub const DLL_PREFIX: &'static str = "lib";
|
||||
|
||||
/// Specifies the filename suffix used for shared libraries on this
|
||||
/// platform: in this case, `.so`.
|
||||
pub const DLL_SUFFIX: &'static str = ".so";
|
||||
|
||||
/// Specifies the file extension used for shared libraries on this
|
||||
/// platform that goes after the dot: in this case, `so`.
|
||||
pub const DLL_EXTENSION: &'static str = "so";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const EXE_SUFFIX: &'static str = "";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, the empty string.
|
||||
pub const EXE_EXTENSION: &'static str = "";
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "unix";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `android`.
|
||||
pub const OS: &'static str = "android";
|
||||
|
||||
/// Specifies the filename prefix used for shared libraries on this
|
||||
/// platform: in this case, `lib`.
|
||||
pub const DLL_PREFIX: &'static str = "lib";
|
||||
|
||||
/// Specifies the filename suffix used for shared libraries on this
|
||||
/// platform: in this case, `.so`.
|
||||
pub const DLL_SUFFIX: &'static str = ".so";
|
||||
|
||||
/// Specifies the file extension used for shared libraries on this
|
||||
/// platform that goes after the dot: in this case, `so`.
|
||||
pub const DLL_EXTENSION: &'static str = "so";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const EXE_SUFFIX: &'static str = "";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, the empty string.
|
||||
pub const EXE_EXTENSION: &'static str = "";
|
||||
}
|
||||
|
||||
/// Constants associated with the current target
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod consts {
|
||||
pub use super::arch_consts::ARCH;
|
||||
|
||||
pub const FAMILY: &'static str = "windows";
|
||||
|
||||
/// A string describing the specific operating system in use: in this
|
||||
/// case, `windows`.
|
||||
pub const OS: &'static str = "windows";
|
||||
|
||||
/// Specifies the filename prefix used for shared libraries on this
|
||||
/// platform: in this case, the empty string.
|
||||
pub const DLL_PREFIX: &'static str = "";
|
||||
|
||||
/// Specifies the filename suffix used for shared libraries on this
|
||||
/// platform: in this case, `.dll`.
|
||||
pub const DLL_SUFFIX: &'static str = ".dll";
|
||||
|
||||
/// Specifies the file extension used for shared libraries on this
|
||||
/// platform that goes after the dot: in this case, `dll`.
|
||||
pub const DLL_EXTENSION: &'static str = "dll";
|
||||
|
||||
/// Specifies the filename suffix used for executable binaries on this
|
||||
/// platform: in this case, `.exe`.
|
||||
pub const EXE_SUFFIX: &'static str = ".exe";
|
||||
|
||||
/// Specifies the file extension, if any, used for executable binaries
|
||||
/// on this platform: in this case, `exe`.
|
||||
pub const EXE_EXTENSION: &'static str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "x86";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "x86_64";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "arm";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "aarch64";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "mips";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "mipsel")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "mipsel";
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "powerpc")]
|
||||
mod arch_consts {
|
||||
pub const ARCH: &'static str = "powerpc";
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::v1::*;
|
||||
use super::*;
|
||||
use iter::repeat;
|
||||
use rand::{self, Rng};
|
||||
use ffi::{OsString, OsStr};
|
||||
|
||||
fn make_rand_name() -> OsString {
|
||||
let mut rng = rand::thread_rng();
|
||||
let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
|
||||
.collect::<String>());
|
||||
let n = OsString::from_string(n);
|
||||
assert!(var(&n).is_none());
|
||||
n
|
||||
}
|
||||
|
||||
fn eq(a: Option<OsString>, b: Option<&str>) {
|
||||
assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::from_str).map(|s| &*s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_var() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "VALUE");
|
||||
eq(var(&n), Some("VALUE"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_var() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "VALUE");
|
||||
remove_var(&n);
|
||||
eq(var(&n), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_var_overwrite() {
|
||||
let n = make_rand_name();
|
||||
set_var(&n, "1");
|
||||
set_var(&n, "2");
|
||||
eq(var(&n), Some("2"));
|
||||
set_var(&n, "");
|
||||
eq(var(&n), Some(""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_var_big() {
|
||||
let mut s = "".to_string();
|
||||
let mut i = 0;
|
||||
while i < 100 {
|
||||
s.push_str("aaaaaaaaaa");
|
||||
i += 1;
|
||||
}
|
||||
let n = make_rand_name();
|
||||
set_var(&n, s.as_slice());
|
||||
eq(var(&n), Some(s.as_slice()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_self_exe_path() {
|
||||
let path = current_exe();
|
||||
assert!(path.is_ok());
|
||||
let path = path.unwrap();
|
||||
|
||||
// Hard to test this function
|
||||
assert!(path.is_absolute());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_env_set_get_huge() {
|
||||
let n = make_rand_name();
|
||||
let s = repeat("x").take(10000).collect::<String>();
|
||||
set_var(&n, &s);
|
||||
eq(var(&n), Some(s.as_slice()));
|
||||
remove_var(&n);
|
||||
eq(var(&n), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_env_set_var() {
|
||||
let n = make_rand_name();
|
||||
|
||||
let mut e = vars();
|
||||
set_var(&n, "VALUE");
|
||||
assert!(!e.any(|(k, v)| {
|
||||
&*k == &*n && &*v == "VALUE"
|
||||
}));
|
||||
|
||||
assert!(vars().any(|(k, v)| {
|
||||
&*k == &*n && &*v == "VALUE"
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
assert!((!Path::new("test-path").is_absolute()));
|
||||
|
||||
current_dir().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn split_paths_windows() {
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>() ==
|
||||
parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
assert!(check_parse(r#""""#, &mut [""]));
|
||||
assert!(check_parse(";;", &mut ["", "", ""]));
|
||||
assert!(check_parse(r"c:\", &mut [r"c:\"]));
|
||||
assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
|
||||
assert!(check_parse(r"c:\;c:\Program Files\",
|
||||
&mut [r"c:\", r"c:\Program Files\"]));
|
||||
assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
|
||||
assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#,
|
||||
&mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn split_paths_unix() {
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>() ==
|
||||
parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
assert!(check_parse("::", &mut ["", "", ""]));
|
||||
assert!(check_parse("/", &mut ["/"]));
|
||||
assert!(check_parse("/:", &mut ["/", ""]));
|
||||
assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn join_paths_unix() {
|
||||
fn test_eq(input: &[&str], output: &str) -> bool {
|
||||
&*join_paths(input.iter().map(|s| *s)).unwrap() ==
|
||||
OsStr::from_str(output)
|
||||
}
|
||||
|
||||
assert!(test_eq(&[], ""));
|
||||
assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"],
|
||||
"/bin:/usr/bin:/usr/local/bin"));
|
||||
assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
|
||||
":/bin:::/usr/bin:"));
|
||||
assert!(join_paths(["/te:st"].iter().map(|s| *s)).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn join_paths_windows() {
|
||||
fn test_eq(input: &[&str], output: &str) -> bool {
|
||||
&*join_paths(input.iter().map(|s| *s)).unwrap() ==
|
||||
OsStr::from_str(output)
|
||||
}
|
||||
|
||||
assert!(test_eq(&[], ""));
|
||||
assert!(test_eq(&[r"c:\windows", r"c:\"],
|
||||
r"c:\windows;c:\"));
|
||||
assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""],
|
||||
r";c:\windows;;;c:\;"));
|
||||
assert!(test_eq(&[r"c:\te;st", r"c:\"],
|
||||
r#""c:\te;st";c:\"#));
|
||||
assert!(join_paths([r#"c:\te"st"#].iter().map(|s| *s)).is_err());
|
||||
}
|
||||
}
|
|
@ -20,7 +20,12 @@ pub use self::c_str::c_str_to_bytes_with_nul;
|
|||
|
||||
pub use self::os_str::OsString;
|
||||
pub use self::os_str::OsStr;
|
||||
pub use self::os_str::AsOsStr;
|
||||
|
||||
mod c_str;
|
||||
mod os_str;
|
||||
|
||||
/// Freely convertible to an `&OsStr` slice.
|
||||
pub trait AsOsStr {
|
||||
/// Convert to an `&OsStr` slice.
|
||||
fn as_os_str(&self) -> &OsStr;
|
||||
}
|
||||
|
|
|
@ -41,9 +41,11 @@ use string::{String, CowString};
|
|||
use ops;
|
||||
use cmp;
|
||||
use hash::{Hash, Hasher, Writer};
|
||||
use path::{Path, GenericPath};
|
||||
|
||||
use sys::os_str::{Buf, Slice};
|
||||
use sys_common::{AsInner, IntoInner, FromInner};
|
||||
use super::AsOsStr;
|
||||
|
||||
/// Owned, mutable OS strings.
|
||||
#[derive(Clone)]
|
||||
|
@ -69,6 +71,11 @@ impl OsString {
|
|||
OsString { inner: Buf::from_str(s) }
|
||||
}
|
||||
|
||||
/// Constructs a new empty `OsString`.
|
||||
pub fn new() -> OsString {
|
||||
OsString { inner: Buf::from_string(String::new()) }
|
||||
}
|
||||
|
||||
/// Convert the `OsString` into a `String` if it contains valid Unicode data.
|
||||
///
|
||||
/// On failure, ownership of the original `OsString` is returned.
|
||||
|
@ -117,6 +124,62 @@ impl Debug for OsString {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for OsString {
|
||||
fn eq(&self, other: &OsString) -> bool {
|
||||
&**self == &**other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for OsString {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
&**self == other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<OsString> for str {
|
||||
fn eq(&self, other: &OsString) -> bool {
|
||||
&**other == self
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for OsString {}
|
||||
|
||||
impl PartialOrd for OsString {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
|
||||
(&**self).partial_cmp(&**other)
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &OsString) -> bool { &**self < &**other }
|
||||
#[inline]
|
||||
fn le(&self, other: &OsString) -> bool { &**self <= &**other }
|
||||
#[inline]
|
||||
fn gt(&self, other: &OsString) -> bool { &**self > &**other }
|
||||
#[inline]
|
||||
fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
|
||||
}
|
||||
|
||||
impl PartialOrd<str> for OsString {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
|
||||
(&**self).partial_cmp(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for OsString {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &OsString) -> cmp::Ordering {
|
||||
(&**self).cmp(&**other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Hasher + Writer> Hash<S> for OsString {
|
||||
#[inline]
|
||||
fn hash(&self, state: &mut S) {
|
||||
(&**self).hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl OsStr {
|
||||
/// Coerce directly from a `&str` slice to a `&OsStr` slice.
|
||||
pub fn from_str(s: &str) -> &OsStr {
|
||||
|
@ -222,10 +285,10 @@ impl ToOwned<OsString> for OsStr {
|
|||
fn to_owned(&self) -> OsString { self.to_os_string() }
|
||||
}
|
||||
|
||||
/// Freely convertible to an `&OsStr` slice.
|
||||
pub trait AsOsStr {
|
||||
/// Convert to an `&OsStr` slice.
|
||||
fn as_os_str(&self) -> &OsStr;
|
||||
impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
(*self).as_os_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOsStr for OsStr {
|
||||
|
@ -252,6 +315,21 @@ impl AsOsStr for String {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl AsOsStr for Path {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
unsafe { mem::transmute(self.as_vec()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl AsOsStr for Path {
|
||||
fn as_os_str(&self) -> &OsStr {
|
||||
// currently .as_str() is actually infallible on windows
|
||||
OsStr::from_str(self.as_str().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<Buf> for OsString {
|
||||
fn from_inner(buf: Buf) -> OsString {
|
||||
OsString { inner: buf }
|
||||
|
|
|
@ -250,6 +250,7 @@ pub mod ffi;
|
|||
pub mod fmt;
|
||||
pub mod old_io;
|
||||
pub mod os;
|
||||
pub mod env;
|
||||
pub mod path;
|
||||
pub mod rand;
|
||||
pub mod time;
|
||||
|
|
|
@ -231,6 +231,7 @@ impl Command {
|
|||
self
|
||||
}
|
||||
// Get a mutable borrow of the environment variable map for this `Command`.
|
||||
#[allow(deprecated)]
|
||||
fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
|
||||
match self.env {
|
||||
Some(ref mut map) => map,
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
|
||||
//! Temporary files and directories
|
||||
|
||||
use env;
|
||||
use iter::{IteratorExt};
|
||||
use old_io::{fs, IoError, IoErrorKind, IoResult};
|
||||
use old_io;
|
||||
use iter::IteratorExt;
|
||||
use ops::Drop;
|
||||
use option::Option;
|
||||
use option::Option::{None, Some};
|
||||
use os;
|
||||
use option::Option;
|
||||
use path::{Path, GenericPath};
|
||||
use rand::{Rng, thread_rng};
|
||||
use result::Result::{Ok, Err};
|
||||
|
@ -97,8 +97,8 @@ impl TempDir {
|
|||
/// If no directory can be created, `Err` is returned.
|
||||
pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
|
||||
if !tmpdir.is_absolute() {
|
||||
let abs_tmpdir = try!(os::make_absolute(tmpdir));
|
||||
return TempDir::new_in(&abs_tmpdir, prefix);
|
||||
let cur_dir = try!(env::current_dir());
|
||||
return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
|
||||
}
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
@ -132,7 +132,7 @@ impl TempDir {
|
|||
///
|
||||
/// If no directory can be created, `Err` is returned.
|
||||
pub fn new(prefix: &str) -> IoResult<TempDir> {
|
||||
TempDir::new_in(&os::tmpdir(), prefix)
|
||||
TempDir::new_in(&env::temp_dir(), prefix)
|
||||
}
|
||||
|
||||
/// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
use prelude::v1::*;
|
||||
|
||||
use env;
|
||||
use libc;
|
||||
use os;
|
||||
use std::old_io::net::ip::*;
|
||||
use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
|
||||
|
@ -41,7 +41,7 @@ fn next_test_unix_socket() -> String {
|
|||
pub fn next_test_unix() -> Path {
|
||||
let string = next_test_unix_socket();
|
||||
if cfg!(unix) {
|
||||
os::tmpdir().join(string)
|
||||
env::temp_dir().join(string)
|
||||
} else {
|
||||
Path::new(format!("{}{}", r"\\.\pipe\", string))
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ fn base_port() -> u16 {
|
|||
];
|
||||
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let path = os::getcwd().unwrap();
|
||||
let path = env::current_dir().unwrap();
|
||||
let path_s = path.as_str().unwrap();
|
||||
|
||||
let mut final_base = base;
|
||||
|
|
247
src/libstd/os.rs
247
src/libstd/os.rs
|
@ -34,29 +34,32 @@ use self::MemoryMapKind::*;
|
|||
use self::MapOption::*;
|
||||
use self::MapError::*;
|
||||
|
||||
use boxed::Box;
|
||||
use clone::Clone;
|
||||
use env;
|
||||
use error::{FromError, Error};
|
||||
use ffi::{OsString, OsStr};
|
||||
use fmt;
|
||||
use old_io::{IoResult, IoError};
|
||||
use iter::{Iterator, IteratorExt};
|
||||
use marker::{Copy, Send};
|
||||
use libc::{c_void, c_int, c_char};
|
||||
use libc;
|
||||
use boxed::Box;
|
||||
use marker::{Copy, Send};
|
||||
use old_io::{IoResult, IoError};
|
||||
use ops::{Drop, FnOnce};
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use option::Option;
|
||||
use path::{Path, GenericPath, BytesContainer};
|
||||
use sys;
|
||||
use sys::os as os_imp;
|
||||
use ptr::PtrExt;
|
||||
use ptr;
|
||||
use result::Result;
|
||||
use result::Result::{Err, Ok};
|
||||
use result::Result;
|
||||
use slice::{AsSlice, SliceExt};
|
||||
use str::{Str, StrExt};
|
||||
use str;
|
||||
use string::{String, ToString};
|
||||
use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
|
||||
use sys::os as os_imp;
|
||||
use sys;
|
||||
use vec::Vec;
|
||||
|
||||
#[cfg(unix)] use ffi::{self, CString};
|
||||
|
@ -97,23 +100,10 @@ pub const TMPBUF_SZ : uint = 1000u;
|
|||
/// let current_working_directory = os::getcwd().unwrap();
|
||||
/// println!("The current directory is {:?}", current_working_directory.display());
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn getcwd() -> IoResult<Path> {
|
||||
sys::os::getcwd()
|
||||
}
|
||||
|
||||
/*
|
||||
Accessing environment variables is not generally threadsafe.
|
||||
Serialize access through a global lock.
|
||||
*/
|
||||
fn with_env_lock<T, F>(f: F) -> T where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
use sync::{StaticMutex, MUTEX_INIT};
|
||||
|
||||
static LOCK: StaticMutex = MUTEX_INIT;
|
||||
|
||||
let _guard = LOCK.lock();
|
||||
f()
|
||||
env::current_dir()
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) pairs, for all the environment
|
||||
|
@ -132,37 +122,22 @@ fn with_env_lock<T, F>(f: F) -> T where
|
|||
/// println!("'{}': '{}'", key, value );
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "use env::vars instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn env() -> Vec<(String,String)> {
|
||||
env_as_bytes().into_iter().map(|(k,v)| {
|
||||
let k = String::from_utf8_lossy(k.as_slice()).into_owned();
|
||||
let v = String::from_utf8_lossy(v.as_slice()).into_owned();
|
||||
(k,v)
|
||||
env::vars().map(|(k, v)| {
|
||||
(k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned())
|
||||
}).collect()
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
|
||||
unsafe {
|
||||
fn env_convert(input: Vec<Vec<u8>>) -> Vec<(Vec<u8>, Vec<u8>)> {
|
||||
let mut pairs = Vec::new();
|
||||
for p in input.iter() {
|
||||
let mut it = p.splitn(1, |b| *b == b'=');
|
||||
let key = it.next().unwrap().to_vec();
|
||||
let default: &[u8] = &[];
|
||||
let val = it.next().unwrap_or(default).to_vec();
|
||||
pairs.push((key, val));
|
||||
}
|
||||
pairs
|
||||
}
|
||||
with_env_lock(|| {
|
||||
let unparsed_environ = sys::os::get_env_pairs();
|
||||
env_convert(unparsed_environ)
|
||||
})
|
||||
}
|
||||
#[deprecated(since = "1.0.0", reason = "use env::vars instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn env_as_bytes() -> Vec<(Vec<u8>, Vec<u8>)> {
|
||||
env::vars().map(|(k, v)| (byteify(k), byteify(v))).collect()
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Fetches the environment variable `n` from the current process, returning
|
||||
/// None if the variable isn't set.
|
||||
///
|
||||
|
@ -184,52 +159,32 @@ pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
|
|||
/// None => println!("{} is not defined in the environment.", key)
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "use env::var or env::var_string instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn getenv(n: &str) -> Option<String> {
|
||||
getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_owned())
|
||||
env::var_string(n).ok()
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
/// Fetches the environment variable `n` byte vector from the current process,
|
||||
/// returning None if the variable isn't set.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `n` has any interior NULs.
|
||||
#[deprecated(since = "1.0.0", reason = "use env::var instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
|
||||
unsafe {
|
||||
with_env_lock(|| {
|
||||
let s = CString::from_slice(n.as_bytes());
|
||||
let s = libc::getenv(s.as_ptr()) as *const _;
|
||||
if s.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(ffi::c_str_to_bytes(&s).to_vec())
|
||||
}
|
||||
})
|
||||
}
|
||||
env::var(n).map(byteify)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
/// Fetches the environment variable `n` from the current process, returning
|
||||
/// None if the variable isn't set.
|
||||
pub fn getenv(n: &str) -> Option<String> {
|
||||
unsafe {
|
||||
with_env_lock(|| {
|
||||
use sys::os::fill_utf16_buf_and_decode;
|
||||
let mut n: Vec<u16> = n.utf16_units().collect();
|
||||
n.push(0);
|
||||
fill_utf16_buf_and_decode(|buf, sz| {
|
||||
libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz)
|
||||
})
|
||||
})
|
||||
}
|
||||
#[cfg(unix)]
|
||||
fn byteify(s: OsString) -> Vec<u8> {
|
||||
use os::unix::*;
|
||||
s.into_vec()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
/// Fetches the environment variable `n` byte vector from the current process,
|
||||
/// returning None if the variable isn't set.
|
||||
pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
|
||||
getenv(n).map(|s| s.into_bytes())
|
||||
fn byteify(s: OsString) -> Vec<u8> {
|
||||
s.to_string_lossy().as_bytes().to_vec()
|
||||
}
|
||||
|
||||
/// Sets the environment variable `n` to the value `v` for the currently running
|
||||
|
@ -247,68 +202,30 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
|
|||
/// None => println!("{} is not defined in the environment.", key)
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn setenv<T: BytesContainer>(n: &str, v: T) {
|
||||
#[cfg(unix)]
|
||||
fn _setenv(n: &str, v: &[u8]) {
|
||||
unsafe {
|
||||
with_env_lock(|| {
|
||||
let k = CString::from_slice(n.as_bytes());
|
||||
let v = CString::from_slice(v);
|
||||
if libc::funcs::posix01::unistd::setenv(k.as_ptr(),
|
||||
v.as_ptr(), 1) != 0 {
|
||||
panic!(IoError::last_error());
|
||||
}
|
||||
})
|
||||
}
|
||||
use os::unix::*;
|
||||
let v: OsString = OsStringExt::from_vec(v.to_vec());
|
||||
env::set_var(n, &v)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn _setenv(n: &str, v: &[u8]) {
|
||||
let mut n: Vec<u16> = n.utf16_units().collect();
|
||||
n.push(0);
|
||||
let mut v: Vec<u16> = ::str::from_utf8(v).unwrap().utf16_units().collect();
|
||||
v.push(0);
|
||||
|
||||
unsafe {
|
||||
with_env_lock(|| {
|
||||
if libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr()) == 0 {
|
||||
panic!(IoError::last_error());
|
||||
}
|
||||
})
|
||||
}
|
||||
let v = str::from_utf8(v).unwrap();
|
||||
env::set_var(n, v)
|
||||
}
|
||||
|
||||
_setenv(n, v.container_as_bytes())
|
||||
}
|
||||
|
||||
/// Remove a variable from the environment entirely.
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn unsetenv(n: &str) {
|
||||
#[cfg(unix)]
|
||||
fn _unsetenv(n: &str) {
|
||||
unsafe {
|
||||
with_env_lock(|| {
|
||||
let nbuf = CString::from_slice(n.as_bytes());
|
||||
if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
|
||||
panic!(IoError::last_error());
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn _unsetenv(n: &str) {
|
||||
let mut n: Vec<u16> = n.utf16_units().collect();
|
||||
n.push(0);
|
||||
unsafe {
|
||||
with_env_lock(|| {
|
||||
if libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null()) == 0 {
|
||||
panic!(IoError::last_error());
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_unsetenv(n)
|
||||
env::remove_var(n)
|
||||
}
|
||||
|
||||
/// Parses input according to platform conventions for the `PATH`
|
||||
|
@ -328,8 +245,12 @@ pub fn unsetenv(n: &str) {
|
|||
/// None => println!("{} is not defined in the environment.", key)
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
|
||||
sys::os::split_paths(unparsed.container_as_bytes())
|
||||
let b = unparsed.container_as_bytes();
|
||||
let s = str::from_utf8(b).unwrap();
|
||||
env::split_paths(s).collect()
|
||||
}
|
||||
|
||||
/// Joins a collection of `Path`s appropriately for the `PATH`
|
||||
|
@ -353,8 +274,14 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
|
|||
/// paths.push(Path::new("/home/xyz/bin"));
|
||||
/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
|
||||
sys::os::join_paths(paths)
|
||||
env::join_paths(paths.iter().map(|s| {
|
||||
str::from_utf8(s.container_as_bytes()).unwrap()
|
||||
})).map(|s| {
|
||||
s.to_string_lossy().into_owned().into_bytes()
|
||||
}).map_err(|_| "failed to join paths")
|
||||
}
|
||||
|
||||
/// A low-level OS in-memory pipe.
|
||||
|
@ -388,6 +315,8 @@ pub unsafe fn pipe() -> IoResult<Pipe> {
|
|||
/// Returns the proper dll filename for the given basename of a file
|
||||
/// as a String.
|
||||
#[cfg(not(target_os="ios"))]
|
||||
#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn dll_filename(base: &str) -> String {
|
||||
format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX)
|
||||
}
|
||||
|
@ -405,8 +334,10 @@ pub fn dll_filename(base: &str) -> String {
|
|||
/// None => println!("Unable to get the path of this executable!")
|
||||
/// };
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn self_exe_name() -> Option<Path> {
|
||||
sys::os::load_self().and_then(Path::new_opt)
|
||||
env::current_exe().ok()
|
||||
}
|
||||
|
||||
/// Optionally returns the filesystem path to the current executable which is
|
||||
|
@ -424,8 +355,10 @@ pub fn self_exe_name() -> Option<Path> {
|
|||
/// None => println!("Impossible to fetch the path of this executable.")
|
||||
/// };
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn self_exe_path() -> Option<Path> {
|
||||
self_exe_name().map(|mut p| { p.pop(); p })
|
||||
env::current_exe().ok().map(|mut p| { p.pop(); p })
|
||||
}
|
||||
|
||||
/// Optionally returns the path to the current user's home directory if known.
|
||||
|
@ -452,6 +385,9 @@ pub fn self_exe_path() -> Option<Path> {
|
|||
/// None => println!("Impossible to get your home dir!")
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")]
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn homedir() -> Option<Path> {
|
||||
#[inline]
|
||||
#[cfg(unix)]
|
||||
|
@ -487,6 +423,9 @@ pub fn homedir() -> Option<Path> {
|
|||
/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
|
||||
/// 'USERPROFILE' environment variable if any are set and not the empty
|
||||
/// string. Otherwise, tmpdir returns the path to the Windows directory.
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")]
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn tmpdir() -> Path {
|
||||
return lookup();
|
||||
|
||||
|
@ -542,11 +481,13 @@ pub fn tmpdir() -> Path {
|
|||
// NB: this is here rather than in path because it is a form of environment
|
||||
// querying; what it does depends on the process working directory, not just
|
||||
// the input paths.
|
||||
#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn make_absolute(p: &Path) -> IoResult<Path> {
|
||||
if p.is_absolute() {
|
||||
Ok(p.clone())
|
||||
} else {
|
||||
getcwd().map(|mut cwd| {
|
||||
env::current_dir().map(|mut cwd| {
|
||||
cwd.push(p);
|
||||
cwd
|
||||
})
|
||||
|
@ -565,6 +506,8 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
|
|||
/// assert!(os::change_dir(&root).is_ok());
|
||||
/// println!("Successfully changed working directory to {}!", root.display());
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn change_dir(p: &Path) -> IoResult<()> {
|
||||
return sys::os::chdir(p);
|
||||
}
|
||||
|
@ -592,8 +535,6 @@ pub fn last_os_error() -> String {
|
|||
error_string(errno() as uint)
|
||||
}
|
||||
|
||||
static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
|
||||
|
||||
/// Sets the process exit code
|
||||
///
|
||||
/// Sets the exit code returned by the process if all supervised tasks
|
||||
|
@ -602,14 +543,18 @@ static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
|
|||
/// ignored and the process exits with the default panic status.
|
||||
///
|
||||
/// Note that this is not synchronized against modifications of other threads.
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn set_exit_status(code: int) {
|
||||
EXIT_STATUS.store(code, Ordering::SeqCst)
|
||||
env::set_exit_status(code as i32)
|
||||
}
|
||||
|
||||
/// Fetches the process's current exit code. This defaults to 0 and can change
|
||||
/// by calling `set_exit_status`.
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn get_exit_status() -> int {
|
||||
EXIT_STATUS.load(Ordering::SeqCst)
|
||||
env::get_exit_status() as isize
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -726,7 +671,7 @@ fn real_args() -> Vec<String> {
|
|||
// Push it onto the list.
|
||||
let ptr = ptr as *const u16;
|
||||
let buf = slice::from_raw_buf(&ptr, len);
|
||||
let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf));
|
||||
let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf));
|
||||
opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16")
|
||||
}).collect();
|
||||
|
||||
|
@ -777,12 +722,16 @@ extern "system" {
|
|||
/// println!("{}", argument);
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "use env::args instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn args() -> Vec<String> {
|
||||
real_args()
|
||||
}
|
||||
|
||||
/// Returns the arguments which this program was started with (normally passed
|
||||
/// via the command line) as byte vectors.
|
||||
#[deprecated(since = "1.0.0", reason = "use env::args_raw instead")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn args_as_bytes() -> Vec<Vec<u8>> {
|
||||
real_args_as_bytes()
|
||||
}
|
||||
|
@ -790,11 +739,13 @@ pub fn args_as_bytes() -> Vec<Vec<u8>> {
|
|||
#[cfg(target_os = "macos")]
|
||||
extern {
|
||||
// These functions are in crt_externs.h.
|
||||
pub fn _NSGetArgc() -> *mut c_int;
|
||||
pub fn _NSGetArgv() -> *mut *mut *mut c_char;
|
||||
fn _NSGetArgc() -> *mut c_int;
|
||||
fn _NSGetArgv() -> *mut *mut *mut c_char;
|
||||
}
|
||||
|
||||
/// Returns the page size of the current architecture in bytes.
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::page_size")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn page_size() -> uint {
|
||||
sys::os::page_size()
|
||||
}
|
||||
|
@ -970,7 +921,7 @@ impl MemoryMap {
|
|||
let mut fd = -1;
|
||||
let mut offset = 0;
|
||||
let mut custom_flags = false;
|
||||
let len = round_up(min_len, page_size());
|
||||
let len = round_up(min_len, env::page_size());
|
||||
|
||||
for &o in options.iter() {
|
||||
match o {
|
||||
|
@ -1020,7 +971,7 @@ impl MemoryMap {
|
|||
/// Granularity that the offset or address must be for `MapOffset` and
|
||||
/// `MapAddr` respectively.
|
||||
pub fn granularity() -> uint {
|
||||
page_size()
|
||||
env::page_size()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1000,7 @@ impl MemoryMap {
|
|||
let mut executable = false;
|
||||
let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE;
|
||||
let mut offset: uint = 0;
|
||||
let len = round_up(min_len, page_size());
|
||||
let len = round_up(min_len, env::page_size());
|
||||
|
||||
for &o in options.iter() {
|
||||
match o {
|
||||
|
@ -1184,6 +1135,8 @@ impl MemoryMap {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
@ -1215,6 +1168,8 @@ pub mod consts {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
@ -1246,6 +1201,8 @@ pub mod consts {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
@ -1265,6 +1222,8 @@ pub mod consts {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
@ -1296,6 +1255,8 @@ pub mod consts {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
@ -1327,6 +1288,8 @@ pub mod consts {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
@ -1358,6 +1321,8 @@ pub mod consts {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
|
||||
#[unstable(feature = "os")]
|
||||
pub mod consts {
|
||||
pub use os::arch_consts::ARCH;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
use prelude::v1::*;
|
||||
|
||||
use os;
|
||||
use env;
|
||||
use sync::atomic::{self, Ordering};
|
||||
|
||||
pub use sys::backtrace::write;
|
||||
|
@ -29,7 +29,7 @@ pub fn log_enabled() -> bool {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let val = match os::getenv("RUST_BACKTRACE") {
|
||||
let val = match env::var("RUST_BACKTRACE") {
|
||||
Some(..) => 2,
|
||||
None => 1,
|
||||
};
|
||||
|
|
|
@ -65,7 +65,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
|
|||
use prelude::v1::*;
|
||||
|
||||
use mem;
|
||||
use os;
|
||||
use env;
|
||||
use rt;
|
||||
use sys_common::thread_info::{self, NewThread};
|
||||
use sys_common;
|
||||
|
@ -131,7 +131,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
|
|||
if failed {
|
||||
rt::DEFAULT_ERROR_CODE
|
||||
} else {
|
||||
os::get_exit_status()
|
||||
env::get_exit_status() as isize
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
use prelude::v1::*;
|
||||
|
||||
use cmp;
|
||||
use env;
|
||||
use fmt;
|
||||
use intrinsics;
|
||||
use libc::{self, uintptr_t};
|
||||
|
@ -51,7 +52,7 @@ pub fn min_stack() -> uint {
|
|||
0 => {}
|
||||
n => return n - 1,
|
||||
}
|
||||
let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse().ok());
|
||||
let amt = env::var_string("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok());
|
||||
let amt = amt.unwrap_or(2 * 1024 * 1024);
|
||||
// 0 is our sentinel value, so ensure that we'll never see 0 after
|
||||
// initialization has run
|
||||
|
@ -62,15 +63,15 @@ pub fn min_stack() -> uint {
|
|||
/// Get's the number of scheduler threads requested by the environment
|
||||
/// either `RUST_THREADS` or `num_cpus`.
|
||||
pub fn default_sched_threads() -> uint {
|
||||
match os::getenv("RUST_THREADS") {
|
||||
Some(nstr) => {
|
||||
match env::var_string("RUST_THREADS") {
|
||||
Ok(nstr) => {
|
||||
let opt_n: Option<uint> = nstr.parse().ok();
|
||||
match opt_n {
|
||||
Some(n) if n > 0 => n,
|
||||
_ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
Err(..) => {
|
||||
if limit_thread_creation_due_to_osx_and_valgrind() {
|
||||
1
|
||||
} else {
|
||||
|
|
|
@ -24,13 +24,6 @@ unsafe impl Sync for Mutex {}
|
|||
pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT);
|
||||
|
||||
impl Mutex {
|
||||
/// Creates a newly initialized mutex.
|
||||
///
|
||||
/// Behavior is undefined if the mutex is moved after the first method is
|
||||
/// called on the mutex.
|
||||
#[inline]
|
||||
pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) }
|
||||
|
||||
/// Lock the mutex blocking the current thread until it is available.
|
||||
///
|
||||
/// Behavior is undefined if the mutex has been moved between this and any
|
||||
|
|
|
@ -21,13 +21,6 @@ pub struct RWLock(imp::RWLock);
|
|||
pub const RWLOCK_INIT: RWLock = RWLock(imp::RWLOCK_INIT);
|
||||
|
||||
impl RWLock {
|
||||
/// Creates a new instance of an RWLock.
|
||||
///
|
||||
/// Usage of an RWLock is undefined if it is moved after its first use (any
|
||||
/// function calls below).
|
||||
#[inline]
|
||||
pub unsafe fn new() -> RWLock { RWLock(imp::RWLock::new()) }
|
||||
|
||||
/// Acquire shared access to the underlying lock, blocking the current
|
||||
/// thread to do so.
|
||||
///
|
||||
|
|
|
@ -240,7 +240,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
|
|||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||
fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
|
||||
use os;
|
||||
use env;
|
||||
use ptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -319,7 +319,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
|
|||
if !STATE.is_null() { return STATE }
|
||||
let selfname = if cfg!(target_os = "freebsd") ||
|
||||
cfg!(target_os = "dragonfly") {
|
||||
os::self_exe_name()
|
||||
env::current_exe().ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
@ -66,6 +66,53 @@ pub const MSG_DONTWAIT: libc::c_int = 0x40;
|
|||
|
||||
pub const WNOHANG: libc::c_int = 1;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70;
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "freebsd"))]
|
||||
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
|
||||
#[cfg(target_os = "android")]
|
||||
pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048;
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg(target_os = "linux")]
|
||||
pub struct passwd {
|
||||
pub pw_name: *mut libc::c_char,
|
||||
pub pw_passwd: *mut libc::c_char,
|
||||
pub pw_uid: libc::uid_t,
|
||||
pub pw_gid: libc::gid_t,
|
||||
pub pw_gecos: *mut libc::c_char,
|
||||
pub pw_dir: *mut libc::c_char,
|
||||
pub pw_shell: *mut libc::c_char,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "freebsd"))]
|
||||
pub struct passwd {
|
||||
pub pw_name: *mut libc::c_char,
|
||||
pub pw_passwd: *mut libc::c_char,
|
||||
pub pw_uid: libc::uid_t,
|
||||
pub pw_gid: libc::gid_t,
|
||||
pub pw_change: libc::time_t,
|
||||
pub pw_class: *mut libc::c_char,
|
||||
pub pw_gecos: *mut libc::c_char,
|
||||
pub pw_dir: *mut libc::c_char,
|
||||
pub pw_shell: *mut libc::c_char,
|
||||
pub pw_expire: libc::time_t,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg(target_os = "android")]
|
||||
pub struct passwd {
|
||||
pub pw_name: *mut libc::c_char,
|
||||
pub pw_passwd: *mut libc::c_char,
|
||||
pub pw_uid: libc::uid_t,
|
||||
pub pw_gid: libc::gid_t,
|
||||
pub pw_dir: *mut libc::c_char,
|
||||
pub pw_shell: *mut libc::c_char,
|
||||
}
|
||||
|
||||
extern {
|
||||
pub fn gettimeofday(timeval: *mut libc::timeval,
|
||||
tzp: *mut libc::c_void) -> libc::c_int;
|
||||
|
@ -92,6 +139,12 @@ extern {
|
|||
pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
|
||||
pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
|
||||
pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
|
||||
|
||||
pub fn getpwuid_r(uid: libc::uid_t,
|
||||
pwd: *mut passwd,
|
||||
buf: *mut libc::c_char,
|
||||
buflen: libc::size_t,
|
||||
result: *mut *mut passwd) -> libc::c_int;
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
|
|
|
@ -141,7 +141,7 @@ pub fn retry<T, F> (mut f: F) -> T where
|
|||
let one: T = Int::one();
|
||||
loop {
|
||||
let n = f();
|
||||
if n == -one && os::errno() == libc::EINTR as int { }
|
||||
if n == -one && os::errno() == libc::EINTR as i32 { }
|
||||
else { return n }
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval {
|
|||
|
||||
pub fn wouldblock() -> bool {
|
||||
let err = os::errno();
|
||||
err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int
|
||||
err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// 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.
|
||||
//
|
||||
|
@ -11,93 +11,64 @@
|
|||
//! Implementation of `std::os` functionality for unix systems
|
||||
|
||||
use prelude::v1::*;
|
||||
use os::unix::*;
|
||||
|
||||
use error::{FromError, Error};
|
||||
use ffi::{self, CString};
|
||||
use error::Error as StdError;
|
||||
use ffi::{self, CString, OsString, OsStr, AsOsStr};
|
||||
use fmt;
|
||||
use old_io::{IoError, IoResult};
|
||||
use iter;
|
||||
use libc::{self, c_int, c_char, c_void};
|
||||
use os::TMPBUF_SZ;
|
||||
use os;
|
||||
use path::{BytesContainer};
|
||||
use mem;
|
||||
use old_io::{IoResult, IoError, fs};
|
||||
use ptr;
|
||||
use slice;
|
||||
use str;
|
||||
use sys::c;
|
||||
use sys::fs::FileDesc;
|
||||
use vec;
|
||||
|
||||
const BUF_BYTES : uint = 2048u;
|
||||
const BUF_BYTES: usize = 2048;
|
||||
const TMPBUF_SZ: usize = 128;
|
||||
|
||||
/// Returns the platform-specific value of errno
|
||||
pub fn errno() -> int {
|
||||
pub fn errno() -> i32 {
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "freebsd"))]
|
||||
fn errno_location() -> *const c_int {
|
||||
extern {
|
||||
fn __error() -> *const c_int;
|
||||
}
|
||||
unsafe {
|
||||
unsafe fn errno_location() -> *const c_int {
|
||||
extern { fn __error() -> *const c_int; }
|
||||
__error()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
fn errno_location() -> *const c_int {
|
||||
extern {
|
||||
fn __dfly_error() -> *const c_int;
|
||||
}
|
||||
unsafe {
|
||||
unsafe fn errno_location() -> *const c_int {
|
||||
extern { fn __dfly_error() -> *const c_int; }
|
||||
__dfly_error()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn errno_location() -> *const c_int {
|
||||
extern {
|
||||
fn __errno_location() -> *const c_int;
|
||||
}
|
||||
unsafe {
|
||||
unsafe fn errno_location() -> *const c_int {
|
||||
extern { fn __errno_location() -> *const c_int; }
|
||||
__errno_location()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
(*errno_location()) as int
|
||||
(*errno_location()) as i32
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a detailed string description for the given error number
|
||||
pub fn error_string(errno: i32) -> String {
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly"))]
|
||||
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t)
|
||||
-> c_int {
|
||||
#[cfg(target_os = "linux")]
|
||||
extern {
|
||||
#[link_name = "__xpg_strerror_r"]
|
||||
fn strerror_r(errnum: c_int, buf: *mut c_char,
|
||||
buflen: libc::size_t) -> c_int;
|
||||
}
|
||||
unsafe {
|
||||
strerror_r(errnum, buf, buflen)
|
||||
}
|
||||
}
|
||||
|
||||
// GNU libc provides a non-compliant version of strerror_r by default
|
||||
// and requires macros to instead use the POSIX compliant variant.
|
||||
// So we just use __xpg_strerror_r which is always POSIX compliant
|
||||
#[cfg(target_os = "linux")]
|
||||
fn strerror_r(errnum: c_int, buf: *mut c_char,
|
||||
buflen: libc::size_t) -> c_int {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
extern {
|
||||
fn __xpg_strerror_r(errnum: c_int,
|
||||
buf: *mut c_char,
|
||||
buflen: libc::size_t)
|
||||
-> c_int;
|
||||
}
|
||||
unsafe {
|
||||
__xpg_strerror_r(errnum, buf, buflen)
|
||||
}
|
||||
fn strerror_r(errnum: c_int, buf: *mut c_char,
|
||||
buflen: libc::size_t) -> c_int;
|
||||
}
|
||||
|
||||
let mut buf = [0 as c_char; TMPBUF_SZ];
|
||||
|
@ -113,15 +84,6 @@ pub fn error_string(errno: i32) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
|
||||
let mut fds = [0; 2];
|
||||
if libc::pipe(fds.as_mut_ptr()) == 0 {
|
||||
Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
|
||||
} else {
|
||||
Err(super::last_error())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getcwd() -> IoResult<Path> {
|
||||
let mut buf = [0 as c_char; BUF_BYTES];
|
||||
unsafe {
|
||||
|
@ -133,102 +95,6 @@ pub fn getcwd() -> IoResult<Path> {
|
|||
}
|
||||
}
|
||||
|
||||
pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
|
||||
extern {
|
||||
fn rust_env_pairs() -> *const *const c_char;
|
||||
}
|
||||
let mut environ = rust_env_pairs();
|
||||
if environ as uint == 0 {
|
||||
panic!("os::env() failure getting env string from OS: {}",
|
||||
os::last_os_error());
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
while *environ != ptr::null() {
|
||||
let env_pair = ffi::c_str_to_bytes(&*environ).to_vec();
|
||||
result.push(env_pair);
|
||||
environ = environ.offset(1);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
|
||||
unparsed.split(|b| *b == b':').map(Path::new).collect()
|
||||
}
|
||||
|
||||
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
|
||||
let mut joined = Vec::new();
|
||||
let sep = b':';
|
||||
|
||||
for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
|
||||
if i > 0 { joined.push(sep) }
|
||||
if path.contains(&sep) { return Err("path segment contains separator `:`") }
|
||||
joined.push_all(path);
|
||||
}
|
||||
|
||||
Ok(joined)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub fn load_self() -> Option<Vec<u8>> {
|
||||
unsafe {
|
||||
use libc::funcs::bsd44::*;
|
||||
use libc::consts::os::extra::*;
|
||||
let mut mib = vec![CTL_KERN as c_int,
|
||||
KERN_PROC as c_int,
|
||||
KERN_PROC_PATHNAME as c_int,
|
||||
-1 as c_int];
|
||||
let mut sz: libc::size_t = 0;
|
||||
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
||||
ptr::null_mut(), &mut sz, ptr::null_mut(),
|
||||
0u as libc::size_t);
|
||||
if err != 0 { return None; }
|
||||
if sz == 0 { return None; }
|
||||
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
||||
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
||||
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
|
||||
ptr::null_mut(), 0u as libc::size_t);
|
||||
if err != 0 { return None; }
|
||||
if sz == 0 { return None; }
|
||||
v.set_len(sz as uint - 1); // chop off trailing NUL
|
||||
Some(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub fn load_self() -> Option<Vec<u8>> {
|
||||
use old_io;
|
||||
|
||||
match old_io::fs::readlink(&Path::new("/proc/curproc/file")) {
|
||||
Ok(path) => Some(path.into_vec()),
|
||||
Err(..) => None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn load_self() -> Option<Vec<u8>> {
|
||||
use old_io;
|
||||
|
||||
match old_io::fs::readlink(&Path::new("/proc/self/exe")) {
|
||||
Ok(path) => Some(path.into_vec()),
|
||||
Err(..) => None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
pub fn load_self() -> Option<Vec<u8>> {
|
||||
unsafe {
|
||||
use libc::funcs::extra::_NSGetExecutablePath;
|
||||
let mut sz: u32 = 0;
|
||||
_NSGetExecutablePath(ptr::null_mut(), &mut sz);
|
||||
if sz == 0 { return None; }
|
||||
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
||||
let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
|
||||
if err != 0 { return None; }
|
||||
v.set_len(sz as uint - 1); // chop off trailing NUL
|
||||
Some(v)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chdir(p: &Path) -> IoResult<()> {
|
||||
let p = CString::from_slice(p.as_vec());
|
||||
unsafe {
|
||||
|
@ -239,8 +105,340 @@ pub fn chdir(p: &Path) -> IoResult<()> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn page_size() -> uint {
|
||||
unsafe {
|
||||
libc::sysconf(libc::_SC_PAGESIZE) as uint
|
||||
pub struct SplitPaths<'a> {
|
||||
iter: iter::Map<&'a [u8], Path,
|
||||
slice::Split<'a, u8, fn(&u8) -> bool>,
|
||||
fn(&'a [u8]) -> Path>,
|
||||
}
|
||||
|
||||
pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
|
||||
fn is_colon(b: &u8) -> bool { *b == b':' }
|
||||
let unparsed = unparsed.as_byte_slice();
|
||||
SplitPaths {
|
||||
iter: unparsed.split(is_colon as fn(&u8) -> bool)
|
||||
.map(Path::new as fn(&'a [u8]) -> Path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SplitPaths<'a> {
|
||||
type Item = Path;
|
||||
fn next(&mut self) -> Option<Path> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
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':';
|
||||
|
||||
for (i, path) in paths.enumerate() {
|
||||
let path = path.as_os_str().as_byte_slice();
|
||||
if i > 0 { joined.push(sep) }
|
||||
if path.contains(&sep) {
|
||||
return Err(JoinPathsError)
|
||||
}
|
||||
joined.push_all(path);
|
||||
}
|
||||
Ok(OsStringExt::from_vec(joined))
|
||||
}
|
||||
|
||||
impl fmt::Display for JoinPathsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
"path segment contains separator `:`".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for JoinPathsError {
|
||||
fn description(&self) -> &str { "failed to join paths" }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
unsafe {
|
||||
use libc::funcs::bsd44::*;
|
||||
use libc::consts::os::extra::*;
|
||||
let mut mib = vec![CTL_KERN as c_int,
|
||||
KERN_PROC as c_int,
|
||||
KERN_PROC_PATHNAME as c_int,
|
||||
-1 as c_int];
|
||||
let mut sz: libc::size_t = 0;
|
||||
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
||||
ptr::null_mut(), &mut sz, ptr::null_mut(),
|
||||
0u as libc::size_t);
|
||||
if err != 0 { return Err(IoError::last_error()); }
|
||||
if sz == 0 { return Err(IoError::last_error()); }
|
||||
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
||||
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
||||
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
|
||||
ptr::null_mut(), 0u as libc::size_t);
|
||||
if err != 0 { return Err(IoError::last_error()); }
|
||||
if sz == 0 { return Err(IoError::last_error()); }
|
||||
v.set_len(sz as uint - 1); // chop off trailing NUL
|
||||
Ok(Path::new(v))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
fs::readlink(&Path::new("/proc/curproc/file"))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
fs::readlink(&Path::new("/proc/self/exe"))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
unsafe {
|
||||
use libc::funcs::extra::_NSGetExecutablePath;
|
||||
let mut sz: u32 = 0;
|
||||
_NSGetExecutablePath(ptr::null_mut(), &mut sz);
|
||||
if sz == 0 { return Err(IoError::last_error()); }
|
||||
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
||||
let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
|
||||
if err != 0 { return Err(IoError::last_error()); }
|
||||
v.set_len(sz as uint - 1); // chop off trailing NUL
|
||||
Ok(Path::new(v))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
_dont_send_or_sync_me: *mut (),
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
/// Returns the command line arguments
|
||||
///
|
||||
/// Returns a list of the command line arguments.
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn args() -> Args {
|
||||
extern {
|
||||
// These functions are in crt_externs.h.
|
||||
fn _NSGetArgc() -> *mut c_int;
|
||||
fn _NSGetArgv() -> *mut *mut *mut c_char;
|
||||
}
|
||||
|
||||
let vec = unsafe {
|
||||
let (argc, argv) = (*_NSGetArgc() as isize,
|
||||
*_NSGetArgv() as *const *const c_char);
|
||||
range(0, argc as isize).map(|i| {
|
||||
let bytes = ffi::c_str_to_bytes(&*argv.offset(i)).to_vec();
|
||||
OsStringExt::from_vec(bytes)
|
||||
}).collect::<Vec<_>>()
|
||||
};
|
||||
Args {
|
||||
iter: vec.into_iter(),
|
||||
_dont_send_or_sync_me: 0 as *mut (),
|
||||
}
|
||||
}
|
||||
|
||||
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
|
||||
// and use underscores in their names - they're most probably
|
||||
// are considered private and therefore should be avoided
|
||||
// Here is another way to get arguments using Objective C
|
||||
// runtime
|
||||
//
|
||||
// In general it looks like:
|
||||
// res = Vec::new()
|
||||
// let args = [[NSProcessInfo processInfo] arguments]
|
||||
// for i in range(0, [args count])
|
||||
// res.push([args objectAtIndex:i])
|
||||
// res
|
||||
#[cfg(target_os = "ios")]
|
||||
pub fn args() -> Args {
|
||||
use iter::range;
|
||||
use mem;
|
||||
|
||||
#[link(name = "objc")]
|
||||
extern {
|
||||
fn sel_registerName(name: *const libc::c_uchar) -> Sel;
|
||||
fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
|
||||
fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
|
||||
}
|
||||
|
||||
#[link(name = "Foundation", kind = "framework")]
|
||||
extern {}
|
||||
|
||||
type Sel = *const libc::c_void;
|
||||
type NsId = *const libc::c_void;
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
||||
unsafe {
|
||||
let processInfoSel = sel_registerName("processInfo\0".as_ptr());
|
||||
let argumentsSel = sel_registerName("arguments\0".as_ptr());
|
||||
let utf8Sel = sel_registerName("UTF8String\0".as_ptr());
|
||||
let countSel = sel_registerName("count\0".as_ptr());
|
||||
let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr());
|
||||
|
||||
let klass = objc_getClass("NSProcessInfo\0".as_ptr());
|
||||
let info = objc_msgSend(klass, processInfoSel);
|
||||
let args = objc_msgSend(info, argumentsSel);
|
||||
|
||||
let cnt: int = mem::transmute(objc_msgSend(args, countSel));
|
||||
for i in range(0, cnt) {
|
||||
let tmp = objc_msgSend(args, objectAtSel, i);
|
||||
let utf_c_str: *const libc::c_char =
|
||||
mem::transmute(objc_msgSend(tmp, utf8Sel));
|
||||
let bytes = ffi::c_str_to_bytes(&utf_c_str).to_vec();
|
||||
res.push(OsString::from_vec(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
Args { iter: res.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly"))]
|
||||
pub fn args() -> Args {
|
||||
use rt;
|
||||
let bytes = rt::args::clone().unwrap_or(Vec::new());
|
||||
let v: Vec<OsString> = bytes.into_iter().map(|v| {
|
||||
OsStringExt::from_vec(v)
|
||||
}).collect();
|
||||
Args { iter: v.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
_dont_send_or_sync_me: *mut (),
|
||||
}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
extern { fn _NSGetEnviron() -> *mut *const *const c_char; }
|
||||
_NSGetEnviron()
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub unsafe fn environ() -> *mut *const *const c_char {
|
||||
extern { static mut environ: *const *const c_char; }
|
||||
&mut environ
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
return unsafe {
|
||||
let mut environ = *environ();
|
||||
if environ as usize == 0 {
|
||||
panic!("os::env() failure getting env string from OS: {}",
|
||||
IoError::last_error());
|
||||
}
|
||||
let mut result = Vec::new();
|
||||
while *environ != ptr::null() {
|
||||
result.push(parse(ffi::c_str_to_bytes(&*environ)));
|
||||
environ = environ.offset(1);
|
||||
}
|
||||
Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
|
||||
};
|
||||
|
||||
fn parse(input: &[u8]) -> (OsString, OsString) {
|
||||
let mut it = input.splitn(1, |b| *b == b'=');
|
||||
let key = it.next().unwrap().to_vec();
|
||||
let default: &[u8] = &[];
|
||||
let val = it.next().unwrap_or(default).to_vec();
|
||||
(OsStringExt::from_vec(key), OsStringExt::from_vec(val))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
||||
unsafe {
|
||||
let s = CString::from_slice(k.as_byte_slice());
|
||||
let s = libc::getenv(s.as_ptr()) as *const _;
|
||||
if s.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(OsStringExt::from_vec(ffi::c_str_to_bytes(&s).to_vec()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setenv(k: &OsStr, v: &OsStr) {
|
||||
unsafe {
|
||||
let k = CString::from_slice(k.as_byte_slice());
|
||||
let v = CString::from_slice(v.as_byte_slice());
|
||||
if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
|
||||
panic!("failed setenv: {}", IoError::last_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unsetenv(n: &OsStr) {
|
||||
unsafe {
|
||||
let nbuf = CString::from_slice(n.as_byte_slice());
|
||||
if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
|
||||
panic!("failed unsetenv: {}", IoError::last_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
|
||||
let mut fds = [0; 2];
|
||||
if libc::pipe(fds.as_mut_ptr()) == 0 {
|
||||
Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
|
||||
} else {
|
||||
Err(IoError::last_error())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn page_size() -> usize {
|
||||
unsafe {
|
||||
libc::sysconf(libc::_SC_PAGESIZE) as usize
|
||||
}
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> Path {
|
||||
getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| {
|
||||
if cfg!(target_os = "android") {
|
||||
Path::new("/data/local/tmp")
|
||||
} else {
|
||||
Path::new("/tmp")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn home_dir() -> Option<Path> {
|
||||
getenv("HOME".as_os_str()).or_else(|| unsafe {
|
||||
let mut amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) {
|
||||
n if n < 0 => 512 as usize,
|
||||
n => n as usize,
|
||||
};
|
||||
let me = libc::getuid();
|
||||
loop {
|
||||
let mut buf = Vec::with_capacity(amt);
|
||||
let mut passwd: c::passwd = mem::zeroed();
|
||||
let mut result = 0 as *mut _;
|
||||
match c::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(),
|
||||
buf.capacity() as libc::size_t,
|
||||
&mut result) {
|
||||
0 if !result.is_null() => {}
|
||||
_ => return None
|
||||
}
|
||||
let ptr = passwd.pw_dir as *const _;
|
||||
let bytes = ffi::c_str_to_bytes(&ptr).to_vec();
|
||||
return Some(OsStringExt::from_vec(bytes))
|
||||
}
|
||||
}).map(|os| {
|
||||
Path::new(os.into_vec())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -72,18 +72,6 @@ impl Process {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
unsafe fn set_environ(envp: *const c_void) {
|
||||
extern { fn _NSGetEnviron() -> *mut *const c_void; }
|
||||
|
||||
*_NSGetEnviron() = envp;
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
unsafe fn set_environ(envp: *const c_void) {
|
||||
extern { static mut environ: *const c_void; }
|
||||
environ = envp;
|
||||
}
|
||||
|
||||
unsafe fn set_cloexec(fd: c_int) {
|
||||
let ret = c::ioctl(fd, c::FIOCLEX);
|
||||
assert_eq!(ret, 0);
|
||||
|
@ -269,7 +257,7 @@ impl Process {
|
|||
fail(&mut output);
|
||||
}
|
||||
if !envp.is_null() {
|
||||
set_environ(envp);
|
||||
*sys::os::environ() = envp as *const _;
|
||||
}
|
||||
let _ = execvp(*argv, argv as *mut _);
|
||||
fail(&mut output);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 func = unsafe {
|
||||
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
|
||||
})
|
||||
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;
|
||||
use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
use mem;
|
||||
|
||||
extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
|
||||
unsafe {
|
||||
::sys::c::compat::store_func(&mut ptr as *mut _ as *mut uint,
|
||||
static PTR: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
fn load() -> usize {
|
||||
::sys::c::compat::store_func(&PTR,
|
||||
stringify!($module),
|
||||
stringify!($symbol),
|
||||
fallback as uint);
|
||||
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
31
src/libstd/sys/windows/handle.rs
Normal file
31
src/libstd/sys/windows/handle.rs
Normal file
|
@ -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); }
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,6 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
|
|||
// no guarantees of fairness.
|
||||
|
||||
impl Mutex {
|
||||
#[inline]
|
||||
pub unsafe fn new() -> Mutex { MUTEX_INIT }
|
||||
#[inline]
|
||||
pub unsafe fn lock(&self) {
|
||||
ffi::AcquireSRWLockExclusive(self.inner.get())
|
||||
|
|
|
@ -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,18 +78,255 @@ 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 struct Env {
|
||||
base: LPWCH,
|
||||
cur: LPWCH,
|
||||
}
|
||||
|
||||
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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Env {
|
||||
fn drop(&mut self) {
|
||||
unsafe { FreeEnvironmentStringsW(self.base); }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let ch = GetEnvironmentStringsW();
|
||||
if ch as usize == 0 {
|
||||
panic!("failure getting env string from OS: {}",
|
||||
IoError::last_error());
|
||||
}
|
||||
Env { base: ch, cur: ch }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SplitPaths<'a> {
|
||||
data: EncodeWide<'a>,
|
||||
must_yield: bool,
|
||||
}
|
||||
|
||||
pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
|
||||
SplitPaths {
|
||||
data: unparsed.encode_wide(),
|
||||
must_yield: true,
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if !must_yield && in_progress.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(super::os2path(&in_progress[]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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';' as u16;
|
||||
|
||||
for (i, path) in paths.enumerate() {
|
||||
let path = path.as_os_str();
|
||||
if i > 0 { joined.push(sep) }
|
||||
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(&v[]);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(OsStringExt::from_wide(&joined[]))
|
||||
}
|
||||
|
||||
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_os_str().encode_wide().collect::<Vec<_>>();
|
||||
p.push(0);
|
||||
|
||||
unsafe {
|
||||
match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
|
||||
true => Ok(()),
|
||||
false => Err(IoError::last_error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 {
|
||||
panic!("failed to set env: {}", IoError::last_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
range: Range<isize>,
|
||||
cur: *mut *mut u16,
|
||||
}
|
||||
|
||||
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() }
|
||||
}
|
||||
|
||||
impl Drop for Args {
|
||||
fn drop(&mut self) {
|
||||
unsafe { c::LocalFree(self.cur as *mut c_void); }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn args() -> Args {
|
||||
unsafe {
|
||||
let mut nArgs: c_int = 0;
|
||||
let lpCmdLine = c::GetCommandLineW();
|
||||
let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
|
||||
|
||||
Args { cur: szArgList, range: range(0, nArgs as isize) }
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -124,213 +345,31 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
pub fn temp_dir() -> Path {
|
||||
super::fill_utf16_buf(|buf, sz| unsafe {
|
||||
c::GetTempPathW(sz, buf)
|
||||
}, super::os2path).unwrap()
|
||||
}
|
||||
|
||||
pub fn getcwd() -> IoResult<Path> {
|
||||
use libc::DWORD;
|
||||
use libc::GetCurrentDirectoryW;
|
||||
use old_io::OtherIoError;
|
||||
|
||||
let mut buf = [0 as u16; BUF_BYTES];
|
||||
unsafe {
|
||||
if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
|
||||
return Err(IoError::last_error());
|
||||
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,
|
||||
}
|
||||
|
||||
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 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());
|
||||
}
|
||||
// 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'"' => {
|
||||
in_quote = !in_quote;
|
||||
}
|
||||
_ => {
|
||||
in_progress.push(*b);
|
||||
}
|
||||
}
|
||||
}
|
||||
parsed.push(Path::new(in_progress));
|
||||
parsed
|
||||
}
|
||||
|
||||
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
|
||||
let mut joined = Vec::new();
|
||||
let sep = b';';
|
||||
|
||||
for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
|
||||
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'"');
|
||||
} else {
|
||||
joined.push_all(path);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(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())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chdir(p: &Path) -> IoResult<()> {
|
||||
let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>();
|
||||
p.push(0);
|
||||
|
||||
unsafe {
|
||||
match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
|
||||
true => Ok(()),
|
||||
false => Err(IoError::last_error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn page_size() -> uint {
|
||||
use mem;
|
||||
unsafe {
|
||||
let mut info = mem::zeroed();
|
||||
libc::GetSystemInfo(&mut info);
|
||||
|
||||
return info.dwPageSize as uint;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::truncate_utf16_at_nul;
|
||||
|
||||
#[test]
|
||||
fn test_truncate_utf16_at_nul() {
|
||||
let v = [];
|
||||
let b: &[u16] = &[];
|
||||
assert_eq!(truncate_utf16_at_nul(&v), b);
|
||||
|
||||
let v = [0, 2, 3];
|
||||
assert_eq!(truncate_utf16_at_nul(&v), b);
|
||||
|
||||
let v = [1, 0, 3];
|
||||
let b: &[u16] = &[1];
|
||||
assert_eq!(truncate_utf16_at_nul(&v), b);
|
||||
|
||||
let v = [1, 2, 0];
|
||||
let b: &[u16] = &[1, 2];
|
||||
assert_eq!(truncate_utf16_at_nul(&v), b);
|
||||
|
||||
let v = [1, 2, 3];
|
||||
let b: &[u16] = &[1, 2, 3];
|
||||
assert_eq!(truncate_utf16_at_nul(&v), b);
|
||||
}
|
||||
}, super::os2path).ok()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 old_io::fs::PathExtensions;
|
||||
use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
|
||||
use old_io::{IoResult, IoError};
|
||||
use old_io;
|
||||
use libc::{pid_t, c_void, c_int};
|
||||
use libc::{pid_t, c_void};
|
||||
use libc;
|
||||
use mem;
|
||||
use old_io::fs::PathExtensions;
|
||||
use old_io::process::{ProcessExit, ExitStatus};
|
||||
use old_io::{IoResult, IoError};
|
||||
use old_io;
|
||||
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() {
|
||||
|
@ -149,7 +149,7 @@ impl Process {
|
|||
// program exists.
|
||||
for path in os::split_paths(v.container_as_bytes()).into_iter() {
|
||||
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()))
|
||||
}
|
||||
|
|
|
@ -18,9 +18,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())
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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> }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -21,7 +21,7 @@ use ext::base;
|
|||
use ext::build::AstBuilder;
|
||||
use parse::token;
|
||||
|
||||
use std::os;
|
||||
use std::env;
|
||||
|
||||
pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
-> Box<base::MacResult+'cx> {
|
||||
|
@ -30,8 +30,8 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT
|
|||
Some(v) => v
|
||||
};
|
||||
|
||||
let e = match os::getenv(&var[]) {
|
||||
None => {
|
||||
let e = match env::var_string(&var[]) {
|
||||
Err(..) => {
|
||||
cx.expr_path(cx.path_all(sp,
|
||||
true,
|
||||
vec!(cx.ident_of("std"),
|
||||
|
@ -48,7 +48,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT
|
|||
ast::MutImmutable)),
|
||||
Vec::new()))
|
||||
}
|
||||
Some(s) => {
|
||||
Ok(s) => {
|
||||
cx.expr_call_global(sp,
|
||||
vec!(cx.ident_of("std"),
|
||||
cx.ident_of("option"),
|
||||
|
@ -101,12 +101,12 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
|||
}
|
||||
}
|
||||
|
||||
let e = match os::getenv(var.get()) {
|
||||
None => {
|
||||
let e = match env::var_string(var.get()) {
|
||||
Err(..) => {
|
||||
cx.span_err(sp, msg.get());
|
||||
cx.expr_usize(sp, 0)
|
||||
}
|
||||
Some(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[]))
|
||||
Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s[]))
|
||||
};
|
||||
MacExpr::new(e)
|
||||
}
|
||||
|
|
|
@ -28,11 +28,11 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(env)]
|
||||
#![feature(hash)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(libc)]
|
||||
#![feature(os)]
|
||||
#![feature(path)]
|
||||
#![feature(quote, unsafe_destructor)]
|
||||
#![feature(rustc_private)]
|
||||
|
|
|
@ -55,13 +55,14 @@
|
|||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(os)]
|
||||
#![feature(path)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(slicing_syntax)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(unicode)]
|
||||
#![feature(env)]
|
||||
#![cfg_attr(windows, feature(libc))]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
use std::old_io::IoResult;
|
||||
use std::os;
|
||||
use std::env;
|
||||
|
||||
use attr;
|
||||
use color;
|
||||
|
@ -172,9 +172,9 @@ impl<T: Writer+Send> TerminfoTerminal<T> {
|
|||
/// Returns `None` whenever the terminal cannot be created for some
|
||||
/// reason.
|
||||
pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
|
||||
let term = match os::getenv("TERM") {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
let term = match env::var_string("TERM") {
|
||||
Ok(t) => t,
|
||||
Err(..) => {
|
||||
debug!("TERM environment variable not defined");
|
||||
return None;
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ impl<T: Writer+Send> TerminfoTerminal<T> {
|
|||
|
||||
let entry = open(&term[]);
|
||||
if entry.is_err() {
|
||||
if os::getenv("MSYSCON").map_or(false, |s| {
|
||||
if env::var_string("MSYSCON").ok().map_or(false, |s| {
|
||||
"mintty.exe" == s
|
||||
}) {
|
||||
// msys terminal
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
|
||||
use std::old_io::File;
|
||||
use std::old_io::fs::PathExtensions;
|
||||
use std::os::getenv;
|
||||
use std::os;
|
||||
use std::env;
|
||||
|
||||
/// Return path to database entry for `term`
|
||||
pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
|
||||
|
@ -23,21 +22,21 @@ pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let homedir = os::homedir();
|
||||
let homedir = env::home_dir();
|
||||
|
||||
let mut dirs_to_search = Vec::new();
|
||||
let first_char = term.char_at(0);
|
||||
|
||||
// Find search directory
|
||||
match getenv("TERMINFO") {
|
||||
Some(dir) => dirs_to_search.push(Path::new(dir)),
|
||||
None => {
|
||||
match env::var_string("TERMINFO") {
|
||||
Ok(dir) => dirs_to_search.push(Path::new(dir)),
|
||||
Err(..) => {
|
||||
if homedir.is_some() {
|
||||
// ncurses compatibility;
|
||||
dirs_to_search.push(homedir.unwrap().join(".terminfo"))
|
||||
}
|
||||
match getenv("TERMINFO_DIRS") {
|
||||
Some(dirs) => for i in dirs.split(':') {
|
||||
match env::var_string("TERMINFO_DIRS") {
|
||||
Ok(dirs) => for i in dirs.split(':') {
|
||||
if i == "" {
|
||||
dirs_to_search.push(Path::new("/usr/share/terminfo"));
|
||||
} else {
|
||||
|
@ -48,7 +47,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
|
|||
// According to /etc/terminfo/README, after looking at
|
||||
// ~/.terminfo, ncurses will search /etc/terminfo, then
|
||||
// /lib/terminfo, and eventually /usr/share/terminfo.
|
||||
None => {
|
||||
Err(..) => {
|
||||
dirs_to_search.push(Path::new("/etc/terminfo"));
|
||||
dirs_to_search.push(Path::new("/lib/terminfo"));
|
||||
dirs_to_search.push(Path::new("/usr/share/terminfo"));
|
||||
|
|
|
@ -38,10 +38,10 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(env)]
|
||||
#![feature(hash)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(io)]
|
||||
#![feature(os)]
|
||||
#![feature(path)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
|
@ -75,7 +75,7 @@ use std::old_io::{File, ChanReader, ChanWriter};
|
|||
use std::old_io;
|
||||
use std::iter::repeat;
|
||||
use std::num::{Float, Int};
|
||||
use std::os;
|
||||
use std::env;
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::thread::{self, Thread};
|
||||
use std::thunk::{Thunk, Invoke};
|
||||
|
@ -388,7 +388,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
|
|||
|
||||
let mut nocapture = matches.opt_present("nocapture");
|
||||
if !nocapture {
|
||||
nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some();
|
||||
nocapture = env::var("RUST_TEST_NOCAPTURE").is_some();
|
||||
}
|
||||
|
||||
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
|
||||
|
@ -817,15 +817,15 @@ fn run_tests<F>(opts: &TestOpts,
|
|||
|
||||
fn get_concurrency() -> uint {
|
||||
use std::rt;
|
||||
match os::getenv("RUST_TEST_TASKS") {
|
||||
Some(s) => {
|
||||
match env::var_string("RUST_TEST_TASKS") {
|
||||
Ok(s) => {
|
||||
let opt_n: Option<uint> = s.parse().ok();
|
||||
match opt_n {
|
||||
Some(n) if n > 0 => n,
|
||||
_ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
Err(..) => {
|
||||
rt::default_sched_threads()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,12 +48,12 @@ use std::simd::f64x2;
|
|||
use std::sync::Arc;
|
||||
use std::thread::Thread;
|
||||
|
||||
const ITER: int = 50;
|
||||
const ITER: usize = 50;
|
||||
const LIMIT: f64 = 2.0;
|
||||
const WORKERS: uint = 16;
|
||||
const WORKERS: usize = 16;
|
||||
|
||||
#[inline(always)]
|
||||
fn mandelbrot<W: old_io::Writer>(w: uint, mut out: W) -> old_io::IoResult<()> {
|
||||
fn mandelbrot<W: old_io::Writer>(w: usize, mut out: W) -> old_io::IoResult<()> {
|
||||
assert!(WORKERS % 2 == 0);
|
||||
|
||||
// Ensure w and h are multiples of 8.
|
||||
|
@ -198,7 +198,6 @@ fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
|
|||
|
||||
fn main() {
|
||||
let args = os::args();
|
||||
let args = args.as_slice();
|
||||
let res = if args.len() < 2 {
|
||||
println!("Test mode: do not dump the image because it's not utf8, \
|
||||
which interferes with the test runner.");
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#![deny(unused_assignments)]
|
||||
#![allow(dead_code, non_camel_case_types)]
|
||||
#![feature(core)]
|
||||
#![feature(os)]
|
||||
|
||||
fn f1(x: isize) {
|
||||
//~^ ERROR unused variable: `x`
|
||||
|
@ -98,7 +97,7 @@ fn f5c() {
|
|||
for (_, x) in [1is, 2, 3].iter().enumerate() {
|
||||
//~^ ERROR unused variable: `x`
|
||||
continue;
|
||||
std::os::set_exit_status(*x); //~ WARNING unreachable statement
|
||||
drop(*x as i32); //~ WARNING unreachable statement
|
||||
}
|
||||
}
|
||||
|
||||
|
|
45
src/test/run-pass/env-home-dir.rs
Normal file
45
src/test/run-pass/env-home-dir.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
// 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 std::env::*;
|
||||
|
||||
#[cfg(unix)]
|
||||
fn main() {
|
||||
let oldhome = var("HOME");
|
||||
|
||||
set_var("HOME", "/home/MountainView");
|
||||
assert!(home_dir() == Some(Path::new("/home/MountainView")));
|
||||
|
||||
remove_var("HOME");
|
||||
assert!(home_dir().is_some());
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn main() {
|
||||
let oldhome = var("HOME");
|
||||
let olduserprofile = var("USERPROFILE");
|
||||
|
||||
remove_var("HOME");
|
||||
remove_var("USERPROFILE");
|
||||
|
||||
assert!(home_dir().is_some());
|
||||
|
||||
set_var("HOME", "/home/MountainView");
|
||||
assert!(home_dir() == Some(Path::new("/home/MountainView")));
|
||||
|
||||
remove_var("HOME");
|
||||
|
||||
set_var("USERPROFILE", "/home/MountainView");
|
||||
assert!(home_dir() == Some(Path::new("/home/MountainView")));
|
||||
|
||||
set_var("HOME", "/home/MountainView");
|
||||
set_var("USERPROFILE", "/home/PaloAlto");
|
||||
assert!(home_dir() == Some(Path::new("/home/MountainView")));
|
||||
}
|
22
src/test/run-pass/env-vars.rs
Normal file
22
src/test/run-pass/env-vars.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// 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 std::env::*;
|
||||
|
||||
fn main() {
|
||||
for (k, v) in vars() {
|
||||
let v2 = var(&k);
|
||||
// MingW seems to set some funky environment variables like
|
||||
// "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
|
||||
// from vars() but not visible from var().
|
||||
assert!(v2.is_none() || v2.as_ref().map(|s| &**s) == Some(&*v),
|
||||
"bad vars->var transition: {:?} {:?} {:?}", k, v, v2);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue