about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAaron Turon <aturon@mozilla.com>2014-09-30 17:03:56 -0700
committerAaron Turon <aturon@mozilla.com>2014-11-08 20:40:38 -0800
commit3a527f2b3311d5b1c6dd7c72db71c45596e6db49 (patch)
tree1a550dd4b679b0ccf13acef6cc7879e486a3d3de /src/libstd
parent93c85eb8bdcc910a27caf6abd20207a626ae98e5 (diff)
downloadrust-3a527f2b3311d5b1c6dd7c72db71c45596e6db49.tar.gz
rust-3a527f2b3311d5b1c6dd7c72db71c45596e6db49.zip
Runtime removal: add private sys, sys_common modules
These modules will house the code that used to be part of the runtime system
in libnative. The `sys_common` module contains a few low-level but
cross-platform details. The `sys` module is set up using `#[cfg()]` to
include either a unix or windows implementation of a common API
surface. This API surface is *not* exported directly in `libstd`, but is
instead used to bulid `std::os` and `std::io`.

Ultimately, the low-level details in `sys` will be exposed in a
controlled way through a separate platform-specific surface, but that
setup is not part of this patch.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/mod.rs92
-rw-r--r--src/libstd/lib.rs7
-rw-r--r--src/libstd/os.rs155
-rw-r--r--src/libstd/sys/common/mod.rs91
-rw-r--r--src/libstd/sys/unix/c.rs262
-rw-r--r--src/libstd/sys/unix/mod.rs92
-rw-r--r--src/libstd/sys/unix/os.rs101
-rw-r--r--src/libstd/sys/windows/c.rs250
-rw-r--r--src/libstd/sys/windows/mod.rs178
-rw-r--r--src/libstd/sys/windows/os.rs103
10 files changed, 1093 insertions, 238 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index c404741b7c3..78abbb9f80d 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -236,8 +236,7 @@ use os;
 use boxed::Box;
 use result::{Ok, Err, Result};
 use rt::rtio;
-use slice::{AsSlice, SlicePrelude};
-use str::{Str, StrPrelude};
+use sys;
 use str;
 use string::String;
 use uint;
@@ -312,91 +311,10 @@ impl IoError {
     /// struct is filled with an allocated string describing the error
     /// in more detail, retrieved from the operating system.
     pub fn from_errno(errno: uint, detail: bool) -> IoError {
-
-        #[cfg(windows)]
-        fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
-            match errno {
-                libc::EOF => (EndOfFile, "end of file"),
-                libc::ERROR_NO_DATA => (BrokenPipe, "the pipe is being closed"),
-                libc::ERROR_FILE_NOT_FOUND => (FileNotFound, "file not found"),
-                libc::ERROR_INVALID_NAME => (InvalidInput, "invalid file name"),
-                libc::WSAECONNREFUSED => (ConnectionRefused, "connection refused"),
-                libc::WSAECONNRESET => (ConnectionReset, "connection reset"),
-                libc::ERROR_ACCESS_DENIED | libc::WSAEACCES =>
-                    (PermissionDenied, "permission denied"),
-                libc::WSAEWOULDBLOCK => {
-                    (ResourceUnavailable, "resource temporarily unavailable")
-                }
-                libc::WSAENOTCONN => (NotConnected, "not connected"),
-                libc::WSAECONNABORTED => (ConnectionAborted, "connection aborted"),
-                libc::WSAEADDRNOTAVAIL => (ConnectionRefused, "address not available"),
-                libc::WSAEADDRINUSE => (ConnectionRefused, "address in use"),
-                libc::ERROR_BROKEN_PIPE => (EndOfFile, "the pipe has ended"),
-                libc::ERROR_OPERATION_ABORTED =>
-                    (TimedOut, "operation timed out"),
-                libc::WSAEINVAL => (InvalidInput, "invalid argument"),
-                libc::ERROR_CALL_NOT_IMPLEMENTED =>
-                    (IoUnavailable, "function not implemented"),
-                libc::ERROR_INVALID_HANDLE =>
-                    (MismatchedFileTypeForOperation,
-                     "invalid handle provided to function"),
-                libc::ERROR_NOTHING_TO_TERMINATE =>
-                    (InvalidInput, "no process to kill"),
-
-                // libuv maps this error code to EISDIR. we do too. if it is found
-                // to be incorrect, we can add in some more machinery to only
-                // return this message when ERROR_INVALID_FUNCTION after certain
-                // Windows calls.
-                libc::ERROR_INVALID_FUNCTION => (InvalidInput,
-                                                 "illegal operation on a directory"),
-
-                _ => (OtherIoError, "unknown error")
-            }
-        }
-
-        #[cfg(not(windows))]
-        fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
-            // FIXME: this should probably be a bit more descriptive...
-            match errno {
-                libc::EOF => (EndOfFile, "end of file"),
-                libc::ECONNREFUSED => (ConnectionRefused, "connection refused"),
-                libc::ECONNRESET => (ConnectionReset, "connection reset"),
-                libc::EPERM | libc::EACCES =>
-                    (PermissionDenied, "permission denied"),
-                libc::EPIPE => (BrokenPipe, "broken pipe"),
-                libc::ENOTCONN => (NotConnected, "not connected"),
-                libc::ECONNABORTED => (ConnectionAborted, "connection aborted"),
-                libc::EADDRNOTAVAIL => (ConnectionRefused, "address not available"),
-                libc::EADDRINUSE => (ConnectionRefused, "address in use"),
-                libc::ENOENT => (FileNotFound, "no such file or directory"),
-                libc::EISDIR => (InvalidInput, "illegal operation on a directory"),
-                libc::ENOSYS => (IoUnavailable, "function not implemented"),
-                libc::EINVAL => (InvalidInput, "invalid argument"),
-                libc::ENOTTY =>
-                    (MismatchedFileTypeForOperation,
-                     "file descriptor is not a TTY"),
-                libc::ETIMEDOUT => (TimedOut, "operation timed out"),
-                libc::ECANCELED => (TimedOut, "operation aborted"),
-
-                // These two constants can have the same value on some systems,
-                // but different values on others, so we can't use a match
-                // clause
-                x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
-                    (ResourceUnavailable, "resource temporarily unavailable"),
-
-                _ => (OtherIoError, "unknown error")
-            }
-        }
-
-        let (kind, desc) = get_err(errno as i32);
-        IoError {
-            kind: kind,
-            desc: desc,
-            detail: if detail && kind == OtherIoError {
-                Some(os::error_string(errno).as_slice().chars().map(|c| c.to_lowercase()).collect())
-            } else {
-                None
-            },
+        let mut err = sys::decode_error(errno as i32);
+        if detail && err.kind == OtherIoError {
+            err.detail = Some(os::error_string(errno).as_slice().chars()
+                                 .map(|c| c.to_lowercase()).collect())
         }
     }
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f10a1d5e5ed..7eac455f97f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -242,6 +242,13 @@ pub mod io;
 pub mod path;
 pub mod fmt;
 
+#[cfg(unix)]
+#[path = "sys/unix/mod.rs"] mod sys;
+#[cfg(windows)]
+#[path = "sys/windows/mod.rs"] mod sys;
+
+#[path = "sys/common/mod.rs"] mod sys_common;
+
 // FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
 // but name resolution doesn't work without it being pub.
 pub mod rt;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 0042a3ae205..175e23bf819 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -34,7 +34,7 @@
 use clone::Clone;
 use error::{FromError, Error};
 use fmt;
-use io::{IoResult, IoError};
+use io::IoResult;
 use iter::Iterator;
 use libc::{c_void, c_int};
 use libc;
@@ -43,6 +43,7 @@ use ops::Drop;
 use option::{Some, None, Option};
 use os;
 use path::{Path, GenericPath, BytesContainer};
+use sys::os as os_imp;
 use ptr::RawPtr;
 use ptr;
 use result::{Err, Ok, Result};
@@ -905,59 +906,9 @@ pub fn change_dir(p: &Path) -> bool {
     }
 }
 
-#[cfg(unix)]
-/// Returns the platform-specific value of errno
-pub fn errno() -> int {
-    #[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()
-        }
-    }
-
-    #[cfg(target_os = "dragonfly")]
-    fn errno_location() -> *const c_int {
-        extern {
-            fn __dfly_error() -> *const c_int;
-        }
-        unsafe {
-            __dfly_error()
-        }
-    }
-
-    #[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 {
-        (*errno_location()) as int
-    }
-}
-
-#[cfg(windows)]
 /// Returns the platform-specific value of errno
 pub fn errno() -> uint {
-    use libc::types::os::arch::extra::DWORD;
-
-    #[link_name = "kernel32"]
-    extern "system" {
-        fn GetLastError() -> DWORD;
-    }
-
-    unsafe {
-        GetLastError() as uint
-    }
+    os_imp::errno() as uint
 }
 
 /// Return the string corresponding to an `errno()` value of `errnum`.
@@ -969,105 +920,7 @@ pub fn errno() -> uint {
 /// println!("{}", os::error_string(os::errno() as uint));
 /// ```
 pub fn error_string(errnum: uint) -> String {
-    return strerror(errnum);
-
-    #[cfg(unix)]
-    fn strerror(errnum: uint) -> 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)
-            }
-        }
-
-        let mut buf = [0 as c_char, ..TMPBUF_SZ];
-
-        let p = buf.as_mut_ptr();
-        unsafe {
-            if strerror_r(errnum as c_int, p, buf.len() as libc::size_t) < 0 {
-                panic!("strerror_r failure");
-            }
-
-            ::string::raw::from_buf(p as *const u8)
-        }
-    }
-
-    #[cfg(windows)]
-    fn strerror(errnum: uint) -> String {
-        use libc::types::os::arch::extra::DWORD;
-        use libc::types::os::arch::extra::LPWSTR;
-        use libc::types::os::arch::extra::LPVOID;
-        use libc::types::os::arch::extra::WCHAR;
-
-        #[link_name = "kernel32"]
-        extern "system" {
-            fn FormatMessageW(flags: DWORD,
-                              lpSrc: LPVOID,
-                              msgId: DWORD,
-                              langId: DWORD,
-                              buf: LPWSTR,
-                              nsize: DWORD,
-                              args: *const c_void)
-                              -> DWORD;
-        }
-
-        static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
-        static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
-
-        // This value is calculated from the macro
-        // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
-        let langId = 0x0800 as DWORD;
-
-        let mut buf = [0 as WCHAR, ..TMPBUF_SZ];
-
-        unsafe {
-            let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
-                                     FORMAT_MESSAGE_IGNORE_INSERTS,
-                                     ptr::null_mut(),
-                                     errnum as DWORD,
-                                     langId,
-                                     buf.as_mut_ptr(),
-                                     buf.len() as DWORD,
-                                     ptr::null());
-            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);
-            }
-
-            let msg = String::from_utf16(::str::truncate_utf16_at_nul(buf));
-            match msg {
-                Some(msg) => format!("OS Error {}: {}", errnum, msg),
-                None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum),
-            }
-        }
-    }
+    return os_imp::error_string(errnum as i32);
 }
 
 /// Get a string representing the platform-dependent last error
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
new file mode 100644
index 00000000000..402c62bb35e
--- /dev/null
+++ b/src/libstd/sys/common/mod.rs
@@ -0,0 +1,91 @@
+// Copyright 2014 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.
+
+#![allow(missing_doc)]
+#![allow(dead_code)]
+
+use io::{mod, IoError, IoResult};
+use prelude::*;
+use num;
+use sys::{last_error, retry, fs};
+use c_str::CString;
+use path::BytesContainer;
+use collections;
+
+pub mod net;
+
+// common error constructors
+
+pub fn eof() -> IoError {
+    IoError {
+        kind: io::EndOfFile,
+        desc: "end of file",
+        detail: None,
+    }
+}
+
+pub fn timeout(desc: &'static str) -> IoError {
+    IoError {
+        kind: io::TimedOut,
+        desc: desc,
+        detail: None,
+    }
+}
+
+pub fn short_write(n: uint, desc: &'static str) -> IoError {
+    IoError {
+        kind: if n == 0 { io::TimedOut } else { io::ShortWrite(n) },
+        desc: desc,
+        detail: None,
+    }
+}
+
+// unix has nonzero values as errors
+pub fn mkerr_libc<Int: num::Zero>(ret: Int) -> IoResult<()> {
+    if !ret.is_zero() {
+        Err(last_error())
+    } else {
+        Ok(())
+    }
+}
+
+pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
+    let origamt = data.len();
+    let mut data = data.as_ptr();
+    let mut amt = origamt;
+    while amt > 0 {
+        let ret = retry(|| f(data, amt));
+        if ret == 0 {
+            break
+        } else if ret != -1 {
+            amt -= ret as uint;
+            data = unsafe { data.offset(ret as int) };
+        } else {
+            return ret;
+        }
+    }
+    return (origamt - amt) as i64;
+}
+
+// traits for extracting representations from
+
+pub trait AsFileDesc {
+    fn as_fd(&self) -> &fs::FileDesc;
+}
+
+pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {
+    fn program(&self) -> &CString;
+    fn args(&self) -> &[CString];
+    fn env(&self) -> Option<&collections::HashMap<K, V>>;
+    fn cwd(&self) -> Option<&CString>;
+    fn uid(&self) -> Option<uint>;
+    fn gid(&self) -> Option<uint>;
+    fn detach(&self) -> bool;
+}
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
new file mode 100644
index 00000000000..e76f2a2b872
--- /dev/null
+++ b/src/libstd/sys/unix/c.rs
@@ -0,0 +1,262 @@
+// Copyright 2014 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.
+
+//! C definitions used by libnative that don't belong in liblibc
+
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+pub use self::select::fd_set;
+pub use self::signal::{sigaction, siginfo, sigset_t};
+pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
+pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};
+
+use libc;
+
+#[cfg(any(target_os = "macos",
+          target_os = "ios",
+          target_os = "freebsd",
+          target_os = "dragonfly"))]
+pub const FIONBIO: libc::c_ulong = 0x8004667e;
+#[cfg(any(all(target_os = "linux",
+              any(target_arch = "x86",
+                  target_arch = "x86_64",
+                  target_arch = "arm")),
+          target_os = "android"))]
+pub const FIONBIO: libc::c_ulong = 0x5421;
+#[cfg(all(target_os = "linux",
+          any(target_arch = "mips", target_arch = "mipsel")))]
+pub const FIONBIO: libc::c_ulong = 0x667e;
+
+#[cfg(any(target_os = "macos",
+          target_os = "ios",
+          target_os = "freebsd",
+          target_os = "dragonfly"))]
+pub const FIOCLEX: libc::c_ulong = 0x20006601;
+#[cfg(any(all(target_os = "linux",
+              any(target_arch = "x86",
+                  target_arch = "x86_64",
+                  target_arch = "arm")),
+          target_os = "android"))]
+pub const FIOCLEX: libc::c_ulong = 0x5451;
+#[cfg(all(target_os = "linux",
+          any(target_arch = "mips", target_arch = "mipsel")))]
+pub const FIOCLEX: libc::c_ulong = 0x6601;
+
+#[cfg(any(target_os = "macos",
+          target_os = "ios",
+          target_os = "freebsd",
+          target_os = "dragonfly"))]
+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;
+
+extern {
+    pub fn gettimeofday(timeval: *mut libc::timeval,
+                        tzp: *mut libc::c_void) -> libc::c_int;
+    pub fn select(nfds: libc::c_int,
+                  readfds: *mut fd_set,
+                  writefds: *mut fd_set,
+                  errorfds: *mut fd_set,
+                  timeout: *mut libc::timeval) -> libc::c_int;
+    pub fn getsockopt(sockfd: libc::c_int,
+                      level: libc::c_int,
+                      optname: libc::c_int,
+                      optval: *mut libc::c_void,
+                      optlen: *mut libc::socklen_t) -> libc::c_int;
+    pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int;
+
+
+    pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
+                   options: libc::c_int) -> libc::pid_t;
+
+    pub fn sigaction(signum: libc::c_int,
+                     act: *const sigaction,
+                     oldact: *mut sigaction) -> libc::c_int;
+
+    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;
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+mod select {
+    pub const FD_SETSIZE: uint = 1024;
+
+    #[repr(C)]
+    pub struct fd_set {
+        fds_bits: [i32, ..(FD_SETSIZE / 32)]
+    }
+
+    pub fn fd_set(set: &mut fd_set, fd: i32) {
+        set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint);
+    }
+}
+
+#[cfg(any(target_os = "android",
+          target_os = "freebsd",
+          target_os = "dragonfly",
+          target_os = "linux"))]
+mod select {
+    use uint;
+    use libc;
+
+    pub const FD_SETSIZE: uint = 1024;
+
+    #[repr(C)]
+    pub struct fd_set {
+        // FIXME: shouldn't this be a c_ulong?
+        fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)]
+    }
+
+    pub fn fd_set(set: &mut fd_set, fd: i32) {
+        let fd = fd as uint;
+        set.fds_bits[fd / uint::BITS] |= 1 << (fd % uint::BITS);
+    }
+}
+
+#[cfg(any(all(target_os = "linux",
+              any(target_arch = "x86",
+                  target_arch = "x86_64",
+                  target_arch = "arm")),
+          target_os = "android"))]
+mod signal {
+    use libc;
+
+    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
+    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
+    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
+    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
+    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
+    pub const SA_RESTART: libc::c_ulong = 0x10000000;
+    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
+    pub const SIGCHLD: libc::c_int = 17;
+
+    // This definition is not as accurate as it could be, {pid, uid, status} is
+    // actually a giant union. Currently we're only interested in these fields,
+    // however.
+    #[repr(C)]
+    pub struct siginfo {
+        si_signo: libc::c_int,
+        si_errno: libc::c_int,
+        si_code: libc::c_int,
+        pub pid: libc::pid_t,
+        pub uid: libc::uid_t,
+        pub status: libc::c_int,
+    }
+
+    #[repr(C)]
+    pub struct sigaction {
+        pub sa_handler: extern fn(libc::c_int),
+        pub sa_mask: sigset_t,
+        pub sa_flags: libc::c_ulong,
+        sa_restorer: *mut libc::c_void,
+    }
+
+    #[repr(C)]
+    #[cfg(target_word_size = "32")]
+    pub struct sigset_t {
+        __val: [libc::c_ulong, ..32],
+    }
+
+    #[repr(C)]
+    #[cfg(target_word_size = "64")]
+    pub struct sigset_t {
+        __val: [libc::c_ulong, ..16],
+    }
+}
+
+#[cfg(all(target_os = "linux",
+          any(target_arch = "mips", target_arch = "mipsel")))]
+mod signal {
+    use libc;
+
+    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
+    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
+    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
+    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
+    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
+    pub const SA_RESTART: libc::c_ulong = 0x10000000;
+    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
+    pub const SIGCHLD: libc::c_int = 18;
+
+    // This definition is not as accurate as it could be, {pid, uid, status} is
+    // actually a giant union. Currently we're only interested in these fields,
+    // however.
+    #[repr(C)]
+    pub struct siginfo {
+        si_signo: libc::c_int,
+        si_code: libc::c_int,
+        si_errno: libc::c_int,
+        pub pid: libc::pid_t,
+        pub uid: libc::uid_t,
+        pub status: libc::c_int,
+    }
+
+    #[repr(C)]
+    pub struct sigaction {
+        pub sa_flags: libc::c_uint,
+        pub sa_handler: extern fn(libc::c_int),
+        pub sa_mask: sigset_t,
+        sa_restorer: *mut libc::c_void,
+        sa_resv: [libc::c_int, ..1],
+    }
+
+    #[repr(C)]
+    pub struct sigset_t {
+        __val: [libc::c_ulong, ..32],
+    }
+}
+
+#[cfg(any(target_os = "macos",
+          target_os = "ios",
+          target_os = "freebsd",
+          target_os = "dragonfly"))]
+mod signal {
+    use libc;
+
+    pub const SA_ONSTACK: libc::c_int = 0x0001;
+    pub const SA_RESTART: libc::c_int = 0x0002;
+    pub const SA_RESETHAND: libc::c_int = 0x0004;
+    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
+    pub const SA_NODEFER: libc::c_int = 0x0010;
+    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
+    pub const SA_SIGINFO: libc::c_int = 0x0040;
+    pub const SIGCHLD: libc::c_int = 20;
+
+    #[cfg(any(target_os = "macos", target_os = "ios"))]
+    pub type sigset_t = u32;
+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+    #[repr(C)]
+    pub struct sigset_t {
+        bits: [u32, ..4],
+    }
+
+    // This structure has more fields, but we're not all that interested in
+    // them.
+    #[repr(C)]
+    pub struct siginfo {
+        pub si_signo: libc::c_int,
+        pub si_errno: libc::c_int,
+        pub si_code: libc::c_int,
+        pub pid: libc::pid_t,
+        pub uid: libc::uid_t,
+        pub status: libc::c_int,
+    }
+
+    #[repr(C)]
+    pub struct sigaction {
+        pub sa_handler: extern fn(libc::c_int),
+        pub sa_flags: libc::c_int,
+        pub sa_mask: sigset_t,
+    }
+}
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
new file mode 100644
index 00000000000..ad5de2dad48
--- /dev/null
+++ b/src/libstd/sys/unix/mod.rs
@@ -0,0 +1,92 @@
+// Copyright 2014 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.
+
+extern crate libc;
+
+use num;
+use prelude::*;
+use io::{mod, IoResult, IoError};
+
+pub mod fs;
+pub mod os;
+pub mod c;
+
+pub type sock_t = io::file::fd_t;
+pub type wrlen = libc::size_t;
+pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); }
+
+pub fn last_error() -> IoError {
+    let errno = os::errno() as i32;
+    let mut err = decode_error(errno);
+    err.detail = Some(os::error_string(errno));
+    err
+}
+
+/// Convert an `errno` value into a high-level error variant and description.
+pub fn decode_error(errno: i32) -> IoError {
+    // FIXME: this should probably be a bit more descriptive...
+    let (kind, desc) = match errno {
+        libc::EOF => (io::EndOfFile, "end of file"),
+        libc::ECONNREFUSED => (io::ConnectionRefused, "connection refused"),
+        libc::ECONNRESET => (io::ConnectionReset, "connection reset"),
+        libc::EPERM | libc::EACCES =>
+            (io::PermissionDenied, "permission denied"),
+        libc::EPIPE => (io::BrokenPipe, "broken pipe"),
+        libc::ENOTCONN => (io::NotConnected, "not connected"),
+        libc::ECONNABORTED => (io::ConnectionAborted, "connection aborted"),
+        libc::EADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
+        libc::EADDRINUSE => (io::ConnectionRefused, "address in use"),
+        libc::ENOENT => (io::FileNotFound, "no such file or directory"),
+        libc::EISDIR => (io::InvalidInput, "illegal operation on a directory"),
+        libc::ENOSYS => (io::IoUnavailable, "function not implemented"),
+        libc::EINVAL => (io::InvalidInput, "invalid argument"),
+        libc::ENOTTY =>
+            (io::MismatchedFileTypeForOperation,
+             "file descriptor is not a TTY"),
+        libc::ETIMEDOUT => (io::TimedOut, "operation timed out"),
+        libc::ECANCELED => (io::TimedOut, "operation aborted"),
+
+        // These two constants can have the same value on some systems,
+        // but different values on others, so we can't use a match
+        // clause
+        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
+            (io::ResourceUnavailable, "resource temporarily unavailable"),
+
+        _ => (io::OtherIoError, "unknown error")
+    };
+    IoError { kind: kind, desc: desc, detail: None }
+}
+
+#[inline]
+pub fn retry<I: PartialEq + num::One + Neg<I>> (f: || -> I) -> I {
+    let minus_one = -num::one::<I>();
+    loop {
+        let n = f();
+        if n == minus_one && os::errno() == libc::EINTR as int { }
+        else { return n }
+    }
+}
+
+pub fn ms_to_timeval(ms: u64) -> libc::timeval {
+    libc::timeval {
+        tv_sec: (ms / 1000) as libc::time_t,
+        tv_usec: ((ms % 1000) * 1000) as libc::suseconds_t,
+    }
+}
+
+pub fn wouldblock() -> bool {
+    let err = os::errno();
+    err == libc::EWOULDBLOCK as int || err == libc::EAGAIN as int
+}
+
+pub fn set_nonblocking(fd: net::sock_t, nb: bool) -> IoResult<()> {
+    let set = nb as libc::c_int;
+    super::mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
+}
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
new file mode 100644
index 00000000000..34699eb27c1
--- /dev/null
+++ b/src/libstd/sys/unix/os.rs
@@ -0,0 +1,101 @@
+// Copyright 2014 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 libc;
+use libc::{c_int, c_char};
+use prelude::*;
+
+use os::TMPBUF_SZ;
+
+/// Returns the platform-specific value of errno
+pub fn errno() -> int {
+    #[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()
+        }
+    }
+
+    #[cfg(target_os = "dragonfly")]
+    fn errno_location() -> *const c_int {
+        extern {
+            fn __dfly_error() -> *const c_int;
+        }
+        unsafe {
+            __dfly_error()
+        }
+    }
+
+    #[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 {
+        (*errno_location()) as int
+    }
+}
+
+/// 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)
+        }
+    }
+
+    let mut buf = [0 as c_char, ..TMPBUF_SZ];
+
+    let p = buf.as_mut_ptr();
+    unsafe {
+        if strerror_r(errno as c_int, p, buf.len() as libc::size_t) < 0 {
+            panic!("strerror_r failure");
+        }
+
+        ::string::raw::from_buf(p as *const u8)
+    }
+}
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
new file mode 100644
index 00000000000..b8e9b1dca3a
--- /dev/null
+++ b/src/libstd/sys/windows/c.rs
@@ -0,0 +1,250 @@
+// Copyright 2014 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.
+
+//! C definitions used by libnative that don't belong in liblibc
+
+#![allow(overflowing_literals)]
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+use libc;
+use prelude::*;
+
+pub const WSADESCRIPTION_LEN: uint = 256;
+pub const WSASYS_STATUS_LEN: uint = 128;
+pub const FIONBIO: libc::c_long = 0x8004667e;
+pub const FD_SETSIZE: uint = 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;
+pub const ENABLE_EXTENDED_FLAGS: libc::DWORD = 0x80;
+pub const ENABLE_INSERT_MODE: libc::DWORD = 0x20;
+pub const ENABLE_LINE_INPUT: libc::DWORD = 0x2;
+pub const ENABLE_PROCESSED_INPUT: libc::DWORD = 0x1;
+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 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;
+
+#[repr(C)]
+#[cfg(target_arch = "x86")]
+pub struct WSADATA {
+    pub wVersion: libc::WORD,
+    pub wHighVersion: libc::WORD,
+    pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1],
+    pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1],
+    pub iMaxSockets: u16,
+    pub iMaxUdpDg: u16,
+    pub lpVendorInfo: *mut u8,
+}
+#[repr(C)]
+#[cfg(target_arch = "x86_64")]
+pub struct WSADATA {
+    pub wVersion: libc::WORD,
+    pub wHighVersion: libc::WORD,
+    pub iMaxSockets: u16,
+    pub iMaxUdpDg: u16,
+    pub lpVendorInfo: *mut u8,
+    pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1],
+    pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1],
+}
+
+pub type LPWSADATA = *mut WSADATA;
+
+#[repr(C)]
+pub struct WSANETWORKEVENTS {
+    pub lNetworkEvents: libc::c_long,
+    pub iErrorCode: [libc::c_int, ..FD_MAX_EVENTS],
+}
+
+pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS;
+
+pub type WSAEVENT = libc::HANDLE;
+
+#[repr(C)]
+pub struct fd_set {
+    fd_count: libc::c_uint,
+    fd_array: [libc::SOCKET, ..FD_SETSIZE],
+}
+
+pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) {
+    set.fd_array[set.fd_count as uint] = s;
+    set.fd_count += 1;
+}
+
+#[link(name = "ws2_32")]
+extern "system" {
+    pub fn WSAStartup(wVersionRequested: libc::WORD,
+                      lpWSAData: LPWSADATA) -> libc::c_int;
+    pub fn WSAGetLastError() -> libc::c_int;
+    pub fn WSACloseEvent(hEvent: WSAEVENT) -> libc::BOOL;
+    pub fn WSACreateEvent() -> WSAEVENT;
+    pub fn WSAEventSelect(s: libc::SOCKET,
+                          hEventObject: WSAEVENT,
+                          lNetworkEvents: libc::c_long) -> libc::c_int;
+    pub fn WSASetEvent(hEvent: WSAEVENT) -> libc::BOOL;
+    pub fn WSAWaitForMultipleEvents(cEvents: libc::DWORD,
+                                    lphEvents: *const WSAEVENT,
+                                    fWaitAll: libc::BOOL,
+                                    dwTimeout: libc::DWORD,
+                                    fAltertable: libc::BOOL) -> libc::DWORD;
+    pub fn WSAEnumNetworkEvents(s: libc::SOCKET,
+                                hEventObject: WSAEVENT,
+                                lpNetworkEvents: LPWSANETWORKEVENTS)
+                                -> libc::c_int;
+
+    pub fn ioctlsocket(s: libc::SOCKET, cmd: libc::c_long,
+                       argp: *mut libc::c_ulong) -> libc::c_int;
+    pub fn select(nfds: libc::c_int,
+                  readfds: *mut fd_set,
+                  writefds: *mut fd_set,
+                  exceptfds: *mut fd_set,
+                  timeout: *mut libc::timeval) -> libc::c_int;
+    pub fn getsockopt(sockfd: libc::SOCKET,
+                      level: libc::c_int,
+                      optname: libc::c_int,
+                      optval: *mut libc::c_char,
+                      optlen: *mut libc::c_int) -> libc::c_int;
+
+    pub fn SetEvent(hEvent: libc::HANDLE) -> libc::BOOL;
+    pub fn WaitForMultipleObjects(nCount: libc::DWORD,
+                                  lpHandles: *const libc::HANDLE,
+                                  bWaitAll: libc::BOOL,
+                                  dwMilliseconds: libc::DWORD) -> libc::DWORD;
+
+    pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL;
+    pub fn CancelIoEx(hFile: libc::HANDLE,
+                      lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
+}
+
+pub mod compat {
+    use intrinsics::{atomic_store_relaxed, transmute};
+    use iter::Iterator;
+    use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
+    use prelude::*;
+
+    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) {
+        let mut module: Vec<u16> = module.utf16_units().collect();
+        module.push(0);
+        symbol.with_c_str(|symbol| {
+            let handle = GetModuleHandleW(module.as_ptr());
+            let func: uint = transmute(GetProcAddress(handle, symbol));
+            atomic_store_relaxed(ptr, if func == 0 {
+                fallback
+            } else {
+                func
+            })
+        })
+    }
+
+    /// Macro for creating a compatibility fallback for a Windows function
+    ///
+    /// # Example
+    /// ```
+    /// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) {
+    ///     // Fallback implementation
+    /// })
+    /// ```
+    ///
+    /// 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:block) => (
+            #[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),*)
+                    }
+                }
+
+                extern "system" fn fallback($($argname: $argtype),*) -> $rettype $fallback
+
+                ::intrinsics::atomic_load_relaxed(&ptr)($($argname),*)
+            }
+        );
+
+        ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => (
+            compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback)
+        )
+    )
+
+    /// Compatibility layer for functions in `kernel32.dll`
+    ///
+    /// Latest versions of Windows this is needed for:
+    ///
+    /// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003
+    /// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003
+    pub mod kernel32 {
+        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);
+        }
+
+        compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
+                                                 _lpTargetFileName: LPCWSTR,
+                                                 _dwFlags: DWORD) -> BOOLEAN {
+            unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
+            0
+        })
+
+        compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
+                                                       _lpszFilePath: LPCWSTR,
+                                                       _cchFilePath: DWORD,
+                                                       _dwFlags: DWORD) -> DWORD {
+            unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
+            0
+        })
+    }
+}
+
+extern "system" {
+    // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL
+    pub fn ReadConsoleW(hConsoleInput: libc::HANDLE,
+                        lpBuffer: libc::LPVOID,
+                        nNumberOfCharsToRead: libc::DWORD,
+                        lpNumberOfCharsRead: libc::LPDWORD,
+                        pInputControl: libc::LPVOID) -> libc::BOOL;
+
+    pub fn WriteConsoleW(hConsoleOutput: libc::HANDLE,
+                         lpBuffer: libc::types::os::arch::extra::LPCVOID,
+                         nNumberOfCharsToWrite: libc::DWORD,
+                         lpNumberOfCharsWritten: libc::LPDWORD,
+                         lpReserved: libc::LPVOID) -> libc::BOOL;
+
+    pub fn GetConsoleMode(hConsoleHandle: libc::HANDLE,
+                          lpMode: libc::LPDWORD) -> libc::BOOL;
+
+    pub fn SetConsoleMode(hConsoleHandle: libc::HANDLE,
+                          lpMode: libc::DWORD) -> libc::BOOL;
+}
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
new file mode 100644
index 00000000000..5f4129c1484
--- /dev/null
+++ b/src/libstd/sys/windows/mod.rs
@@ -0,0 +1,178 @@
+// Copyright 2014 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.
+
+#![allow(missing_doc)]
+#![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 num;
+use mem;
+use prelude::*;
+use io::{mod, IoResult, IoError};
+use sync::{Once, ONCE_INIT};
+
+macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
+    static $name: Helper<$m> = Helper {
+        lock: ::rt::mutex::NATIVE_MUTEX_INIT,
+        chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
+        signal: ::cell::UnsafeCell { value: 0 },
+        initialized: ::cell::UnsafeCell { value: false },
+    };
+) )
+
+pub mod fs;
+pub mod os;
+pub mod c;
+
+pub type sock_t = libc::SOCKET;
+pub type wrlen = libc::c_int;
+pub unsafe fn close_sock(sock: sock_t) { let _ = libc::closesocket(sock); }
+
+// windows has zero values as errors
+fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
+    if ret == 0 {
+        Err(last_error())
+    } else {
+        Ok(())
+    }
+}
+
+pub fn last_error() -> IoError {
+    let errno = os::errno() as i32;
+    let mut err = decode_error(errno);
+    err.detail = Some(os::error_string(errno));
+    err
+}
+
+pub fn last_net_error() -> IoError {
+    let errno = unsafe { c::WSAGetLastError() as i32 };
+    let mut err = decode_error(errno);
+    err.detail = Some(os::error_string(errno));
+    err
+}
+
+pub fn last_gai_error(_errno: i32) -> IoError {
+    last_net_error()
+}
+
+/// Convert an `errno` value into a high-level error variant and description.
+pub fn decode_error(errno: i32) -> IoError {
+    let (kind, desc) = match errno {
+        libc::EOF => (io::EndOfFile, "end of file"),
+        libc::ERROR_NO_DATA => (io::BrokenPipe, "the pipe is being closed"),
+        libc::ERROR_FILE_NOT_FOUND => (io::FileNotFound, "file not found"),
+        libc::ERROR_INVALID_NAME => (io::InvalidInput, "invalid file name"),
+        libc::WSAECONNREFUSED => (io::ConnectionRefused, "connection refused"),
+        libc::WSAECONNRESET => (io::ConnectionReset, "connection reset"),
+        libc::ERROR_ACCESS_DENIED | libc::WSAEACCES =>
+            (io::PermissionDenied, "permission denied"),
+        libc::WSAEWOULDBLOCK => {
+            (io::ResourceUnavailable, "resource temporarily unavailable")
+        }
+        libc::WSAENOTCONN => (io::NotConnected, "not connected"),
+        libc::WSAECONNABORTED => (io::ConnectionAborted, "connection aborted"),
+        libc::WSAEADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
+        libc::WSAEADDRINUSE => (io::ConnectionRefused, "address in use"),
+        libc::ERROR_BROKEN_PIPE => (io::EndOfFile, "the pipe has ended"),
+        libc::ERROR_OPERATION_ABORTED =>
+            (io::TimedOut, "operation timed out"),
+        libc::WSAEINVAL => (io::InvalidInput, "invalid argument"),
+        libc::ERROR_CALL_NOT_IMPLEMENTED =>
+            (io::IoUnavailable, "function not implemented"),
+        libc::ERROR_INVALID_HANDLE =>
+            (io::MismatchedFileTypeForOperation,
+             "invalid handle provided to function"),
+        libc::ERROR_NOTHING_TO_TERMINATE =>
+            (io::InvalidInput, "no process to kill"),
+
+        // libuv maps this error code to EISDIR. we do too. if it is found
+        // to be incorrect, we can add in some more machinery to only
+        // return this message when ERROR_INVALID_FUNCTION after certain
+        // Windows calls.
+        libc::ERROR_INVALID_FUNCTION => (io::InvalidInput,
+                                         "illegal operation on a directory"),
+
+        _ => (io::OtherIoError, "unknown error")
+    };
+    IoError { kind: kind, desc: desc, detail: None }
+}
+
+pub fn decode_error_detailed(errno: i32) -> IoError {
+    let mut err = decode_error(errno);
+    err.detail = Some(os::error_string(errno));
+    err
+}
+
+#[inline]
+pub fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
+
+pub fn ms_to_timeval(ms: u64) -> libc::timeval {
+    libc::timeval {
+        tv_sec: (ms / 1000) as libc::c_long,
+        tv_usec: ((ms % 1000) * 1000) as libc::c_long,
+    }
+}
+
+pub fn wouldblock() -> bool {
+    let err = os::errno();
+    err == libc::WSAEWOULDBLOCK as uint
+}
+
+pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
+    let mut set = nb as libc::c_ulong;
+    if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
+        Err(last_error())
+    } else {
+        Ok(())
+    }
+}
+
+// FIXME: call this
+pub fn init_net() {
+    unsafe {
+        static START: Once = ONCE_INIT;
+
+        START.doit(|| {
+            let mut data: c::WSADATA = mem::zeroed();
+            let ret = c::WSAStartup(0x202, // version 2.2
+                                    &mut data);
+            assert_eq!(ret, 0);
+        });
+    }
+}
+
+pub fn unimpl() -> IoError {
+    IoError {
+        kind: io::IoUnavailable,
+        desc: "operation is not implemented",
+        detail: None,
+    }
+}
+
+pub 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
+        }),
+        None => Err(IoError {
+            kind: io::InvalidInput,
+            desc: "valid unicode input required",
+            detail: None
+        })
+    }
+}
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
new file mode 100644
index 00000000000..aaa1aaf6327
--- /dev/null
+++ b/src/libstd/sys/windows/os.rs
@@ -0,0 +1,103 @@
+// Copyright 2014 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.
+
+// FIXME: move various extern bindings from here into liblibc or
+// something similar
+
+use libc;
+use libc::{c_int, c_char, c_void};
+use prelude::*;
+use io::{IoResult, IoError};
+use sys::fs::FileDesc;
+use ptr;
+
+use os::TMPBUF_SZ;
+
+pub fn errno() -> uint {
+    use libc::types::os::arch::extra::DWORD;
+
+    #[link_name = "kernel32"]
+    extern "system" {
+        fn GetLastError() -> DWORD;
+    }
+
+    unsafe {
+        GetLastError() as uint
+    }
+}
+
+/// Get a detailed string description for the given error number
+pub fn error_string(errnum: i32) -> String {
+    use libc::types::os::arch::extra::DWORD;
+    use libc::types::os::arch::extra::LPWSTR;
+    use libc::types::os::arch::extra::LPVOID;
+    use libc::types::os::arch::extra::WCHAR;
+
+    #[link_name = "kernel32"]
+    extern "system" {
+        fn FormatMessageW(flags: DWORD,
+                          lpSrc: LPVOID,
+                          msgId: DWORD,
+                          langId: DWORD,
+                          buf: LPWSTR,
+                          nsize: DWORD,
+                          args: *const c_void)
+                          -> DWORD;
+    }
+
+    static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
+    static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
+
+    // This value is calculated from the macro
+    // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
+    let langId = 0x0800 as DWORD;
+
+    let mut buf = [0 as WCHAR, ..TMPBUF_SZ];
+
+    unsafe {
+        let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+                                 FORMAT_MESSAGE_IGNORE_INSERTS,
+                                 ptr::null_mut(),
+                                 errnum as DWORD,
+                                 langId,
+                                 buf.as_mut_ptr(),
+                                 buf.len() as DWORD,
+                                 ptr::null());
+        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);
+        }
+
+        let msg = String::from_utf16(::str::truncate_utf16_at_nul(buf));
+        match msg {
+            Some(msg) => format!("OS Error {}: {}", errnum, msg),
+            None => 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()),
+    }
+}