about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorJeremy Soller <jackpot51@gmail.com>2016-10-28 14:17:34 -0600
committerJeremy Soller <jackpot51@gmail.com>2016-10-28 14:17:34 -0600
commita5de9bb591c9752d39c87339fd8f5ff49ea4b2da (patch)
tree69c296d20f5fe58d0bbd2b603bd4143430a5d6a2 /src/libstd
parent8b09e01fef9912e7c3eef997c40f9f4f91d09e4c (diff)
downloadrust-a5de9bb591c9752d39c87339fd8f5ff49ea4b2da.tar.gz
rust-a5de9bb591c9752d39c87339fd8f5ff49ea4b2da.zip
Remove unsafe libc layer
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/fs.rs10
-rw-r--r--src/libstd/sys/redox/ext/io.rs3
-rw-r--r--src/libstd/sys/redox/fd.rs32
-rw-r--r--src/libstd/sys/redox/fs.rs186
-rw-r--r--src/libstd/sys/redox/mod.rs39
-rw-r--r--src/libstd/sys/redox/os.rs102
-rw-r--r--src/libstd/sys/redox/pipe.rs6
-rw-r--r--src/libstd/sys/redox/process.rs137
-rw-r--r--src/libstd/sys/redox/thread.rs29
-rw-r--r--src/libstd/sys/redox/time.rs286
10 files changed, 193 insertions, 637 deletions
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index df5741d00a2..5845963d31a 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -348,6 +348,16 @@ impl File {
             inner: self.inner.duplicate()?
         })
     }
+
+    /// Get the path that this file points to.
+    ///
+    /// This function is only implemented on Redox, but could be
+    /// implemented on other operating systems using readlink
+    #[cfg(redox)]
+    #[stable(feature = "rust1", since = "1.14.0")]
+    pub fn path(&self) -> io::Result<PathBuf> {
+        self.inner.path()
+    }
 }
 
 impl AsInner<fs_imp::File> for File {
diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs
index bffd4f66a28..4f39f3b4f33 100644
--- a/src/libstd/sys/redox/ext/io.rs
+++ b/src/libstd/sys/redox/ext/io.rs
@@ -13,13 +13,12 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use fs;
-use os::raw;
 use sys;
 use sys_common::{AsInner, FromInner, IntoInner};
 
 /// Raw file descriptors.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub type RawFd = raw::c_int;
+pub type RawFd = usize;
 
 /// A trait to extract the raw unix file descriptor from an underlying
 /// object.
diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs
index 99ae089b5c0..4c4dae7cd41 100644
--- a/src/libstd/sys/redox/fd.rs
+++ b/src/libstd/sys/redox/fd.rs
@@ -11,37 +11,32 @@
 #![unstable(reason = "not public", issue = "0", feature = "fd")]
 
 use io::{self, Read};
-use libc::{self, c_int, c_void};
+use libc;
 use mem;
 use sys::cvt;
 use sys_common::AsInner;
 use sys_common::io::read_to_end_uninitialized;
 
 pub struct FileDesc {
-    fd: c_int,
+    fd: usize,
 }
 
 impl FileDesc {
-    pub fn new(fd: c_int) -> FileDesc {
+    pub fn new(fd: usize) -> FileDesc {
         FileDesc { fd: fd }
     }
 
-    pub fn raw(&self) -> c_int { self.fd }
+    pub fn raw(&self) -> usize { self.fd }
 
     /// Extracts the actual filedescriptor without closing it.
-    pub fn into_raw(self) -> c_int {
+    pub fn into_raw(self) -> usize {
         let fd = self.fd;
         mem::forget(self);
         fd
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            libc::read(self.fd,
-                       buf.as_mut_ptr() as *mut c_void,
-                       buf.len())
-        })?;
-        Ok(ret as usize)
+        cvt(libc::read(self.fd, buf))
     }
 
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@@ -50,12 +45,7 @@ impl FileDesc {
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            libc::write(self.fd,
-                        buf.as_ptr() as *const c_void,
-                        buf.len())
-        })?;
-        Ok(ret as usize)
+        cvt(libc::write(self.fd, buf))
     }
 
     pub fn set_cloexec(&self) -> io::Result<()> {
@@ -86,7 +76,7 @@ impl FileDesc {
     }
 
     pub fn duplicate(&self) -> io::Result<FileDesc> {
-        let new_fd = cvt(unsafe { libc::dup(self.fd) })?;
+        let new_fd = cvt(libc::dup(self.fd, &[]))?;
         Ok(FileDesc::new(new_fd))
     }
 }
@@ -101,8 +91,8 @@ impl<'a> Read for &'a FileDesc {
     }
 }
 
-impl AsInner<c_int> for FileDesc {
-    fn as_inner(&self) -> &c_int { &self.fd }
+impl AsInner<usize> for FileDesc {
+    fn as_inner(&self) -> &usize { &self.fd }
 }
 
 impl Drop for FileDesc {
@@ -112,6 +102,6 @@ impl Drop for FileDesc {
         // the file descriptor was closed or not, and if we retried (for
         // something like EINTR), we might close another valid file descriptor
         // (opened after we closed ours.
-        let _ = unsafe { libc::close(self.fd) };
+        let _ = libc::close(self.fd);
     }
 }
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
index 56b1bf95ae8..ca1a7963f8e 100644
--- a/src/libstd/sys/redox/fs.rs
+++ b/src/libstd/sys/redox/fs.rs
@@ -10,26 +10,24 @@
 
 use os::unix::prelude::*;
 
-use ffi::{CString, CStr, OsString, OsStr};
+use ffi::{OsString, OsStr};
 use fmt;
 use io::{self, Error, ErrorKind, SeekFrom};
 use libc::{self, c_int, mode_t};
-use mem;
 use path::{Path, PathBuf};
 use sync::Arc;
 use sys::fd::FileDesc;
 use sys::time::SystemTime;
-use sys::{cvt, cvt_r};
+use sys::cvt;
 use sys_common::{AsInner, FromInner};
 
-use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
-           ftruncate as ftruncate64, lseek as lseek64, open as open64};
+use libc::{stat, fstat, fsync, ftruncate, lseek, open};
 
 pub struct File(FileDesc);
 
 #[derive(Clone)]
 pub struct FileAttr {
-    stat: stat64,
+    stat: stat,
 }
 
 pub struct ReadDir {
@@ -104,8 +102,8 @@ impl FileAttr {
     }
 }
 
-impl AsInner<stat64> for FileAttr {
-    fn as_inner(&self) -> &stat64 { &self.stat }
+impl AsInner<stat> for FileAttr {
+    fn as_inner(&self) -> &stat { &self.stat }
 }
 
 impl FilePermissions {
@@ -254,60 +252,32 @@ impl OpenOptions {
 
 impl File {
     pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
-        let path = cstr(path)?;
-        File::open_c(&path, opts)
-    }
-
-    pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
-        let flags = libc::O_CLOEXEC as i32 |
-                    opts.get_access_mode()? |
-                    opts.get_creation_mode()? |
-                    (opts.custom_flags as usize & !libc::O_ACCMODE) as i32;
-        let fd = cvt_r(|| unsafe {
-            open64(path.as_ptr(), flags, opts.mode as mode_t)
-        })?;
-        let fd = FileDesc::new(fd);
-
-        Ok(File(fd))
+        let flags = libc::O_CLOEXEC |
+                    opts.get_access_mode()? as usize |
+                    opts.get_creation_mode()? as usize |
+                    (opts.custom_flags as usize & !libc::O_ACCMODE);
+        let fd = cvt(open(path.to_str().unwrap(), flags | opts.mode as usize))?;
+        Ok(File(FileDesc::new(fd)))
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
-        let mut stat: stat64 = unsafe { mem::zeroed() };
-        cvt(unsafe {
-            fstat64(self.0.raw(), &mut stat)
-        })?;
+        let mut stat: stat = stat::default();
+        cvt(fstat(self.0.raw(), &mut stat))?;
         Ok(FileAttr { stat: stat })
     }
 
     pub fn fsync(&self) -> io::Result<()> {
-        cvt_r(|| unsafe { libc::fsync(self.0.raw()) })?;
+        cvt(fsync(self.0.raw()))?;
         Ok(())
     }
 
     pub fn datasync(&self) -> io::Result<()> {
-        cvt_r(|| unsafe { os_datasync(self.0.raw()) })?;
-        return Ok(());
-
-        #[cfg(any(target_os = "macos", target_os = "ios"))]
-        unsafe fn os_datasync(fd: c_int) -> c_int {
-            libc::fcntl(fd, libc::F_FULLFSYNC)
-        }
-        #[cfg(target_os = "linux")]
-        unsafe fn os_datasync(fd: c_int) -> c_int { libc::fdatasync(fd) }
-        #[cfg(not(any(target_os = "macos",
-                      target_os = "ios",
-                      target_os = "linux")))]
-        unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) }
+        self.fsync()
     }
 
     pub fn truncate(&self, size: u64) -> io::Result<()> {
-        #[cfg(target_os = "android")]
-        return ::sys::android::ftruncate64(self.0.raw(), size);
-
-        #[cfg(not(target_os = "android"))]
-        return cvt_r(|| unsafe {
-            ftruncate64(self.0.raw(), size as off64_t)
-        }).map(|_| ());
+        cvt(ftruncate(self.0.raw(), size as usize))?;
+        Ok(())
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -332,7 +302,7 @@ impl File {
             SeekFrom::End(off) => (libc::SEEK_END, off),
             SeekFrom::Current(off) => (libc::SEEK_CUR, off),
         };
-        let n = cvt(unsafe { lseek64(self.0.raw(), pos as usize, whence) } as isize)?;
+        let n = cvt(lseek(self.0.raw(), pos as isize, whence))?;
         Ok(n as u64)
     }
 
@@ -341,9 +311,8 @@ impl File {
     }
 
     pub fn dup(&self, buf: &[u8]) -> io::Result<File> {
-        libc::dup_extra(*self.fd().as_inner() as usize, buf)
-            .map(|fd| File(FileDesc::new(fd as i32)))
-            .map_err(|err| Error::from_raw_os_error(err.errno))
+        let fd = cvt(libc::dup(*self.fd().as_inner() as usize, buf))?;
+        Ok(File(FileDesc::new(fd)))
     }
 
     pub fn path(&self) -> io::Result<PathBuf> {
@@ -365,8 +334,7 @@ impl DirBuilder {
     }
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let p = cstr(p)?;
-        cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?;
+        cvt(libc::mkdir(p.to_str().unwrap(), self.mode))?;
         Ok(())
     }
 
@@ -375,96 +343,39 @@ impl DirBuilder {
     }
 }
 
-fn cstr(path: &Path) -> io::Result<CString> {
-    Ok(CString::new(path.as_os_str().as_bytes())?)
-}
-
-impl FromInner<c_int> for File {
-    fn from_inner(fd: c_int) -> File {
+impl FromInner<usize> for File {
+    fn from_inner(fd: usize) -> File {
         File(FileDesc::new(fd))
     }
 }
 
 impl fmt::Debug for File {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        #[cfg(target_os = "linux")]
-        fn get_path(fd: c_int) -> Option<PathBuf> {
-            let mut p = PathBuf::from("/proc/self/fd");
-            p.push(&fd.to_string());
-            readlink(&p).ok()
-        }
-
-        #[cfg(target_os = "macos")]
-        fn get_path(fd: c_int) -> Option<PathBuf> {
-            // FIXME: The use of PATH_MAX is generally not encouraged, but it
-            // is inevitable in this case because OS X defines `fcntl` with
-            // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
-            // alternatives. If a better method is invented, it should be used
-            // instead.
-            let mut buf = vec![0;libc::PATH_MAX as usize];
-            let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
-            if n == -1 {
-                return None;
-            }
-            let l = buf.iter().position(|&c| c == 0).unwrap();
-            buf.truncate(l as usize);
-            buf.shrink_to_fit();
-            Some(PathBuf::from(OsString::from_vec(buf)))
-        }
-
-        #[cfg(not(any(target_os = "linux", target_os = "macos")))]
-        fn get_path(_fd: c_int) -> Option<PathBuf> {
-            // FIXME(#24570): implement this for other Unix platforms
-            None
-        }
-
-        #[cfg(any(target_os = "linux", target_os = "macos"))]
-        fn get_mode(fd: c_int) -> Option<(bool, bool)> {
-            let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
-            if mode == -1 {
-                return None;
-            }
-            match mode & libc::O_ACCMODE {
-                libc::O_RDONLY => Some((true, false)),
-                libc::O_RDWR => Some((true, true)),
-                libc::O_WRONLY => Some((false, true)),
-                _ => None
-            }
-        }
-
-        #[cfg(not(any(target_os = "linux", target_os = "macos")))]
-        fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
-            // FIXME(#24570): implement this for other Unix platforms
-            None
-        }
-
-        let fd = self.0.raw();
         let mut b = f.debug_struct("File");
-        b.field("fd", &fd);
-        if let Some(path) = get_path(fd) {
+        b.field("fd", &self.0.raw());
+        if let Ok(path) = self.path() {
             b.field("path", &path);
         }
+        /*
         if let Some((read, write)) = get_mode(fd) {
             b.field("read", &read).field("write", &write);
         }
+        */
         b.finish()
     }
 }
 
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
     let root = Arc::new(p.to_path_buf());
-    let p = cstr(p)?;
-    unsafe {
-        let fd = FileDesc::new(cvt(libc::open(p.as_ptr(), 0, 0))?);
-        let mut data = Vec::new();
-        fd.read_to_end(&mut data)?;
-        Ok(ReadDir { data: data, i: 0, root: root })
-    }
+    let options = OpenOptions::new();
+    let fd = File::open(p, &options)?;
+    let mut data = Vec::new();
+    fd.read_to_end(&mut data)?;
+    Ok(ReadDir { data: data, i: 0, root: root })
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
-    let p = cstr(p)?;
-    cvt(unsafe { libc::unlink(p.as_ptr()) })?;
+    cvt(libc::unlink(p.to_str().unwrap()))?;
     Ok(())
 }
 
@@ -477,8 +388,7 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
 }
 
 pub fn rmdir(p: &Path) -> io::Result<()> {
-    let p = cstr(p)?;
-    cvt(unsafe { libc::rmdir(p.as_ptr()) })?;
+    cvt(libc::rmdir(p.to_str().unwrap()))?;
     Ok(())
 }
 
@@ -503,8 +413,8 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
     rmdir(path)
 }
 
-pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
-    unimplemented!();
+pub fn readlink(p: &Path) -> io::Result<PathBuf> {
+    canonicalize(p)
 }
 
 pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
@@ -516,25 +426,21 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    let p = cstr(p)?;
-    let mut stat: stat64 = unsafe { mem::zeroed() };
-    cvt(unsafe {
-        stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
-    })?;
+    let mut stat: stat = stat::default();
+    let options = OpenOptions::new();
+    let file = File::open(p, &options)?;
+    cvt(fstat(file.0.raw(), &mut stat))?;
     Ok(FileAttr { stat: stat })
 }
 
 pub fn lstat(p: &Path) -> io::Result<FileAttr> {
-    let p = cstr(p)?;
-    let mut stat: stat64 = unsafe { mem::zeroed() };
-    cvt(unsafe {
-        lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
-    })?;
-    Ok(FileAttr { stat: stat })
+    stat(p)
 }
 
-pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
-    unimplemented!();
+pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+    let options = OpenOptions::new();
+    let file = File::open(p, &options)?;
+    file.path()
 }
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
index 108ebb0800e..f7465d01fad 100644
--- a/src/libstd/sys/redox/mod.rs
+++ b/src/libstd/sys/redox/mod.rs
@@ -41,9 +41,7 @@ pub fn init() {
         use intrinsics;
         let msg = "fatal runtime error: out of memory\n";
         unsafe {
-            libc::write(libc::STDERR_FILENO,
-                        msg.as_ptr() as *const libc::c_void,
-                        msg.len());
+            let _ = libc::write(libc::STDERR_FILENO, msg.as_bytes());
             intrinsics::abort();
         }
     }
@@ -75,37 +73,6 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
     }
 }
 
-#[doc(hidden)]
-pub trait IsMinusOne {
-    fn is_minus_one(&self) -> bool;
-}
-
-macro_rules! impl_is_minus_one {
-    ($($t:ident)*) => ($(impl IsMinusOne for $t {
-        fn is_minus_one(&self) -> bool {
-            *self == -1
-        }
-    })*)
-}
-
-impl_is_minus_one! { i8 i16 i32 i64 isize }
-
-pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
-    if t.is_minus_one() {
-        Err(io::Error::last_os_error())
-    } else {
-        Ok(t)
-    }
-}
-
-pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
-    where T: IsMinusOne,
-          F: FnMut() -> T
-{
-    loop {
-        match cvt(f()) {
-            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
-            other => return other,
-        }
-    }
+pub fn cvt(result: Result<usize, libc::Error>) -> io::Result<usize> {
+    result.map_err(|err| io::Error::from_raw_os_error(err.errno as i32))
 }
diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs
index a2262369e92..c2e419aeaaa 100644
--- a/src/libstd/sys/redox/os.rs
+++ b/src/libstd/sys/redox/os.rs
@@ -35,109 +35,28 @@ use vec;
 const TMPBUF_SZ: usize = 128;
 static ENV_LOCK: Mutex = Mutex::new();
 
-
-extern {
-    #[cfg(not(target_os = "dragonfly"))]
-    #[cfg_attr(any(target_os = "linux", target_os = "emscripten", target_os = "fuchsia"),
-               link_name = "__errno_location")]
-    #[cfg_attr(any(target_os = "bitrig",
-                   target_os = "netbsd",
-                   target_os = "openbsd",
-                   target_os = "android",
-                   target_env = "newlib"),
-               link_name = "__errno")]
-    #[cfg_attr(target_os = "solaris", link_name = "___errno")]
-    #[cfg_attr(any(target_os = "macos",
-                   target_os = "ios",
-                   target_os = "freebsd"),
-               link_name = "__error")]
-    #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
-    fn errno_location() -> *mut c_int;
-}
-
 /// Returns the platform-specific value of errno
-#[cfg(not(target_os = "dragonfly"))]
 pub fn errno() -> i32 {
-    unsafe {
-        (*errno_location()) as i32
-    }
-}
-
-/// Sets the platform-specific value of errno
-#[cfg(target_os = "solaris")] // only needed for readdir so far
-pub fn set_errno(e: i32) {
-    unsafe {
-        *errno_location() = e as c_int
-    }
-}
-
-#[cfg(target_os = "dragonfly")]
-pub fn errno() -> i32 {
-    extern {
-        #[thread_local]
-        static errno: c_int;
-    }
-
-    errno as i32
+    0
 }
 
 /// Gets a detailed string description for the given error number.
 pub fn error_string(errno: i32) -> String {
-    extern {
-        #[cfg_attr(any(target_os = "linux", target_env = "newlib"),
-                   link_name = "__xpg_strerror_r")]
-        fn strerror_r(errnum: c_int, buf: *mut c_char,
-                      buflen: libc::size_t) -> c_int;
-    }
-
-    let mut buf = [0 as c_char; TMPBUF_SZ];
-
-    let p = buf.as_mut_ptr();
-    unsafe {
-        if strerror_r(errno as c_int, p, buf.len()) < 0 {
-            panic!("strerror_r failure");
-        }
-
-        let p = p as *const _;
-        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
+    if let Some(string) = libc::STR_ERROR.get(errno as usize) {
+        string.to_string()
+    } else {
+        "unknown error".to_string()
     }
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    let mut buf = Vec::with_capacity(512);
-    loop {
-        unsafe {
-            let ptr = buf.as_mut_ptr() as *mut libc::c_char;
-            if !libc::getcwd(ptr, buf.capacity()).is_null() {
-                let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
-                buf.set_len(len);
-                buf.shrink_to_fit();
-                return Ok(PathBuf::from(OsString::from_vec(buf)));
-            } else {
-                let error = io::Error::last_os_error();
-                if error.raw_os_error() != Some(libc::ERANGE) {
-                    return Err(error);
-                }
-            }
-
-            // Trigger the internal buffer resizing logic of `Vec` by requiring
-            // more space than the current capacity.
-            let cap = buf.capacity();
-            buf.set_len(cap);
-            buf.reserve(1);
-        }
-    }
+    let mut buf = [0; 4096];
+    let count = cvt(libc::getcwd(&mut buf))?;
+    Ok(PathBuf::from(OsString::from_vec(buf[.. count].to_vec())))
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
-    let p: &OsStr = p.as_ref();
-    let p = CString::new(p.as_bytes())?;
-    unsafe {
-        match libc::chdir(p.as_ptr()) == (0 as c_int) {
-            true => Ok(()),
-            false => Err(io::Error::last_os_error()),
-        }
-    }
+    cvt(libc::chdir(p.to_str().unwrap())).and(Ok(()))
 }
 
 pub struct SplitPaths<'a> {
@@ -242,5 +161,6 @@ pub fn home_dir() -> Option<PathBuf> {
 }
 
 pub fn exit(code: i32) -> ! {
-    unsafe { libc::exit(code as c_int) }
+    let _ = libc::exit(code as usize);
+    unreachable!();
 }
diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs
index f77f1e0dc68..5902ba128e8 100644
--- a/src/libstd/sys/redox/pipe.rs
+++ b/src/libstd/sys/redox/pipe.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use io;
-use libc::{self, c_int};
+use libc;
 use sys::fd::FileDesc;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -23,8 +23,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
 
     libc::pipe2(&mut fds, libc::O_CLOEXEC).map_err(|err| io::Error::from_raw_os_error(err.errno))?;
 
-    let fd0 = FileDesc::new(fds[0] as c_int);
-    let fd1 = FileDesc::new(fds[1] as c_int);
+    let fd0 = FileDesc::new(fds[0]);
+    let fd1 = FileDesc::new(fds[1]);
     Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?))
 }
 
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
index b025623fc9f..921e3f056da 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -12,14 +12,15 @@ use os::unix::prelude::*;
 
 use collections::hash_map::HashMap;
 use env;
-use ffi::{OsStr, CString, CStr};
+use ffi::{OsStr, CString};
 use fmt;
 use io::{self, Error, ErrorKind};
 use libc::{self, pid_t, c_int, gid_t, uid_t};
+use path::Path;
 use sys::fd::FileDesc;
 use sys::fs::{File, OpenOptions};
 use sys::pipe::{self, AnonPipe};
-use sys::{self, cvt, cvt_r};
+use sys::{self, cvt};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Command
@@ -47,7 +48,7 @@ pub struct Command {
     args: Vec<String>,
     env: HashMap<String, String>,
 
-    cwd: Option<CString>,
+    cwd: Option<String>,
     uid: Option<uid_t>,
     gid: Option<gid_t>,
     saw_nul: bool,
@@ -75,7 +76,7 @@ struct ChildPipes {
 
 enum ChildStdio {
     Inherit,
-    Explicit(c_int),
+    Explicit(usize),
     Owned(FileDesc),
 }
 
@@ -120,7 +121,7 @@ impl Command {
     }
 
     pub fn cwd(&mut self, dir: &OsStr) {
-        self.cwd = Some(os2c(dir, &mut self.saw_nul));
+        self.cwd = Some(dir.to_str().unwrap().to_owned());
     }
     pub fn uid(&mut self, id: uid_t) {
         self.uid = Some(id);
@@ -157,7 +158,7 @@ impl Command {
         let (input, output) = sys::pipe::anon_pipe()?;
 
         let pid = unsafe {
-            match cvt(libc::fork() as isize)? {
+            match cvt(libc::clone(0))? {
                 0 => {
                     drop(input);
                     let err = self.do_exec(theirs);
@@ -174,7 +175,8 @@ impl Command {
                     // we want to be sure we *don't* run at_exit destructors as
                     // we're being torn down regardless
                     assert!(output.write(&bytes).is_ok());
-                    libc::_exit(1)
+                    let _ = libc::exit(1);
+                    unreachable!();
                 }
                 n => n as pid_t,
             }
@@ -271,29 +273,29 @@ impl Command {
         }
 
         if let Some(fd) = stdio.stderr.fd() {
-            libc::close(libc::STDERR_FILENO);
-            t!(cvt(libc::dup(fd)));
-            libc::close(fd);
+            let _ = libc::close(libc::STDERR_FILENO);
+            t!(cvt(libc::dup(fd, &[])));
+            let _ = libc::close(fd);
         }
         if let Some(fd) = stdio.stdout.fd() {
-            libc::close(libc::STDOUT_FILENO);
-            t!(cvt(libc::dup(fd)));
-            libc::close(fd);
+            let _ = libc::close(libc::STDOUT_FILENO);
+            t!(cvt(libc::dup(fd, &[])));
+            let _ = libc::close(fd);
         }
         if let Some(fd) = stdio.stdin.fd() {
-            libc::close(libc::STDIN_FILENO);
-            t!(cvt(libc::dup(fd)));
-            libc::close(fd);
+            let _ = libc::close(libc::STDIN_FILENO);
+            t!(cvt(libc::dup(fd, &[])));
+            let _ = libc::close(fd);
         }
 
-        if let Some(u) = self.gid {
-            t!(cvt(libc::setgid(u as gid_t)));
+        if let Some(g) = self.gid {
+            t!(cvt(libc::setgid(g)));
         }
         if let Some(u) = self.uid {
-            t!(cvt(libc::setuid(u as uid_t)));
+            t!(cvt(libc::setuid(u)));
         }
         if let Some(ref cwd) = self.cwd {
-            t!(cvt(libc::chdir(cwd.as_ptr())));
+            t!(cvt(libc::chdir(cwd)));
         }
 
         for callback in self.closures.iter_mut() {
@@ -363,7 +365,7 @@ impl Stdio {
             // stderr. No matter which we dup first, the second will get
             // overwritten prematurely.
             Stdio::Fd(ref fd) => {
-                if fd.raw() >= 0 && fd.raw() <= libc::STDERR_FILENO {
+                if fd.raw() <= libc::STDERR_FILENO {
                     Ok((ChildStdio::Owned(fd.duplicate()?), None))
                 } else {
                     Ok((ChildStdio::Explicit(fd.raw()), None))
@@ -384,10 +386,7 @@ impl Stdio {
                 let mut opts = OpenOptions::new();
                 opts.read(readable);
                 opts.write(!readable);
-                let path = unsafe {
-                    CStr::from_ptr("/dev/null\0".as_ptr() as *const _)
-                };
-                let fd = File::open_c(&path, &opts)?;
+                let fd = File::open(&Path::new("null:"), &opts)?;
                 Ok((ChildStdio::Owned(fd.into_fd()), None))
             }
         }
@@ -395,7 +394,7 @@ impl Stdio {
 }
 
 impl ChildStdio {
-    fn fd(&self) -> Option<c_int> {
+    fn fd(&self) -> Option<usize> {
         match *self {
             ChildStdio::Inherit => None,
             ChildStdio::Explicit(fd) => Some(fd),
@@ -496,7 +495,8 @@ impl Process {
             Err(Error::new(ErrorKind::InvalidInput,
                            "invalid argument: can't kill an exited process"))
         } else {
-            cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ())
+            cvt(libc::kill(self.pid, libc::SIGKILL))?;
+            Ok(())
         }
     }
 
@@ -505,89 +505,8 @@ impl Process {
             return Ok(status)
         }
         let mut status = 0;
-        cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
+        cvt(libc::waitpid(self.pid, &mut status, 0))?;
         self.status = Some(ExitStatus(status as i32));
         Ok(ExitStatus(status as i32))
     }
 }
-
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod tests {
-    use super::*;
-
-    use ffi::OsStr;
-    use mem;
-    use ptr;
-    use libc;
-    use sys::cvt;
-
-    macro_rules! t {
-        ($e:expr) => {
-            match $e {
-                Ok(t) => t,
-                Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
-            }
-        }
-    }
-
-    #[cfg(not(target_os = "android"))]
-    extern {
-        #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
-        fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int;
-    }
-
-    #[cfg(target_os = "android")]
-    unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
-        use slice;
-
-        let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>());
-        let bit = (signum - 1) as usize;
-        raw[bit / 8] |= 1 << (bit % 8);
-        return 0;
-    }
-
-    // See #14232 for more information, but it appears that signal delivery to a
-    // newly spawned process may just be raced in the OSX, so to prevent this
-    // test from being flaky we ignore it on OSX.
-    #[test]
-    #[cfg_attr(target_os = "macos", ignore)]
-    #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl.
-    fn test_process_mask() {
-        unsafe {
-            // Test to make sure that a signal mask does not get inherited.
-            let mut cmd = Command::new(OsStr::new("cat"));
-
-            let mut set: libc::sigset_t = mem::uninitialized();
-            let mut old_set: libc::sigset_t = mem::uninitialized();
-            t!(cvt(libc::sigemptyset(&mut set)));
-            t!(cvt(sigaddset(&mut set, libc::SIGINT)));
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set)));
-
-            cmd.stdin(Stdio::MakePipe);
-            cmd.stdout(Stdio::MakePipe);
-
-            let (mut cat, mut pipes) = t!(cmd.spawn(Stdio::Null, true));
-            let stdin_write = pipes.stdin.take().unwrap();
-            let stdout_read = pipes.stdout.take().unwrap();
-
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set,
-                                         ptr::null_mut())));
-
-            t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
-            // We need to wait until SIGINT is definitely delivered. The
-            // easiest way is to write something to cat, and try to read it
-            // back: if SIGINT is unmasked, it'll get delivered when cat is
-            // next scheduled.
-            let _ = stdin_write.write(b"Hello");
-            drop(stdin_write);
-
-            // Either EOF or failure (EPIPE) is okay.
-            let mut buf = [0; 5];
-            if let Ok(ret) = stdout_read.read(&mut buf) {
-                assert!(ret == 0);
-            }
-
-            t!(cat.wait());
-        }
-    }
-}
diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs
index eaf908dc53e..616da662d9a 100644
--- a/src/libstd/sys/redox/thread.rs
+++ b/src/libstd/sys/redox/thread.rs
@@ -14,7 +14,6 @@ use ffi::CStr;
 use io;
 use libc;
 use mem;
-use sys::os;
 use sys_common::thread::start_thread;
 use time::Duration;
 
@@ -42,7 +41,7 @@ impl Thread {
     }
 
     pub fn set_name(_name: &CStr) {
-
+        unimplemented!();
     }
 
     pub fn sleep(dur: Duration) {
@@ -51,20 +50,18 @@ impl Thread {
 
         // If we're awoken with a signal then the return value will be -1 and
         // nanosleep will fill in `ts` with the remaining time.
-        unsafe {
-            while secs > 0 || nsecs > 0 {
-                let mut ts = libc::timespec {
-                    tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
-                    tv_nsec: nsecs,
-                };
-                secs -= ts.tv_sec as u64;
-                if libc::nanosleep(&ts, &mut ts) == -1 {
-                    assert_eq!(os::errno(), libc::EINTR);
-                    secs += ts.tv_sec as u64;
-                    nsecs = ts.tv_nsec;
-                } else {
-                    nsecs = 0;
-                }
+        while secs > 0 || nsecs > 0 {
+            let req = libc::timespec {
+                tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
+                tv_nsec: nsecs,
+            };
+            secs -= req.tv_sec as u64;
+            let mut rem = libc::timespec::default();
+            if libc::nanosleep(&req, &mut rem).is_err() {
+                secs += rem.tv_sec as u64;
+                nsecs = rem.tv_nsec;
+            } else {
+                nsecs = 0;
             }
         }
     }
diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs
index 5caaf20fdf8..4e1a82bcc9a 100644
--- a/src/libstd/sys/redox/time.rs
+++ b/src/libstd/sys/redox/time.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 use cmp::Ordering;
+use fmt;
 use libc;
+use sys::cvt;
 use time::Duration;
 
-pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
-
 const NSEC_PER_SEC: u64 = 1_000_000_000;
 
 #[derive(Copy, Clone)]
@@ -103,249 +103,97 @@ impl Ord for Timespec {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-mod inner {
-    use fmt;
-    use libc;
-    use sync::Once;
-    use sys::cvt;
-    use sys_common::mul_div_u64;
-    use time::Duration;
-
-    use super::NSEC_PER_SEC;
-    use super::Timespec;
-
-    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
-    pub struct Instant {
-        t: u64
-    }
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Instant {
+    t: Timespec,
+}
 
-    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-    pub struct SystemTime {
-        t: Timespec,
-    }
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct SystemTime {
+    t: Timespec,
+}
 
-    pub const UNIX_EPOCH: SystemTime = SystemTime {
-        t: Timespec {
-            t: libc::timespec {
-                tv_sec: 0,
-                tv_nsec: 0,
-            },
+pub const UNIX_EPOCH: SystemTime = SystemTime {
+    t: Timespec {
+        t: libc::timespec {
+            tv_sec: 0,
+            tv_nsec: 0,
         },
-    };
+    },
+};
 
-    impl Instant {
-        pub fn now() -> Instant {
-            Instant { t: unsafe { libc::mach_absolute_time() } }
-        }
-
-        pub fn sub_instant(&self, other: &Instant) -> Duration {
-            let info = info();
-            let diff = self.t.checked_sub(other.t)
-                           .expect("second instant is later than self");
-            let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
-            Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
-        }
-
-        pub fn add_duration(&self, other: &Duration) -> Instant {
-            Instant {
-                t: self.t.checked_add(dur2intervals(other))
-                       .expect("overflow when adding duration to instant"),
-            }
-        }
-
-        pub fn sub_duration(&self, other: &Duration) -> Instant {
-            Instant {
-                t: self.t.checked_sub(dur2intervals(other))
-                       .expect("overflow when adding duration to instant"),
-            }
-        }
+impl Instant {
+    pub fn now() -> Instant {
+        Instant { t: now(libc::CLOCK_MONOTONIC) }
     }
 
-    impl SystemTime {
-        pub fn now() -> SystemTime {
-            use ptr;
-
-            let mut s = libc::timeval {
-                tv_sec: 0,
-                tv_usec: 0,
-            };
-            cvt(unsafe {
-                libc::gettimeofday(&mut s, ptr::null_mut())
-            }).unwrap();
-            return SystemTime::from(s)
-        }
-
-        pub fn sub_time(&self, other: &SystemTime)
-                        -> Result<Duration, Duration> {
-            self.t.sub_timespec(&other.t)
-        }
-
-        pub fn add_duration(&self, other: &Duration) -> SystemTime {
-            SystemTime { t: self.t.add_duration(other) }
-        }
-
-        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
-            SystemTime { t: self.t.sub_duration(other) }
-        }
-    }
-
-    impl From<libc::timeval> for SystemTime {
-        fn from(t: libc::timeval) -> SystemTime {
-            SystemTime::from(libc::timespec {
-                tv_sec: t.tv_sec,
-                tv_nsec: (t.tv_usec * 1000) as libc::c_long,
-            })
-        }
+    pub fn sub_instant(&self, other: &Instant) -> Duration {
+        self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
+            panic!("other was less than the current instant")
+        })
     }
 
-    impl From<libc::timespec> for SystemTime {
-        fn from(t: libc::timespec) -> SystemTime {
-            SystemTime { t: Timespec { t: t } }
-        }
+    pub fn add_duration(&self, other: &Duration) -> Instant {
+        Instant { t: self.t.add_duration(other) }
     }
 
-    impl fmt::Debug for SystemTime {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            f.debug_struct("SystemTime")
-             .field("tv_sec", &self.t.t.tv_sec)
-             .field("tv_nsec", &self.t.t.tv_nsec)
-             .finish()
-        }
-    }
-
-    fn dur2intervals(dur: &Duration) -> u64 {
-        let info = info();
-        let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
-            nanos.checked_add(dur.subsec_nanos() as u64)
-        }).expect("overflow converting duration to nanoseconds");
-        mul_div_u64(nanos, info.denom as u64, info.numer as u64)
-    }
-
-    fn info() -> &'static libc::mach_timebase_info {
-        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
-            numer: 0,
-            denom: 0,
-        };
-        static ONCE: Once = Once::new();
-
-        unsafe {
-            ONCE.call_once(|| {
-                libc::mach_timebase_info(&mut INFO);
-            });
-            &INFO
-        }
+    pub fn sub_duration(&self, other: &Duration) -> Instant {
+        Instant { t: self.t.sub_duration(other) }
     }
 }
 
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
-mod inner {
-    use fmt;
-    use libc;
-    use sys::cvt;
-    use time::Duration;
-
-    use super::Timespec;
-
-    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-    pub struct Instant {
-        t: Timespec,
+impl fmt::Debug for Instant {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Instant")
+         .field("tv_sec", &self.t.t.tv_sec)
+         .field("tv_nsec", &self.t.t.tv_nsec)
+         .finish()
     }
+}
 
-    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-    pub struct SystemTime {
-        t: Timespec,
+impl SystemTime {
+    pub fn now() -> SystemTime {
+        SystemTime { t: now(libc::CLOCK_REALTIME) }
     }
 
-    pub const UNIX_EPOCH: SystemTime = SystemTime {
-        t: Timespec {
-            t: libc::timespec {
-                tv_sec: 0,
-                tv_nsec: 0,
-            },
-        },
-    };
-
-    impl Instant {
-        pub fn now() -> Instant {
-            Instant { t: now(libc::CLOCK_MONOTONIC) }
-        }
-
-        pub fn sub_instant(&self, other: &Instant) -> Duration {
-            self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-                panic!("other was less than the current instant")
-            })
-        }
-
-        pub fn add_duration(&self, other: &Duration) -> Instant {
-            Instant { t: self.t.add_duration(other) }
-        }
-
-        pub fn sub_duration(&self, other: &Duration) -> Instant {
-            Instant { t: self.t.sub_duration(other) }
-        }
+    pub fn sub_time(&self, other: &SystemTime)
+                    -> Result<Duration, Duration> {
+        self.t.sub_timespec(&other.t)
     }
 
-    impl fmt::Debug for Instant {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            f.debug_struct("Instant")
-             .field("tv_sec", &self.t.t.tv_sec)
-             .field("tv_nsec", &self.t.t.tv_nsec)
-             .finish()
-        }
+    pub fn add_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime { t: self.t.add_duration(other) }
     }
 
-    impl SystemTime {
-        pub fn now() -> SystemTime {
-            SystemTime { t: now(libc::CLOCK_REALTIME) }
-        }
-
-        pub fn sub_time(&self, other: &SystemTime)
-                        -> Result<Duration, Duration> {
-            self.t.sub_timespec(&other.t)
-        }
-
-        pub fn add_duration(&self, other: &Duration) -> SystemTime {
-            SystemTime { t: self.t.add_duration(other) }
-        }
-
-        pub fn sub_duration(&self, other: &Duration) -> SystemTime {
-            SystemTime { t: self.t.sub_duration(other) }
-        }
+    pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime { t: self.t.sub_duration(other) }
     }
+}
 
-    impl From<libc::timespec> for SystemTime {
-        fn from(t: libc::timespec) -> SystemTime {
-            SystemTime { t: Timespec { t: t } }
-        }
+impl From<libc::timespec> for SystemTime {
+    fn from(t: libc::timespec) -> SystemTime {
+        SystemTime { t: Timespec { t: t } }
     }
+}
 
-    impl fmt::Debug for SystemTime {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            f.debug_struct("SystemTime")
-             .field("tv_sec", &self.t.t.tv_sec)
-             .field("tv_nsec", &self.t.t.tv_nsec)
-             .finish()
-        }
+impl fmt::Debug for SystemTime {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SystemTime")
+         .field("tv_sec", &self.t.t.tv_sec)
+         .field("tv_nsec", &self.t.t.tv_nsec)
+         .finish()
     }
+}
 
-    #[cfg(not(any(target_os = "dragonfly", target_os = "redox")))]
-    pub type clock_t = libc::c_int;
-    #[cfg(target_os = "dragonfly")]
-    pub type clock_t = libc::c_ulong;
-    #[cfg(target_os = "redox")]
-    pub type clock_t = usize;
+pub type clock_t = usize;
 
-    fn now(clock: clock_t) -> Timespec {
-        let mut t = Timespec {
-            t: libc::timespec {
-                tv_sec: 0,
-                tv_nsec: 0,
-            }
-        };
-        cvt(unsafe {
-            libc::clock_gettime(clock, &mut t.t)
-        }).unwrap();
-        t
-    }
+fn now(clock: clock_t) -> Timespec {
+    let mut t = Timespec {
+        t: libc::timespec {
+            tv_sec: 0,
+            tv_nsec: 0,
+        }
+    };
+    cvt(libc::clock_gettime(clock, &mut t.t)).unwrap();
+    t
 }