about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-02-03 03:44:05 +0000
committerbors <bors@rust-lang.org>2015-02-03 03:44:05 +0000
commit7858cb432d3f2efc0374424cb2b51518f697c172 (patch)
treebccd460a861e61f758d2d459cb9da02b1ad8792b /src/libstd
parenteaf4c5c784637f3df8bdebc6ec21dbd4bc69420a (diff)
parent9ece22ee00033cdf0b6b418c451112c92c8ad922 (diff)
downloadrust-7858cb432d3f2efc0374424cb2b51518f697c172.tar.gz
rust-7858cb432d3f2efc0374424cb2b51518f697c172.zip
Auto merge of #21872 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/ascii.rs6
-rw-r--r--src/libstd/collections/hash/map.rs62
-rw-r--r--src/libstd/collections/hash/set.rs40
-rw-r--r--src/libstd/dynamic_lib.rs29
-rw-r--r--src/libstd/env.rs833
-rw-r--r--src/libstd/ffi/mod.rs7
-rw-r--r--src/libstd/ffi/os_str.rs97
-rw-r--r--src/libstd/fmt.rs4
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libstd/old_io/extensions.rs12
-rw-r--r--src/libstd/old_io/fs.rs6
-rw-r--r--src/libstd/old_io/net/addrinfo.rs2
-rw-r--r--src/libstd/old_io/net/ip.rs2
-rw-r--r--src/libstd/old_io/net/mod.rs2
-rw-r--r--src/libstd/old_io/process.rs7
-rw-r--r--src/libstd/old_io/tempfile.rs12
-rw-r--r--src/libstd/old_io/test.rs8
-rw-r--r--src/libstd/old_io/util.rs4
-rw-r--r--src/libstd/os.rs293
-rw-r--r--src/libstd/path/mod.rs6
-rw-r--r--src/libstd/path/posix.rs2
-rw-r--r--src/libstd/path/windows.rs6
-rw-r--r--src/libstd/prelude/v1.rs4
-rw-r--r--src/libstd/rand/mod.rs2
-rw-r--r--src/libstd/rand/os.rs2
-rw-r--r--src/libstd/rt/args.rs5
-rw-r--r--src/libstd/rt/at_exit_imp.rs2
-rw-r--r--src/libstd/rt/backtrace.rs4
-rw-r--r--src/libstd/rt/libunwind.rs2
-rw-r--r--src/libstd/rt/mod.rs4
-rw-r--r--src/libstd/rt/unwind.rs6
-rw-r--r--src/libstd/rt/util.rs9
-rw-r--r--src/libstd/rtdeps.rs4
-rw-r--r--src/libstd/sync/rwlock.rs2
-rw-r--r--src/libstd/sys/common/mutex.rs7
-rw-r--r--src/libstd/sys/common/net.rs12
-rw-r--r--src/libstd/sys/common/rwlock.rs7
-rw-r--r--src/libstd/sys/common/stack.rs43
-rw-r--r--src/libstd/sys/common/wtf8.rs13
-rw-r--r--src/libstd/sys/unix/backtrace.rs9
-rw-r--r--src/libstd/sys/unix/c.rs70
-rw-r--r--src/libstd/sys/unix/mod.rs4
-rw-r--r--src/libstd/sys/unix/os.rs462
-rw-r--r--src/libstd/sys/unix/process.rs21
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs23
-rw-r--r--src/libstd/sys/unix/sync.rs4
-rw-r--r--src/libstd/sys/unix/thread.rs57
-rw-r--r--src/libstd/sys/unix/thread_local.rs8
-rw-r--r--src/libstd/sys/unix/time.rs3
-rw-r--r--src/libstd/sys/unix/tty.rs6
-rw-r--r--src/libstd/sys/windows/backtrace.rs34
-rw-r--r--src/libstd/sys/windows/c.rs190
-rw-r--r--src/libstd/sys/windows/fs.rs20
-rw-r--r--src/libstd/sys/windows/handle.rs31
-rw-r--r--src/libstd/sys/windows/mod.rs111
-rw-r--r--src/libstd/sys/windows/mutex.rs2
-rw-r--r--src/libstd/sys/windows/os.rs453
-rw-r--r--src/libstd/sys/windows/pipe.rs18
-rw-r--r--src/libstd/sys/windows/process.rs32
-rw-r--r--src/libstd/sys/windows/rwlock.rs3
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs10
-rw-r--r--src/libstd/sys/windows/sync.rs2
-rw-r--r--src/libstd/sys/windows/tcp.rs9
-rw-r--r--src/libstd/sys/windows/thread.rs2
-rw-r--r--src/libstd/sys/windows/thread_local.rs3
-rw-r--r--src/libstd/sys/windows/timer.rs2
-rw-r--r--src/libstd/sys/windows/tty.rs5
-rw-r--r--src/libstd/thread_local/mod.rs2
68 files changed, 2325 insertions, 843 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 9aa38e711e7..274c669d8df 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -134,7 +134,7 @@ impl AsciiExt<Vec<u8>> for [u8] {
 impl OwnedAsciiExt for Vec<u8> {
     #[inline]
     fn into_ascii_uppercase(mut self) -> Vec<u8> {
-        for byte in self.iter_mut() {
+        for byte in &mut self {
             *byte = byte.to_ascii_uppercase();
         }
         self
@@ -142,7 +142,7 @@ impl OwnedAsciiExt for Vec<u8> {
 
     #[inline]
     fn into_ascii_lowercase(mut self) -> Vec<u8> {
-        for byte in self.iter_mut() {
+        for byte in &mut self {
             *byte = byte.to_ascii_lowercase();
         }
         self
@@ -232,7 +232,7 @@ pub fn escape_default<F>(c: u8, mut f: F) where
         _ => {
             f(b'\\');
             f(b'x');
-            for &offset in [4u, 0u].iter() {
+            for &offset in &[4u, 0u] {
                 match ((c as i32) >> offset) & 0xf {
                     i @ 0 ... 9 => f(b'0' + (i as u8)),
                     i => f(b'a' + (i as u8 - 10)),
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 3e2c7627dbe..7b3cc434f0c 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -20,7 +20,7 @@ use cmp::{max, Eq, PartialEq};
 use default::Default;
 use fmt::{self, Debug};
 use hash::{self, Hash, SipHasher};
-use iter::{self, Iterator, ExactSizeIterator, IteratorExt, FromIterator, Extend, Map};
+use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
 use marker::Sized;
 use mem::{self, replace};
 use num::{Int, UnsignedInt};
@@ -1300,18 +1300,13 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
 /// HashMap move iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
-    inner: iter::Map<
-        (SafeHash, K, V),
-        (K, V),
-        table::IntoIter<K, V>,
-        fn((SafeHash, K, V)) -> (K, V),
-    >
+    inner: iter::Map<table::IntoIter<K, V>, fn((SafeHash, K, V)) -> (K, V)>
 }
 
 /// HashMap keys iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Keys<'a, K: 'a, V: 'a> {
-    inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
+    inner: Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
@@ -1326,7 +1321,7 @@ impl<'a, K, V> Clone for Keys<'a, K, V> {
 /// HashMap values iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
-    inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
+    inner: Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
 }
 
 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
@@ -1342,12 +1337,7 @@ impl<'a, K, V> Clone for Values<'a, K, V> {
 #[unstable(feature = "std_misc",
            reason = "matches collection reform specification, waiting for dust to settle")]
 pub struct Drain<'a, K: 'a, V: 'a> {
-    inner: iter::Map<
-        (SafeHash, K, V),
-        (K, V),
-        table::Drain<'a, K, V>,
-        fn((SafeHash, K, V)) -> (K, V),
-    >
+    inner: iter::Map<table::Drain<'a, K, V>, fn((SafeHash, K, V)) -> (K, V)>
 }
 
 /// A view into a single occupied location in a HashMap.
@@ -1385,6 +1375,42 @@ enum VacantEntryState<K, V, M> {
     NoElem(EmptyBucket<K, V, M>),
 }
 
+impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    type Iter = Iter<'a, K, V>;
+
+    fn into_iter(self) -> Iter<'a, K, V> {
+        self.iter()
+    }
+}
+
+impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    type Iter = IterMut<'a, K, V>;
+
+    fn into_iter(mut self) -> IterMut<'a, K, V> {
+        self.iter_mut()
+    }
+}
+
+impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    type Iter = IntoIter<K, V>;
+
+    fn into_iter(self) -> IntoIter<K, V> {
+        self.into_iter()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
@@ -1539,7 +1565,7 @@ impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
           S: HashState<Hasher=H>,
           H: hash::Hasher<Output=u64>
 {
-    fn extend<T: Iterator<Item=(K, V)>>(&mut self, mut iter: T) {
+    fn extend<T: Iterator<Item=(K, V)>>(&mut self, iter: T) {
         for (k, v) in iter {
             self.insert(k, v);
         }
@@ -1941,7 +1967,7 @@ mod test_map {
 
         let mut observed: u32 = 0;
 
-        for (k, v) in m.iter() {
+        for (k, v) in &m {
             assert_eq!(*v, *k * 2);
             observed |= 1 << *k;
         }
@@ -2131,7 +2157,7 @@ mod test_map {
 
         let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
 
-        for &(k, v) in xs.iter() {
+        for &(k, v) in &xs {
             assert_eq!(map.get(&k), Some(&v));
         }
     }
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index c6dcb0d230f..f5877e1dd99 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -18,7 +18,9 @@ use default::Default;
 use fmt::Debug;
 use fmt;
 use hash::{self, Hash};
-use iter::{Iterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend};
+use iter::{
+    Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend,
+};
 use ops::{BitOr, BitAnd, BitXor, Sub};
 use option::Option::{Some, None, self};
 
@@ -634,7 +636,7 @@ impl<T, S, H> Extend<T> for HashSet<T, S>
           S: HashState<Hasher=H>,
           H: hash::Hasher<Output=u64>
 {
-    fn extend<I: Iterator<Item=T>>(&mut self, mut iter: I) {
+    fn extend<I: Iterator<Item=T>>(&mut self, iter: I) {
         for k in iter {
             self.insert(k);
         }
@@ -794,13 +796,13 @@ pub struct Iter<'a, K: 'a> {
 /// HashSet move iterator
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K> {
-    iter: Map<(K, ()), K, map::IntoIter<K, ()>, fn((K, ())) -> K>
+    iter: Map<map::IntoIter<K, ()>, fn((K, ())) -> K>
 }
 
 /// HashSet drain iterator
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Drain<'a, K: 'a> {
-    iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>,
+    iter: Map<map::Drain<'a, K, ()>, fn((K, ())) -> K>,
 }
 
 /// Intersection iterator
@@ -833,6 +835,30 @@ pub struct Union<'a, T: 'a, S: 'a> {
     iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
 }
 
+impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    type Iter = Iter<'a, T>;
+
+    fn into_iter(self) -> Iter<'a, T> {
+        self.iter()
+    }
+}
+
+impl<T, S, H> IntoIterator for HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    type Iter = IntoIter<T>;
+
+    fn into_iter(self) -> IntoIter<T> {
+        self.into_iter()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> Iterator for Iter<'a, K> {
     type Item = &'a K;
@@ -1007,7 +1033,7 @@ mod test_set {
             assert!(a.insert(i));
         }
         let mut observed: u32 = 0;
-        for k in a.iter() {
+        for k in &a {
             observed |= 1 << *k;
         }
         assert_eq!(observed, 0xFFFF_FFFF);
@@ -1128,7 +1154,7 @@ mod test_set {
 
         let set: HashSet<int> = xs.iter().map(|&x| x).collect();
 
-        for x in xs.iter() {
+        for x in &xs {
             assert!(set.contains(x));
         }
     }
@@ -1214,7 +1240,7 @@ mod test_set {
                 assert_eq!(last_i, 49);
             }
 
-            for _ in s.iter() { panic!("s should be empty!"); }
+            for _ in &s { panic!("s should be empty!"); }
 
             // reset to try again.
             s.extend(1..100);
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
index f35f63143ef..68ae0f7e5b5 100644
--- a/src/libstd/dynamic_lib.rs
+++ b/src/libstd/dynamic_lib.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -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
@@ -173,7 +165,8 @@ mod test {
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "freebsd",
-              target_os = "dragonfly"))]
+              target_os = "dragonfly",
+              target_os = "openbsd"))]
     fn test_errors_do_not_crash() {
         // Open /dev/null as a library to get an error, and make sure
         // that only causes an error, and not a crash.
@@ -190,7 +183,8 @@ mod test {
           target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 mod dl {
     use prelude::v1::*;
 
@@ -254,7 +248,6 @@ mod dl {
         dlclose(handle as *mut libc::c_void); ()
     }
 
-    #[link_name = "dl"]
     extern {
         fn dlopen(filename: *const libc::c_char,
                   flag: libc::c_int) -> *mut libc::c_void;
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
new file mode 100644
index 00000000000..5070f8c547a
--- /dev/null
+++ b/src/libstd/env.rs
@@ -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());
+    }
+    }
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 69ada28a4b4..76f925a23f1 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -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;
+}
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 18e2aa8c098..b8d770e6ad6 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -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.
@@ -82,17 +89,6 @@ impl OsString {
     }
 }
 
-#[cfg(stage0)]
-impl ops::Index<ops::FullRange> for OsString {
-    type Output = OsStr;
-
-    #[inline]
-    fn index(&self, _index: &ops::FullRange) -> &OsStr {
-        unsafe { mem::transmute(self.inner.as_slice()) }
-    }
-}
-
-#[cfg(not(stage0))]
 impl ops::Index<ops::RangeFull> for OsString {
     type Output = OsStr;
 
@@ -117,6 +113,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 +274,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 +304,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 }
diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs
index 8e86aa65196..47f5d64e260 100644
--- a/src/libstd/fmt.rs
+++ b/src/libstd/fmt.rs
@@ -413,10 +413,6 @@ pub use core::fmt::{LowerExp, UpperExp};
 pub use core::fmt::Error;
 pub use core::fmt::{ArgumentV1, Arguments, write, radix, Radix, RadixFmt};
 
-#[doc(hidden)]
-#[cfg(stage0)]
-pub use core::fmt::{argument, argumentuint};
-
 /// The format function takes a precompiled format string and a list of
 /// arguments, to return the resulting formatted string.
 ///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 96aebb735ef..839983d336d 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -120,14 +120,13 @@
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![cfg_attr(not(stage0), feature(macro_reexport))]
+#![feature(macro_reexport)]
 #![cfg_attr(test, feature(test))]
 
 // Don't link to std. We are std.
 #![no_std]
 
 #![deny(missing_docs)]
-#![cfg_attr(not(stage0), allow(unused_mut))] // NOTE: remove after stage0 snap
 
 #[cfg(test)]
 #[macro_use]
@@ -250,6 +249,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;
diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs
index f429f731b7d..d729c2800ce 100644
--- a/src/libstd/old_io/extensions.rs
+++ b/src/libstd/old_io/extensions.rs
@@ -406,12 +406,12 @@ mod test {
         let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::MAX];
 
         let mut writer = Vec::new();
-        for i in uints.iter() {
+        for i in &uints {
             writer.write_le_u64(*i).unwrap();
         }
 
         let mut reader = MemReader::new(writer);
-        for i in uints.iter() {
+        for i in &uints {
             assert!(reader.read_le_u64().unwrap() == *i);
         }
     }
@@ -422,12 +422,12 @@ mod test {
         let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::MAX];
 
         let mut writer = Vec::new();
-        for i in uints.iter() {
+        for i in &uints {
             writer.write_be_u64(*i).unwrap();
         }
 
         let mut reader = MemReader::new(writer);
-        for i in uints.iter() {
+        for i in &uints {
             assert!(reader.read_be_u64().unwrap() == *i);
         }
     }
@@ -437,12 +437,12 @@ mod test {
         let ints = [::i32::MIN, -123456, -42, -5, 0, 1, ::i32::MAX];
 
         let mut writer = Vec::new();
-        for i in ints.iter() {
+        for i in &ints {
             writer.write_be_i32(*i).unwrap();
         }
 
         let mut reader = MemReader::new(writer);
-        for i in ints.iter() {
+        for i in &ints {
             // this tests that the sign extension is working
             // (comparing the values as i32 would not test this)
             assert!(reader.read_be_int_n(4).unwrap() == *i as i64);
diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs
index 0a9aeb849be..abf215988bb 100644
--- a/src/libstd/old_io/fs.rs
+++ b/src/libstd/old_io/fs.rs
@@ -597,7 +597,7 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> {
         return Ok(())
     }
 
-    let mut comps = path.components();
+    let comps = path.components();
     let mut curpath = path.root_path().unwrap_or(Path::new("."));
 
     for c in comps {
@@ -649,7 +649,7 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> {
 
         // delete all regular files in the way and push subdirs
         // on the stack
-        for child in children.into_iter() {
+        for child in children {
             // FIXME(#12795) we should use lstat in all cases
             let child_type = match cfg!(windows) {
                 true => try!(update_err(stat(&child), path)),
@@ -1110,7 +1110,7 @@ mod test {
         }
         let files = check!(readdir(dir));
         let mut mem = [0u8; 4];
-        for f in files.iter() {
+        for f in &files {
             {
                 let n = f.filestem_str();
                 check!(File::open(f).read(&mut mem));
diff --git a/src/libstd/old_io/net/addrinfo.rs b/src/libstd/old_io/net/addrinfo.rs
index e37744f3aa3..2b7506b5c34 100644
--- a/src/libstd/old_io/net/addrinfo.rs
+++ b/src/libstd/old_io/net/addrinfo.rs
@@ -121,7 +121,7 @@ mod test {
         let ipaddrs = get_host_addresses("localhost").unwrap();
         let mut found_local = false;
         let local_addr = &Ipv4Addr(127, 0, 0, 1);
-        for addr in ipaddrs.iter() {
+        for addr in &ipaddrs {
             found_local = found_local || addr == local_addr;
         }
         assert!(found_local);
diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs
index 565f9d83818..d85251795c8 100644
--- a/src/libstd/old_io/net/ip.rs
+++ b/src/libstd/old_io/net/ip.rs
@@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
     // Return result of first successful parser
     fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T>>])
                -> Option<T> {
-        for pf in parsers.iter_mut() {
+        for pf in parsers {
             match self.read_atomically(|p: &mut Parser| pf.call_mut((p,))) {
                 Some(r) => return Some(r),
                 None => {}
diff --git a/src/libstd/old_io/net/mod.rs b/src/libstd/old_io/net/mod.rs
index d8394aa8b6a..bbe3a71dcc0 100644
--- a/src/libstd/old_io/net/mod.rs
+++ b/src/libstd/old_io/net/mod.rs
@@ -36,7 +36,7 @@ fn with_addresses<A, T, F>(addr: A, mut action: F) -> IoResult<T> where
 
     let addresses = try!(addr.to_socket_addr_all());
     let mut err = DEFAULT_ERROR;
-    for addr in addresses.into_iter() {
+    for addr in addresses {
         match action(addr) {
             Ok(r) => return Ok(r),
             Err(e) => err = e
diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs
index f253f9799e9..61a07bc8208 100644
--- a/src/libstd/old_io/process.rs
+++ b/src/libstd/old_io/process.rs
@@ -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,
@@ -400,7 +401,7 @@ impl fmt::Debug for Command {
     /// character.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{:?}", self.program));
-        for arg in self.args.iter() {
+        for arg in &self.args {
             try!(write!(f, " '{:?}'", arg));
         }
         Ok(())
@@ -1045,7 +1046,7 @@ mod tests {
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
 
         let r = os::env();
-        for &(ref k, ref v) in r.iter() {
+        for &(ref k, ref v) in &r {
             // don't check windows magical empty-named variables
             assert!(k.is_empty() ||
                     output.contains(format!("{}={}", *k, *v).as_slice()),
@@ -1063,7 +1064,7 @@ mod tests {
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
 
         let r = os::env();
-        for &(ref k, ref v) in r.iter() {
+        for &(ref k, ref v) in &r {
             // don't check android RANDOM variables
             if *k != "RANDOM".to_string() {
                 assert!(output.contains(format!("{}={}",
diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs
index 20cbde5db71..83a42549424 100644
--- a/src/libstd/old_io/tempfile.rs
+++ b/src/libstd/old_io/tempfile.rs
@@ -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.
diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs
index f49e2397d42..ee72beccfa8 100644
--- a/src/libstd/old_io/test.rs
+++ b/src/libstd/old_io/test.rs
@@ -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,12 +87,12 @@ 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;
 
-    for &(dir, base) in bases.iter() {
+    for &(dir, base) in &bases {
         if path_s.contains(dir) {
             final_base = base;
             break;
diff --git a/src/libstd/old_io/util.rs b/src/libstd/old_io/util.rs
index 9a55f32c372..f78e3ac1f14 100644
--- a/src/libstd/old_io/util.rs
+++ b/src/libstd/old_io/util.rs
@@ -144,7 +144,7 @@ impl<W> MultiWriter<W> where W: Writer {
 impl<W> Writer for MultiWriter<W> where W: Writer {
     #[inline]
     fn write_all(&mut self, buf: &[u8]) -> old_io::IoResult<()> {
-        for writer in self.writers.iter_mut() {
+        for writer in &mut self.writers {
             try!(writer.write_all(buf));
         }
         Ok(())
@@ -152,7 +152,7 @@ impl<W> Writer for MultiWriter<W> where W: Writer {
 
     #[inline]
     fn flush(&mut self) -> old_io::IoResult<()> {
-        for writer in self.writers.iter_mut() {
+        for writer in &mut self.writers {
             try!(writer.flush());
         }
         Ok(())
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 600ca60349a..d92f361af0b 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -34,29 +34,32 @@ use self::MemoryMapKind::*;
 use self::MapOption::*;
 use self::MapError::*;
 
+use boxed::Box;
 use clone::Clone;
+use env;
 use error::{FromError, Error};
+use ffi::{OsString, OsStr};
 use fmt;
-use old_io::{IoResult, IoError};
 use iter::{Iterator, IteratorExt};
-use marker::{Copy, Send};
 use libc::{c_void, c_int, c_char};
 use libc;
-use boxed::Box;
+use marker::{Copy, Send};
+use old_io::{IoResult, IoError};
 use ops::{Drop, FnOnce};
-use option::Option;
 use option::Option::{Some, None};
+use option::Option;
 use path::{Path, GenericPath, BytesContainer};
-use sys;
-use sys::os as os_imp;
 use ptr::PtrExt;
 use ptr;
-use result::Result;
 use result::Result::{Err, Ok};
+use result::Result;
 use slice::{AsSlice, SliceExt};
 use str::{Str, StrExt};
+use str;
 use string::{String, ToString};
 use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
+use sys::os as os_imp;
+use sys;
 use vec::Vec;
 
 #[cfg(unix)] use ffi::{self, CString};
@@ -97,23 +100,10 @@ pub const TMPBUF_SZ : uint = 1000u;
 /// let current_working_directory = os::getcwd().unwrap();
 /// println!("The current directory is {:?}", current_working_directory.display());
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")]
+#[unstable(feature = "os")]
 pub fn getcwd() -> IoResult<Path> {
-    sys::os::getcwd()
-}
-
-/*
-Accessing environment variables is not generally threadsafe.
-Serialize access through a global lock.
-*/
-fn with_env_lock<T, F>(f: F) -> T where
-    F: FnOnce() -> T,
-{
-    use sync::{StaticMutex, MUTEX_INIT};
-
-    static LOCK: StaticMutex = MUTEX_INIT;
-
-    let _guard = LOCK.lock();
-    f()
+    env::current_dir()
 }
 
 /// Returns a vector of (variable, value) pairs, for all the environment
@@ -132,37 +122,22 @@ fn with_env_lock<T, F>(f: F) -> T where
 ///     println!("'{}': '{}'", key, value );
 /// }
 /// ```
+#[deprecated(since = "1.0.0", reason = "use env::vars instead")]
+#[unstable(feature = "os")]
 pub fn env() -> Vec<(String,String)> {
-    env_as_bytes().into_iter().map(|(k,v)| {
-        let k = String::from_utf8_lossy(k.as_slice()).into_owned();
-        let v = String::from_utf8_lossy(v.as_slice()).into_owned();
-        (k,v)
+    env::vars().map(|(k, v)| {
+        (k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned())
     }).collect()
 }
 
 /// Returns a vector of (variable, value) byte-vector pairs for all the
 /// environment variables of the current process.
-pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
-    unsafe {
-        fn env_convert(input: Vec<Vec<u8>>) -> Vec<(Vec<u8>, Vec<u8>)> {
-            let mut pairs = Vec::new();
-            for p in input.iter() {
-                let mut it = p.splitn(1, |b| *b == b'=');
-                let key = it.next().unwrap().to_vec();
-                let default: &[u8] = &[];
-                let val = it.next().unwrap_or(default).to_vec();
-                pairs.push((key, val));
-            }
-            pairs
-        }
-        with_env_lock(|| {
-            let unparsed_environ = sys::os::get_env_pairs();
-            env_convert(unparsed_environ)
-        })
-    }
+#[deprecated(since = "1.0.0", reason = "use env::vars instead")]
+#[unstable(feature = "os")]
+pub fn env_as_bytes() -> Vec<(Vec<u8>, Vec<u8>)> {
+    env::vars().map(|(k, v)| (byteify(k), byteify(v))).collect()
 }
 
-#[cfg(unix)]
 /// Fetches the environment variable `n` from the current process, returning
 /// None if the variable isn't set.
 ///
@@ -184,52 +159,32 @@ pub fn env_as_bytes() -> Vec<(Vec<u8>,Vec<u8>)> {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
+#[deprecated(since = "1.0.0", reason = "use env::var or env::var_string instead")]
+#[unstable(feature = "os")]
 pub fn getenv(n: &str) -> Option<String> {
-    getenv_as_bytes(n).map(|v| String::from_utf8_lossy(v.as_slice()).into_owned())
+    env::var_string(n).ok()
 }
 
-#[cfg(unix)]
 /// Fetches the environment variable `n` byte vector from the current process,
 /// returning None if the variable isn't set.
 ///
 /// # Panics
 ///
 /// Panics if `n` has any interior NULs.
+#[deprecated(since = "1.0.0", reason = "use env::var instead")]
+#[unstable(feature = "os")]
 pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
-    unsafe {
-        with_env_lock(|| {
-            let s = CString::from_slice(n.as_bytes());
-            let s = libc::getenv(s.as_ptr()) as *const _;
-            if s.is_null() {
-                None
-            } else {
-                Some(ffi::c_str_to_bytes(&s).to_vec())
-            }
-        })
-    }
+    env::var(n).map(byteify)
 }
 
-#[cfg(windows)]
-/// Fetches the environment variable `n` from the current process, returning
-/// None if the variable isn't set.
-pub fn getenv(n: &str) -> Option<String> {
-    unsafe {
-        with_env_lock(|| {
-            use sys::os::fill_utf16_buf_and_decode;
-            let mut n: Vec<u16> = n.utf16_units().collect();
-            n.push(0);
-            fill_utf16_buf_and_decode(|buf, sz| {
-                libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz)
-            })
-        })
-    }
+#[cfg(unix)]
+fn byteify(s: OsString) -> Vec<u8> {
+    use os::unix::*;
+    s.into_vec()
 }
-
 #[cfg(windows)]
-/// Fetches the environment variable `n` byte vector from the current process,
-/// returning None if the variable isn't set.
-pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
-    getenv(n).map(|s| s.into_bytes())
+fn byteify(s: OsString) -> Vec<u8> {
+    s.to_string_lossy().as_bytes().to_vec()
 }
 
 /// Sets the environment variable `n` to the value `v` for the currently running
@@ -247,68 +202,30 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")]
+#[unstable(feature = "os")]
 pub fn setenv<T: BytesContainer>(n: &str, v: T) {
     #[cfg(unix)]
     fn _setenv(n: &str, v: &[u8]) {
-        unsafe {
-            with_env_lock(|| {
-                let k = CString::from_slice(n.as_bytes());
-                let v = CString::from_slice(v);
-                if libc::funcs::posix01::unistd::setenv(k.as_ptr(),
-                                                        v.as_ptr(), 1) != 0 {
-                    panic!(IoError::last_error());
-                }
-            })
-        }
+        use os::unix::*;
+        let v: OsString = OsStringExt::from_vec(v.to_vec());
+        env::set_var(n, &v)
     }
 
     #[cfg(windows)]
     fn _setenv(n: &str, v: &[u8]) {
-        let mut n: Vec<u16> = n.utf16_units().collect();
-        n.push(0);
-        let mut v: Vec<u16> = ::str::from_utf8(v).unwrap().utf16_units().collect();
-        v.push(0);
-
-        unsafe {
-            with_env_lock(|| {
-                if libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr()) == 0 {
-                    panic!(IoError::last_error());
-                }
-            })
-        }
+        let v = str::from_utf8(v).unwrap();
+        env::set_var(n, v)
     }
 
     _setenv(n, v.container_as_bytes())
 }
 
 /// Remove a variable from the environment entirely.
+#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")]
+#[unstable(feature = "os")]
 pub fn unsetenv(n: &str) {
-    #[cfg(unix)]
-    fn _unsetenv(n: &str) {
-        unsafe {
-            with_env_lock(|| {
-                let nbuf = CString::from_slice(n.as_bytes());
-                if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
-                    panic!(IoError::last_error());
-                }
-            })
-        }
-    }
-
-    #[cfg(windows)]
-    fn _unsetenv(n: &str) {
-        let mut n: Vec<u16> = n.utf16_units().collect();
-        n.push(0);
-        unsafe {
-            with_env_lock(|| {
-                if libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null()) == 0 {
-                    panic!(IoError::last_error());
-                }
-            })
-        }
-    }
-
-    _unsetenv(n)
+    env::remove_var(n)
 }
 
 /// Parses input according to platform conventions for the `PATH`
@@ -328,8 +245,12 @@ pub fn unsetenv(n: &str) {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")]
+#[unstable(feature = "os")]
 pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-    sys::os::split_paths(unparsed.container_as_bytes())
+    let b = unparsed.container_as_bytes();
+    let s = str::from_utf8(b).unwrap();
+    env::split_paths(s).collect()
 }
 
 /// Joins a collection of `Path`s appropriately for the `PATH`
@@ -353,8 +274,14 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
 /// paths.push(Path::new("/home/xyz/bin"));
 /// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")]
+#[unstable(feature = "os")]
 pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
-    sys::os::join_paths(paths)
+    env::join_paths(paths.iter().map(|s| {
+        str::from_utf8(s.container_as_bytes()).unwrap()
+    })).map(|s| {
+        s.to_string_lossy().into_owned().into_bytes()
+    }).map_err(|_| "failed to join paths")
 }
 
 /// A low-level OS in-memory pipe.
@@ -388,6 +315,8 @@ pub unsafe fn pipe() -> IoResult<Pipe> {
 /// Returns the proper dll filename for the given basename of a file
 /// as a String.
 #[cfg(not(target_os="ios"))]
+#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")]
+#[unstable(feature = "os")]
 pub fn dll_filename(base: &str) -> String {
     format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX)
 }
@@ -405,8 +334,10 @@ pub fn dll_filename(base: &str) -> String {
 ///     None => println!("Unable to get the path of this executable!")
 /// };
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")]
+#[unstable(feature = "os")]
 pub fn self_exe_name() -> Option<Path> {
-    sys::os::load_self().and_then(Path::new_opt)
+    env::current_exe().ok()
 }
 
 /// Optionally returns the filesystem path to the current executable which is
@@ -424,8 +355,10 @@ pub fn self_exe_name() -> Option<Path> {
 ///     None => println!("Impossible to fetch the path of this executable.")
 /// };
 /// ```
+#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")]
+#[unstable(feature = "os")]
 pub fn self_exe_path() -> Option<Path> {
-    self_exe_name().map(|mut p| { p.pop(); p })
+    env::current_exe().ok().map(|mut p| { p.pop(); p })
 }
 
 /// Optionally returns the path to the current user's home directory if known.
@@ -452,6 +385,9 @@ pub fn self_exe_path() -> Option<Path> {
 ///     None => println!("Impossible to get your home dir!")
 /// }
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")]
+#[allow(deprecated)]
+#[unstable(feature = "os")]
 pub fn homedir() -> Option<Path> {
     #[inline]
     #[cfg(unix)]
@@ -487,6 +423,9 @@ pub fn homedir() -> Option<Path> {
 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
 /// 'USERPROFILE' environment variable  if any are set and not the empty
 /// string. Otherwise, tmpdir returns the path to the Windows directory.
+#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")]
+#[allow(deprecated)]
+#[unstable(feature = "os")]
 pub fn tmpdir() -> Path {
     return lookup();
 
@@ -542,11 +481,13 @@ pub fn tmpdir() -> Path {
 // NB: this is here rather than in path because it is a form of environment
 // querying; what it does depends on the process working directory, not just
 // the input paths.
+#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")]
+#[unstable(feature = "os")]
 pub fn make_absolute(p: &Path) -> IoResult<Path> {
     if p.is_absolute() {
         Ok(p.clone())
     } else {
-        getcwd().map(|mut cwd| {
+        env::current_dir().map(|mut cwd| {
             cwd.push(p);
             cwd
         })
@@ -565,6 +506,8 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
 /// assert!(os::change_dir(&root).is_ok());
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
+#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")]
+#[unstable(feature = "os")]
 pub fn change_dir(p: &Path) -> IoResult<()> {
     return sys::os::chdir(p);
 }
@@ -592,8 +535,6 @@ pub fn last_os_error() -> String {
     error_string(errno() as uint)
 }
 
-static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
-
 /// Sets the process exit code
 ///
 /// Sets the exit code returned by the process if all supervised tasks
@@ -602,14 +543,18 @@ static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
 /// ignored and the process exits with the default panic status.
 ///
 /// Note that this is not synchronized against modifications of other threads.
+#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")]
+#[unstable(feature = "os")]
 pub fn set_exit_status(code: int) {
-    EXIT_STATUS.store(code, Ordering::SeqCst)
+    env::set_exit_status(code as i32)
 }
 
 /// Fetches the process's current exit code. This defaults to 0 and can change
 /// by calling `set_exit_status`.
+#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")]
+#[unstable(feature = "os")]
 pub fn get_exit_status() -> int {
-    EXIT_STATUS.load(Ordering::SeqCst)
+    env::get_exit_status() as isize
 }
 
 #[cfg(target_os = "macos")]
@@ -693,7 +638,8 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
 #[cfg(any(target_os = "linux",
           target_os = "android",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
     use rt;
     rt::args::clone().unwrap_or_else(|| vec![])
@@ -726,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();
 
@@ -777,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()
 }
@@ -790,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()
 }
@@ -970,9 +922,9 @@ 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() {
+        for &o in options {
             match o {
                 MapReadable => { prot |= libc::PROT_READ; },
                 MapWritable => { prot |= libc::PROT_WRITE; },
@@ -1020,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()
     }
 }
 
@@ -1049,9 +1001,9 @@ 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() {
+        for &o in options {
             match o {
                 MapReadable => { readable = true; },
                 MapWritable => { writable = true; },
@@ -1184,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;
 
@@ -1215,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;
 
@@ -1246,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;
 
@@ -1265,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;
 
@@ -1296,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;
 
@@ -1326,7 +1288,40 @@ pub mod consts {
     pub const EXE_EXTENSION: &'static str = "";
 }
 
+#[cfg(target_os = "openbsd")]
+pub mod consts {
+    pub use os::arch_consts::ARCH;
+
+    pub const FAMILY: &'static str = "unix";
+
+    /// A string describing the specific operating system in use: in this
+    /// case, `openbsd`.
+    pub const SYSNAME: &'static str = "openbsd";
+
+    /// 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 = "";
+}
+
 #[cfg(target_os = "android")]
+#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
+#[unstable(feature = "os")]
 pub mod consts {
     pub use os::arch_consts::ARCH;
 
@@ -1358,6 +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;
 
@@ -1522,7 +1519,7 @@ mod tests {
     fn test_env_getenv() {
         let e = env();
         assert!(e.len() > 0u);
-        for p in e.iter() {
+        for p in &e {
             let (n, v) = (*p).clone();
             debug!("{}", n);
             let v2 = getenv(n.as_slice());
@@ -1577,7 +1574,7 @@ mod tests {
         setenv("HOME", "");
         assert!(os::homedir().is_none());
 
-        for s in oldhome.iter() {
+        if let Some(s) = oldhome {
             setenv("HOME", s.as_slice());
         }
     }
@@ -1606,10 +1603,10 @@ mod tests {
         setenv("USERPROFILE", "/home/PaloAlto");
         assert!(os::homedir() == Some(Path::new("/home/MountainView")));
 
-        for s in oldhome.iter() {
+        if let Some(s) = oldhome {
             setenv("HOME", s.as_slice());
         }
-        for s in olduserprofile.iter() {
+        if let Some(s) = olduserprofile {
             setenv("USERPROFILE", s.as_slice());
         }
     }
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index b5409da9c9c..0d80258d7e0 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -68,8 +68,6 @@ use fmt;
 use iter::IteratorExt;
 use option::Option;
 use option::Option::{None, Some};
-#[cfg(stage0)]
-use ops::FullRange;
 use str;
 use str::StrExt;
 use string::{String, CowString};
@@ -625,11 +623,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     fn push_many<T: BytesContainer>(&mut self, paths: &[T]) {
         let t: Option<&T> = None;
         if BytesContainer::is_str(t) {
-            for p in paths.iter() {
+            for p in paths {
                 self.push(p.container_as_str().unwrap())
             }
         } else {
-            for p in paths.iter() {
+            for p in paths {
                 self.push(p.container_as_bytes())
             }
         }
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 6a0c8a93010..69f815e3f8b 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -31,7 +31,7 @@ pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>;
 
 /// Iterator that yields successive components of a Path as Option<&str>
 pub type StrComponents<'a> =
-    Map<&'a [u8], Option<&'a str>, Components<'a>, fn(&[u8]) -> Option<&str>>;
+    Map<Components<'a>, fn(&[u8]) -> Option<&str>>;
 
 /// Represents a POSIX file path
 #[derive(Clone)]
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index b524b89ef9f..fcdebaf2cd3 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -25,8 +25,6 @@ use iter::{AdditiveIterator, Extend};
 use iter::{Iterator, IteratorExt, Map, repeat};
 use mem;
 use option::Option::{self, Some, None};
-#[cfg(stage0)]
-use ops::FullRange;
 use result::Result::{self, Ok, Err};
 use slice::{SliceExt, SliceConcatExt};
 use str::{SplitTerminator, FromStr, StrExt};
@@ -40,11 +38,11 @@ use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
 /// Each component is yielded as Option<&str> for compatibility with PosixPath, but
 /// every component in WindowsPath is guaranteed to be Some.
 pub type StrComponents<'a> =
-    Map<&'a str, Option<&'a str>, SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>;
+    Map<SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>;
 
 /// Iterator that yields successive components of a Path as &[u8]
 pub type Components<'a> =
-    Map<Option<&'a str>, &'a [u8], StrComponents<'a>, fn(Option<&str>) -> &[u8]>;
+    Map<StrComponents<'a>, fn(Option<&str>) -> &[u8]>;
 
 /// Represents a Windows path
 // Notes for Windows path impl:
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index b3c4ffa5120..2398485afef 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -18,10 +18,6 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce};
 
-#[cfg(stage0)]
-#[unstable(feature = "std_misc")]
-#[doc(no_inline)] pub use ops::FullRange;
-
 // Reexported functions
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use mem::drop;
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 211abc2fc83..cc72c5bed99 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -464,7 +464,7 @@ mod test {
         // check every remainder mod 8, both in small and big vectors.
         let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
                        80, 81, 82, 83, 84, 85, 86, 87];
-        for &n in lengths.iter() {
+        for &n in &lengths {
             let mut v = repeat(0u8).take(n).collect::<Vec<_>>();
             r.fill_bytes(v.as_mut_slice());
 
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 992afb2d10f..4b45d5501c2 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -404,7 +404,7 @@ mod test {
         }
 
         // start all the tasks
-        for tx in txs.iter() {
+        for tx in &txs {
             tx.send(()).unwrap();
         }
     }
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
index b63f2e2d73a..b3bed4af962 100644
--- a/src/libstd/rt/args.rs
+++ b/src/libstd/rt/args.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -42,7 +42,8 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
 #[cfg(any(target_os = "linux",
           target_os = "android",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 mod imp {
     use prelude::v1::*;
 
diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs
index 5823f8453d8..3f15cf71ec3 100644
--- a/src/libstd/rt/at_exit_imp.rs
+++ b/src/libstd/rt/at_exit_imp.rs
@@ -58,7 +58,7 @@ pub fn cleanup() {
         // If we never called init, not need to cleanup!
         if queue as uint != 0 {
             let queue: Box<Queue> = mem::transmute(queue);
-            for to_run in queue.into_iter() {
+            for to_run in *queue {
                 to_run.invoke(());
             }
         }
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index f2d66e1a4d7..905cc06c4f0 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -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,
     };
diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs
index dd9923307d6..43e3a43f56d 100644
--- a/src/libstd/rt/libunwind.rs
+++ b/src/libstd/rt/libunwind.rs
@@ -101,7 +101,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
 #[link(name = "gcc_s")]
 extern {}
 
-#[cfg(target_os = "android")]
+#[cfg(any(target_os = "android", target_os = "openbsd"))]
 #[link(name = "gcc")]
 extern {}
 
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 7e19f1cac2c..00088d6d99a 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -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
     }
 }
 
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
index fb40a6c8f60..81ca5aa0e8a 100644
--- a/src/libstd/rt/unwind.rs
+++ b/src/libstd/rt/unwind.rs
@@ -160,7 +160,7 @@ pub fn panicking() -> bool {
 // An uninlined, unmangled function upon which to slap yer breakpoints
 #[inline(never)]
 #[no_mangle]
-#[cfg_attr(not(stage0), allow(private_no_mangle_fns))]
+#[allow(private_no_mangle_fns)]
 fn rust_panic(cause: Box<Any + Send>) -> ! {
     rtdebug!("begin_unwind()");
 
@@ -238,7 +238,7 @@ pub mod eabi {
 
     #[lang="eh_personality"]
     #[no_mangle] // referenced from rust_try.ll
-    #[cfg_attr(not(stage0), allow(private_no_mangle_fns))]
+    #[allow(private_no_mangle_fns)]
     extern fn rust_eh_personality(
         version: c_int,
         actions: uw::_Unwind_Action,
@@ -551,7 +551,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
         let amt = CALLBACK_CNT.load(Ordering::SeqCst);
         &CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)]
     };
-    for cb in callbacks.iter() {
+    for cb in callbacks {
         match cb.load(Ordering::SeqCst) {
             0 => {}
             n => {
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index f5727a38b69..86d21cf7278 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -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 {
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index 06b68162487..1392bc815c4 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -39,7 +39,7 @@ extern {}
 #[link(name = "pthread")]
 extern {}
 
-#[cfg(target_os = "dragonfly")]
+#[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
 #[link(name = "pthread")]
 extern {}
 
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 95b570dd9c8..2dfc708e15b 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -508,7 +508,7 @@ mod tests {
         }
 
         // Wait for children to pass their asserts
-        for r in children.into_iter() {
+        for r in children {
             assert!(r.join().is_ok());
         }
 
diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs
index 9aea0fb3b31..0ca22826700 100644
--- a/src/libstd/sys/common/mutex.rs
+++ b/src/libstd/sys/common/mutex.rs
@@ -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
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 51b6e0a1c1e..833de8adda4 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -554,7 +554,7 @@ pub fn await(fds: &[sock_t], deadline: Option<u64>,
              status: SocketStatus) -> IoResult<()> {
     let mut set: c::fd_set = unsafe { mem::zeroed() };
     let mut max = 0;
-    for &fd in fds.iter() {
+    for &fd in fds {
         c::fd_set(&mut set, fd);
         max = cmp::max(max, fd + 1);
     }
@@ -694,10 +694,16 @@ impl TcpStream {
         setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
                    seconds as libc::c_int)
     }
+    #[cfg(target_os = "openbsd")]
+    fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
+        setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE,
+                   seconds as libc::c_int)
+    }
     #[cfg(not(any(target_os = "macos",
                   target_os = "ios",
                   target_os = "freebsd",
-                  target_os = "dragonfly")))]
+                  target_os = "dragonfly",
+                  target_os = "openbsd")))]
     fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> {
         Ok(())
     }
diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys/common/rwlock.rs
index df016b9e293..fe374e1fd78 100644
--- a/src/libstd/sys/common/rwlock.rs
+++ b/src/libstd/sys/common/rwlock.rs
@@ -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.
     ///
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
index 88bb9395cf1..8dd2f154fa8 100644
--- a/src/libstd/sys/common/stack.rs
+++ b/src/libstd/sys/common/stack.rs
@@ -227,18 +227,13 @@ pub unsafe fn record_sp_limit(limit: uint) {
     }
 
     // aarch64 - FIXME(AARCH64): missing...
-    #[cfg(target_arch = "aarch64")]
-    unsafe fn target_record_sp_limit(_: uint) {
-    }
-
     // powerpc - FIXME(POWERPC): missing...
-    #[cfg(target_arch = "powerpc")]
-    unsafe fn target_record_sp_limit(_: uint) {
-    }
-
-
-    // iOS segmented stack is disabled for now, see related notes
-    #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
+    // arm-ios - iOS segmented stack is disabled for now, see related notes
+    // openbsd - segmented stack is disabled
+    #[cfg(any(target_arch = "aarch64",
+              target_arch = "powerpc",
+              all(target_arch = "arm", target_os = "ios"),
+              target_os = "openbsd"))]
     unsafe fn target_record_sp_limit(_: uint) {
     }
 }
@@ -327,21 +322,17 @@ pub unsafe fn get_sp_limit() -> uint {
     }
 
     // aarch64 - FIXME(AARCH64): missing...
-    #[cfg(target_arch = "aarch64")]
-    unsafe fn target_get_sp_limit() -> uint {
-        1024
-    }
-
-    // powepc - FIXME(POWERPC): missing...
-    #[cfg(target_arch = "powerpc")]
-    unsafe fn target_get_sp_limit() -> uint {
-        1024
-    }
-
-    // iOS doesn't support segmented stacks yet. This function might
-    // be called by runtime though so it is unsafe to mark it as
-    // unreachable, let's return a fixed constant.
-    #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
+    // powerpc - FIXME(POWERPC): missing...
+    // arm-ios - iOS doesn't support segmented stacks yet.
+    // openbsd - OpenBSD doesn't support segmented stacks.
+    //
+    // This function might be called by runtime though
+    // so it is unsafe to unreachable, let's return a fixed constant.
+    #[cfg(any(target_arch = "aarch64",
+              target_arch = "powerpc",
+              all(target_arch = "arm", target_os = "ios"),
+              target_os = "openbsd"))]
+    #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         1024
     }
diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs
index fdcb0c19f30..b30af10986b 100644
--- a/src/libstd/sys/common/wtf8.rs
+++ b/src/libstd/sys/common/wtf8.rs
@@ -366,7 +366,7 @@ impl FromIterator<CodePoint> for Wtf8Buf {
 /// This replaces surrogate code point pairs with supplementary code points,
 /// like concatenating ill-formed UTF-16 strings effectively would.
 impl Extend<CodePoint> for Wtf8Buf {
-    fn extend<T: Iterator<Item=CodePoint>>(&mut self, mut iterator: T) {
+    fn extend<T: Iterator<Item=CodePoint>>(&mut self, iterator: T) {
         let (low, _high) = iterator.size_hint();
         // Lower bound of one byte per code point (ASCII only)
         self.bytes.reserve(low);
@@ -680,17 +680,6 @@ impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
     }
 }
 
-#[cfg(stage0)]
-impl ops::Index<ops::FullRange> for Wtf8 {
-    type Output = Wtf8;
-
-    #[inline]
-    fn index(&self, _range: &ops::FullRange) -> &Wtf8 {
-        self
-    }
-}
-
-#[cfg(not(stage0))]
 impl ops::Index<ops::RangeFull> for Wtf8 {
     type Output = Wtf8;
 
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
index e310b8f6d90..5e512e9261b 100644
--- a/src/libstd/sys/unix/backtrace.rs
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -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;
 
     ////////////////////////////////////////////////////////////////////////
@@ -318,8 +318,9 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
         static mut LAST_FILENAME: [libc::c_char; 256] = [0; 256];
         if !STATE.is_null() { return STATE }
         let selfname = if cfg!(target_os = "freebsd") ||
-                          cfg!(target_os = "dragonfly") {
-            os::self_exe_name()
+                          cfg!(target_os = "dragonfly") ||
+                          cfg!(target_os = "openbsd") {
+            env::current_exe().ok()
         } else {
             None
         };
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index 9016d1a2c99..89bd9a23406 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -23,7 +23,8 @@ use libc;
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 pub const FIONBIO: libc::c_ulong = 0x8004667e;
 #[cfg(any(all(target_os = "linux",
               any(target_arch = "x86",
@@ -41,7 +42,8 @@ pub const FIONBIO: libc::c_ulong = 0x667e;
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 pub const FIOCLEX: libc::c_ulong = 0x20006601;
 #[cfg(any(all(target_os = "linux",
               any(target_arch = "x86",
@@ -59,13 +61,61 @@ pub const FIOCLEX: libc::c_ulong = 0x6601;
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 pub const MSG_DONTWAIT: libc::c_int = 0x80;
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub const MSG_DONTWAIT: libc::c_int = 0x40;
 
 pub const WNOHANG: libc::c_int = 1;
 
+#[cfg(target_os = "linux")]
+pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70;
+#[cfg(any(target_os = "macos",
+          target_os = "freebsd"))]
+pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
+#[cfg(target_os = "android")]
+pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048;
+
+#[repr(C)]
+#[cfg(target_os = "linux")]
+pub struct passwd {
+    pub pw_name: *mut libc::c_char,
+    pub pw_passwd: *mut libc::c_char,
+    pub pw_uid: libc::uid_t,
+    pub pw_gid: libc::gid_t,
+    pub pw_gecos: *mut libc::c_char,
+    pub pw_dir: *mut libc::c_char,
+    pub pw_shell: *mut libc::c_char,
+}
+
+#[repr(C)]
+#[cfg(any(target_os = "macos",
+          target_os = "freebsd"))]
+pub struct passwd {
+    pub pw_name: *mut libc::c_char,
+    pub pw_passwd: *mut libc::c_char,
+    pub pw_uid: libc::uid_t,
+    pub pw_gid: libc::gid_t,
+    pub pw_change: libc::time_t,
+    pub pw_class: *mut libc::c_char,
+    pub pw_gecos: *mut libc::c_char,
+    pub pw_dir: *mut libc::c_char,
+    pub pw_shell: *mut libc::c_char,
+    pub pw_expire: libc::time_t,
+}
+
+#[repr(C)]
+#[cfg(target_os = "android")]
+pub struct passwd {
+    pub pw_name: *mut libc::c_char,
+    pub pw_passwd: *mut libc::c_char,
+    pub pw_uid: libc::uid_t,
+    pub pw_gid: libc::gid_t,
+    pub pw_dir: *mut libc::c_char,
+    pub pw_shell: *mut libc::c_char,
+}
+
 extern {
     pub fn gettimeofday(timeval: *mut libc::timeval,
                         tzp: *mut libc::c_void) -> libc::c_int;
@@ -92,6 +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"))]
@@ -111,6 +167,7 @@ mod select {
 #[cfg(any(target_os = "android",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "openbsd",
           target_os = "linux"))]
 mod select {
     use uint;
@@ -235,7 +292,8 @@ mod signal {
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 mod signal {
     use libc;
 
@@ -248,7 +306,9 @@ mod signal {
     pub const SA_SIGINFO: libc::c_int = 0x0040;
     pub const SIGCHLD: libc::c_int = 20;
 
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
+    #[cfg(any(target_os = "macos",
+              target_os = "ios",
+              target_os = "openbsd"))]
     pub type sigset_t = u32;
     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
     #[repr(C)]
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index f2f2e7436bf..b03b9046966 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -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<()> {
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index dd343baa7c9..b3f37962945 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -11,93 +11,74 @@
 //! 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")]
+    unsafe fn errno_location() -> *const c_int {
+        extern { fn __dfly_error() -> *const c_int; }
+        __dfly_error()
+    }
+
+    #[cfg(target_os = "openbsd")]
     fn errno_location() -> *const c_int {
         extern {
-            fn __dfly_error() -> *const c_int;
+            fn __errno() -> *const c_int;
         }
         unsafe {
-            __dfly_error()
+            __errno()
         }
     }
 
     #[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"))]
-    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];
@@ -113,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 {
@@ -133,43 +105,68 @@ pub fn getcwd() -> IoResult<Path> {
     }
 }
 
-pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-    extern {
-        fn rust_env_pairs() -> *const *const c_char;
-    }
-    let mut environ = rust_env_pairs();
-    if environ as uint == 0 {
-        panic!("os::env() failure getting env string from OS: {}",
-               os::last_os_error());
+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 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);
+}
+
+pub struct SplitPaths<'a> {
+    iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
+                    fn(&'a [u8]) -> Path>,
+}
+
+pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
+    fn is_colon(b: &u8) -> bool { *b == b':' }
+    let unparsed = unparsed.as_byte_slice();
+    SplitPaths {
+        iter: unparsed.split(is_colon as fn(&u8) -> bool)
+                      .map(Path::new as fn(&'a [u8]) ->  Path)
     }
-    result
 }
 
-pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
-    unparsed.split(|b| *b == b':').map(Path::new).collect()
+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() }
 }
 
-pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+#[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))
+}
+
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "path segment contains separator `:`".fmt(f)
+    }
+}
 
-    Ok(joined)
+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::*;
@@ -181,66 +178,305 @@ 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 current_exe() -> IoResult<Path> {
+    fs::readlink(&Path::new("/proc/curproc/file"))
+}
+
+#[cfg(target_os = "openbsd")]
 pub fn load_self() -> Option<Vec<u8>> {
-    use old_io;
+    use sync::{StaticMutex, MUTEX_INIT};
 
-    match old_io::fs::readlink(&Path::new("/proc/curproc/file")) {
-        Ok(path) => Some(path.into_vec()),
-        Err(..) => None
+    static LOCK: StaticMutex = MUTEX_INIT;
+
+    extern {
+        fn rust_load_self() -> *const c_char;
     }
-}
 
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn load_self() -> Option<Vec<u8>> {
-    use old_io;
+    let _guard = LOCK.lock();
 
-    match old_io::fs::readlink(&Path::new("/proc/self/exe")) {
-        Ok(path) => Some(path.into_vec()),
-        Err(..) => None
+    unsafe {
+        let v = rust_load_self();
+        if v.is_null() {
+            None
+        } else {
+            Some(ffi::c_str_to_bytes(&v).to_vec())
+        }
     }
 }
 
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub fn current_exe() -> IoResult<Path> {
+    fs::readlink(&Path::new("/proc/self/exe"))
+}
+
 #[cfg(any(target_os = "macos", target_os = "ios"))]
-pub fn 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 setenv(k: &OsStr, v: &OsStr) {
+    unsafe {
+        let k = CString::from_slice(k.as_byte_slice());
+        let v = CString::from_slice(v.as_byte_slice());
+        if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
+            panic!("failed setenv: {}", IoError::last_error());
+        }
+    }
+}
+
+pub fn unsetenv(n: &OsStr) {
+    unsafe {
+        let nbuf = CString::from_slice(n.as_byte_slice());
+        if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
+            panic!("failed unsetenv: {}", IoError::last_error());
         }
     }
 }
 
-pub fn page_size() -> uint {
+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 uint
+        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> {
+    return getenv("HOME".as_os_str()).or_else(|| unsafe {
+        fallback()
+    }).map(|os| {
+        Path::new(os.into_vec())
+    });
+
+    #[cfg(target_os = "android")]
+    unsafe fn fallback() -> Option<OsString> { None }
+    #[cfg(not(target_os = "android"))]
+    unsafe fn fallback() -> Option<OsString> {
+        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))
+        }
     }
 }
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index b004a47f8a3..7e117b10a34 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -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);
@@ -570,7 +558,7 @@ fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
         Some(env) => {
             let mut tmps = Vec::with_capacity(env.len());
 
-            for pair in env.iter() {
+            for pair in env {
                 let mut kv = Vec::new();
                 kv.push_all(pair.0.container_as_bytes());
                 kv.push('=' as u8);
@@ -604,7 +592,8 @@ fn translate_status(status: c_int) -> ProcessExit {
     #[cfg(any(target_os = "macos",
               target_os = "ios",
               target_os = "freebsd",
-              target_os = "dragonfly"))]
+              target_os = "dragonfly",
+              target_os = "openbsd"))]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
         pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 }
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index a526f3393f2..3512fa36eb3 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -32,7 +32,9 @@ impl Drop for Handler {
     }
 }
 
-#[cfg(any(target_os = "linux", target_os = "macos"))]
+#[cfg(any(target_os = "linux",
+          target_os = "macos",
+          target_os = "openbsd"))]
 mod imp {
     use core::prelude::*;
     use sys_common::stack;
@@ -203,7 +205,7 @@ mod imp {
 
     }
 
-    #[cfg(target_os = "macos")]
+    #[cfg(any(target_os = "macos", target_os = "openbsd"))]
     mod signal {
         use libc;
         use super::sighandler_t;
@@ -212,7 +214,10 @@ mod imp {
         pub const SA_SIGINFO: libc::c_int = 0x0040;
         pub const SIGBUS: libc::c_int = 10;
 
+        #[cfg(target_os = "macos")]
         pub const SIGSTKSZ: libc::size_t = 131072;
+        #[cfg(target_os = "openbsd")]
+        pub const SIGSTKSZ: libc::size_t = 40960;
 
         pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
 
@@ -220,6 +225,7 @@ mod imp {
 
         // This structure has more fields, but we're not all that interested in
         // them.
+        #[cfg(target_os = "macos")]
         #[repr(C)]
         pub struct siginfo {
             pub si_signo: libc::c_int,
@@ -231,6 +237,16 @@ mod imp {
             pub si_addr: *mut libc::c_void
         }
 
+        #[cfg(target_os = "openbsd")]
+        #[repr(C)]
+        pub struct siginfo {
+            pub si_signo: libc::c_int,
+            pub si_code: libc::c_int,
+            pub si_errno: libc::c_int,
+            // union
+            pub si_addr: *mut libc::c_void,
+        }
+
         #[repr(C)]
         pub struct sigaltstack {
             pub ss_sp: *mut libc::c_void,
@@ -260,7 +276,8 @@ mod imp {
 }
 
 #[cfg(not(any(target_os = "linux",
-              target_os = "macos")))]
+              target_os = "macos",
+              target_os = "openbsd")))]
 mod imp {
     use libc;
 
diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs
index c1e3fc88794..bc93513af63 100644
--- a/src/libstd/sys/unix/sync.rs
+++ b/src/libstd/sys/unix/sync.rs
@@ -44,7 +44,9 @@ extern {
     pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
 }
 
-#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+#[cfg(any(target_os = "freebsd",
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 mod os {
     use libc;
 
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 26a450b8599..6f030ee91fe 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -31,7 +31,9 @@ pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
     return start_thread(main);
 }
 
-#[cfg(all(not(target_os = "linux"), not(target_os = "macos")))]
+#[cfg(all(not(target_os = "linux"),
+          not(target_os = "macos"),
+          not(target_os = "openbsd")))]
 pub mod guard {
     pub unsafe fn current() -> uint {
         0
@@ -45,10 +47,15 @@ pub mod guard {
     }
 }
 
-#[cfg(any(target_os = "linux", target_os = "macos"))]
+
+#[cfg(any(target_os = "linux",
+          target_os = "macos",
+          target_os = "openbsd"))]
 pub mod guard {
     use super::*;
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux",
+              target_os = "android",
+              target_os = "openbsd"))]
     use mem;
     #[cfg(any(target_os = "linux", target_os = "android"))]
     use ptr;
@@ -64,7 +71,7 @@ pub mod guard {
     static mut PAGE_SIZE: uint = 0;
     static mut GUARD_PAGE: uint = 0;
 
-    #[cfg(target_os = "macos")]
+    #[cfg(any(target_os = "macos", target_os = "openbsd"))]
     unsafe fn get_stack_start() -> *mut libc::c_void {
         current() as *mut libc::c_void
     }
@@ -141,6 +148,23 @@ pub mod guard {
          pthread_get_stacksize_np(pthread_self())) as uint
     }
 
+    #[cfg(target_os = "openbsd")]
+    pub unsafe fn current() -> uint {
+        let mut current_stack: stack_t = mem::zeroed();
+        if pthread_stackseg_np(pthread_self(), &mut current_stack) != 0 {
+            panic!("failed to get current stack: pthread_stackseg_np")
+        }
+
+        if pthread_main_np() == 1 {
+            // main thread
+            current_stack.ss_sp as uint - current_stack.ss_size as uint + 3 * PAGE_SIZE as uint
+
+        } else {
+            // new thread
+            current_stack.ss_sp as uint - current_stack.ss_size as uint
+        }
+    }
+
     #[cfg(any(target_os = "linux", target_os = "android"))]
     pub unsafe fn current() -> uint {
         let mut attr: libc::pthread_attr_t = mem::zeroed();
@@ -224,7 +248,9 @@ pub unsafe fn set_name(name: &str) {
     }
 }
 
-#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+#[cfg(any(target_os = "freebsd",
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 pub unsafe fn set_name(name: &str) {
     // pthread_set_name_np() since almost forever on all BSDs
     let cname = CString::from_slice(name.as_bytes());
@@ -290,7 +316,9 @@ extern {
                                  stacksize: *mut libc::size_t) -> libc::c_int;
 }
 
-#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+#[cfg(any(target_os = "freebsd",
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 extern {
     pub fn pthread_self() -> libc::pthread_t;
     fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
@@ -304,6 +332,21 @@ extern {
     fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
 }
 
+#[cfg(target_os = "openbsd")]
+extern {
+        pub fn pthread_stackseg_np(thread: libc::pthread_t,
+                                   sinfo: *mut stack_t) -> libc::c_uint;
+        pub fn pthread_main_np() -> libc::c_uint;
+}
+
+#[cfg(target_os = "openbsd")]
+#[repr(C)]
+pub struct stack_t {
+    pub ss_sp: *mut libc::c_void,
+    pub ss_size: libc::size_t,
+    pub ss_flags: libc::c_int,
+}
+
 extern {
     fn pthread_create(native: *mut libc::pthread_t,
                       attr: *const libc::pthread_attr_t,
diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs
index ea1e9c261fe..62d9a33c83d 100644
--- a/src/libstd/sys/unix/thread_local.rs
+++ b/src/libstd/sys/unix/thread_local.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -42,13 +42,15 @@ pub unsafe fn destroy(key: Key) {
 type pthread_key_t = ::libc::c_ulong;
 
 #[cfg(any(target_os = "freebsd",
-          target_os = "dragonfly"))]
+          target_os = "dragonfly",
+          target_os = "openbsd"))]
 type pthread_key_t = ::libc::c_int;
 
 #[cfg(not(any(target_os = "macos",
               target_os = "ios",
               target_os = "freebsd",
-              target_os = "dragonfly")))]
+              target_os = "dragonfly",
+              target_os = "openbsd")))]
 type pthread_key_t = ::libc::c_uint;
 
 extern {
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index cc1e23fbca9..bddf7b075df 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -80,7 +80,8 @@ mod inner {
     }
 
     // Apparently android provides this in some other library?
-    #[cfg(not(target_os = "android"))]
+    // OpenBSD provide it via libc
+    #[cfg(not(any(target_os = "android", target_os = "openbsd")))]
     #[link(name = "rt")]
     extern {}
 
diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs
index d414f70152d..3a79047445c 100644
--- a/src/libstd/sys/unix/tty.rs
+++ b/src/libstd/sys/unix/tty.rs
@@ -21,7 +21,8 @@ pub struct TTY {
 }
 
 #[cfg(any(target_os = "macos",
-          target_os = "freebsd"))]
+          target_os = "freebsd",
+          target_os = "openbsd"))]
 const TIOCGWINSZ: c_ulong = 0x40087468;
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -53,7 +54,8 @@ impl TTY {
     #[cfg(any(target_os = "linux",
               target_os = "android",
               target_os = "macos",
-              target_os = "freebsd"))]
+              target_os = "freebsd",
+              target_os = "openbsd"))]
     pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
         unsafe {
             #[repr(C)]
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
index 1be1a412ffa..66712b9e3a1 100644
--- a/src/libstd/sys/windows/backtrace.rs
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -7,29 +7,31 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-/// As always, windows has something very different than unix, we mainly want
-/// to avoid having to depend too much on libunwind for windows.
-///
-/// If you google around, you'll find a fair bit of references to built-in
-/// functions to get backtraces on windows. It turns out that most of these are
-/// in an external library called dbghelp. I was unable to find this library
-/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
-/// of it.
-///
-/// You'll also find that there's a function called CaptureStackBackTrace
-/// mentioned frequently (which is also easy to use), but sadly I didn't have a
-/// copy of that function in my mingw install (maybe it was broken?). Instead,
-/// this takes the route of using StackWalk64 in order to walk the stack.
+
+//! As always, windows has something very different than unix, we mainly want
+//! to avoid having to depend too much on libunwind for windows.
+//!
+//! If you google around, you'll find a fair bit of references to built-in
+//! functions to get backtraces on windows. It turns out that most of these are
+//! in an external library called dbghelp. I was unable to find this library
+//! via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
+//! of it.
+//!
+//! You'll also find that there's a function called CaptureStackBackTrace
+//! mentioned frequently (which is also easy to use), but sadly I didn't have a
+//! copy of that function in my mingw install (maybe it was broken?). Instead,
+//! this takes the route of using StackWalk64 in order to walk the stack.
+
+#![allow(dead_code)]
 
 use dynamic_lib::DynamicLibrary;
 use ffi;
-use core::ops::Index;
 use intrinsics;
 use old_io::{IoResult, Writer};
 use libc;
 use mem;
 use ops::Drop;
-use option::Option::{Some, None};
+use option::Option::{Some};
 use path::Path;
 use ptr;
 use result::Result::{Ok, Err};
@@ -296,7 +298,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
     // According to windows documentation, all dbghelp functions are
     // single-threaded.
     static LOCK: StaticMutex = MUTEX_INIT;
-    let _g = unsafe { LOCK.lock() };
+    let _g = LOCK.lock();
 
     // Open up dbghelp.dll, we don't link to it explicitly because it can't
     // always be found. Additionally, it's nice having fewer dependencies.
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index da3b7ee2f2f..0355565cf00 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -10,17 +10,21 @@
 
 //! C definitions used by libnative that don't belong in liblibc
 
-#![allow(overflowing_literals)]
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
+#![allow(bad_style, dead_code, overflowing_literals)]
 
 use libc;
-use prelude::v1::*;
 
-pub const WSADESCRIPTION_LEN: uint = 256;
-pub const WSASYS_STATUS_LEN: uint = 128;
+pub use self::GET_FILEEX_INFO_LEVELS::*;
+pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
+pub use libc::consts::os::extra::{
+    FILE_ATTRIBUTE_READONLY,
+    FILE_ATTRIBUTE_DIRECTORY,
+};
+
+pub const WSADESCRIPTION_LEN: usize = 256;
+pub const WSASYS_STATUS_LEN: usize = 128;
 pub const FIONBIO: libc::c_long = 0x8004667e;
-pub const FD_SETSIZE: uint = 64;
+pub const FD_SETSIZE: usize = 64;
 pub const MSG_DONTWAIT: libc::c_int = 0;
 pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582;
 pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4;
@@ -32,12 +36,15 @@ pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40;
 pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT;
 
 pub const FD_ACCEPT: libc::c_long = 0x08;
-pub const FD_MAX_EVENTS: uint = 10;
+pub const FD_MAX_EVENTS: usize = 10;
 pub const WSA_INFINITE: libc::DWORD = libc::INFINITE;
 pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT;
 pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0;
 pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED;
 
+pub const ERROR_NO_MORE_FILES: libc::DWORD = 18;
+pub const TOKEN_READ: libc::DWORD = 0x20008;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -80,7 +87,7 @@ pub struct fd_set {
 }
 
 pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) {
-    set.fd_array[set.fd_count as uint] = s;
+    set.fd_array[set.fd_count as usize] = s;
     set.fd_count += 1;
 }
 
@@ -110,6 +117,69 @@ pub struct CONSOLE_SCREEN_BUFFER_INFO {
 }
 pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
 
+#[repr(C)]
+pub struct WIN32_FILE_ATTRIBUTE_DATA {
+    pub dwFileAttributes: libc::DWORD,
+    pub ftCreationTime: libc::FILETIME,
+    pub ftLastAccessTime: libc::FILETIME,
+    pub ftLastWriteTime: libc::FILETIME,
+    pub nFileSizeHigh: libc::DWORD,
+    pub nFileSizeLow: libc::DWORD,
+}
+
+#[repr(C)]
+pub struct BY_HANDLE_FILE_INFORMATION {
+    pub dwFileAttributes: libc::DWORD,
+    pub ftCreationTime: libc::FILETIME,
+    pub ftLastAccessTime: libc::FILETIME,
+    pub ftLastWriteTime: libc::FILETIME,
+    pub dwVolumeSerialNumber: libc::DWORD,
+    pub nFileSizeHigh: libc::DWORD,
+    pub nFileSizeLow: libc::DWORD,
+    pub nNumberOfLinks: libc::DWORD,
+    pub nFileIndexHigh: libc::DWORD,
+    pub nFileIndexLow: libc::DWORD,
+}
+
+pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
+
+#[repr(C)]
+pub enum GET_FILEEX_INFO_LEVELS {
+    GetFileExInfoStandard,
+    GetFileExMaxInfoLevel
+}
+
+#[repr(C)]
+pub enum FILE_INFO_BY_HANDLE_CLASS {
+    FileBasicInfo                   = 0,
+    FileStandardInfo                = 1,
+    FileNameInfo                    = 2,
+    FileRenameInfo                  = 3,
+    FileDispositionInfo             = 4,
+    FileAllocationInfo              = 5,
+    FileEndOfFileInfo               = 6,
+    FileStreamInfo                  = 7,
+    FileCompressionInfo             = 8,
+    FileAttributeTagInfo            = 9,
+    FileIdBothDirectoryInfo         = 10, // 0xA
+    FileIdBothDirectoryRestartInfo  = 11, // 0xB
+    FileIoPriorityHintInfo          = 12, // 0xC
+    FileRemoteProtocolInfo          = 13, // 0xD
+    FileFullDirectoryInfo           = 14, // 0xE
+    FileFullDirectoryRestartInfo    = 15, // 0xF
+    FileStorageInfo                 = 16, // 0x10
+    FileAlignmentInfo               = 17, // 0x11
+    FileIdInfo                      = 18, // 0x12
+    FileIdExtdDirectoryInfo         = 19, // 0x13
+    FileIdExtdDirectoryRestartInfo  = 20, // 0x14
+    MaximumFileInfoByHandlesClass
+}
+
+#[repr(C)]
+pub struct FILE_END_OF_FILE_INFO {
+    pub EndOfFile: libc::LARGE_INTEGER,
+}
+
 #[link(name = "ws2_32")]
 extern "system" {
     pub fn WSAStartup(wVersionRequested: libc::WORD,
@@ -156,31 +226,29 @@ extern "system" {
 }
 
 pub mod compat {
-    use intrinsics::{atomic_store_relaxed, transmute};
-    use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::v1::*;
+
     use ffi::CString;
+    use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
+    use sync::atomic::{AtomicUsize, Ordering};
 
     extern "system" {
         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
         fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
     }
 
-    // store_func() is idempotent, so using relaxed ordering for the atomics
-    // should be enough.  This way, calling a function in this compatibility
-    // layer (after it's loaded) shouldn't be any slower than a regular DLL
-    // call.
-    unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
+    fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
+                  fallback: usize) -> usize {
         let mut module: Vec<u16> = module.utf16_units().collect();
         module.push(0);
         let symbol = CString::from_slice(symbol.as_bytes());
-        let handle = GetModuleHandleW(module.as_ptr());
-        let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
-        atomic_store_relaxed(ptr, if func == 0 {
-            fallback
-        } else {
-            func
-        })
+        let func = unsafe {
+            let handle = GetModuleHandleW(module.as_ptr());
+            GetProcAddress(handle, symbol.as_ptr()) as usize
+        };
+        let value = if func == 0 {fallback} else {func};
+        ptr.store(value, Ordering::SeqCst);
+        value
     }
 
     /// Macro for creating a compatibility fallback for a Windows function
@@ -192,29 +260,36 @@ pub mod compat {
     /// })
     /// ```
     ///
-    /// Note that arguments unused by the fallback implementation should not be called `_` as
-    /// they are used to be passed to the real function if available.
+    /// Note that arguments unused by the fallback implementation should not be
+    /// called `_` as they are used to be passed to the real function if
+    /// available.
     macro_rules! compat_fn {
         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
                                       -> $rettype:ty { $fallback:expr }) => (
             #[inline(always)]
             pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
-                static mut ptr: extern "system" fn($($argname: $argtype),*) -> $rettype = thunk;
-
-                extern "system" fn thunk($($argname: $argtype),*) -> $rettype {
-                    unsafe {
-                        ::sys::c::compat::store_func(&mut ptr as *mut _ as *mut uint,
-                                                    stringify!($module),
-                                                    stringify!($symbol),
-                                                    fallback as uint);
-                        ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
-                    }
+                use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+                use mem;
+
+                static PTR: AtomicUsize = ATOMIC_USIZE_INIT;
+
+                fn load() -> usize {
+                    ::sys::c::compat::store_func(&PTR,
+                                                 stringify!($module),
+                                                 stringify!($symbol),
+                                                 fallback as usize)
                 }
 
                 extern "system" fn fallback($($argname: $argtype),*)
                                             -> $rettype { $fallback }
 
-                ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
+                let addr = match PTR.load(Ordering::SeqCst) {
+                    0 => load(),
+                    n => n,
+                };
+                let f: extern "system" fn($($argtype),*) -> $rettype =
+                    mem::transmute(addr);
+                f($($argname),*)
             }
         )
     }
@@ -229,10 +304,7 @@ pub mod compat {
         use libc::c_uint;
         use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
         use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
-
-        extern "system" {
-            fn SetLastError(dwErrCode: DWORD);
-        }
+        use sys::c::SetLastError;
 
         compat_fn! {
             kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
@@ -282,4 +354,42 @@ extern "system" {
         hConsoleOutput: libc::HANDLE,
         lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO,
     ) -> libc::BOOL;
+
+    pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR,
+                                fInfoLevelId: GET_FILEEX_INFO_LEVELS,
+                                lpFileInformation: libc::LPVOID) -> libc::BOOL;
+    pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL;
+    pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR,
+                              dwFileAttributes: libc::DWORD) -> libc::BOOL;
+    pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD;
+    pub fn GetFileInformationByHandle(hFile: libc::HANDLE,
+                            lpFileInformation: LPBY_HANDLE_FILE_INFORMATION)
+                            -> libc::BOOL;
+
+    pub fn SetLastError(dwErrCode: libc::DWORD);
+    pub fn GetCommandLineW() -> *mut libc::LPCWSTR;
+    pub fn LocalFree(ptr: *mut libc::c_void);
+    pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR,
+                              pNumArgs: *mut libc::c_int) -> *mut *mut u16;
+    pub fn SetFileTime(hFile: libc::HANDLE,
+                       lpCreationTime: *const libc::FILETIME,
+                       lpLastAccessTime: *const libc::FILETIME,
+                       lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL;
+    pub fn SetFileInformationByHandle(hFile: libc::HANDLE,
+                    FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
+                    lpFileInformation: libc::LPVOID,
+                    dwBufferSize: libc::DWORD) -> libc::BOOL;
+    pub fn GetTempPathW(nBufferLength: libc::DWORD,
+                        lpBuffer: libc::LPCWSTR) -> libc::DWORD;
+    pub fn OpenProcessToken(ProcessHandle: libc::HANDLE,
+                            DesiredAccess: libc::DWORD,
+                            TokenHandle: *mut libc::HANDLE) -> libc::BOOL;
+    pub fn GetCurrentProcess() -> libc::HANDLE;
+}
+
+#[link(name = "userenv")]
+extern "system" {
+    pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
+                                    lpProfileDir: libc::LPCWSTR,
+                                    lpcchSize: *mut libc::DWORD) -> libc::BOOL;
 }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 80cdf9782f2..304d7e01532 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -10,20 +10,15 @@
 
 //! Blocking Windows-based file I/O
 
-use alloc::arc::Arc;
 use libc::{self, c_int};
 
 use mem;
-use sys::os::fill_utf16_buf_and_decode;
-use path;
 use ptr;
-use str;
 use old_io;
 
 use prelude::v1::*;
 use sys;
-use sys::os;
-use sys_common::{keep_going, eof, mkerr_libc};
+use sys_common::{mkerr_libc};
 
 use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use old_io::{IoResult, IoError, FileStat, SeekStyle};
@@ -262,7 +257,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
             let mut more_files = 1 as libc::BOOL;
             while more_files != 0 {
                 {
-                    let filename = os::truncate_utf16_at_nul(&wfd.cFileName);
+                    let filename = super::truncate_utf16_at_nul(&wfd.cFileName);
                     match String::from_utf16(filename) {
                         Ok(filename) => paths.push(Path::new(filename)),
                         Err(..) => {
@@ -368,19 +363,12 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
     }
     // Specify (sz - 1) because the documentation states that it's the size
     // without the null pointer
-    let ret = fill_utf16_buf_and_decode(|buf, sz| unsafe {
+    let ret = super::fill_utf16_buf(|buf, sz| unsafe {
         GetFinalPathNameByHandleW(handle,
                                   buf as *const u16,
                                   sz - 1,
                                   libc::VOLUME_NAME_DOS)
-    });
-    let ret = match ret {
-        Some(ref s) if s.starts_with(r"\\?\") => { // "
-            Ok(Path::new(&s[4..]))
-        }
-        Some(s) => Ok(Path::new(s)),
-        None => Err(super::last_error()),
-    };
+    }, super::os2path);
     assert!(unsafe { libc::CloseHandle(handle) } != 0);
     return ret;
 }
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
new file mode 100644
index 00000000000..6737eeef125
--- /dev/null
+++ b/src/libstd/sys/windows/handle.rs
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use prelude::v1::*;
+
+use libc::{self, HANDLE};
+
+pub struct Handle(HANDLE);
+
+unsafe impl Send for Handle {}
+unsafe impl Sync for Handle {}
+
+impl Handle {
+    pub fn new(handle: HANDLE) -> Handle {
+        Handle(handle)
+    }
+}
+
+impl Drop for Handle {
+    fn drop(&mut self) {
+        unsafe { let _ = libc::CloseHandle(self.0); }
+    }
+}
+
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index e8b65c9b64e..8dd467eba9e 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -11,18 +11,14 @@
 #![allow(missing_docs)]
 #![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
-#![allow(unused_imports)]
-#![allow(dead_code)]
-#![allow(unused_unsafe)]
-#![allow(unused_mut)]
-
-extern crate libc;
 
 use prelude::v1::*;
 
-use num;
+use ffi::OsStr;
+use libc;
 use mem;
 use old_io::{self, IoResult, IoError};
+use os::windows::OsStrExt;
 use sync::{Once, ONCE_INIT};
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
@@ -38,9 +34,10 @@ macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
 
 pub mod backtrace;
 pub mod c;
-pub mod ext;
 pub mod condvar;
+pub mod ext;
 pub mod fs;
+pub mod handle;
 pub mod helper_signal;
 pub mod mutex;
 pub mod os;
@@ -48,12 +45,12 @@ pub mod os_str;
 pub mod pipe;
 pub mod process;
 pub mod rwlock;
-pub mod sync;
 pub mod stack_overflow;
+pub mod sync;
 pub mod tcp;
-pub mod time;
 pub mod thread;
 pub mod thread_local;
+pub mod time;
 pub mod timer;
 pub mod tty;
 pub mod udp;
@@ -158,7 +155,7 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval {
 
 pub fn wouldblock() -> bool {
     let err = os::errno();
-    err == libc::WSAEWOULDBLOCK as uint
+    err == libc::WSAEWOULDBLOCK as i32
 }
 
 pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
@@ -191,17 +188,93 @@ pub fn unimpl() -> IoError {
     }
 }
 
-pub fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
+fn to_utf16(s: Option<&str>) -> IoResult<Vec<u16>> {
     match s {
-        Some(s) => Ok({
-            let mut s = s.utf16_units().collect::<Vec<u16>>();
-            s.push(0);
-            s
-        }),
+        Some(s) => Ok(to_utf16_os(OsStr::from_str(s))),
         None => Err(IoError {
             kind: old_io::InvalidInput,
             desc: "valid unicode input required",
-            detail: None
-        })
+            detail: None,
+        }),
+    }
+}
+
+fn to_utf16_os(s: &OsStr) -> Vec<u16> {
+    let mut v: Vec<_> = s.encode_wide().collect();
+    v.push(0);
+    v
+}
+
+// Many Windows APIs follow a pattern of where we hand the a buffer and then
+// they will report back to us how large the buffer should be or how many bytes
+// currently reside in the buffer. This function is an abstraction over these
+// functions by making them easier to call.
+//
+// The first callback, `f1`, is yielded a (pointer, len) pair which can be
+// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
+// The closure is expected to return what the syscall returns which will be
+// interpreted by this function to determine if the syscall needs to be invoked
+// again (with more buffer space).
+//
+// Once the syscall has completed (errors bail out early) the second closure is
+// yielded the data which has been read from the syscall. The return value
+// from this closure is then the return value of the function.
+fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> IoResult<T>
+    where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD,
+          F2: FnOnce(&[u16]) -> T
+{
+    // Start off with a stack buf but then spill over to the heap if we end up
+    // needing more space.
+    let mut stack_buf = [0u16; 512];
+    let mut heap_buf = Vec::new();
+    unsafe {
+        let mut n = stack_buf.len();
+        loop {
+            let buf = if n <= stack_buf.len() {
+                &mut stack_buf[]
+            } else {
+                let extra = n - heap_buf.len();
+                heap_buf.reserve(extra);
+                heap_buf.set_len(n);
+                &mut heap_buf[]
+            };
+
+            // This function is typically called on windows API functions which
+            // will return the correct length of the string, but these functions
+            // also return the `0` on error. In some cases, however, the
+            // returned "correct length" may actually be 0!
+            //
+            // To handle this case we call `SetLastError` to reset it to 0 and
+            // then check it again if we get the "0 error value". If the "last
+            // error" is still 0 then we interpret it as a 0 length buffer and
+            // not an actual error.
+            c::SetLastError(0);
+            let k = match f1(buf.as_mut_ptr(), n as libc::DWORD) {
+                0 if libc::GetLastError() == 0 => 0,
+                0 => return Err(IoError::last_error()),
+                n => n,
+            } as usize;
+            if k == n && libc::GetLastError() ==
+                            libc::ERROR_INSUFFICIENT_BUFFER as libc::DWORD {
+                n *= 2;
+            } else if k >= n {
+                n = k;
+            } else {
+                return Ok(f2(&buf[..k]))
+            }
+        }
+    }
+}
+
+fn os2path(s: &[u16]) -> Path {
+    // FIXME: this should not be a panicking conversion (aka path reform)
+    Path::new(String::from_utf16(s).unwrap())
+}
+
+pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
+    match v.iter().position(|c| *c == 0) {
+        // don't include the 0
+        Some(i) => &v[..i],
+        None => v
     }
 }
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 828ad795ed3..75495efc7cb 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -38,8 +38,6 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
 
 impl Mutex {
     #[inline]
-    pub unsafe fn new() -> Mutex { MUTEX_INIT }
-    #[inline]
     pub unsafe fn lock(&self) {
         ffi::AcquireSRWLockExclusive(self.inner.get())
     }
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index a82259ad5ec..c71e2d057c3 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -10,48 +10,32 @@
 
 //! Implementation of `std::os` functionality for Windows
 
-// FIXME: move various extern bindings from here into liblibc or
-// something similar
+#![allow(bad_style)]
 
 use prelude::v1::*;
+use os::windows::*;
 
+use error::Error as StdError;
+use ffi::{OsString, OsStr, AsOsStr};
 use fmt;
-use old_io::{IoResult, IoError};
-use iter::repeat;
-use libc::{c_int, c_void};
-use libc;
-use os;
-use path::BytesContainer;
+use iter::Range;
+use libc::types::os::arch::extra::LPWCH;
+use libc::{self, c_int, c_void};
+use mem;
+use old_io::{IoError, IoResult};
 use ptr;
 use slice;
+use sys::c;
 use sys::fs::FileDesc;
+use sys::handle::Handle as RawHandle;
 
-use os::TMPBUF_SZ;
-use libc::types::os::arch::extra::DWORD;
+use libc::funcs::extra::kernel32::{
+    GetEnvironmentStringsW,
+    FreeEnvironmentStringsW
+};
 
-const BUF_BYTES : uint = 2048u;
-
-/// Return a slice of `v` ending at (and not including) the first NUL
-/// (0).
-pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
-    match v.iter().position(|c| *c == 0) {
-        // don't include the 0
-        Some(i) => &v[..i],
-        None => v
-    }
-}
-
-pub fn errno() -> uint {
-    use libc::types::os::arch::extra::DWORD;
-
-    #[link_name = "kernel32"]
-    extern "system" {
-        fn GetLastError() -> DWORD;
-    }
-
-    unsafe {
-        GetLastError() as uint
-    }
+pub fn errno() -> i32 {
+    unsafe { libc::GetLastError() as i32 }
 }
 
 /// Get a detailed string description for the given error number
@@ -80,7 +64,7 @@ pub fn error_string(errnum: i32) -> String {
     // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
     let langId = 0x0800 as DWORD;
 
-    let mut buf = [0 as WCHAR; TMPBUF_SZ];
+    let mut buf = [0 as WCHAR; 2048];
 
     unsafe {
         let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
@@ -94,200 +78,170 @@ pub fn error_string(errnum: i32) -> String {
         if res == 0 {
             // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
             let fm_err = errno();
-            return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err);
+            return format!("OS Error {} (FormatMessageW() returned error {})",
+                           errnum, fm_err);
         }
 
-        let msg = String::from_utf16(truncate_utf16_at_nul(&buf));
+        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
+        let msg = String::from_utf16(&buf[..b]);
         match msg {
-            Ok(msg) => format!("OS Error {}: {}", errnum, msg),
+            Ok(msg) => msg,
             Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                 invalid UTF-16)", errnum),
         }
     }
 }
 
-pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
-    // Windows pipes work subtly differently than unix pipes, and their
-    // inheritance has to be handled in a different way that I do not
-    // fully understand. Here we explicitly make the pipe non-inheritable,
-    // which means to pass it to a subprocess they need to be duplicated
-    // first, as in std::run.
-    let mut fds = [0; 2];
-    match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
-                     (libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
-        0 => {
-            assert!(fds[0] != -1 && fds[0] != 0);
-            assert!(fds[1] != -1 && fds[1] != 0);
-            Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
-        }
-        _ => Err(IoError::last_error()),
-    }
+pub struct Env {
+    base: LPWCH,
+    cur: LPWCH,
 }
 
-pub fn fill_utf16_buf_and_decode<F>(mut f: F) -> Option<String> where
-    F: FnMut(*mut u16, DWORD) -> DWORD,
-{
-    unsafe {
-        let mut n = TMPBUF_SZ as DWORD;
-        let mut res = None;
-        let mut done = false;
-        while !done {
-            let mut buf: Vec<u16> = repeat(0u16).take(n as uint).collect();
-            let k = f(buf.as_mut_ptr(), n);
-            if k == (0 as DWORD) {
-                done = true;
-            } else if k == n &&
-                      libc::GetLastError() ==
-                      libc::ERROR_INSUFFICIENT_BUFFER as DWORD {
-                n *= 2 as DWORD;
-            } else if k >= n {
-                n = k;
-            } else {
-                done = true;
-            }
-            if k != 0 && done {
-                let sub = &buf[.. (k as uint)];
-                // We want to explicitly catch the case when the
-                // closure returned invalid UTF-16, rather than
-                // set `res` to None and continue.
-                let s = String::from_utf16(sub).ok()
-                    .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16");
-                res = Some(s)
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        unsafe {
+            if *self.cur == 0 { return None }
+            let p = &*self.cur;
+            let mut len = 0;
+            while *(p as *const _).offset(len) != 0 {
+                len += 1;
             }
+            let p = p as *const u16;
+            let s = slice::from_raw_buf(&p, len as usize);
+            self.cur = self.cur.offset(len + 1);
+
+            let (k, v) = match s.iter().position(|&b| b == '=' as u16) {
+                Some(n) => (&s[..n], &s[n+1..]),
+                None => (s, &[][]),
+            };
+            Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v)))
         }
-        return res;
     }
 }
 
-pub fn getcwd() -> IoResult<Path> {
-    use libc::DWORD;
-    use libc::GetCurrentDirectoryW;
-    use old_io::OtherIoError;
+impl Drop for Env {
+    fn drop(&mut self) {
+        unsafe { FreeEnvironmentStringsW(self.base); }
+    }
+}
 
-    let mut buf = [0 as u16; BUF_BYTES];
+pub fn env() -> Env {
     unsafe {
-        if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
-            return Err(IoError::last_error());
+        let ch = GetEnvironmentStringsW();
+        if ch as usize == 0 {
+            panic!("failure getting env string from OS: {}",
+                   IoError::last_error());
         }
+        Env { base: ch, cur: ch }
     }
+}
 
-    match String::from_utf16(truncate_utf16_at_nul(&buf)) {
-        Ok(ref cwd) => Ok(Path::new(cwd)),
-        Err(..) => Err(IoError {
-            kind: OtherIoError,
-            desc: "GetCurrentDirectoryW returned invalid UTF-16",
-            detail: None,
-        }),
-    }
+pub struct SplitPaths<'a> {
+    data: EncodeWide<'a>,
+    must_yield: bool,
 }
 
-pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
-    use libc::funcs::extra::kernel32::{
-        GetEnvironmentStringsW,
-        FreeEnvironmentStringsW
-    };
-    let ch = GetEnvironmentStringsW();
-    if ch as uint == 0 {
-        panic!("os::env() failure getting env string from OS: {}",
-               os::last_os_error());
+pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
+    SplitPaths {
+        data: unparsed.encode_wide(),
+        must_yield: true,
     }
-    // Here, we lossily decode the string as UTF16.
-    //
-    // The docs suggest that the result should be in Unicode, but
-    // Windows doesn't guarantee it's actually UTF16 -- it doesn't
-    // validate the environment string passed to CreateProcess nor
-    // SetEnvironmentVariable.  Yet, it's unlikely that returning a
-    // raw u16 buffer would be of practical use since the result would
-    // be inherently platform-dependent and introduce additional
-    // complexity to this code.
-    //
-    // Using the non-Unicode version of GetEnvironmentStrings is even
-    // worse since the result is in an OEM code page.  Characters that
-    // can't be encoded in the code page would be turned into question
-    // marks.
-    let mut result = Vec::new();
-    let mut i = 0;
-    while *ch.offset(i) != 0 {
-        let p = &*ch.offset(i);
-        let mut len = 0;
-        while *(p as *const _).offset(len) != 0 {
-            len += 1;
-        }
-        let p = p as *const u16;
-        let s = slice::from_raw_buf(&p, len as uint);
-        result.push(String::from_utf16_lossy(s).into_bytes());
-        i += len as int + 1;
-    }
-    FreeEnvironmentStringsW(ch);
-    result
 }
 
-pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
-    // On Windows, the PATH environment variable is semicolon separated.  Double
-    // quotes are used as a way of introducing literal semicolons (since
-    // c:\some;dir is a valid Windows path). Double quotes are not themselves
-    // permitted in path names, so there is no way to escape a double quote.
-    // Quoted regions can appear in arbitrary locations, so
-    //
-    //   c:\foo;c:\som"e;di"r;c:\bar
-    //
-    // Should parse as [c:\foo, c:\some;dir, c:\bar].
-    //
-    // (The above is based on testing; there is no clear reference available
-    // for the grammar.)
-
-    let mut parsed = Vec::new();
-    let mut in_progress = Vec::new();
-    let mut in_quote = false;
-
-    for b in unparsed.iter() {
-        match *b {
-            b';' if !in_quote => {
-                parsed.push(Path::new(in_progress.as_slice()));
-                in_progress.truncate(0)
-            }
-            b'"' => {
+impl<'a> Iterator for SplitPaths<'a> {
+    type Item = Path;
+    fn next(&mut self) -> Option<Path> {
+        // On Windows, the PATH environment variable is semicolon separated.
+        // Double quotes are used as a way of introducing literal semicolons
+        // (since c:\some;dir is a valid Windows path). Double quotes are not
+        // themselves permitted in path names, so there is no way to escape a
+        // double quote.  Quoted regions can appear in arbitrary locations, so
+        //
+        //   c:\foo;c:\som"e;di"r;c:\bar
+        //
+        // Should parse as [c:\foo, c:\some;dir, c:\bar].
+        //
+        // (The above is based on testing; there is no clear reference available
+        // for the grammar.)
+
+
+        let must_yield = self.must_yield;
+        self.must_yield = false;
+
+        let mut in_progress = Vec::new();
+        let mut in_quote = false;
+        for b in self.data.by_ref() {
+            if b == '"' as u16 {
                 in_quote = !in_quote;
+            } else if b == ';' as u16 && !in_quote {
+                self.must_yield = true;
+                break
+            } else {
+                in_progress.push(b)
             }
-            _  => {
-                in_progress.push(*b);
-            }
+        }
+
+        if !must_yield && in_progress.is_empty() {
+            None
+        } else {
+            Some(super::os2path(&in_progress[]))
         }
     }
-    parsed.push(Path::new(in_progress));
-    parsed
 }
 
-pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+#[derive(Show)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
+    where I: Iterator<Item=T>, T: AsOsStr
+{
     let mut joined = Vec::new();
-    let sep = b';';
+    let sep = b';' as u16;
 
-    for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+    for (i, path) in paths.enumerate() {
+        let path = path.as_os_str();
         if i > 0 { joined.push(sep) }
-        if path.contains(&b'"') {
-            return Err("path segment contains `\"`");
-        } else if path.contains(&sep) {
-            joined.push(b'"');
-            joined.push_all(path);
-            joined.push(b'"');
+        let v = path.encode_wide().collect::<Vec<u16>>();
+        if v.contains(&(b'"' as u16)) {
+            return Err(JoinPathsError)
+        } else if v.contains(&sep) {
+            joined.push(b'"' as u16);
+            joined.push_all(&v[]);
+            joined.push(b'"' as u16);
         } else {
-            joined.push_all(path);
+            joined.push_all(&v[]);
         }
     }
 
-    Ok(joined)
+    Ok(OsStringExt::from_wide(&joined[]))
 }
 
-pub fn load_self() -> Option<Vec<u8>> {
-    unsafe {
-        fill_utf16_buf_and_decode(|buf, sz| {
-            libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
-        }).map(|s| s.to_string().into_bytes())
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "path segment contains `\"`".fmt(f)
     }
 }
 
+impl StdError for JoinPathsError {
+    fn description(&self) -> &str { "failed to join paths" }
+}
+
+pub fn current_exe() -> IoResult<Path> {
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
+    }, super::os2path)
+}
+
+pub fn getcwd() -> IoResult<Path> {
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        libc::GetCurrentDirectoryW(sz, buf)
+    }, super::os2path)
+}
+
 pub fn chdir(p: &Path) -> IoResult<()> {
-    let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>();
+    let mut p = p.as_os_str().encode_wide().collect::<Vec<_>>();
     p.push(0);
 
     unsafe {
@@ -298,39 +252,124 @@ pub fn chdir(p: &Path) -> IoResult<()> {
     }
 }
 
-pub fn page_size() -> uint {
-    use mem;
+pub fn getenv(k: &OsStr) -> Option<OsString> {
+    let k = super::to_utf16_os(k);
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
+    }, |buf| {
+        OsStringExt::from_wide(buf)
+    }).ok()
+}
+
+pub fn setenv(k: &OsStr, v: &OsStr) {
+    let k = super::to_utf16_os(k);
+    let v = super::to_utf16_os(v);
+
     unsafe {
-        let mut info = mem::zeroed();
-        libc::GetSystemInfo(&mut info);
+        if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 {
+            panic!("failed to set env: {}", IoError::last_error());
+        }
+    }
+}
 
-        return info.dwPageSize as uint;
+pub fn unsetenv(n: &OsStr) {
+    let v = super::to_utf16_os(n);
+    unsafe {
+        if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 {
+            panic!("failed to unset env: {}", IoError::last_error());
+        }
     }
 }
 
-#[cfg(test)]
-mod tests {
-    use super::truncate_utf16_at_nul;
+pub struct Args {
+    range: Range<isize>,
+    cur: *mut *mut u16,
+}
 
-    #[test]
-    fn test_truncate_utf16_at_nul() {
-        let v = [];
-        let b: &[u16] = &[];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> {
+        self.range.next().map(|i| unsafe {
+            let ptr = *self.cur.offset(i);
+            let mut len = 0;
+            while *ptr.offset(len) != 0 { len += 1; }
+
+            // Push it onto the list.
+            let ptr = ptr as *const u16;
+            let buf = slice::from_raw_buf(&ptr, len as usize);
+            OsStringExt::from_wide(buf)
+        })
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+}
 
-        let v = [0, 2, 3];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+impl Drop for Args {
+    fn drop(&mut self) {
+        unsafe { c::LocalFree(self.cur as *mut c_void); }
+    }
+}
 
-        let v = [1, 0, 3];
-        let b: &[u16] = &[1];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+pub fn args() -> Args {
+    unsafe {
+        let mut nArgs: c_int = 0;
+        let lpCmdLine = c::GetCommandLineW();
+        let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
 
-        let v = [1, 2, 0];
-        let b: &[u16] = &[1, 2];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+        Args { cur: szArgList, range: range(0, nArgs as isize) }
+    }
+}
 
-        let v = [1, 2, 3];
-        let b: &[u16] = &[1, 2, 3];
-        assert_eq!(truncate_utf16_at_nul(&v), b);
+pub fn page_size() -> usize {
+    unsafe {
+        let mut info = mem::zeroed();
+        libc::GetSystemInfo(&mut info);
+        return info.dwPageSize as usize;
+    }
+}
+
+pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
+    // Windows pipes work subtly differently than unix pipes, and their
+    // inheritance has to be handled in a different way that I do not
+    // fully understand. Here we explicitly make the pipe non-inheritable,
+    // which means to pass it to a subprocess they need to be duplicated
+    // first, as in std::run.
+    let mut fds = [0; 2];
+    match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
+    (libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
+        0 => {
+            assert!(fds[0] != -1 && fds[0] != 0);
+            assert!(fds[1] != -1 && fds[1] != 0);
+            Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
+        }
+        _ => Err(IoError::last_error()),
     }
 }
+
+pub fn temp_dir() -> Path {
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        c::GetTempPathW(sz, buf)
+    }, super::os2path).unwrap()
+}
+
+pub fn home_dir() -> Option<Path> {
+    getenv("HOME".as_os_str()).or_else(|| {
+        getenv("USERPROFILE".as_os_str())
+    }).map(|os| {
+        // FIXME: OsString => Path
+        Path::new(os.to_str().unwrap())
+    }).or_else(|| unsafe {
+        let me = c::GetCurrentProcess();
+        let mut token = ptr::null_mut();
+        if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
+            return None
+        }
+        let _handle = RawHandle::new(token);
+        super::fill_utf16_buf(|buf, mut sz| {
+            match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
+                0 if libc::GetLastError() != 0 => 0,
+                0 => sz,
+                n => n as libc::DWORD,
+            }
+        }, super::os2path).ok()
+    })
+}
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 0bc2a827272..1f228b7d32e 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -352,7 +352,7 @@ impl UnixStream {
 
     fn cancel_io(&self) -> IoResult<()> {
         match unsafe { c::CancelIoEx(self.handle(), ptr::null_mut()) } {
-            0 if os::errno() == libc::ERROR_NOT_FOUND as uint => {
+            0 if os::errno() == libc::ERROR_NOT_FOUND as i32 => {
                 Ok(())
             }
             0 => Err(super::last_error()),
@@ -374,7 +374,7 @@ impl UnixStream {
         // acquire the lock.
         //
         // See comments in close_read() about why this lock is necessary.
-        let guard = unsafe { self.inner.lock.lock() };
+        let guard = self.inner.lock.lock();
         if self.read_closed() {
             return Err(eof())
         }
@@ -392,7 +392,7 @@ impl UnixStream {
 
         // If our errno doesn't say that the I/O is pending, then we hit some
         // legitimate error and return immediately.
-        if os::errno() != libc::ERROR_IO_PENDING as uint {
+        if os::errno() != libc::ERROR_IO_PENDING as i32 {
             return Err(super::last_error())
         }
 
@@ -417,7 +417,7 @@ impl UnixStream {
             // If we succeeded, or we failed for some reason other than
             // CancelIoEx, return immediately
             if ret != 0 { return Ok(bytes_read as uint) }
-            if os::errno() != libc::ERROR_OPERATION_ABORTED as uint {
+            if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 {
                 return Err(super::last_error())
             }
 
@@ -450,7 +450,7 @@ impl UnixStream {
             // going after we woke up.
             //
             // See comments in close_read() about why this lock is necessary.
-            let guard = unsafe { self.inner.lock.lock() };
+            let guard = self.inner.lock.lock();
             if self.write_closed() {
                 return Err(epipe())
             }
@@ -465,7 +465,7 @@ impl UnixStream {
             drop(guard);
 
             if ret == 0 {
-                if err != libc::ERROR_IO_PENDING as uint {
+                if err != libc::ERROR_IO_PENDING as i32 {
                     return Err(decode_error_detailed(err as i32))
                 }
                 // Process a timeout if one is pending
@@ -481,7 +481,7 @@ impl UnixStream {
                 // aborted, then check to see if the write half was actually
                 // closed or whether we woke up from the read half closing.
                 if ret == 0 {
-                    if os::errno() != libc::ERROR_OPERATION_ABORTED as uint {
+                    if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 {
                         return Err(super::last_error())
                     }
                     if !wait_succeeded.is_ok() {
@@ -525,14 +525,14 @@ impl UnixStream {
         // close_read() between steps 1 and 2. By atomically executing steps 1
         // and 2 with a lock with respect to close_read(), we're guaranteed that
         // no thread will erroneously sit in a read forever.
-        let _guard = unsafe { self.inner.lock.lock() };
+        let _guard = self.inner.lock.lock();
         self.inner.read_closed.store(true, Ordering::SeqCst);
         self.cancel_io()
     }
 
     pub fn close_write(&mut self) -> IoResult<()> {
         // see comments in close_read() for why this lock is necessary
-        let _guard = unsafe { self.inner.lock.lock() };
+        let _guard = self.inner.lock.lock();
         self.inner.write_closed.store(true, Ordering::SeqCst);
         self.cancel_io()
     }
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 3d66718d00b..3ca735f7fdf 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -10,28 +10,27 @@
 
 use prelude::v1::*;
 
+use collections::hash_map::Hasher;
 use collections;
+use env;
 use ffi::CString;
 use hash::Hash;
-use collections::hash_map::Hasher;
+use libc::{pid_t, c_void};
+use libc;
+use mem;
 use old_io::fs::PathExtensions;
-use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
+use old_io::process::{ProcessExit, ExitStatus};
 use old_io::{IoResult, IoError};
 use old_io;
-use libc::{pid_t, c_void, c_int};
-use libc;
-use mem;
 use os;
 use path::BytesContainer;
 use ptr;
 use str;
-use sys::fs::FileDesc;
 use sync::{StaticMutex, MUTEX_INIT};
+use sys::fs::FileDesc;
 
-use sys::fs;
-use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
-use sys_common::helper_thread::Helper;
-use sys_common::{AsInner, mkerr_libc, timeout};
+use sys::timer;
+use sys_common::{AsInner, timeout};
 
 pub use sys_common::ProcessConfig;
 
@@ -106,6 +105,7 @@ impl Process {
         return ret;
     }
 
+    #[allow(deprecated)]
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
@@ -128,7 +128,7 @@ impl Process {
         use libc::funcs::extra::msvcrt::get_osfhandle;
 
         use mem;
-        use iter::{Iterator, IteratorExt};
+        use iter::IteratorExt;
         use str::StrExt;
 
         if cfg.gid().is_some() || cfg.uid().is_some() {
@@ -142,14 +142,14 @@ impl Process {
         // To have the spawning semantics of unix/windows stay the same, we need to
         // read the *child's* PATH if one is provided. See #15149 for more details.
         let program = cfg.env().and_then(|env| {
-            for (key, v) in env.iter() {
+            for (key, v) in env {
                 if b"PATH" != key.container_as_bytes() { continue }
 
                 // Split the value and test each path to see if the
                 // program exists.
-                for path in os::split_paths(v.container_as_bytes()).into_iter() {
+                for path in os::split_paths(v.container_as_bytes()) {
                     let path = path.join(cfg.program().as_bytes())
-                                   .with_extension(os::consts::EXE_EXTENSION);
+                                   .with_extension(env::consts::EXE_EXTENSION);
                     if path.exists() {
                         return Some(CString::from_slice(path.as_vec()))
                     }
@@ -372,7 +372,7 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
     let mut cmd = String::new();
     append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok()
                              .expect("expected program name to be utf-8 encoded"));
-    for arg in args.iter() {
+    for arg in args {
         cmd.push(' ');
         append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok()
                                 .expect("expected argument to be utf-8 encoded"));
@@ -437,7 +437,7 @@ fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
         Some(env) => {
             let mut blk = Vec::new();
 
-            for pair in env.iter() {
+            for pair in env {
                 let kv = format!("{}={}",
                                  pair.0.container_as_str().unwrap(),
                                  pair.1.container_as_str().unwrap());
diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs
index 88ce85c39f6..76fe352ed77 100644
--- a/src/libstd/sys/windows/rwlock.rs
+++ b/src/libstd/sys/windows/rwlock.rs
@@ -19,9 +19,6 @@ pub const RWLOCK_INIT: RWLock = RWLock {
 
 impl RWLock {
     #[inline]
-    pub unsafe fn new() -> RWLock { RWLOCK_INIT }
-
-    #[inline]
     pub unsafe fn read(&self) {
         ffi::AcquireSRWLockShared(self.inner.get())
     }
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
index 0cb4c573ae3..b0410701ee1 100644
--- a/src/libstd/sys/windows/stack_overflow.rs
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -14,7 +14,7 @@ use ptr;
 use mem;
 use libc;
 use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
-use sys_common::{stack, thread_info};
+use sys_common::stack;
 
 pub struct Handler {
     _data: *mut libc::c_void
@@ -30,14 +30,6 @@ impl Drop for Handler {
     fn drop(&mut self) {}
 }
 
-// get_task_info is called from an exception / signal handler.
-// It returns the guard page of the current task or 0 if that
-// guard page doesn't exist. None is returned if there's currently
-// no local task.
-unsafe fn get_task_guard_page() -> uint {
-    thread_info::stack_guard()
-}
-
 // This is initialized in init() and only read from after
 static mut PAGE_SIZE: uint = 0;
 
diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs
index d60646b7db9..7614104c98b 100644
--- a/src/libstd/sys/windows/sync.rs
+++ b/src/libstd/sys/windows/sync.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc::{BOOL, DWORD, c_void, LPVOID, c_ulong};
+use libc::{BOOL, DWORD, LPVOID, c_ulong};
 use libc::types::os::arch::extra::BOOLEAN;
 
 pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs
index 64e440331c1..4804ca510cb 100644
--- a/src/libstd/sys/windows/tcp.rs
+++ b/src/libstd/sys/windows/tcp.rs
@@ -14,12 +14,11 @@ use libc;
 use mem;
 use ptr;
 use prelude::v1::*;
-use super::{last_error, last_net_error, retry, sock_t};
+use super::{last_error, last_net_error, sock_t};
 use sync::Arc;
 use sync::atomic::{AtomicBool, Ordering};
-use sys::fs::FileDesc;
 use sys::{self, c, set_nonblocking, wouldblock, timer};
-use sys_common::{self, timeout, eof, net};
+use sys_common::{timeout, eof, net};
 
 pub use sys_common::net::TcpStream;
 
@@ -202,10 +201,6 @@ impl TcpAcceptor {
         Err(eof())
     }
 
-    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        net::sockname(self.socket(), libc::getsockname)
-    }
-
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
         self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
     }
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index a94adcb3bc7..a38dc9b2d34 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::prelude::*;
-
 use boxed::Box;
 use cmp;
 use mem;
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index 0f8ceed39a6..54a32e43daf 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -233,6 +233,7 @@ unsafe extern "system" fn on_tls_callback(h: LPVOID,
     }
 }
 
+#[allow(dead_code)] // actually called above
 unsafe fn run_dtors() {
     let mut any_run = true;
     for _ in 0..5 {
@@ -248,7 +249,7 @@ unsafe fn run_dtors() {
             DTOR_LOCK.unlock();
             ret
         };
-        for &(key, dtor) in dtors.iter() {
+        for &(key, dtor) in &dtors {
             let ptr = TlsGetValue(key);
             if !ptr.is_null() {
                 TlsSetValue(key, ptr::null_mut());
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 34f3c418c55..d156dd801f9 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -28,8 +28,6 @@ use ptr;
 
 use old_io::IoResult;
 use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
-use sys::c;
-use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
 
 helper_init! { static HELPER: Helper<Req> }
diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs
index 6ecabfa9853..f02c8e49f41 100644
--- a/src/libstd/sys/windows/tty.rs
+++ b/src/libstd/sys/windows/tty.rs
@@ -38,7 +38,7 @@ use str::from_utf8;
 use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
 use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
 use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
-use super::c::{ERROR_ILLEGAL_CHARACTER, CONSOLE_SCREEN_BUFFER_INFO};
+use super::c::{CONSOLE_SCREEN_BUFFER_INFO};
 use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
 use super::c::{GetConsoleScreenBufferInfo};
 
@@ -155,9 +155,6 @@ impl TTY {
                      (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)),
         }
     }
-
-    // Let us magically declare this as a TTY
-    pub fn isatty(&self) -> bool { true }
 }
 
 impl Drop for TTY {
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
index 2a9bf452329..d4d777789dd 100644
--- a/src/libstd/thread_local/mod.rs
+++ b/src/libstd/thread_local/mod.rs
@@ -425,7 +425,7 @@ mod imp {
         unsafe extern fn run_dtors(mut ptr: *mut u8) {
             while !ptr.is_null() {
                 let list: Box<List> = mem::transmute(ptr);
-                for &(ptr, dtor) in list.iter() {
+                for &(ptr, dtor) in &*list {
                     dtor(ptr);
                 }
                 ptr = DTORS.get();