about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-12-12 17:54:53 -0800
committerAlex Crichton <alex@alexcrichton.com>2013-12-24 14:42:00 -0800
commit6aadc9d18856f8e7ea8038e2c4b2ba0f9507e26a (patch)
tree563ed3086b2bb3ddd683d0cf5d654763895b1201 /src/libstd
parent49e5493587162d53a693ba7e7833edd8f1718e94 (diff)
downloadrust-6aadc9d18856f8e7ea8038e2c4b2ba0f9507e26a.tar.gz
rust-6aadc9d18856f8e7ea8038e2c4b2ba0f9507e26a.zip
native: Introduce libnative
This commit introduces a new crate called "native" which will be the crate that
implements the 1:1 runtime of rust. This currently entails having an
implementation of std::rt::Runtime inside of libnative as well as moving all of
the native I/O implementations to libnative.

The current snag is that the start lang item must currently be defined in
libnative in order to start running, but this will change in the future.

Cool fact about this crate, there are no extra features that are enabled.

Note that this commit does not include any makefile support necessary for
building libnative, that's all coming in a later commit.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/mod.rs5
-rw-r--r--src/libstd/io/native/file.rs965
-rw-r--r--src/libstd/io/native/mod.rs228
-rw-r--r--src/libstd/io/native/process.rs654
4 files changed, 0 insertions, 1852 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index bd0b9e08b7c..0852c4cadb6 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -164,9 +164,6 @@ requests are implemented by descheduling the running task and
 performing an asynchronous request; the task is only resumed once the
 asynchronous request completes.
 
-For blocking (but possibly more efficient) implementations, look
-in the `io::native` module.
-
 # Error Handling
 
 I/O is an area where nearly every operation can result in unexpected
@@ -349,8 +346,6 @@ pub mod timer;
 /// Buffered I/O wrappers
 pub mod buffered;
 
-pub mod native;
-
 /// Signal handling
 pub mod signal;
 
diff --git a/src/libstd/io/native/file.rs b/src/libstd/io/native/file.rs
deleted file mode 100644
index de2655303d6..00000000000
--- a/src/libstd/io/native/file.rs
+++ /dev/null
@@ -1,965 +0,0 @@
-// Copyright 2013 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.
-
-//! Blocking posix-based file I/O
-
-#[allow(non_camel_case_types)];
-
-use c_str::CString;
-use io::IoError;
-use io;
-use libc::c_int;
-use libc;
-use ops::Drop;
-use option::{Some, None, Option};
-use os;
-use path::{Path, GenericPath};
-use ptr::RawPtr;
-use result::{Result, Ok, Err};
-use rt::rtio;
-use super::IoResult;
-use unstable::intrinsics;
-use vec::ImmutableVector;
-use vec;
-
-#[cfg(windows)] use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
-#[cfg(windows)] use ptr;
-#[cfg(windows)] use str;
-
-fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 {
-    #[cfg(windows)] static eintr: int = 0; // doesn't matter
-    #[cfg(not(windows))] static eintr: int = libc::EINTR as int;
-
-    let origamt = data.len();
-    let mut data = data.as_ptr();
-    let mut amt = origamt;
-    while amt > 0 {
-        let mut ret;
-        loop {
-            ret = f(data, amt);
-            if cfg!(not(windows)) { break } // windows has no eintr
-            // if we get an eintr, then try again
-            if ret != -1 || os::errno() as int != eintr { break }
-        }
-        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;
-}
-
-pub type fd_t = libc::c_int;
-
-pub struct FileDesc {
-    priv fd: fd_t,
-    priv close_on_drop: bool,
-}
-
-impl FileDesc {
-    /// Create a `FileDesc` from an open C file descriptor.
-    ///
-    /// The `FileDesc` will take ownership of the specified file descriptor and
-    /// close it upon destruction if the `close_on_drop` flag is true, otherwise
-    /// it will not close the file descriptor when this `FileDesc` is dropped.
-    ///
-    /// Note that all I/O operations done on this object will be *blocking*, but
-    /// they do not require the runtime to be active.
-    pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
-        FileDesc { fd: fd, close_on_drop: close_on_drop }
-    }
-
-    fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
-        #[cfg(windows)] type rlen = libc::c_uint;
-        #[cfg(not(windows))] type rlen = libc::size_t;
-        let ret = keep_going(buf, |buf, len| {
-            unsafe {
-                libc::read(self.fd, buf as *mut libc::c_void, len as rlen) as i64
-            }
-        });
-        if ret == 0 {
-            Err(io::standard_error(io::EndOfFile))
-        } else if ret < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(ret as uint)
-        }
-    }
-    fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
-        #[cfg(windows)] type wlen = libc::c_uint;
-        #[cfg(not(windows))] type wlen = libc::size_t;
-        let ret = keep_going(buf, |buf, len| {
-            unsafe {
-                libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
-            }
-        });
-        if ret < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(())
-        }
-    }
-}
-
-impl io::Reader for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match self.inner_read(buf) { Ok(n) => Some(n), Err(..) => None }
-    }
-    fn eof(&mut self) -> bool { false }
-}
-
-impl io::Writer for FileDesc {
-    fn write(&mut self, buf: &[u8]) {
-        self.inner_write(buf);
-    }
-}
-
-impl rtio::RtioFileStream for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
-        self.inner_read(buf).map(|i| i as int)
-    }
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
-        self.inner_write(buf)
-    }
-    fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
-        return os_pread(self.fd, buf.as_ptr(), buf.len(), offset);
-
-        #[cfg(windows)]
-        fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<int> {
-            unsafe {
-                let mut overlap: libc::OVERLAPPED = intrinsics::init();
-                let handle = libc::get_osfhandle(fd) as libc::HANDLE;
-                let mut bytes_read = 0;
-                overlap.Offset = offset as libc::DWORD;
-                overlap.OffsetHigh = (offset >> 32) as libc::DWORD;
-
-                match libc::ReadFile(handle, buf as libc::LPVOID,
-                                     amt as libc::DWORD,
-                                     &mut bytes_read, &mut overlap) {
-                    0 => Err(super::last_error()),
-                    _ => Ok(bytes_read as int)
-                }
-            }
-        }
-
-        #[cfg(unix)]
-        fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<int> {
-            match unsafe {
-                libc::pread(fd, buf as *libc::c_void, amt as libc::size_t,
-                            offset as libc::off_t)
-            } {
-                -1 => Err(super::last_error()),
-                n => Ok(n as int)
-            }
-        }
-    }
-    fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
-        return os_pwrite(self.fd, buf.as_ptr(), buf.len(), offset);
-
-        #[cfg(windows)]
-        fn os_pwrite(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<()> {
-            unsafe {
-                let mut overlap: libc::OVERLAPPED = intrinsics::init();
-                let handle = libc::get_osfhandle(fd) as libc::HANDLE;
-                overlap.Offset = offset as libc::DWORD;
-                overlap.OffsetHigh = (offset >> 32) as libc::DWORD;
-
-                match libc::WriteFile(handle, buf as libc::LPVOID,
-                                      amt as libc::DWORD,
-                                      ptr::mut_null(), &mut overlap) {
-                    0 => Err(super::last_error()),
-                    _ => Ok(()),
-                }
-            }
-        }
-
-        #[cfg(unix)]
-        fn os_pwrite(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<()> {
-            super::mkerr_libc(unsafe {
-                libc::pwrite(fd, buf as *libc::c_void, amt as libc::size_t,
-                             offset as libc::off_t)
-            } as c_int)
-        }
-    }
-    #[cfg(windows)]
-    fn seek(&mut self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
-        let whence = match style {
-            io::SeekSet => libc::FILE_BEGIN,
-            io::SeekEnd => libc::FILE_END,
-            io::SeekCur => libc::FILE_CURRENT,
-        };
-        unsafe {
-            let handle = libc::get_osfhandle(self.fd) as libc::HANDLE;
-            let mut newpos = 0;
-            match libc::SetFilePointerEx(handle, pos, &mut newpos, whence) {
-                0 => Err(super::last_error()),
-                _ => Ok(newpos as u64),
-            }
-        }
-    }
-    #[cfg(unix)]
-    fn seek(&mut self, pos: i64, whence: io::SeekStyle) -> Result<u64, IoError> {
-        let whence = match whence {
-            io::SeekSet => libc::SEEK_SET,
-            io::SeekEnd => libc::SEEK_END,
-            io::SeekCur => libc::SEEK_CUR,
-        };
-        let n = unsafe { libc::lseek(self.fd, pos as libc::off_t, whence) };
-        if n < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(n as u64)
-        }
-    }
-    fn tell(&self) -> Result<u64, IoError> {
-        let n = unsafe { libc::lseek(self.fd, 0, libc::SEEK_CUR) };
-        if n < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(n as u64)
-        }
-    }
-    fn fsync(&mut self) -> Result<(), IoError> {
-        return os_fsync(self.fd);
-
-        #[cfg(windows)]
-        fn os_fsync(fd: c_int) -> IoResult<()> {
-            super::mkerr_winbool(unsafe {
-                let handle = libc::get_osfhandle(fd);
-                libc::FlushFileBuffers(handle as libc::HANDLE)
-            })
-        }
-        #[cfg(unix)]
-        fn os_fsync(fd: c_int) -> IoResult<()> {
-            super::mkerr_libc(unsafe { libc::fsync(fd) })
-        }
-    }
-    #[cfg(windows)]
-    fn datasync(&mut self) -> Result<(), IoError> { return self.fsync(); }
-
-    #[cfg(not(windows))]
-    fn datasync(&mut self) -> Result<(), IoError> {
-        return super::mkerr_libc(os_datasync(self.fd));
-
-        #[cfg(target_os = "macos")]
-        fn os_datasync(fd: c_int) -> c_int {
-            unsafe { libc::fcntl(fd, libc::F_FULLFSYNC) }
-        }
-        #[cfg(target_os = "linux")]
-        fn os_datasync(fd: c_int) -> c_int { unsafe { libc::fdatasync(fd) } }
-        #[cfg(not(target_os = "macos"), not(target_os = "linux"))]
-        fn os_datasync(fd: c_int) -> c_int { unsafe { libc::fsync(fd) } }
-    }
-
-    #[cfg(windows)]
-    fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
-        let orig_pos = match self.tell() { Ok(i) => i, Err(e) => return Err(e) };
-        match self.seek(offset, io::SeekSet) {
-            Ok(_) => {}, Err(e) => return Err(e),
-        };
-        let ret = unsafe {
-            let handle = libc::get_osfhandle(self.fd) as libc::HANDLE;
-            match libc::SetEndOfFile(handle) {
-                0 => Err(super::last_error()),
-                _ => Ok(())
-            }
-        };
-        self.seek(orig_pos as i64, io::SeekSet);
-        return ret;
-    }
-    #[cfg(unix)]
-    fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
-        super::mkerr_libc(unsafe {
-            libc::ftruncate(self.fd, offset as libc::off_t)
-        })
-    }
-}
-
-impl rtio::RtioPipe for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
-        self.inner_read(buf)
-    }
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
-        self.inner_write(buf)
-    }
-}
-
-impl rtio::RtioTTY for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
-        self.inner_read(buf)
-    }
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
-        self.inner_write(buf)
-    }
-    fn set_raw(&mut self, _raw: bool) -> Result<(), IoError> {
-        Err(super::unimpl())
-    }
-    fn get_winsize(&mut self) -> Result<(int, int), IoError> {
-        Err(super::unimpl())
-    }
-    fn isatty(&self) -> bool { false }
-}
-
-impl Drop for FileDesc {
-    fn drop(&mut self) {
-        // closing stdio file handles makes no sense, so never do it
-        if self.close_on_drop && self.fd > libc::STDERR_FILENO {
-            unsafe { libc::close(self.fd); }
-        }
-    }
-}
-
-pub struct CFile {
-    priv file: *libc::FILE,
-    priv fd: FileDesc,
-}
-
-impl CFile {
-    /// Create a `CFile` from an open `FILE` pointer.
-    ///
-    /// The `CFile` takes ownership of the `FILE` pointer and will close it upon
-    /// destruction.
-    pub fn new(file: *libc::FILE) -> CFile {
-        CFile {
-            file: file,
-            fd: FileDesc::new(unsafe { libc::fileno(file) }, false)
-        }
-    }
-
-    pub fn flush(&mut self) -> Result<(), IoError> {
-        super::mkerr_libc(unsafe { libc::fflush(self.file) })
-    }
-}
-
-impl rtio::RtioFileStream for CFile {
-    fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
-        let ret = keep_going(buf, |buf, len| {
-            unsafe {
-                libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
-                            self.file) as i64
-            }
-        });
-        if ret == 0 {
-            Err(io::standard_error(io::EndOfFile))
-        } else if ret < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(ret as int)
-        }
-    }
-
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
-        let ret = keep_going(buf, |buf, len| {
-            unsafe {
-                libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
-                            self.file) as i64
-            }
-        });
-        if ret < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(())
-        }
-    }
-
-    fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
-        self.flush();
-        self.fd.pread(buf, offset)
-    }
-    fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
-        self.flush();
-        self.fd.pwrite(buf, offset)
-    }
-    fn seek(&mut self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
-        let whence = match style {
-            io::SeekSet => libc::SEEK_SET,
-            io::SeekEnd => libc::SEEK_END,
-            io::SeekCur => libc::SEEK_CUR,
-        };
-        let n = unsafe { libc::fseek(self.file, pos as libc::c_long, whence) };
-        if n < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(n as u64)
-        }
-    }
-    fn tell(&self) -> Result<u64, IoError> {
-        let ret = unsafe { libc::ftell(self.file) };
-        if ret < 0 {
-            Err(super::last_error())
-        } else {
-            Ok(ret as u64)
-        }
-    }
-    fn fsync(&mut self) -> Result<(), IoError> {
-        self.flush();
-        self.fd.fsync()
-    }
-    fn datasync(&mut self) -> Result<(), IoError> {
-        self.flush();
-        self.fd.fsync()
-    }
-    fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
-        self.flush();
-        self.fd.truncate(offset)
-    }
-}
-
-impl Drop for CFile {
-    fn drop(&mut self) {
-        unsafe { libc::fclose(self.file); }
-    }
-}
-
-pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
-        -> IoResult<FileDesc> {
-    let flags = match fm {
-        io::Open => 0,
-        io::Append => libc::O_APPEND,
-        io::Truncate => libc::O_TRUNC,
-    };
-    // Opening with a write permission must silently create the file.
-    let (flags, mode) = match fa {
-        io::Read => (flags | libc::O_RDONLY, 0),
-        io::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
-                      libc::S_IRUSR | libc::S_IWUSR),
-        io::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
-                          libc::S_IRUSR | libc::S_IWUSR),
-    };
-
-    return match os_open(path, flags, mode) {
-        -1 => Err(super::last_error()),
-        fd => Ok(FileDesc::new(fd, true)),
-    };
-
-    #[cfg(windows)]
-    fn os_open(path: &CString, flags: c_int, mode: c_int) -> c_int {
-        as_utf16_p(path.as_str().unwrap(), |path| {
-            unsafe { libc::wopen(path, flags, mode) }
-        })
-    }
-
-    #[cfg(unix)]
-    fn os_open(path: &CString, flags: c_int, mode: c_int) -> c_int {
-        unsafe { libc::open(path.with_ref(|p| p), flags, mode) }
-    }
-}
-
-pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
-    return os_mkdir(p, mode as c_int);
-
-    #[cfg(windows)]
-    fn os_mkdir(p: &CString, _mode: c_int) -> IoResult<()> {
-        super::mkerr_winbool(unsafe {
-            // FIXME: turn mode into something useful? #2623
-            as_utf16_p(p.as_str().unwrap(), |buf| {
-                libc::CreateDirectoryW(buf, ptr::mut_null())
-            })
-        })
-    }
-
-    #[cfg(unix)]
-    fn os_mkdir(p: &CString, mode: c_int) -> IoResult<()> {
-        super::mkerr_libc(unsafe {
-            libc::mkdir(p.with_ref(|p| p), mode as libc::mode_t)
-        })
-    }
-}
-
-pub fn readdir(p: &CString) -> IoResult<~[Path]> {
-    fn prune(root: &CString, dirs: ~[Path]) -> ~[Path] {
-        let root = unsafe { CString::new(root.with_ref(|p| p), false) };
-        let root = Path::new(root);
-
-        dirs.move_iter().filter(|path| {
-            path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..")
-        }).map(|path| root.join(path)).collect()
-    }
-
-    unsafe {
-        #[cfg(not(windows))]
-        unsafe fn get_list(p: &CString) -> IoResult<~[Path]> {
-            use libc::{dirent_t};
-            use libc::{opendir, readdir, closedir};
-            extern {
-                fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
-            }
-            debug!("os::list_dir -- BEFORE OPENDIR");
-
-            let dir_ptr = p.with_ref(|buf| opendir(buf));
-
-            if (dir_ptr as uint != 0) {
-                let mut paths = ~[];
-                debug!("os::list_dir -- opendir() SUCCESS");
-                let mut entry_ptr = readdir(dir_ptr);
-                while (entry_ptr as uint != 0) {
-                    let cstr = CString::new(rust_list_dir_val(entry_ptr), false);
-                    paths.push(Path::new(cstr));
-                    entry_ptr = readdir(dir_ptr);
-                }
-                closedir(dir_ptr);
-                Ok(paths)
-            } else {
-                Err(super::last_error())
-            }
-        }
-
-        #[cfg(windows)]
-        unsafe fn get_list(p: &CString) -> IoResult<~[Path]> {
-            use libc::consts::os::extra::INVALID_HANDLE_VALUE;
-            use libc::{wcslen, free};
-            use libc::funcs::extra::kernel32::{
-                FindFirstFileW,
-                FindNextFileW,
-                FindClose,
-            };
-            use libc::types::os::arch::extra::HANDLE;
-            use os::win32::{
-                as_utf16_p
-            };
-            use rt::global_heap::malloc_raw;
-
-            #[nolink]
-            extern {
-                fn rust_list_dir_wfd_size() -> libc::size_t;
-                fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16;
-            }
-            let p = CString::new(p.with_ref(|p| p), false);
-            let p = Path::new(p);
-            let star = p.join("*");
-            as_utf16_p(star.as_str().unwrap(), |path_ptr| {
-                let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
-                let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE);
-                if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
-                    let mut paths = ~[];
-                    let mut more_files = 1 as libc::c_int;
-                    while more_files != 0 {
-                        let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr);
-                        if fp_buf as uint == 0 {
-                            fail!("os::list_dir() failure: got null ptr from wfd");
-                        }
-                        else {
-                            let fp_vec = vec::from_buf(
-                                fp_buf, wcslen(fp_buf) as uint);
-                            let fp_str = str::from_utf16(fp_vec);
-                            paths.push(Path::new(fp_str));
-                        }
-                        more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE);
-                    }
-                    FindClose(find_handle);
-                    free(wfd_ptr);
-                    Ok(paths)
-                } else {
-                    Err(super::last_error())
-                }
-            })
-        }
-
-        get_list(p).map(|paths| prune(p, paths))
-    }
-}
-
-pub fn unlink(p: &CString) -> IoResult<()> {
-    return os_unlink(p);
-
-    #[cfg(windows)]
-    fn os_unlink(p: &CString) -> IoResult<()> {
-        super::mkerr_winbool(unsafe {
-            as_utf16_p(p.as_str().unwrap(), |buf| {
-                libc::DeleteFileW(buf)
-            })
-        })
-    }
-
-    #[cfg(unix)]
-    fn os_unlink(p: &CString) -> IoResult<()> {
-        super::mkerr_libc(unsafe { libc::unlink(p.with_ref(|p| p)) })
-    }
-}
-
-pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
-    return os_rename(old, new);
-
-    #[cfg(windows)]
-    fn os_rename(old: &CString, new: &CString) -> IoResult<()> {
-        super::mkerr_winbool(unsafe {
-            as_utf16_p(old.as_str().unwrap(), |old| {
-                as_utf16_p(new.as_str().unwrap(), |new| {
-                    libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING)
-                })
-            })
-        })
-    }
-
-    #[cfg(unix)]
-    fn os_rename(old: &CString, new: &CString) -> IoResult<()> {
-        super::mkerr_libc(unsafe {
-            libc::rename(old.with_ref(|p| p), new.with_ref(|p| p))
-        })
-    }
-}
-
-pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
-    return super::mkerr_libc(os_chmod(p, mode as c_int));
-
-    #[cfg(windows)]
-    fn os_chmod(p: &CString, mode: c_int) -> c_int {
-        unsafe {
-            as_utf16_p(p.as_str().unwrap(), |p| libc::wchmod(p, mode))
-        }
-    }
-
-    #[cfg(unix)]
-    fn os_chmod(p: &CString, mode: c_int) -> c_int {
-        unsafe { libc::chmod(p.with_ref(|p| p), mode as libc::mode_t) }
-    }
-}
-
-pub fn rmdir(p: &CString) -> IoResult<()> {
-    return super::mkerr_libc(os_rmdir(p));
-
-    #[cfg(windows)]
-    fn os_rmdir(p: &CString) -> c_int {
-        unsafe {
-            as_utf16_p(p.as_str().unwrap(), |p| libc::wrmdir(p))
-        }
-    }
-
-    #[cfg(unix)]
-    fn os_rmdir(p: &CString) -> c_int {
-        unsafe { libc::rmdir(p.with_ref(|p| p)) }
-    }
-}
-
-pub fn chown(p: &CString, uid: int, gid: int) -> IoResult<()> {
-    return super::mkerr_libc(os_chown(p, uid, gid));
-
-    // libuv has this as a no-op, so seems like this should as well?
-    #[cfg(windows)]
-    fn os_chown(_p: &CString, _uid: int, _gid: int) -> c_int { 0 }
-
-    #[cfg(unix)]
-    fn os_chown(p: &CString, uid: int, gid: int) -> c_int {
-        unsafe {
-            libc::chown(p.with_ref(|p| p), uid as libc::uid_t,
-                        gid as libc::gid_t)
-        }
-    }
-}
-
-pub fn readlink(p: &CString) -> IoResult<Path> {
-    return os_readlink(p);
-
-    // XXX: I have a feeling that this reads intermediate symlinks as well.
-    #[cfg(windows)]
-    fn os_readlink(p: &CString) -> IoResult<Path> {
-        let handle = unsafe {
-            as_utf16_p(p.as_str().unwrap(), |p| {
-                libc::CreateFileW(p,
-                                  libc::GENERIC_READ,
-                                  libc::FILE_SHARE_READ,
-                                  ptr::mut_null(),
-                                  libc::OPEN_EXISTING,
-                                  libc::FILE_ATTRIBUTE_NORMAL,
-                                  ptr::mut_null())
-            })
-        };
-        if handle == ptr::mut_null() { return Err(super::last_error()) }
-        let ret = fill_utf16_buf_and_decode(|buf, sz| {
-            unsafe {
-                libc::GetFinalPathNameByHandleW(handle, buf as *u16, sz,
-                                                libc::VOLUME_NAME_NT)
-            }
-        });
-        let ret = match ret {
-            Some(s) => Ok(Path::new(s)),
-            None => Err(super::last_error()),
-        };
-        unsafe { libc::CloseHandle(handle) };
-        return ret;
-
-    }
-
-    #[cfg(unix)]
-    fn os_readlink(p: &CString) -> IoResult<Path> {
-        let p = p.with_ref(|p| p);
-        let mut len = unsafe { libc::pathconf(p, libc::_PC_NAME_MAX) };
-        if len == -1 {
-            len = 1024; // XXX: read PATH_MAX from C ffi?
-        }
-        let mut buf = vec::with_capacity::<u8>(len as uint);
-        match unsafe {
-            libc::readlink(p, buf.as_ptr() as *mut libc::c_char,
-                           len as libc::size_t)
-        } {
-            -1 => Err(super::last_error()),
-            n => {
-                assert!(n > 0);
-                unsafe { buf.set_len(n as uint); }
-                Ok(Path::new(buf))
-            }
-        }
-    }
-}
-
-pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
-    return os_symlink(src, dst);
-
-    #[cfg(windows)]
-    fn os_symlink(src: &CString, dst: &CString) -> IoResult<()> {
-        super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
-            as_utf16_p(dst.as_str().unwrap(), |dst| {
-                unsafe { libc::CreateSymbolicLinkW(dst, src, 0) }
-            })
-        }))
-    }
-
-    #[cfg(unix)]
-    fn os_symlink(src: &CString, dst: &CString) -> IoResult<()> {
-        super::mkerr_libc(unsafe {
-            libc::symlink(src.with_ref(|p| p), dst.with_ref(|p| p))
-        })
-    }
-}
-
-pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
-    return os_link(src, dst);
-
-    #[cfg(windows)]
-    fn os_link(src: &CString, dst: &CString) -> IoResult<()> {
-        super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
-            as_utf16_p(dst.as_str().unwrap(), |dst| {
-                unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) }
-            })
-        }))
-    }
-
-    #[cfg(unix)]
-    fn os_link(src: &CString, dst: &CString) -> IoResult<()> {
-        super::mkerr_libc(unsafe {
-            libc::link(src.with_ref(|p| p), dst.with_ref(|p| p))
-        })
-    }
-}
-
-#[cfg(windows)]
-fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
-    let path = unsafe { CString::new(path.with_ref(|p| p), false) };
-    let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
-        libc::S_IFREG => io::TypeFile,
-        libc::S_IFDIR => io::TypeDirectory,
-        libc::S_IFIFO => io::TypeNamedPipe,
-        libc::S_IFBLK => io::TypeBlockSpecial,
-        libc::S_IFLNK => io::TypeSymlink,
-        _ => io::TypeUnknown,
-    };
-
-    io::FileStat {
-        path: Path::new(path),
-        size: stat.st_size as u64,
-        kind: kind,
-        perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
-        created: stat.st_ctime as u64,
-        modified: stat.st_mtime as u64,
-        accessed: stat.st_atime as u64,
-        unstable: io::UnstableFileStat {
-            device: stat.st_dev as u64,
-            inode: stat.st_ino as u64,
-            rdev: stat.st_rdev as u64,
-            nlink: stat.st_nlink as u64,
-            uid: stat.st_uid as u64,
-            gid: stat.st_gid as u64,
-            blksize: 0,
-            blocks: 0,
-            flags: 0,
-            gen: 0,
-        }
-    }
-}
-
-#[cfg(unix)]
-fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
-    let path = unsafe { CString::new(path.with_ref(|p| p), false) };
-
-    // FileStat times are in milliseconds
-    fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
-
-    let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
-        libc::S_IFREG => io::TypeFile,
-        libc::S_IFDIR => io::TypeDirectory,
-        libc::S_IFIFO => io::TypeNamedPipe,
-        libc::S_IFBLK => io::TypeBlockSpecial,
-        libc::S_IFLNK => io::TypeSymlink,
-        _ => io::TypeUnknown,
-    };
-
-    #[cfg(not(target_os = "linux"), not(target_os = "android"))]
-    fn flags(stat: &libc::stat) -> u64 { stat.st_flags as u64 }
-    #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
-    fn flags(_stat: &libc::stat) -> u64 { 0 }
-
-    #[cfg(not(target_os = "linux"), not(target_os = "android"))]
-    fn gen(stat: &libc::stat) -> u64 { stat.st_gen as u64 }
-    #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
-    fn gen(_stat: &libc::stat) -> u64 { 0 }
-
-    io::FileStat {
-        path: Path::new(path),
-        size: stat.st_size as u64,
-        kind: kind,
-        perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
-        created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
-        modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
-        accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
-        unstable: io::UnstableFileStat {
-            device: stat.st_dev as u64,
-            inode: stat.st_ino as u64,
-            rdev: stat.st_rdev as u64,
-            nlink: stat.st_nlink as u64,
-            uid: stat.st_uid as u64,
-            gid: stat.st_gid as u64,
-            blksize: stat.st_blksize as u64,
-            blocks: stat.st_blocks as u64,
-            flags: flags(stat),
-            gen: gen(stat),
-        }
-    }
-}
-
-pub fn stat(p: &CString) -> IoResult<io::FileStat> {
-    return os_stat(p);
-
-    #[cfg(windows)]
-    fn os_stat(p: &CString) -> IoResult<io::FileStat> {
-        let mut stat: libc::stat = unsafe { intrinsics::uninit() };
-        as_utf16_p(p.as_str().unwrap(), |up| {
-            match unsafe { libc::wstat(up, &mut stat) } {
-                0 => Ok(mkstat(&stat, p)),
-                _ => Err(super::last_error()),
-            }
-        })
-    }
-
-    #[cfg(unix)]
-    fn os_stat(p: &CString) -> IoResult<io::FileStat> {
-        let mut stat: libc::stat = unsafe { intrinsics::uninit() };
-        match unsafe { libc::stat(p.with_ref(|p| p), &mut stat) } {
-            0 => Ok(mkstat(&stat, p)),
-            _ => Err(super::last_error()),
-        }
-    }
-}
-
-pub fn lstat(p: &CString) -> IoResult<io::FileStat> {
-    return os_lstat(p);
-
-    // XXX: windows implementation is missing
-    #[cfg(windows)]
-    fn os_lstat(_p: &CString) -> IoResult<io::FileStat> {
-        Err(super::unimpl())
-    }
-
-    #[cfg(unix)]
-    fn os_lstat(p: &CString) -> IoResult<io::FileStat> {
-        let mut stat: libc::stat = unsafe { intrinsics::uninit() };
-        match unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) } {
-            0 => Ok(mkstat(&stat, p)),
-            _ => Err(super::last_error()),
-        }
-    }
-}
-
-pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
-    return super::mkerr_libc(os_utime(p, atime, mtime));
-
-    #[cfg(windows)]
-    fn os_utime(p: &CString, atime: u64, mtime: u64) -> c_int {
-        let buf = libc::utimbuf {
-            actime: (atime / 1000) as libc::time64_t,
-            modtime: (mtime / 1000) as libc::time64_t,
-        };
-        unsafe {
-            as_utf16_p(p.as_str().unwrap(), |p| libc::wutime(p, &buf))
-        }
-    }
-
-    #[cfg(unix)]
-    fn os_utime(p: &CString, atime: u64, mtime: u64) -> c_int {
-        let buf = libc::utimbuf {
-            actime: (atime / 1000) as libc::time_t,
-            modtime: (mtime / 1000) as libc::time_t,
-        };
-        unsafe { libc::utime(p.with_ref(|p| p), &buf) }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use io::native::file::{CFile, FileDesc};
-    use io;
-    use libc;
-    use os;
-    use result::Ok;
-    use rt::rtio::RtioFileStream;
-
-    #[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer
-    #[test]
-    fn test_file_desc() {
-        // Run this test with some pipes so we don't have to mess around with
-        // opening or closing files.
-        unsafe {
-            let os::Pipe { input, out } = os::pipe();
-            let mut reader = FileDesc::new(input, true);
-            let mut writer = FileDesc::new(out, true);
-
-            writer.inner_write(bytes!("test"));
-            let mut buf = [0u8, ..4];
-            match reader.inner_read(buf) {
-                Ok(4) => {
-                    assert_eq!(buf[0], 't' as u8);
-                    assert_eq!(buf[1], 'e' as u8);
-                    assert_eq!(buf[2], 's' as u8);
-                    assert_eq!(buf[3], 't' as u8);
-                }
-                r => fail!("invalid read: {:?}", r)
-            }
-
-            assert!(writer.inner_read(buf).is_err());
-            assert!(reader.inner_write(buf).is_err());
-        }
-    }
-
-    #[ignore(cfg(windows))] // apparently windows doesn't like tmpfile
-    #[test]
-    fn test_cfile() {
-        unsafe {
-            let f = libc::tmpfile();
-            assert!(!f.is_null());
-            let mut file = CFile::new(f);
-
-            file.write(bytes!("test"));
-            let mut buf = [0u8, ..4];
-            file.seek(0, io::SeekSet);
-            match file.read(buf) {
-                Ok(4) => {
-                    assert_eq!(buf[0], 't' as u8);
-                    assert_eq!(buf[1], 'e' as u8);
-                    assert_eq!(buf[2], 's' as u8);
-                    assert_eq!(buf[3], 't' as u8);
-                }
-                r => fail!("invalid read: {:?}", r)
-            }
-        }
-    }
-}
diff --git a/src/libstd/io/native/mod.rs b/src/libstd/io/native/mod.rs
deleted file mode 100644
index d9dccc84f1c..00000000000
--- a/src/libstd/io/native/mod.rs
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2013 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.
-
-//! Native thread-blocking I/O implementation
-//!
-//! This module contains the implementation of native thread-blocking
-//! implementations of I/O on all platforms. This module is not intended to be
-//! used directly, but rather the rust runtime will fall back to using it if
-//! necessary.
-//!
-//! Rust code normally runs inside of green tasks with a local scheduler using
-//! asynchronous I/O to cooperate among tasks. This model is not always
-//! available, however, and that's where these native implementations come into
-//! play. The only dependencies of these modules are the normal system libraries
-//! that you would find on the respective platform.
-
-use c_str::CString;
-use comm::SharedChan;
-use libc::c_int;
-use libc;
-use option::{Option, None, Some};
-use os;
-use path::Path;
-use result::{Result, Ok, Err};
-use rt::rtio;
-use rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket, RtioUnixListener,
-               RtioPipe, RtioFileStream, RtioProcess, RtioSignal, RtioTTY,
-               CloseBehavior, RtioTimer};
-use io;
-use io::IoError;
-use io::net::ip::SocketAddr;
-use io::process::ProcessConfig;
-use io::signal::Signum;
-use ai = io::net::addrinfo;
-
-// Local re-exports
-pub use self::file::FileDesc;
-pub use self::process::Process;
-
-// Native I/O implementations
-pub mod file;
-pub mod process;
-
-type IoResult<T> = Result<T, IoError>;
-
-fn unimpl() -> IoError {
-    IoError {
-        kind: io::IoUnavailable,
-        desc: "unimplemented I/O interface",
-        detail: None,
-    }
-}
-
-fn last_error() -> IoError {
-    #[cfg(windows)]
-    fn get_err(errno: i32) -> (io::IoErrorKind, &'static str) {
-        match errno {
-            libc::EOF => (io::EndOfFile, "end of file"),
-            _ => (io::OtherIoError, "unknown error"),
-        }
-    }
-
-    #[cfg(not(windows))]
-    fn get_err(errno: i32) -> (io::IoErrorKind, &'static str) {
-        // XXX: this should probably be a bit more descriptive...
-        match errno {
-            libc::EOF => (io::EndOfFile, "end of file"),
-
-            // 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"),
-        }
-    }
-
-    let (kind, desc) = get_err(os::errno() as i32);
-    IoError {
-        kind: kind,
-        desc: desc,
-        detail: Some(os::last_os_error())
-    }
-}
-
-// unix has nonzero values as errors
-fn mkerr_libc(ret: libc::c_int) -> IoResult<()> {
-    if ret != 0 {
-        Err(last_error())
-    } else {
-        Ok(())
-    }
-}
-
-// windows has zero values as errors
-#[cfg(windows)]
-fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
-    if ret == 0 {
-        Err(last_error())
-    } else {
-        Ok(())
-    }
-}
-
-/// Implementation of rt::rtio's IoFactory trait to generate handles to the
-/// native I/O functionality.
-pub struct IoFactory;
-
-impl rtio::IoFactory for IoFactory {
-    // networking
-    fn tcp_connect(&mut self, _addr: SocketAddr) -> IoResult<~RtioTcpStream> {
-        Err(unimpl())
-    }
-    fn tcp_bind(&mut self, _addr: SocketAddr) -> IoResult<~RtioTcpListener> {
-        Err(unimpl())
-    }
-    fn udp_bind(&mut self, _addr: SocketAddr) -> IoResult<~RtioUdpSocket> {
-        Err(unimpl())
-    }
-    fn unix_bind(&mut self, _path: &CString) -> IoResult<~RtioUnixListener> {
-        Err(unimpl())
-    }
-    fn unix_connect(&mut self, _path: &CString) -> IoResult<~RtioPipe> {
-        Err(unimpl())
-    }
-    fn get_host_addresses(&mut self, _host: Option<&str>, _servname: Option<&str>,
-                          _hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
-        Err(unimpl())
-    }
-
-    // filesystem operations
-    fn fs_from_raw_fd(&mut self, fd: c_int,
-                      close: CloseBehavior) -> ~RtioFileStream {
-        let close = match close {
-            rtio::CloseSynchronously | rtio::CloseAsynchronously => true,
-            rtio::DontClose => false
-        };
-        ~file::FileDesc::new(fd, close) as ~RtioFileStream
-    }
-    fn fs_open(&mut self, path: &CString, fm: io::FileMode, fa: io::FileAccess)
-        -> IoResult<~RtioFileStream> {
-        file::open(path, fm, fa).map(|fd| ~fd as ~RtioFileStream)
-    }
-    fn fs_unlink(&mut self, path: &CString) -> IoResult<()> {
-        file::unlink(path)
-    }
-    fn fs_stat(&mut self, path: &CString) -> IoResult<io::FileStat> {
-        file::stat(path)
-    }
-    fn fs_mkdir(&mut self, path: &CString,
-                mode: io::FilePermission) -> IoResult<()> {
-        file::mkdir(path, mode)
-    }
-    fn fs_chmod(&mut self, path: &CString,
-                mode: io::FilePermission) -> IoResult<()> {
-        file::chmod(path, mode)
-    }
-    fn fs_rmdir(&mut self, path: &CString) -> IoResult<()> {
-        file::rmdir(path)
-    }
-    fn fs_rename(&mut self, path: &CString, to: &CString) -> IoResult<()> {
-        file::rename(path, to)
-    }
-    fn fs_readdir(&mut self, path: &CString, _flags: c_int) -> IoResult<~[Path]> {
-        file::readdir(path)
-    }
-    fn fs_lstat(&mut self, path: &CString) -> IoResult<io::FileStat> {
-        file::lstat(path)
-    }
-    fn fs_chown(&mut self, path: &CString, uid: int, gid: int) -> IoResult<()> {
-        file::chown(path, uid, gid)
-    }
-    fn fs_readlink(&mut self, path: &CString) -> IoResult<Path> {
-        file::readlink(path)
-    }
-    fn fs_symlink(&mut self, src: &CString, dst: &CString) -> IoResult<()> {
-        file::symlink(src, dst)
-    }
-    fn fs_link(&mut self, src: &CString, dst: &CString) -> IoResult<()> {
-        file::link(src, dst)
-    }
-    fn fs_utime(&mut self, src: &CString, atime: u64,
-                mtime: u64) -> IoResult<()> {
-        file::utime(src, atime, mtime)
-    }
-
-    // misc
-    fn timer_init(&mut self) -> IoResult<~RtioTimer> {
-        Err(unimpl())
-    }
-    fn spawn(&mut self, config: ProcessConfig)
-            -> IoResult<(~RtioProcess, ~[Option<~RtioPipe>])> {
-        process::Process::spawn(config).map(|(p, io)| {
-            (~p as ~RtioProcess,
-             io.move_iter().map(|p| p.map(|p| ~p as ~RtioPipe)).collect())
-        })
-    }
-    fn pipe_open(&mut self, fd: c_int) -> IoResult<~RtioPipe> {
-        Ok(~file::FileDesc::new(fd, true) as ~RtioPipe)
-    }
-    fn tty_open(&mut self, fd: c_int, _readable: bool) -> IoResult<~RtioTTY> {
-        if unsafe { libc::isatty(fd) } != 0 {
-            // Don't ever close the stdio file descriptors, nothing good really
-            // comes of that.
-            Ok(~file::FileDesc::new(fd, fd > libc::STDERR_FILENO) as ~RtioTTY)
-        } else {
-            Err(IoError {
-                kind: io::MismatchedFileTypeForOperation,
-                desc: "file descriptor is not a TTY",
-                detail: None,
-            })
-        }
-    }
-    fn signal(&mut self, _signal: Signum, _channel: SharedChan<Signum>)
-        -> IoResult<~RtioSignal> {
-        Err(unimpl())
-    }
-}
-
-pub static mut NATIVE_IO_FACTORY: IoFactory = IoFactory;
-
diff --git a/src/libstd/io/native/process.rs b/src/libstd/io/native/process.rs
deleted file mode 100644
index ef972dc4d0a..00000000000
--- a/src/libstd/io/native/process.rs
+++ /dev/null
@@ -1,654 +0,0 @@
-// Copyright 2012-2013 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 io;
-use libc::{pid_t, c_void, c_int};
-use libc;
-use os;
-use prelude::*;
-use ptr;
-use rt::rtio;
-use super::file;
-#[cfg(windows)]
-use cast;
-
-use p = io::process;
-
-/**
- * A value representing a child process.
- *
- * The lifetime of this value is linked to the lifetime of the actual
- * process - the Process destructor calls self.finish() which waits
- * for the process to terminate.
- */
-pub struct Process {
-    /// The unique id of the process (this should never be negative).
-    priv pid: pid_t,
-
-    /// A handle to the process - on unix this will always be NULL, but on
-    /// windows it will be a HANDLE to the process, which will prevent the
-    /// pid being re-used until the handle is closed.
-    priv handle: *(),
-
-    /// None until finish() is called.
-    priv exit_code: Option<int>,
-}
-
-impl Process {
-    /// Creates a new process using native process-spawning abilities provided
-    /// by the OS. Operations on this process will be blocking instead of using
-    /// the runtime for sleeping just this current task.
-    ///
-    /// # Arguments
-    ///
-    /// * prog - the program to run
-    /// * args - the arguments to pass to the program, not including the program
-    ///          itself
-    /// * env - an optional environment to specify for the child process. If
-    ///         this value is `None`, then the child will inherit the parent's
-    ///         environment
-    /// * cwd - an optionally specified current working directory of the child,
-    ///         defaulting to the parent's current working directory
-    /// * stdin, stdout, stderr - These optionally specified file descriptors
-    ///     dictate where the stdin/out/err of the child process will go. If
-    ///     these are `None`, then this module will bind the input/output to an
-    ///     os pipe instead. This process takes ownership of these file
-    ///     descriptors, closing them upon destruction of the process.
-    pub fn spawn(config: p::ProcessConfig)
-        -> Result<(Process, ~[Option<file::FileDesc>]), io::IoError>
-    {
-        // right now we only handle stdin/stdout/stderr.
-        if config.io.len() > 3 {
-            return Err(super::unimpl());
-        }
-
-        fn get_io(io: &[p::StdioContainer],
-                  ret: &mut ~[Option<file::FileDesc>],
-                  idx: uint) -> (Option<os::Pipe>, c_int) {
-            if idx >= io.len() { return (None, -1); }
-            ret.push(None);
-            match io[idx] {
-                p::Ignored => (None, -1),
-                p::InheritFd(fd) => (None, fd),
-                p::CreatePipe(readable, _writable) => {
-                    let pipe = os::pipe();
-                    let (theirs, ours) = if readable {
-                        (pipe.input, pipe.out)
-                    } else {
-                        (pipe.out, pipe.input)
-                    };
-                    ret[idx] = Some(file::FileDesc::new(ours, true));
-                    (Some(pipe), theirs)
-                }
-            }
-        }
-
-        let mut ret_io = ~[];
-        let (in_pipe, in_fd) = get_io(config.io, &mut ret_io, 0);
-        let (out_pipe, out_fd) = get_io(config.io, &mut ret_io, 1);
-        let (err_pipe, err_fd) = get_io(config.io, &mut ret_io, 2);
-
-        let env = config.env.map(|a| a.to_owned());
-        let cwd = config.cwd.map(|a| Path::new(a));
-        let res = spawn_process_os(config.program, config.args, env,
-                                   cwd.as_ref(), in_fd, out_fd, err_fd);
-
-        unsafe {
-            for pipe in in_pipe.iter() { libc::close(pipe.input); }
-            for pipe in out_pipe.iter() { libc::close(pipe.out); }
-            for pipe in err_pipe.iter() { libc::close(pipe.out); }
-        }
-
-        Ok((Process { pid: res.pid, handle: res.handle, exit_code: None }, ret_io))
-    }
-}
-
-impl rtio::RtioProcess for Process {
-    fn id(&self) -> pid_t { self.pid }
-
-    fn wait(&mut self) -> p::ProcessExit {
-        let code = match self.exit_code {
-            Some(code) => code,
-            None => {
-                let code = waitpid(self.pid);
-                self.exit_code = Some(code);
-                code
-            }
-        };
-        return p::ExitStatus(code); // XXX: this is wrong
-    }
-
-    fn kill(&mut self, signum: int) -> Result<(), io::IoError> {
-        // if the process has finished, and therefore had waitpid called,
-        // and we kill it, then on unix we might ending up killing a
-        // newer process that happens to have the same (re-used) id
-        match self.exit_code {
-            Some(..) => return Err(io::IoError {
-                kind: io::OtherIoError,
-                desc: "can't kill an exited process",
-                detail: None,
-            }),
-            None => {}
-        }
-        return unsafe { killpid(self.pid, signum) };
-
-        #[cfg(windows)]
-        unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
-            match signal {
-                io::process::PleaseExitSignal | io::process::MustDieSignal => {
-                    libc::funcs::extra::kernel32::TerminateProcess(
-                        cast::transmute(pid), 1);
-                    Ok(())
-                }
-                _ => Err(io::IoError {
-                    kind: io::OtherIoError,
-                    desc: "unsupported signal on windows",
-                    detail: None,
-                })
-            }
-        }
-
-        #[cfg(not(windows))]
-        unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
-            libc::funcs::posix88::signal::kill(pid, signal as c_int);
-            Ok(())
-        }
-    }
-}
-
-impl Drop for Process {
-    fn drop(&mut self) {
-        free_handle(self.handle);
-    }
-}
-
-struct SpawnProcessResult {
-    pid: pid_t,
-    handle: *(),
-}
-
-#[cfg(windows)]
-fn spawn_process_os(prog: &str, args: &[~str],
-                    env: Option<~[(~str, ~str)]>,
-                    dir: Option<&Path>,
-                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
-    use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
-    use libc::consts::os::extra::{
-        TRUE, FALSE,
-        STARTF_USESTDHANDLES,
-        INVALID_HANDLE_VALUE,
-        DUPLICATE_SAME_ACCESS
-    };
-    use libc::funcs::extra::kernel32::{
-        GetCurrentProcess,
-        DuplicateHandle,
-        CloseHandle,
-        CreateProcessA
-    };
-    use libc::funcs::extra::msvcrt::get_osfhandle;
-
-    use mem;
-
-    unsafe {
-
-        let mut si = zeroed_startupinfo();
-        si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
-        si.dwFlags = STARTF_USESTDHANDLES;
-
-        let cur_proc = GetCurrentProcess();
-
-        let orig_std_in = get_osfhandle(in_fd) as HANDLE;
-        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
-        }
-
-        let orig_std_out = get_osfhandle(out_fd) as HANDLE;
-        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
-        }
-
-        let orig_std_err = get_osfhandle(err_fd) as HANDLE;
-        if orig_std_err == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
-        }
-
-        let cmd = make_command_line(prog, args);
-        let mut pi = zeroed_process_information();
-        let mut create_err = None;
-
-        with_envp(env, |envp| {
-            with_dirp(dir, |dirp| {
-                cmd.with_c_str(|cmdp| {
-                    let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
-                                                 ptr::mut_null(), ptr::mut_null(), TRUE,
-                                                 0, envp, dirp, &mut si, &mut pi);
-                    if created == FALSE {
-                        create_err = Some(os::last_os_error());
-                    }
-                })
-            })
-        });
-
-        CloseHandle(si.hStdInput);
-        CloseHandle(si.hStdOutput);
-        CloseHandle(si.hStdError);
-
-        for msg in create_err.iter() {
-            fail!("failure in CreateProcess: {}", *msg);
-        }
-
-        // We close the thread handle because we don't care about keeping the
-        // thread id valid, and we aren't keeping the thread handle around to be
-        // able to close it later. We don't close the process handle however
-        // because we want the process id to stay valid at least until the
-        // calling code closes the process handle.
-        CloseHandle(pi.hThread);
-
-        SpawnProcessResult {
-            pid: pi.dwProcessId as pid_t,
-            handle: pi.hProcess as *()
-        }
-    }
-}
-
-#[cfg(windows)]
-fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO {
-    libc::types::os::arch::extra::STARTUPINFO {
-        cb: 0,
-        lpReserved: ptr::mut_null(),
-        lpDesktop: ptr::mut_null(),
-        lpTitle: ptr::mut_null(),
-        dwX: 0,
-        dwY: 0,
-        dwXSize: 0,
-        dwYSize: 0,
-        dwXCountChars: 0,
-        dwYCountCharts: 0,
-        dwFillAttribute: 0,
-        dwFlags: 0,
-        wShowWindow: 0,
-        cbReserved2: 0,
-        lpReserved2: ptr::mut_null(),
-        hStdInput: ptr::mut_null(),
-        hStdOutput: ptr::mut_null(),
-        hStdError: ptr::mut_null()
-    }
-}
-
-#[cfg(windows)]
-fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION {
-    libc::types::os::arch::extra::PROCESS_INFORMATION {
-        hProcess: ptr::mut_null(),
-        hThread: ptr::mut_null(),
-        dwProcessId: 0,
-        dwThreadId: 0
-    }
-}
-
-// FIXME: this is only pub so it can be tested (see issue #4536)
-#[cfg(windows)]
-pub fn make_command_line(prog: &str, args: &[~str]) -> ~str {
-    let mut cmd = ~"";
-    append_arg(&mut cmd, prog);
-    for arg in args.iter() {
-        cmd.push_char(' ');
-        append_arg(&mut cmd, *arg);
-    }
-    return cmd;
-
-    fn append_arg(cmd: &mut ~str, arg: &str) {
-        let quote = arg.chars().any(|c| c == ' ' || c == '\t');
-        if quote {
-            cmd.push_char('"');
-        }
-        for i in range(0u, arg.len()) {
-            append_char_at(cmd, arg, i);
-        }
-        if quote {
-            cmd.push_char('"');
-        }
-    }
-
-    fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) {
-        match arg[i] as char {
-            '"' => {
-                // Escape quotes.
-                cmd.push_str("\\\"");
-            }
-            '\\' => {
-                if backslash_run_ends_in_quote(arg, i) {
-                    // Double all backslashes that are in runs before quotes.
-                    cmd.push_str("\\\\");
-                } else {
-                    // Pass other backslashes through unescaped.
-                    cmd.push_char('\\');
-                }
-            }
-            c => {
-                cmd.push_char(c);
-            }
-        }
-    }
-
-    fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool {
-        while i < s.len() && s[i] as char == '\\' {
-            i += 1;
-        }
-        return i < s.len() && s[i] as char == '"';
-    }
-}
-
-#[cfg(unix)]
-fn spawn_process_os(prog: &str, args: &[~str],
-                    env: Option<~[(~str, ~str)]>,
-                    dir: Option<&Path>,
-                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
-    use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
-    use libc::funcs::bsd44::getdtablesize;
-
-    mod rustrt {
-        extern {
-            pub fn rust_unset_sigprocmask();
-        }
-    }
-
-    #[cfg(windows)]
-    unsafe fn set_environ(_envp: *c_void) {}
-    #[cfg(target_os = "macos")]
-    unsafe fn set_environ(envp: *c_void) {
-        extern { fn _NSGetEnviron() -> *mut *c_void; }
-
-        *_NSGetEnviron() = envp;
-    }
-    #[cfg(not(target_os = "macos"), not(windows))]
-    unsafe fn set_environ(envp: *c_void) {
-        extern {
-            static mut environ: *c_void;
-        }
-        environ = envp;
-    }
-
-    unsafe {
-
-        let pid = fork();
-        if pid < 0 {
-            fail!("failure in fork: {}", os::last_os_error());
-        } else if pid > 0 {
-            return SpawnProcessResult {pid: pid, handle: ptr::null()};
-        }
-
-        rustrt::rust_unset_sigprocmask();
-
-        if dup2(in_fd, 0) == -1 {
-            fail!("failure in dup2(in_fd, 0): {}", os::last_os_error());
-        }
-        if dup2(out_fd, 1) == -1 {
-            fail!("failure in dup2(out_fd, 1): {}", os::last_os_error());
-        }
-        if dup2(err_fd, 2) == -1 {
-            fail!("failure in dup3(err_fd, 2): {}", os::last_os_error());
-        }
-        // close all other fds
-        for fd in range(3, getdtablesize()).invert() {
-            close(fd as c_int);
-        }
-
-        with_dirp(dir, |dirp| {
-            if !dirp.is_null() && chdir(dirp) == -1 {
-                fail!("failure in chdir: {}", os::last_os_error());
-            }
-        });
-
-        with_envp(env, |envp| {
-            if !envp.is_null() {
-                set_environ(envp);
-            }
-            with_argv(prog, args, |argv| {
-                execvp(*argv, argv);
-                // execvp only returns if an error occurred
-                fail!("failure in execvp: {}", os::last_os_error());
-            })
-        })
-    }
-}
-
-#[cfg(unix)]
-fn with_argv<T>(prog: &str, args: &[~str], cb: |**libc::c_char| -> T) -> T {
-    use vec;
-
-    // We can't directly convert `str`s into `*char`s, as someone needs to hold
-    // a reference to the intermediary byte buffers. So first build an array to
-    // hold all the ~[u8] byte strings.
-    let mut tmps = vec::with_capacity(args.len() + 1);
-
-    tmps.push(prog.to_c_str());
-
-    for arg in args.iter() {
-        tmps.push(arg.to_c_str());
-    }
-
-    // Next, convert each of the byte strings into a pointer. This is
-    // technically unsafe as the caller could leak these pointers out of our
-    // scope.
-    let mut ptrs = tmps.map(|tmp| tmp.with_ref(|buf| buf));
-
-    // Finally, make sure we add a null pointer.
-    ptrs.push(ptr::null());
-
-    cb(ptrs.as_ptr())
-}
-
-#[cfg(unix)]
-fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: |*c_void| -> T) -> T {
-    use vec;
-
-    // On posixy systems we can pass a char** for envp, which is a
-    // null-terminated array of "k=v\n" strings. Like `with_argv`, we have to
-    // have a temporary buffer to hold the intermediary `~[u8]` byte strings.
-    match env {
-        Some(env) => {
-            let mut tmps = vec::with_capacity(env.len());
-
-            for pair in env.iter() {
-                let kv = format!("{}={}", pair.first(), pair.second());
-                tmps.push(kv.to_c_str());
-            }
-
-            // Once again, this is unsafe.
-            let mut ptrs = tmps.map(|tmp| tmp.with_ref(|buf| buf));
-            ptrs.push(ptr::null());
-
-            cb(ptrs.as_ptr() as *c_void)
-        }
-        _ => cb(ptr::null())
-    }
-}
-
-#[cfg(windows)]
-fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: |*mut c_void| -> T) -> T {
-    // On win32 we pass an "environment block" which is not a char**, but
-    // rather a concatenation of null-terminated k=v\0 sequences, with a final
-    // \0 to terminate.
-    match env {
-        Some(env) => {
-            let mut blk = ~[];
-
-            for pair in env.iter() {
-                let kv = format!("{}={}", pair.first(), pair.second());
-                blk.push_all(kv.as_bytes());
-                blk.push(0);
-            }
-
-            blk.push(0);
-
-            cb(blk.as_mut_ptr() as *mut c_void)
-        }
-        _ => cb(ptr::mut_null())
-    }
-}
-
-fn with_dirp<T>(d: Option<&Path>, cb: |*libc::c_char| -> T) -> T {
-    match d {
-      Some(dir) => dir.with_c_str(|buf| cb(buf)),
-      None => cb(ptr::null())
-    }
-}
-
-#[cfg(windows)]
-fn free_handle(handle: *()) {
-    unsafe {
-        libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle));
-    }
-}
-
-#[cfg(unix)]
-fn free_handle(_handle: *()) {
-    // unix has no process handle object, just a pid
-}
-
-/**
- * Waits for a process to exit and returns the exit code, failing
- * if there is no process with the specified id.
- *
- * Note that this is private to avoid race conditions on unix where if
- * a user calls waitpid(some_process.get_id()) then some_process.finish()
- * and some_process.destroy() and some_process.finalize() will then either
- * operate on a none-existent process or, even worse, on a newer process
- * with the same id.
- */
-fn waitpid(pid: pid_t) -> int {
-    return waitpid_os(pid);
-
-    #[cfg(windows)]
-    fn waitpid_os(pid: pid_t) -> int {
-        use libc::types::os::arch::extra::DWORD;
-        use libc::consts::os::extra::{
-            SYNCHRONIZE,
-            PROCESS_QUERY_INFORMATION,
-            FALSE,
-            STILL_ACTIVE,
-            INFINITE,
-            WAIT_FAILED
-        };
-        use libc::funcs::extra::kernel32::{
-            OpenProcess,
-            GetExitCodeProcess,
-            CloseHandle,
-            WaitForSingleObject
-        };
-
-        unsafe {
-
-            let process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
-                                      FALSE,
-                                      pid as DWORD);
-            if process.is_null() {
-                fail!("failure in OpenProcess: {}", os::last_os_error());
-            }
-
-            loop {
-                let mut status = 0;
-                if GetExitCodeProcess(process, &mut status) == FALSE {
-                    CloseHandle(process);
-                    fail!("failure in GetExitCodeProcess: {}", os::last_os_error());
-                }
-                if status != STILL_ACTIVE {
-                    CloseHandle(process);
-                    return status as int;
-                }
-                if WaitForSingleObject(process, INFINITE) == WAIT_FAILED {
-                    CloseHandle(process);
-                    fail!("failure in WaitForSingleObject: {}", os::last_os_error());
-                }
-            }
-        }
-    }
-
-    #[cfg(unix)]
-    fn waitpid_os(pid: pid_t) -> int {
-        use libc::funcs::posix01::wait::*;
-
-        #[cfg(target_os = "linux")]
-        #[cfg(target_os = "android")]
-        fn WIFEXITED(status: i32) -> bool {
-            (status & 0xffi32) == 0i32
-        }
-
-        #[cfg(target_os = "macos")]
-        #[cfg(target_os = "freebsd")]
-        fn WIFEXITED(status: i32) -> bool {
-            (status & 0x7fi32) == 0i32
-        }
-
-        #[cfg(target_os = "linux")]
-        #[cfg(target_os = "android")]
-        fn WEXITSTATUS(status: i32) -> i32 {
-            (status >> 8i32) & 0xffi32
-        }
-
-        #[cfg(target_os = "macos")]
-        #[cfg(target_os = "freebsd")]
-        fn WEXITSTATUS(status: i32) -> i32 {
-            status >> 8i32
-        }
-
-        let mut status = 0 as c_int;
-        if unsafe { waitpid(pid, &mut status, 0) } == -1 {
-            fail!("failure in waitpid: {}", os::last_os_error());
-        }
-
-        return if WIFEXITED(status) {
-            WEXITSTATUS(status) as int
-        } else {
-            1
-        };
-    }
-}
-
-#[cfg(test)]
-mod tests {
-
-    #[test] #[cfg(windows)]
-    fn test_make_command_line() {
-        use super::make_command_line;
-        assert_eq!(
-            make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]),
-            ~"prog aaa bbb ccc"
-        );
-        assert_eq!(
-            make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]),
-            ~"\"C:\\Program Files\\blah\\blah.exe\" aaa"
-        );
-        assert_eq!(
-            make_command_line("C:\\Program Files\\test", [~"aa\"bb"]),
-            ~"\"C:\\Program Files\\test\" aa\\\"bb"
-        );
-        assert_eq!(
-            make_command_line("echo", [~"a b c"]),
-            ~"echo \"a b c\""
-        );
-    }
-
-    // Currently most of the tests of this functionality live inside std::run,
-    // but they may move here eventually as a non-blocking backend is added to
-    // std::run
-}