rollup merge of #21787: alexcrichton/std-env

Conflicts:
	src/libstd/sys/unix/backtrace.rs
	src/libstd/sys/unix/os.rs
This commit is contained in:
Alex Crichton 2015-02-02 10:58:01 -08:00
commit 902abab144
66 changed files with 2215 additions and 823 deletions

View File

@ -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) => {}

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -32,7 +32,7 @@
#![feature(int_uint)]
#![feature(io)]
#![feature(libc)]
#![feature(os)]
#![feature(env)]
#![feature(path)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]

View File

@ -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() {

View File

@ -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);

View File

@ -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,

View File

@ -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()),

View File

@ -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]);

View File

@ -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) {

View File

@ -40,6 +40,7 @@
#![feature(path)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(env)]
extern crate syntax;
extern crate serialize;

View File

@ -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()
}

View File

@ -303,7 +303,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;
@ -383,12 +384,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);

View File

@ -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 {

View File

@ -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);
}

View File

@ -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)]

View File

@ -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"),
},

View File

@ -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> {

View File

@ -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),

View File

@ -19,7 +19,7 @@ use prelude::v1::*;
use ffi::CString;
use mem;
use os;
use env;
use str;
#[allow(missing_copy_implementations)]
@ -68,8 +68,8 @@ 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(),
str::from_utf8(newval.as_slice()).unwrap());
env::set_var(DynamicLibrary::envvar(),
str::from_utf8(newval.as_slice()).unwrap());
}
/// From a slice of paths, create a new vector which is suitable to be an
@ -102,18 +102,10 @@ 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));
}
}
None => {}
match env::var(DynamicLibrary::envvar()) {
Some(var) => env::split_paths(&var).collect(),
None => Vec::new(),
}
return ret;
}
/// Access the value at the symbol of the dynamic library

833
src/libstd/env.rs Normal file
View 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());
}
}

View File

@ -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;
}

View File

@ -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 }

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -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;

View File

@ -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")]
@ -727,7 +672,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();
@ -778,12 +723,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()
}
@ -791,11 +740,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()
}
@ -971,7 +922,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 {
@ -1021,7 +972,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()
}
}
@ -1050,7 +1001,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 {
@ -1185,6 +1136,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;
@ -1216,6 +1169,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;
@ -1247,6 +1202,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;
@ -1266,6 +1223,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;
@ -1297,6 +1256,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;
@ -1359,6 +1320,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;
@ -1390,6 +1353,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;

View File

@ -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,
};

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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.
///

View File

@ -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;
////////////////////////////////////////////////////////////////////////
@ -320,7 +320,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
let selfname = if cfg!(target_os = "freebsd") ||
cfg!(target_os = "dragonfly") ||
cfg!(target_os = "openbsd") {
os::self_exe_name()
env::current_exe().ok()
} else {
None
};

View File

@ -69,6 +69,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;
@ -95,6 +142,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"))]

View File

@ -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<()> {

View File

@ -1,4 +1,4 @@
// Copyright 2014-2015 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,43 +11,39 @@
//! 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 {
__error()
}
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 {
__dfly_error()
}
unsafe fn errno_location() -> *const c_int {
extern { fn __dfly_error() -> *const c_int; }
__dfly_error()
}
#[cfg(target_os = "openbsd")]
@ -61,54 +57,28 @@ pub fn errno() -> int {
}
#[cfg(any(target_os = "linux", target_os = "android"))]
fn errno_location() -> *const c_int {
extern {
fn __errno_location() -> *const c_int;
}
unsafe {
__errno_location()
}
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",
target_os = "openbsd"))]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t)
-> c_int {
extern {
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 {
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)
}
extern {
#[link_name = "__xpg_strerror_r"]
fn strerror_r(errnum: c_int, buf: *mut c_char,
buflen: libc::size_t) -> c_int;
}
#[cfg(not(target_os = "linux"))]
extern {
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];
@ -124,15 +94,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 {
@ -144,43 +105,69 @@ pub fn getcwd() -> IoResult<Path> {
}
}
pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
extern {
fn rust_env_pairs() -> *const *const c_char;
pub fn chdir(p: &Path) -> IoResult<()> {
let p = CString::from_slice(p.as_vec());
unsafe {
match libc::chdir(p.as_ptr()) == (0 as c_int) {
true => Ok(()),
false => Err(IoError::last_error()),
}
}
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 struct SplitPaths<'a> {
iter: iter::Map<&'a [u8], Path,
slice::Split<'a, u8, fn(&u8) -> bool>,
fn(&'a [u8]) -> Path>,
}
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
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.iter().map(|p| p.container_as_bytes()).enumerate() {
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("path segment contains separator `:`") }
if path.contains(&sep) {
return Err(JoinPathsError)
}
joined.push_all(path);
}
Ok(OsStringExt::from_vec(joined))
}
Ok(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 load_self() -> Option<Vec<u8>> {
pub fn current_exe() -> IoResult<Path> {
unsafe {
use libc::funcs::bsd44::*;
use libc::consts::os::extra::*;
@ -192,27 +179,22 @@ pub fn load_self() -> Option<Vec<u8>> {
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; }
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 None; }
if sz == 0 { return None; }
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
Some(v)
Ok(Path::new(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
}
pub fn current_exe() -> IoResult<Path> {
fs::readlink(&Path::new("/proc/curproc/file"))
}
#[cfg(target_os = "openbsd")]
@ -238,42 +220,257 @@ pub fn load_self() -> Option<Vec<u8>> {
}
#[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
}
pub fn current_exe() -> IoResult<Path> {
fs::readlink(&Path::new("/proc/self/exe"))
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn load_self() -> Option<Vec<u8>> {
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 None; }
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 None; }
if err != 0 { return Err(IoError::last_error()); }
v.set_len(sz as uint - 1); // chop off trailing NUL
Some(v)
Ok(Path::new(v))
}
}
pub fn chdir(p: &Path) -> IoResult<()> {
let p = CString::from_slice(p.as_vec());
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 {
match libc::chdir(p.as_ptr()) == (0 as c_int) {
true => Ok(()),
false => Err(IoError::last_error()),
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 page_size() -> uint {
pub fn setenv(k: &OsStr, v: &OsStr) {
unsafe {
libc::sysconf(libc::_SC_PAGESIZE) as uint
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())
})
}

View File

@ -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);

View File

@ -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.

View File

@ -10,17 +10,21 @@
//! C definitions used by libnative that don't belong in liblibc
#![allow(overflowing_literals)]
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(bad_style, dead_code, overflowing_literals)]
use libc;
use prelude::v1::*;
pub const WSADESCRIPTION_LEN: uint = 256;
pub const WSASYS_STATUS_LEN: uint = 128;
pub use self::GET_FILEEX_INFO_LEVELS::*;
pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
pub use libc::consts::os::extra::{
FILE_ATTRIBUTE_READONLY,
FILE_ATTRIBUTE_DIRECTORY,
};
pub const WSADESCRIPTION_LEN: usize = 256;
pub const WSASYS_STATUS_LEN: usize = 128;
pub const FIONBIO: libc::c_long = 0x8004667e;
pub const FD_SETSIZE: uint = 64;
pub const FD_SETSIZE: usize = 64;
pub const MSG_DONTWAIT: libc::c_int = 0;
pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582;
pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4;
@ -32,12 +36,15 @@ pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40;
pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT;
pub const FD_ACCEPT: libc::c_long = 0x08;
pub const FD_MAX_EVENTS: uint = 10;
pub const FD_MAX_EVENTS: usize = 10;
pub const WSA_INFINITE: libc::DWORD = libc::INFINITE;
pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT;
pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0;
pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED;
pub const ERROR_NO_MORE_FILES: libc::DWORD = 18;
pub const TOKEN_READ: libc::DWORD = 0x20008;
#[repr(C)]
#[cfg(target_arch = "x86")]
pub struct WSADATA {
@ -80,7 +87,7 @@ pub struct fd_set {
}
pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) {
set.fd_array[set.fd_count as uint] = s;
set.fd_array[set.fd_count as usize] = s;
set.fd_count += 1;
}
@ -110,6 +117,69 @@ pub struct CONSOLE_SCREEN_BUFFER_INFO {
}
pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
#[repr(C)]
pub struct WIN32_FILE_ATTRIBUTE_DATA {
pub dwFileAttributes: libc::DWORD,
pub ftCreationTime: libc::FILETIME,
pub ftLastAccessTime: libc::FILETIME,
pub ftLastWriteTime: libc::FILETIME,
pub nFileSizeHigh: libc::DWORD,
pub nFileSizeLow: libc::DWORD,
}
#[repr(C)]
pub struct BY_HANDLE_FILE_INFORMATION {
pub dwFileAttributes: libc::DWORD,
pub ftCreationTime: libc::FILETIME,
pub ftLastAccessTime: libc::FILETIME,
pub ftLastWriteTime: libc::FILETIME,
pub dwVolumeSerialNumber: libc::DWORD,
pub nFileSizeHigh: libc::DWORD,
pub nFileSizeLow: libc::DWORD,
pub nNumberOfLinks: libc::DWORD,
pub nFileIndexHigh: libc::DWORD,
pub nFileIndexLow: libc::DWORD,
}
pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
#[repr(C)]
pub enum GET_FILEEX_INFO_LEVELS {
GetFileExInfoStandard,
GetFileExMaxInfoLevel
}
#[repr(C)]
pub enum FILE_INFO_BY_HANDLE_CLASS {
FileBasicInfo = 0,
FileStandardInfo = 1,
FileNameInfo = 2,
FileRenameInfo = 3,
FileDispositionInfo = 4,
FileAllocationInfo = 5,
FileEndOfFileInfo = 6,
FileStreamInfo = 7,
FileCompressionInfo = 8,
FileAttributeTagInfo = 9,
FileIdBothDirectoryInfo = 10, // 0xA
FileIdBothDirectoryRestartInfo = 11, // 0xB
FileIoPriorityHintInfo = 12, // 0xC
FileRemoteProtocolInfo = 13, // 0xD
FileFullDirectoryInfo = 14, // 0xE
FileFullDirectoryRestartInfo = 15, // 0xF
FileStorageInfo = 16, // 0x10
FileAlignmentInfo = 17, // 0x11
FileIdInfo = 18, // 0x12
FileIdExtdDirectoryInfo = 19, // 0x13
FileIdExtdDirectoryRestartInfo = 20, // 0x14
MaximumFileInfoByHandlesClass
}
#[repr(C)]
pub struct FILE_END_OF_FILE_INFO {
pub EndOfFile: libc::LARGE_INTEGER,
}
#[link(name = "ws2_32")]
extern "system" {
pub fn WSAStartup(wVersionRequested: libc::WORD,
@ -156,31 +226,29 @@ extern "system" {
}
pub mod compat {
use intrinsics::{atomic_store_relaxed, transmute};
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
use prelude::v1::*;
use ffi::CString;
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
use sync::atomic::{AtomicUsize, Ordering};
extern "system" {
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
}
// store_func() is idempotent, so using relaxed ordering for the atomics
// should be enough. This way, calling a function in this compatibility
// layer (after it's loaded) shouldn't be any slower than a regular DLL
// call.
unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
fallback: usize) -> usize {
let mut module: Vec<u16> = module.utf16_units().collect();
module.push(0);
let symbol = CString::from_slice(symbol.as_bytes());
let handle = GetModuleHandleW(module.as_ptr());
let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
atomic_store_relaxed(ptr, if func == 0 {
fallback
} else {
func
})
let func = unsafe {
let handle = GetModuleHandleW(module.as_ptr());
GetProcAddress(handle, symbol.as_ptr()) as usize
};
let value = if func == 0 {fallback} else {func};
ptr.store(value, Ordering::SeqCst);
value
}
/// Macro for creating a compatibility fallback for a Windows function
@ -192,29 +260,36 @@ pub mod compat {
/// })
/// ```
///
/// Note that arguments unused by the fallback implementation should not be called `_` as
/// they are used to be passed to the real function if available.
/// Note that arguments unused by the fallback implementation should not be
/// called `_` as they are used to be passed to the real function if
/// available.
macro_rules! compat_fn {
($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
-> $rettype:ty { $fallback:expr }) => (
#[inline(always)]
pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk;
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,
stringify!($module),
stringify!($symbol),
fallback as uint);
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
}
static PTR: AtomicUsize = ATOMIC_USIZE_INIT;
fn load() -> usize {
::sys::c::compat::store_func(&PTR,
stringify!($module),
stringify!($symbol),
fallback as usize)
}
extern "system" fn fallback($($argname: $argtype),*)
-> $rettype { $fallback }
::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
let addr = match PTR.load(Ordering::SeqCst) {
0 => load(),
n => n,
};
let f: extern "system" fn($($argtype),*) -> $rettype =
mem::transmute(addr);
f($($argname),*)
}
)
}
@ -229,10 +304,7 @@ pub mod compat {
use libc::c_uint;
use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
extern "system" {
fn SetLastError(dwErrCode: DWORD);
}
use sys::c::SetLastError;
compat_fn! {
kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
@ -282,4 +354,42 @@ extern "system" {
hConsoleOutput: libc::HANDLE,
lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO,
) -> libc::BOOL;
pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR,
fInfoLevelId: GET_FILEEX_INFO_LEVELS,
lpFileInformation: libc::LPVOID) -> libc::BOOL;
pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL;
pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR,
dwFileAttributes: libc::DWORD) -> libc::BOOL;
pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD;
pub fn GetFileInformationByHandle(hFile: libc::HANDLE,
lpFileInformation: LPBY_HANDLE_FILE_INFORMATION)
-> libc::BOOL;
pub fn SetLastError(dwErrCode: libc::DWORD);
pub fn GetCommandLineW() -> *mut libc::LPCWSTR;
pub fn LocalFree(ptr: *mut libc::c_void);
pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR,
pNumArgs: *mut libc::c_int) -> *mut *mut u16;
pub fn SetFileTime(hFile: libc::HANDLE,
lpCreationTime: *const libc::FILETIME,
lpLastAccessTime: *const libc::FILETIME,
lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL;
pub fn SetFileInformationByHandle(hFile: libc::HANDLE,
FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
lpFileInformation: libc::LPVOID,
dwBufferSize: libc::DWORD) -> libc::BOOL;
pub fn GetTempPathW(nBufferLength: libc::DWORD,
lpBuffer: libc::LPCWSTR) -> libc::DWORD;
pub fn OpenProcessToken(ProcessHandle: libc::HANDLE,
DesiredAccess: libc::DWORD,
TokenHandle: *mut libc::HANDLE) -> libc::BOOL;
pub fn GetCurrentProcess() -> libc::HANDLE;
}
#[link(name = "userenv")]
extern "system" {
pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
lpProfileDir: libc::LPCWSTR,
lpcchSize: *mut libc::DWORD) -> libc::BOOL;
}

View File

@ -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;
}

View 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); }
}
}

View File

@ -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
}
}

View File

@ -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())

View File

@ -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
@ -114,7 +335,7 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
// first, as in std::run.
let mut fds = [0; 2];
match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
(libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
(libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
0 => {
assert!(fds[0] != -1 && fds[0] != 0);
assert!(fds[1] != -1 && fds[1] != 0);
@ -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;
pub fn temp_dir() -> Path {
super::fill_utf16_buf(|buf, sz| unsafe {
c::GetTempPathW(sz, buf)
}, super::os2path).unwrap()
}
pub fn home_dir() -> Option<Path> {
getenv("HOME".as_os_str()).or_else(|| {
getenv("USERPROFILE".as_os_str())
}).map(|os| {
// FIXME: OsString => Path
Path::new(os.to_str().unwrap())
}).or_else(|| unsafe {
let me = c::GetCurrentProcess();
let mut token = ptr::null_mut();
if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
return None
}
let _handle = RawHandle::new(token);
super::fill_utf16_buf(|buf, mut sz| {
match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
0 if libc::GetLastError() != 0 => 0,
0 => sz,
n => n as libc::DWORD,
}
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 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());
}
}
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()
})
}

View File

@ -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()
}

View File

@ -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()))
}

View File

@ -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())

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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 {

View File

@ -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> }

View File

@ -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 {

View File

@ -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)
}

View File

@ -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)]

View File

@ -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;

View File

@ -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

View File

@ -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"));

View File

@ -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()
}
}

View File

@ -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.");

View File

@ -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 [1, 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
}
}

View 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")));
}

View 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);
}
}