diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs
index 6774e6b49e344288635ffc9f1972dba3fb8c260e..c21b279287a3f0235e005341d9f1cf382d20e0c2 100644
--- a/src/header/fcntl/mod.rs
+++ b/src/header/fcntl/mod.rs
@@ -55,7 +55,7 @@ pub unsafe extern "C" fn fcntl(fildes: c_int, cmd: c_int, mut __valist: ...) ->
         _ => 0,
     };
 
-    Sys::fcntl(fildes, cmd, arg)
+    Sys::fcntl(fildes, cmd, arg).or_minus_one_errno()
 }
 
 #[no_mangle]
diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
index e36a182db69fde296dfb3c048d1380ff5c9c000f..6719aed47a87610be9c95868f839a32e22b23bcf 100644
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -837,7 +837,7 @@ pub unsafe extern "C" fn pclose(stream: *mut FILE) -> c_int {
     fclose(stream);
 
     let mut wstatus = 0;
-    if Sys::waitpid(pid, &mut wstatus, 0) < 0 {
+    if Sys::waitpid(pid, &mut wstatus, 0).or_minus_one_errno() == -1 {
         return -1;
     }
 
diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index 47dd99e5eb3c8ba75925a3270441b841e33d8b8e..f3486018dc757437145cb182f3753f5c6494f9be 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -1320,7 +1320,7 @@ pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
         unreachable!();
     } else if child_pid > 0 {
         let mut wstatus = 0;
-        if Sys::waitpid(child_pid, &mut wstatus, 0) == !0 {
+        if Sys::waitpid(child_pid, &mut wstatus, 0).or_minus_one_errno() == -1 {
             return -1;
         }
 
diff --git a/src/header/sys_file/mod.rs b/src/header/sys_file/mod.rs
index 7d8e6324035c00ac9bd3e1a6470c3bca2d35c392..15e0f81ec1e868c22816362ac1cca1877c026534 100644
--- a/src/header/sys_file/mod.rs
+++ b/src/header/sys_file/mod.rs
@@ -1,6 +1,9 @@
 //! sys/file.h implementation
 
-use crate::platform::{types::*, Pal, Sys};
+use crate::{
+    error::ResultExt,
+    platform::{types::*, Pal, Sys},
+};
 
 pub const LOCK_SH: usize = 1;
 pub const LOCK_EX: usize = 2;
@@ -13,5 +16,5 @@ pub const L_XTND: usize = 2;
 
 #[no_mangle]
 pub extern "C" fn flock(fd: c_int, operation: c_int) -> c_int {
-    Sys::flock(fd, operation)
+    Sys::flock(fd, operation).map(|()| 0).or_minus_one_errno()
 }
diff --git a/src/header/sys_ioctl/linux.rs b/src/header/sys_ioctl/linux.rs
index 949052dbaeaa1fcaff8f3502c0e27a421849e324..e6b95848e0e64bc0a9726f48110aafa4c240dc66 100644
--- a/src/header/sys_ioctl/linux.rs
+++ b/src/header/sys_ioctl/linux.rs
@@ -1,9 +1,12 @@
-use crate::platform::{types::*, Sys};
+use crate::{
+    error::ResultExt,
+    platform::{types::*, Sys},
+};
 
 #[no_mangle]
 pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
     // TODO: Somehow support varargs to syscall??
-    Sys::ioctl(fd, request, out)
+    Sys::ioctl(fd, request, out).or_minus_one_errno()
 }
 
 pub const TCGETS: c_ulong = 0x5401;
diff --git a/src/header/sys_mman/mod.rs b/src/header/sys_mman/mod.rs
index 29f639a7a44ce6ea02bf5ff501d31f1d6ae225d3..3133a74159a01a962c09de1c70d04b3513d00ee2 100644
--- a/src/header/sys_mman/mod.rs
+++ b/src/header/sys_mman/mod.rs
@@ -1,7 +1,8 @@
 use crate::{
     c_str::{CStr, CString},
+    error::{Errno, ResultExt},
     header::{fcntl, unistd},
-    platform::{types::*, Pal, Sys},
+    platform::{types::*, Pal, Sys, ERRNO},
 };
 
 pub use self::sys::*;
@@ -45,12 +46,12 @@ pub const POSIX_MADV_WONTNEED: c_int = 4;
 
 #[no_mangle]
 pub unsafe extern "C" fn mlock(addr: *const c_void, len: usize) -> c_int {
-    Sys::mlock(addr, len)
+    Sys::mlock(addr, len).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
-pub extern "C" fn mlockall(flags: c_int) -> c_int {
-    Sys::mlockall(flags)
+pub unsafe extern "C" fn mlockall(flags: c_int) -> c_int {
+    Sys::mlockall(flags).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -62,7 +63,13 @@ pub unsafe extern "C" fn mmap(
     fildes: c_int,
     off: off_t,
 ) -> *mut c_void {
-    Sys::mmap(addr, len, prot, flags, fildes, off)
+    match Sys::mmap(addr, len, prot, flags, fildes, off) {
+        Ok(ptr) => ptr,
+        Err(Errno(errno)) => {
+            ERRNO.set(errno);
+            MAP_FAILED
+        }
+    }
 }
 
 #[no_mangle]
@@ -74,37 +81,49 @@ unsafe extern "C" fn mremap(
     mut __valist: ...
 ) -> *mut c_void {
     let new_address = __valist.arg::<*mut c_void>();
-    Sys::mremap(old_address, old_size, new_size, flags, new_address)
+    match Sys::mremap(old_address, old_size, new_size, flags, new_address) {
+        Ok(ptr) => ptr,
+        Err(Errno(errno)) => {
+            ERRNO.set(errno);
+            MAP_FAILED
+        }
+    }
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int {
     Sys::mprotect(addr, len, prot)
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int {
     Sys::msync(addr, len, flags)
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn munlock(addr: *const c_void, len: usize) -> c_int {
-    Sys::munlock(addr, len)
+    Sys::munlock(addr, len).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
-pub extern "C" fn munlockall() -> c_int {
-    Sys::munlockall()
+pub unsafe extern "C" fn munlockall() -> c_int {
+    Sys::munlockall().map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn munmap(addr: *mut c_void, len: size_t) -> c_int {
-    Sys::munmap(addr, len)
+    Sys::munmap(addr, len).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn madvise(addr: *mut c_void, len: size_t, flags: c_int) -> c_int {
     Sys::madvise(addr, len, flags)
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
 
 #[cfg(target_os = "linux")]
diff --git a/src/header/sys_random/mod.rs b/src/header/sys_random/mod.rs
index 957f8c7753eb374471cf095f37b8956799180716..407739a7b0a6c706bfe1ef1eda63822edf2eff5c 100644
--- a/src/header/sys_random/mod.rs
+++ b/src/header/sys_random/mod.rs
@@ -1,6 +1,9 @@
 use core::slice;
 
-use crate::platform::{types::*, Pal, Sys};
+use crate::{
+    error::ResultExt,
+    platform::{types::*, Pal, Sys},
+};
 
 pub const GRND_NONBLOCK: c_uint = 1;
 pub const GRND_RANDOM: c_uint = 2;
@@ -11,4 +14,5 @@ pub unsafe extern "C" fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_ui
         slice::from_raw_parts_mut(buf as *mut u8, buflen as usize),
         flags,
     )
+    .or_minus_one_errno()
 }
diff --git a/src/header/sys_resource/mod.rs b/src/header/sys_resource/mod.rs
index d8a44b968651f075ed4fb5c328e7fecc9a0326c6..4e54febacbfcc7caa314049ce9fa15f0e8373798 100644
--- a/src/header/sys_resource/mod.rs
+++ b/src/header/sys_resource/mod.rs
@@ -68,7 +68,7 @@ pub const PRIO_USER: c_int = 2;
 
 #[no_mangle]
 pub unsafe extern "C" fn getpriority(which: c_int, who: id_t) -> c_int {
-    let r = Sys::getpriority(which, who);
+    let r = Sys::getpriority(which, who).or_minus_one_errno();
     if r < 0 {
         return r;
     }
@@ -99,4 +99,6 @@ pub unsafe extern "C" fn setrlimit(resource: c_int, rlp: *const rlimit) -> c_int
 #[no_mangle]
 pub unsafe extern "C" fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
     Sys::getrusage(who, &mut *r_usage)
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
diff --git a/src/header/sys_stat/mod.rs b/src/header/sys_stat/mod.rs
index 17dfe6bcd339630422fce1e2b4cb433a548dc69a..5b75c31a30733d1592b7d51ce2c20f5d74fb929e 100644
--- a/src/header/sys_stat/mod.rs
+++ b/src/header/sys_stat/mod.rs
@@ -77,18 +77,18 @@ pub extern "C" fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
 }
 
 #[no_mangle]
-pub extern "C" fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
-    Sys::fstat(fildes, buf)
+pub unsafe extern "C" fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+    Sys::fstat(fildes, buf).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
-pub extern "C" fn __fxstat(_ver: c_int, fildes: c_int, buf: *mut stat) -> c_int {
+pub unsafe extern "C" fn __fxstat(_ver: c_int, fildes: c_int, buf: *mut stat) -> c_int {
     fstat(fildes, buf)
 }
 
 #[no_mangle]
-pub extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
-    Sys::futimens(fd, times)
+pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
+    Sys::futimens(fd, times).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -100,7 +100,8 @@ pub unsafe extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
         return -1;
     }
 
-    let res = Sys::fstat(fd, buf);
+    // TODO: Rustify
+    let res = Sys::fstat(fd, buf).map(|()| 0).or_minus_one_errno();
 
     Sys::close(fd);
 
@@ -147,7 +148,8 @@ pub unsafe extern "C" fn stat(file: *const c_char, buf: *mut stat) -> c_int {
         return -1;
     }
 
-    let res = Sys::fstat(fd, buf);
+    // TODO: Rustify
+    let res = Sys::fstat(fd, buf).map(|()| 0).or_minus_one_errno();
 
     Sys::close(fd);
 
diff --git a/src/header/sys_statvfs/mod.rs b/src/header/sys_statvfs/mod.rs
index 6bfde24f0cd1c90487944ae24745be2386ba3a0c..306e0436bf60adc890bf5c20b00dcd8585b72393 100644
--- a/src/header/sys_statvfs/mod.rs
+++ b/src/header/sys_statvfs/mod.rs
@@ -27,8 +27,8 @@ pub struct statvfs {
 }
 
 #[no_mangle]
-pub extern "C" fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
-    Sys::fstatvfs(fildes, buf)
+pub unsafe extern "C" fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
+    Sys::fstatvfs(fildes, buf).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -40,7 +40,7 @@ pub unsafe extern "C" fn statvfs(file: *const c_char, buf: *mut statvfs) -> c_in
         return -1;
     }
 
-    let res = Sys::fstatvfs(fd, buf);
+    let res = Sys::fstatvfs(fd, buf).map(|()| 0).or_minus_one_errno();
 
     Sys::close(fd);
 
diff --git a/src/header/sys_time/mod.rs b/src/header/sys_time/mod.rs
index e9641493ecffab1d7b118d42a98a9f1c3222e205..3a5a7f9f512965e1ed21ac9645e83bd9d5fee5ae 100644
--- a/src/header/sys_time/mod.rs
+++ b/src/header/sys_time/mod.rs
@@ -2,6 +2,7 @@
 
 use crate::{
     c_str::CStr,
+    error::ResultExt,
     header::time::timespec,
     platform::{types::*, Pal, PalSignal, Sys},
 };
@@ -52,7 +53,7 @@ pub unsafe extern "C" fn setitimer(
 
 #[no_mangle]
 pub unsafe extern "C" fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
-    Sys::gettimeofday(tp, tzp)
+    Sys::gettimeofday(tp, tzp).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -77,4 +78,6 @@ pub unsafe extern "C" fn utimes(path: *const c_char, times: *const timeval) -> c
         .as_ptr()
     };
     Sys::utimens(path, times_spec)
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
diff --git a/src/header/sys_wait/mod.rs b/src/header/sys_wait/mod.rs
index 3628353977a5e398687e784402529b2657a55a90..e482bb3211e3f84e153b17d5bc47505c8000188b 100644
--- a/src/header/sys_wait/mod.rs
+++ b/src/header/sys_wait/mod.rs
@@ -1,6 +1,7 @@
 //! sys/wait.h implementation for Redox, following
 //! http://pubs.opengroup.org/onlinepubs/7908799/xsh/syswait.h.html
 
+use crate::error::ResultExt;
 //use header::sys_resource::rusage;
 use crate::platform::{types::*, Pal, Sys};
 
@@ -47,5 +48,5 @@ pub unsafe extern "C" fn wait(stat_loc: *mut c_int) -> pid_t {
 
 #[no_mangle]
 pub unsafe extern "C" fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
-    Sys::waitpid(pid, stat_loc, options)
+    Sys::waitpid(pid, stat_loc, options).or_minus_one_errno()
 }
diff --git a/src/header/time/mod.rs b/src/header/time/mod.rs
index 0ea67045389cc9a6f20a1681f75aa326dfcedf88..3942ecb2069253206842766c8c188dfdc28b43f6 100644
--- a/src/header/time/mod.rs
+++ b/src/header/time/mod.rs
@@ -488,8 +488,8 @@ pub unsafe extern "C" fn mktime(timeptr: *mut tm) -> time_t {
 }
 
 #[no_mangle]
-pub extern "C" fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
-    Sys::nanosleep(rqtp, rmtp)
+pub unsafe extern "C" fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
+    Sys::nanosleep(rqtp, rmtp).map(|()| 0).or_minus_one_errno()
 }
 
 #[no_mangle]
diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs
index 03ef809cbbed04d34049495d7c1763c38533a963..e987f43b8efbc949fbd9596ce537c67c609c23c8 100644
--- a/src/header/unistd/mod.rs
+++ b/src/header/unistd/mod.rs
@@ -163,7 +163,7 @@ pub extern "C" fn daemon(nochdir: c_int, noclose: c_int) -> c_int {
         }
     }
 
-    match fork() {
+    match unsafe { fork() } {
         0 => {}
         -1 => return -1,
         _ => _exit(0),
@@ -283,6 +283,8 @@ pub unsafe extern "C" fn execve(
 ) -> c_int {
     let path = CStr::from_ptr(path);
     Sys::execve(path, argv, envp)
+        .map(|()| unreachable!())
+        .or_minus_one_errno()
 }
 
 #[cfg(target_os = "linux")]
@@ -344,12 +346,12 @@ pub extern "C" fn fdatasync(fildes: c_int) -> c_int {
 }
 
 #[no_mangle]
-pub extern "C" fn fork() -> pid_t {
-    let fork_hooks = unsafe { init_fork_hooks() };
+pub unsafe extern "C" fn fork() -> pid_t {
+    let fork_hooks = init_fork_hooks();
     for prepare in &fork_hooks[0] {
         prepare();
     }
-    let pid = Sys::fork();
+    let pid = Sys::fork().or_minus_one_errno();
     if pid == 0 {
         for child in &fork_hooks[2] {
             child();
@@ -442,7 +444,7 @@ pub extern "C" fn getgid() -> gid_t {
 
 #[no_mangle]
 pub unsafe extern "C" fn getgroups(size: c_int, list: *mut gid_t) -> c_int {
-    Sys::getgroups(size, list)
+    Sys::getgroups(size, list).or_minus_one_errno()
 }
 
 // #[no_mangle]
@@ -506,12 +508,12 @@ pub extern "C" fn getpagesize() -> c_int {
 
 #[no_mangle]
 pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
-    Sys::getpgid(pid)
+    Sys::getpgid(pid).or_minus_one_errno()
 }
 
 #[no_mangle]
 pub extern "C" fn getpgrp() -> pid_t {
-    Sys::getpgid(Sys::getpid())
+    Sys::getpgid(Sys::getpid()).or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -526,7 +528,7 @@ pub extern "C" fn getppid() -> pid_t {
 
 #[no_mangle]
 pub extern "C" fn getsid(pid: pid_t) -> pid_t {
-    Sys::getsid(pid)
+    Sys::getsid(pid).or_minus_one_errno()
 }
 
 #[no_mangle]
@@ -775,7 +777,7 @@ pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
         tv_nsec: 0,
     };
     let rmtp = ptr::null_mut();
-    Sys::nanosleep(&rqtp, rmtp);
+    unsafe { Sys::nanosleep(&rqtp, rmtp).map(|()| 0).or_minus_one_errno() };
     0
 }
 
@@ -902,7 +904,9 @@ pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
         tv_nsec: ((useconds % 1_000_000) * 1000) as c_long,
     };
     let rmtp = ptr::null_mut();
-    Sys::nanosleep(&rqtp, rmtp)
+    unsafe { Sys::nanosleep(&rqtp, rmtp) }
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
 
 // #[no_mangle]
diff --git a/src/header/utime/mod.rs b/src/header/utime/mod.rs
index 5098cec7f576586b33e1a1c1e22c8c9cc391deab..bb17488d23c1d73971f453251bc7769a595cd158 100644
--- a/src/header/utime/mod.rs
+++ b/src/header/utime/mod.rs
@@ -2,6 +2,7 @@
 
 use crate::{
     c_str::CStr,
+    error::ResultExt,
     header::time::timespec,
     platform::{types::*, Pal, Sys},
 };
@@ -27,4 +28,6 @@ pub unsafe extern "C" fn utime(filename: *const c_char, times: *const utimbuf) -
         },
     ];
     Sys::utimens(filename, times_spec.as_ptr())
+        .map(|()| 0)
+        .or_minus_one_errno()
 }
diff --git a/src/lib.rs b/src/lib.rs
index 8ab4e35145c794f252916c2f2c768e82034d4dd5..4ae044e0dc1544bcae2112cf207f86b11aee2907 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,5 @@
 #![no_std]
+#![allow(warnings)]
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 #![allow(unused_variables)]
diff --git a/src/platform/allocator/sys.rs b/src/platform/allocator/sys.rs
index a2e6543fc19ff5392a1848989eb61cfa4c96effa..8241907c1df708a8649c08ee572db5b4dd642e38 100644
--- a/src/platform/allocator/sys.rs
+++ b/src/platform/allocator/sys.rs
@@ -25,7 +25,7 @@ static LOCK: Mutex<()> = Mutex::new(());
 
 unsafe impl Allocator for System {
     fn alloc(&self, size: usize) -> (*mut u8, usize, u32) {
-        let addr = unsafe {
+        let Ok(addr) = (unsafe {
             Sys::mmap(
                 0 as *mut _,
                 size,
@@ -34,36 +34,33 @@ unsafe impl Allocator for System {
                 -1,
                 0,
             )
+        }) else {
+            return (ptr::null_mut(), 0, 0);
         };
-        if addr as *mut c_void == MAP_FAILED {
-            (ptr::null_mut(), 0, 0)
-        } else {
-            (addr as *mut u8, size, 0)
-        }
+        (addr as *mut u8, size, 0)
     }
 
     fn remap(&self, ptr: *mut u8, oldsize: usize, newsize: usize, can_move: bool) -> *mut u8 {
         let flags = if can_move { MREMAP_MAYMOVE } else { 0 };
-        let ptr = unsafe { Sys::mremap(ptr as *mut _, oldsize, newsize, flags, ptr::null_mut()) };
-        if ptr as *mut c_void == MAP_FAILED {
-            ptr::null_mut()
-        } else {
-            ptr as *mut u8
-        }
+        let Ok(ptr) =
+            (unsafe { Sys::mremap(ptr as *mut _, oldsize, newsize, flags, ptr::null_mut()) })
+        else {
+            return ptr::null_mut();
+        };
+        ptr as *mut u8
     }
 
     fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool {
         unsafe {
-            let rc = Sys::mremap(ptr as *mut _, oldsize, newsize, 0, ptr::null_mut());
-            if rc as *mut c_void != MAP_FAILED {
+            if Sys::mremap(ptr as *mut _, oldsize, newsize, 0, ptr::null_mut()).is_ok() {
                 return true;
             }
-            Sys::munmap(ptr.offset(newsize as isize) as *mut _, oldsize - newsize) == 0
+            Sys::munmap(ptr.add(newsize) as *mut _, oldsize - newsize).is_ok()
         }
     }
 
     fn free(&self, ptr: *mut u8, size: usize) -> bool {
-        unsafe { Sys::munmap(ptr as *mut _, size) == 0 }
+        unsafe { Sys::munmap(ptr as *mut _, size).is_ok() }
     }
 
     fn can_release_part(&self, _flags: u32) -> bool {
diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs
index 3258a900a205b3bcd7a1cd3286b5e8e9340d4158..4c505cebd46e3f74a356e5165afe6feca13017e2 100644
--- a/src/platform/linux/mod.rs
+++ b/src/platform/linux/mod.rs
@@ -77,9 +77,9 @@ pub fn e(sys: usize) -> usize {
 pub struct Sys;
 
 impl Sys {
-    pub unsafe fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
+    pub unsafe fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> Result<c_int> {
         // TODO: Somehow support varargs to syscall??
-        e(syscall!(IOCTL, fd, request, out)) as c_int
+        Ok(e_raw(syscall!(IOCTL, fd, request, out))? as c_int)
     }
 
     // fn times(out: *mut tms) -> clock_t {
@@ -144,10 +144,15 @@ impl Pal for Sys {
         e_raw(unsafe { syscall!(DUP3, fildes, fildes2, 0) }).map(|f| f as c_int)
     }
 
-    unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
-        e(syscall!(EXECVE, path.as_ptr(), argv, envp)) as c_int
+    unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> Result<()> {
+        e_raw(syscall!(EXECVE, path.as_ptr(), argv, envp))?;
+        unreachable!()
     }
-    unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
+    unsafe fn fexecve(
+        fildes: c_int,
+        argv: *const *mut c_char,
+        envp: *const *mut c_char,
+    ) -> Result<()> {
         todo!("not yet used by relibc")
     }
 
@@ -178,50 +183,47 @@ impl Pal for Sys {
         e_raw(unsafe { syscall!(FDATASYNC, fildes) }).map(|_| ())
     }
 
-    fn flock(fd: c_int, operation: c_int) -> c_int {
-        e(unsafe { syscall!(FLOCK, fd, operation) }) as c_int
+    fn flock(fd: c_int, operation: c_int) -> Result<()> {
+        e_raw(unsafe { syscall!(FLOCK, fd, operation) }).map(|_| ())
     }
 
-    fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+    unsafe fn fstat(fildes: c_int, buf: *mut stat) -> Result<()> {
         let empty = b"\0";
         let empty_ptr = empty.as_ptr() as *const c_char;
-        e(unsafe { syscall!(NEWFSTATAT, fildes, empty_ptr, buf, AT_EMPTY_PATH) }) as c_int
+        e_raw(unsafe { syscall!(NEWFSTATAT, fildes, empty_ptr, buf, AT_EMPTY_PATH) }).map(|_| ())
     }
 
-    fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
+    unsafe fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> Result<()> {
         let mut kbuf = linux_statfs::default();
         let kbuf_ptr = &mut kbuf as *mut linux_statfs;
-        let res = e(unsafe { syscall!(FSTATFS, fildes, kbuf_ptr) }) as c_int;
-        if res == 0 {
-            unsafe {
-                if !buf.is_null() {
-                    (*buf).f_bsize = kbuf.f_bsize as c_ulong;
-                    (*buf).f_frsize = if kbuf.f_frsize != 0 {
-                        kbuf.f_frsize
-                    } else {
-                        kbuf.f_bsize
-                    } as c_ulong;
-                    (*buf).f_blocks = kbuf.f_blocks;
-                    (*buf).f_bfree = kbuf.f_bfree;
-                    (*buf).f_bavail = kbuf.f_bavail;
-                    (*buf).f_files = kbuf.f_files;
-                    (*buf).f_ffree = kbuf.f_ffree;
-                    (*buf).f_favail = kbuf.f_ffree;
-                    (*buf).f_fsid = kbuf.f_fsid as c_ulong;
-                    (*buf).f_flag = kbuf.f_flags as c_ulong;
-                    (*buf).f_namemax = kbuf.f_namelen as c_ulong;
-                }
-            }
+        e_raw(syscall!(FSTATFS, fildes, kbuf_ptr))?;
+
+        if !buf.is_null() {
+            (*buf).f_bsize = kbuf.f_bsize as c_ulong;
+            (*buf).f_frsize = if kbuf.f_frsize != 0 {
+                kbuf.f_frsize
+            } else {
+                kbuf.f_bsize
+            } as c_ulong;
+            (*buf).f_blocks = kbuf.f_blocks;
+            (*buf).f_bfree = kbuf.f_bfree;
+            (*buf).f_bavail = kbuf.f_bavail;
+            (*buf).f_files = kbuf.f_files;
+            (*buf).f_ffree = kbuf.f_ffree;
+            (*buf).f_favail = kbuf.f_ffree;
+            (*buf).f_fsid = kbuf.f_fsid as c_ulong;
+            (*buf).f_flag = kbuf.f_flags as c_ulong;
+            (*buf).f_namemax = kbuf.f_namelen as c_ulong;
         }
-        res
+        Ok(())
     }
 
-    fn fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> c_int {
-        e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> Result<c_int> {
+        Ok(e_raw(unsafe { syscall!(FCNTL, fildes, cmd, arg) })? as c_int)
     }
 
-    fn fork() -> pid_t {
-        e(unsafe { syscall!(CLONE, SIGCHLD, 0, 0, 0, 0) }) as pid_t
+    unsafe fn fork() -> Result<pid_t> {
+        Ok(e_raw(unsafe { syscall!(CLONE, SIGCHLD, 0, 0, 0, 0) })? as pid_t)
     }
 
     fn fpath(fildes: c_int, out: &mut [u8]) -> Result<ssize_t> {
@@ -263,12 +265,12 @@ impl Pal for Sys {
         .map(|n| n as u32)
     }
 
-    fn futimens(fd: c_int, times: *const timespec) -> c_int {
-        e(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }) as c_int
+    unsafe fn futimens(fd: c_int, times: *const timespec) -> Result<()> {
+        e_raw(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }).map(|_| ())
     }
 
-    fn utimens(path: CStr, times: *const timespec) -> c_int {
-        e(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path.as_ptr(), times, 0) }) as c_int
+    unsafe fn utimens(path: CStr, times: *const timespec) -> Result<()> {
+        e_raw(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path.as_ptr(), times, 0) }).map(|_| ())
     }
 
     fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
@@ -292,43 +294,48 @@ impl Pal for Sys {
     }
 
     fn getegid() -> gid_t {
-        e(unsafe { syscall!(GETEGID) }) as gid_t
+        // Always successful
+        unsafe { syscall!(GETEGID) as gid_t }
     }
 
     fn geteuid() -> uid_t {
-        e(unsafe { syscall!(GETEUID) }) as uid_t
+        // Always successful
+        unsafe { syscall!(GETEUID) as uid_t }
     }
 
     fn getgid() -> gid_t {
-        e(unsafe { syscall!(GETGID) }) as gid_t
+        // Always successful
+        unsafe { syscall!(GETGID) as gid_t }
     }
 
-    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> c_int {
-        e(unsafe { syscall!(GETGROUPS, size, list) }) as c_int
+    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> Result<c_int> {
+        Ok(e_raw(unsafe { syscall!(GETGROUPS, size, list) })? as c_int)
     }
 
     fn getpagesize() -> usize {
         4096
     }
 
-    fn getpgid(pid: pid_t) -> pid_t {
-        e(unsafe { syscall!(GETPGID, pid) }) as pid_t
+    fn getpgid(pid: pid_t) -> Result<pid_t> {
+        Ok(e_raw(unsafe { syscall!(GETPGID, pid) })? as pid_t)
     }
 
     fn getpid() -> pid_t {
-        e(unsafe { syscall!(GETPID) }) as pid_t
+        // Always successful
+        unsafe { syscall!(GETPID) as pid_t }
     }
 
     fn getppid() -> pid_t {
-        e(unsafe { syscall!(GETPPID) }) as pid_t
+        // Always successful
+        unsafe { syscall!(GETPPID) as pid_t }
     }
 
-    fn getpriority(which: c_int, who: id_t) -> c_int {
-        e(unsafe { syscall!(GETPRIORITY, which, who) }) as c_int
+    fn getpriority(which: c_int, who: id_t) -> Result<c_int> {
+        Ok(e_raw(unsafe { syscall!(GETPRIORITY, which, who) })? as c_int)
     }
 
-    fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t {
-        e(unsafe { syscall!(GETRANDOM, buf.as_mut_ptr(), buf.len(), flags) }) as ssize_t
+    fn getrandom(buf: &mut [u8], flags: c_uint) -> Result<ssize_t> {
+        Ok(e_raw(unsafe { syscall!(GETRANDOM, buf.as_mut_ptr(), buf.len(), flags) })? as ssize_t)
     }
 
     unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> Result<()> {
@@ -339,24 +346,26 @@ impl Pal for Sys {
         e_raw(syscall!(SETRLIMIT, resource, rlimit)).map(|_| ())
     }
 
-    fn getrusage(who: c_int, r_usage: &mut rusage) -> c_int {
-        e(unsafe { syscall!(GETRUSAGE, who, r_usage as *mut rusage) }) as c_int
+    fn getrusage(who: c_int, r_usage: &mut rusage) -> Result<()> {
+        e_raw(unsafe { syscall!(GETRUSAGE, who, r_usage as *mut rusage) })?;
+        Ok(())
     }
 
-    fn getsid(pid: pid_t) -> pid_t {
-        e(unsafe { syscall!(GETSID, pid) }) as pid_t
+    fn getsid(pid: pid_t) -> Result<pid_t> {
+        Ok(e_raw(unsafe { syscall!(GETSID, pid) })? as pid_t)
     }
 
     fn gettid() -> pid_t {
-        e(unsafe { syscall!(GETTID) }) as pid_t
+        // Always successful
+        unsafe { syscall!(GETTID) as pid_t }
     }
 
-    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
-        e(unsafe { syscall!(GETTIMEOFDAY, tp, tzp) }) as c_int
+    unsafe fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> Result<()> {
+        e_raw(unsafe { syscall!(GETTIMEOFDAY, tp, tzp) }).map(|_| ())
     }
 
     fn getuid() -> uid_t {
-        e(unsafe { syscall!(GETUID) }) as uid_t
+        unsafe { syscall!(GETUID) as uid_t }
     }
 
     fn lchown(path: CStr, owner: uid_t, group: gid_t) -> Result<()> {
@@ -404,12 +413,12 @@ impl Pal for Sys {
         Sys::mknod(path, mode | S_IFIFO, 0)
     }
 
-    unsafe fn mlock(addr: *const c_void, len: usize) -> c_int {
-        e(syscall!(MLOCK, addr, len)) as c_int
+    unsafe fn mlock(addr: *const c_void, len: usize) -> Result<()> {
+        e_raw(unsafe { syscall!(MLOCK, addr, len) }).map(|_| ())
     }
 
-    fn mlockall(flags: c_int) -> c_int {
-        e(unsafe { syscall!(MLOCKALL, flags) }) as c_int
+    unsafe fn mlockall(flags: c_int) -> Result<()> {
+        e_raw(unsafe { syscall!(MLOCKALL, flags) }).map(|_| ())
     }
 
     unsafe fn mmap(
@@ -419,8 +428,8 @@ impl Pal for Sys {
         flags: c_int,
         fildes: c_int,
         off: off_t,
-    ) -> *mut c_void {
-        e(syscall!(MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
+    ) -> Result<*mut c_void> {
+        Ok(e_raw(syscall!(MMAP, addr, len, prot, flags, fildes, off))? as *mut c_void)
     }
 
     unsafe fn mremap(
@@ -429,36 +438,36 @@ impl Pal for Sys {
         new_len: usize,
         flags: c_int,
         args: *mut c_void,
-    ) -> *mut c_void {
-        e(syscall!(MREMAP, addr, len, new_len, flags, args)) as *mut c_void
+    ) -> Result<*mut c_void> {
+        Ok(e_raw(syscall!(MREMAP, addr, len, new_len, flags, args))? as *mut c_void)
     }
 
-    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
-        e(syscall!(MPROTECT, addr, len, prot)) as c_int
+    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> Result<()> {
+        e_raw(syscall!(MPROTECT, addr, len, prot)).map(|_| ())
     }
 
-    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
-        e(syscall!(MSYNC, addr, len, flags)) as c_int
+    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> Result<()> {
+        e_raw(syscall!(MSYNC, addr, len, flags)).map(|_| ())
     }
 
-    unsafe fn munlock(addr: *const c_void, len: usize) -> c_int {
-        e(syscall!(MUNLOCK, addr, len)) as c_int
+    unsafe fn munlock(addr: *const c_void, len: usize) -> Result<()> {
+        e_raw(syscall!(MUNLOCK, addr, len)).map(|_| ())
     }
 
-    fn munlockall() -> c_int {
-        e(unsafe { syscall!(MUNLOCKALL) }) as c_int
+    unsafe fn munlockall() -> Result<()> {
+        e_raw(unsafe { syscall!(MUNLOCKALL) }).map(|_| ())
     }
 
-    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
-        e(syscall!(MUNMAP, addr, len)) as c_int
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> Result<()> {
+        e_raw(syscall!(MUNMAP, addr, len)).map(|_| ())
     }
 
-    unsafe fn madvise(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
-        e(syscall!(MADVISE, addr, len, flags)) as c_int
+    unsafe fn madvise(addr: *mut c_void, len: usize, flags: c_int) -> Result<()> {
+        e_raw(syscall!(MADVISE, addr, len, flags)).map(|_| ())
     }
 
-    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
-        e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
+    unsafe fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> Result<()> {
+        e_raw(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }).map(|_| ())
     }
 
     fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
@@ -614,8 +623,8 @@ impl Pal for Sys {
         e_raw(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), 0) }).map(|_| ())
     }
 
-    fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
-        e(unsafe { syscall!(WAIT4, pid, stat_loc, options, 0) }) as pid_t
+    unsafe fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> Result<pid_t> {
+        e_raw(unsafe { syscall!(WAIT4, pid, stat_loc, options, 0) }).map(|p| p as pid_t)
     }
 
     fn write(fildes: c_int, buf: &[u8]) -> Result<ssize_t> {
@@ -627,6 +636,6 @@ impl Pal for Sys {
 
     fn verify() -> bool {
         // GETPID on Linux is 39, which does not exist on Redox
-        e(unsafe { sc::syscall5(sc::nr::GETPID, !0, !0, !0, !0, !0) }) != !0
+        e_raw(unsafe { sc::syscall5(sc::nr::GETPID, !0, !0, !0, !0, !0) }).is_ok()
     }
 }
diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs
index e8716defdea9e06d38a38c1147286add0b8ee2c7..071d644fbf9d08b79c241d5586281437020ba3d1 100644
--- a/src/platform/pal/mod.rs
+++ b/src/platform/pal/mod.rs
@@ -50,8 +50,12 @@ pub trait Pal {
 
     fn dup2(fildes: c_int, fildes2: c_int) -> Result<c_int>;
 
-    unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
-    unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
+    unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> Result<()>;
+    unsafe fn fexecve(
+        fildes: c_int,
+        argv: *const *mut c_char,
+        envp: *const *mut c_char,
+    ) -> Result<()>;
 
     fn exit(status: c_int) -> !;
 
@@ -65,15 +69,15 @@ pub trait Pal {
 
     fn fdatasync(fildes: c_int) -> Result<()>;
 
-    fn flock(fd: c_int, operation: c_int) -> c_int;
+    fn flock(fd: c_int, operation: c_int) -> Result<()>;
 
-    fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+    unsafe fn fstat(fildes: c_int, buf: *mut stat) -> Result<()>;
 
-    fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int;
+    unsafe fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> Result<()>;
 
-    fn fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> c_int;
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> Result<c_int>;
 
-    fn fork() -> pid_t;
+    unsafe fn fork() -> Result<pid_t>;
 
     fn fpath(fildes: c_int, out: &mut [u8]) -> Result<ssize_t>;
 
@@ -84,9 +88,9 @@ pub trait Pal {
     unsafe fn futex_wait(addr: *mut u32, val: u32, deadline: Option<&timespec>) -> Result<()>;
     unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<u32>;
 
-    fn futimens(fd: c_int, times: *const timespec) -> c_int;
+    unsafe fn futimens(fd: c_int, times: *const timespec) -> Result<()>;
 
-    fn utimens(path: CStr, times: *const timespec) -> c_int;
+    unsafe fn utimens(path: CStr, times: *const timespec) -> Result<()>;
 
     fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
 
@@ -104,34 +108,34 @@ pub trait Pal {
 
     fn getgid() -> gid_t;
 
-    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> c_int;
+    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> Result<c_int>;
 
     /* Note that this is distinct from the legacy POSIX function
      * getpagesize(), which returns a c_int. On some Linux platforms,
      * page size may be determined through a syscall ("getpagesize"). */
     fn getpagesize() -> usize;
 
-    fn getpgid(pid: pid_t) -> pid_t;
+    fn getpgid(pid: pid_t) -> Result<pid_t>;
 
     fn getpid() -> pid_t;
 
     fn getppid() -> pid_t;
 
-    fn getpriority(which: c_int, who: id_t) -> c_int;
+    fn getpriority(which: c_int, who: id_t) -> Result<c_int>;
 
-    fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t;
+    fn getrandom(buf: &mut [u8], flags: c_uint) -> Result<ssize_t>;
 
     unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> Result<()>;
 
     unsafe fn setrlimit(resource: c_int, rlim: *const rlimit) -> Result<()>;
 
-    fn getrusage(who: c_int, r_usage: &mut rusage) -> c_int;
+    fn getrusage(who: c_int, r_usage: &mut rusage) -> Result<()>;
 
-    fn getsid(pid: pid_t) -> pid_t;
+    fn getsid(pid: pid_t) -> Result<pid_t>;
 
     fn gettid() -> pid_t;
 
-    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int;
+    unsafe fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> Result<()>;
 
     fn getuid() -> uid_t;
 
@@ -149,9 +153,9 @@ pub trait Pal {
 
     fn mknod(path: CStr, mode: mode_t, dev: dev_t) -> Result<()>;
 
-    unsafe fn mlock(addr: *const c_void, len: usize) -> c_int;
+    unsafe fn mlock(addr: *const c_void, len: usize) -> Result<()>;
 
-    fn mlockall(flags: c_int) -> c_int;
+    unsafe fn mlockall(flags: c_int) -> Result<()>;
 
     unsafe fn mmap(
         addr: *mut c_void,
@@ -160,7 +164,7 @@ pub trait Pal {
         flags: c_int,
         fildes: c_int,
         off: off_t,
-    ) -> *mut c_void;
+    ) -> Result<*mut c_void>;
 
     unsafe fn mremap(
         addr: *mut c_void,
@@ -168,21 +172,21 @@ pub trait Pal {
         new_len: usize,
         flags: c_int,
         args: *mut c_void,
-    ) -> *mut c_void;
+    ) -> Result<*mut c_void>;
 
-    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int;
+    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> Result<()>;
 
-    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int;
+    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> Result<()>;
 
-    unsafe fn munlock(addr: *const c_void, len: usize) -> c_int;
+    unsafe fn munlock(addr: *const c_void, len: usize) -> Result<()>;
 
-    unsafe fn madvise(addr: *mut c_void, len: usize, flags: c_int) -> c_int;
+    unsafe fn madvise(addr: *mut c_void, len: usize, flags: c_int) -> Result<()>;
 
-    fn munlockall() -> c_int;
+    unsafe fn munlockall() -> Result<()>;
 
-    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int;
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> Result<()>;
 
-    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int;
+    unsafe fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> Result<()>;
 
     fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int>;
 
@@ -226,7 +230,7 @@ pub trait Pal {
 
     fn unlink(path: CStr) -> Result<()>;
 
-    fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t;
+    unsafe fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> Result<pid_t>;
 
     fn write(fildes: c_int, buf: &[u8]) -> Result<ssize_t>;
     fn pwrite(fildes: c_int, buf: &[u8], offset: off_t) -> Result<ssize_t>;
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index 62cfab1ac94e36a6d9d5a3dbecbab982109e24b3..31b8adce36f31183e786affbef4c6ecb77a02ba3 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -118,25 +118,27 @@ impl Pal for Sys {
         Ok(())
     }
 
+    // TODO: Rustify
     unsafe fn brk(addr: *mut c_void) -> *mut c_void {
         // On first invocation, allocate a buffer for brk
         if BRK_CUR.is_null() {
             // 4 megabytes of RAM ought to be enough for anybody
             const BRK_MAX_SIZE: usize = 4 * 1024 * 1024;
 
-            let allocated = Self::mmap(
+            let allocated = match Self::mmap(
                 ptr::null_mut(),
                 BRK_MAX_SIZE,
                 PROT_READ | PROT_WRITE,
                 MAP_ANONYMOUS,
                 0,
                 0,
-            );
-            if allocated == !0 as *mut c_void
-            /* MAP_FAILED */
-            {
-                return !0 as *mut c_void;
-            }
+            ) {
+                Ok(allocated) => allocated,
+                Err(Errno(errno)) => {
+                    ERRNO.set(errno);
+                    return !0 as *mut c_void;
+                }
+            };
 
             BRK_CUR = allocated;
             BRK_END = (allocated as *mut u8).add(BRK_MAX_SIZE) as *mut c_void;
@@ -214,22 +216,28 @@ impl Pal for Sys {
         loop {}
     }
 
-    unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
-        e(self::exec::execve(
+    unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> Result<()> {
+        self::exec::execve(
             Executable::AtPath(path),
             self::exec::ArgEnv::C { argv, envp },
             None,
-        )) as c_int
+        )?;
+        unreachable!()
     }
-    unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
-        e(self::exec::execve(
+    unsafe fn fexecve(
+        fildes: c_int,
+        argv: *const *mut c_char,
+        envp: *const *mut c_char,
+    ) -> Result<()> {
+        self::exec::execve(
             Executable::InFd {
                 file: File::new(fildes),
                 arg0: CStr::from_ptr(argv.read()).to_bytes(),
             },
             self::exec::ArgEnv::C { argv, envp },
             None,
-        )) as c_int
+        )?;
+        unreachable!()
     }
 
     fn fchdir(fd: c_int) -> Result<()> {
@@ -251,8 +259,8 @@ impl Pal for Sys {
         Ok(())
     }
 
-    fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> c_int {
-        e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
+    fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result<c_int> {
+        Ok(syscall::fcntl(fd as usize, cmd as usize, args as usize)? as c_int)
     }
 
     fn fdatasync(fd: c_int) -> Result<()> {
@@ -261,25 +269,26 @@ impl Pal for Sys {
         Ok(())
     }
 
-    fn flock(_fd: c_int, _operation: c_int) -> c_int {
+    fn flock(_fd: c_int, _operation: c_int) -> Result<()> {
         // TODO: Redox does not have file locking yet
-        0
+        Ok(())
     }
 
-    fn fork() -> pid_t {
+    unsafe fn fork() -> Result<pid_t> {
+        // TODO: Find way to avoid lock.
         let _guard = clone::wrlock();
-        let res = clone::fork_impl();
-        e(res) as pid_t
+
+        Ok(clone::fork_impl()? as pid_t)
     }
 
-    // FIXME: unsound
-    fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
-        unsafe { e(libredox::fstat(fildes as usize, buf).map(|()| 0)) as c_int }
+    unsafe fn fstat(fildes: c_int, buf: *mut stat) -> Result<()> {
+        libredox::fstat(fildes as usize, buf)?;
+        Ok(())
     }
 
-    // FIXME: unsound
-    fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int {
-        unsafe { e(libredox::fstatvfs(fildes as usize, buf).map(|()| 0)) as c_int }
+    unsafe fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> Result<()> {
+        libredox::fstatvfs(fildes as usize, buf)?;
+        Ok(())
     }
 
     fn fsync(fd: c_int) -> Result<()> {
@@ -306,17 +315,14 @@ impl Pal for Sys {
         Ok(redox_rt::sys::sys_futex_wake(addr, num)?)
     }
 
-    // FIXME: unsound
-    fn futimens(fd: c_int, times: *const timespec) -> c_int {
-        unsafe { e(libredox::futimens(fd as usize, times).map(|()| 0)) as c_int }
+    unsafe fn futimens(fd: c_int, times: *const timespec) -> Result<()> {
+        libredox::futimens(fd as usize, times)?;
+        Ok(())
     }
 
-    // FIXME: unsound
-    fn utimens(path: CStr, times: *const timespec) -> c_int {
-        match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
-            Ok(file) => Self::futimens(*file, times),
-            Err(_) => -1,
-        }
+    unsafe fn utimens(path: CStr, times: *const timespec) -> Result<()> {
+        let file = File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC)?;
+        Self::futimens(*file, times)
     }
 
     // FIXME: unsound
@@ -414,30 +420,29 @@ impl Pal for Sys {
     }
 
     fn getegid() -> gid_t {
-        e(syscall::getegid()) as gid_t
+        syscall::getegid().unwrap() as gid_t
     }
 
     fn geteuid() -> uid_t {
-        e(syscall::geteuid()) as uid_t
+        syscall::geteuid().unwrap() as uid_t
     }
 
     fn getgid() -> gid_t {
-        e(syscall::getgid()) as gid_t
+        syscall::getgid().unwrap() as gid_t
     }
 
-    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> c_int {
+    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> Result<c_int> {
         // TODO
         eprintln!("relibc getgroups({}, {:p}): not implemented", size, list);
-        ERRNO.set(ENOSYS);
-        -1
+        Err(Errno(ENOSYS))
     }
 
     fn getpagesize() -> usize {
         PAGE_SIZE
     }
 
-    fn getpgid(pid: pid_t) -> pid_t {
-        e(syscall::getpgid(pid as usize)) as pid_t
+    fn getpgid(pid: pid_t) -> Result<pid_t> {
+        Ok(syscall::getpgid(pid as usize)? as pid_t)
     }
 
     fn getpid() -> pid_t {
@@ -445,19 +450,16 @@ impl Pal for Sys {
     }
 
     fn getppid() -> pid_t {
-        e(syscall::getppid()) as pid_t
+        syscall::getppid().unwrap() as pid_t
     }
 
-    fn getpriority(which: c_int, who: id_t) -> c_int {
+    fn getpriority(which: c_int, who: id_t) -> Result<c_int> {
         // TODO
         eprintln!("getpriority({}, {}): not implemented", which, who);
-        ERRNO.set(ENOSYS);
-        -1
+        Err(Errno(ENOSYS))
     }
 
-    fn getrandom(buf: &mut [u8], flags: c_uint) -> ssize_t {
-        //TODO: make this a system call?
-
+    fn getrandom(buf: &mut [u8], flags: c_uint) -> Result<ssize_t> {
         let path = if flags & sys_random::GRND_RANDOM != 0 {
             //TODO: /dev/random equivalent
             "/scheme/rand"
@@ -470,16 +472,9 @@ impl Pal for Sys {
             open_flags |= syscall::O_NONBLOCK;
         }
 
-        let fd = e(syscall::open(path, open_flags));
-        if fd == !0 {
-            return -1;
-        }
-
-        let res = e(syscall::read(fd, buf)) as ssize_t;
-
-        let _ = syscall::close(fd);
-
-        res
+        //TODO: store fd internally
+        let fd = FdGuard::new(syscall::open(path, open_flags)?);
+        Ok(syscall::read(*fd, buf)? as ssize_t)
     }
 
     unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> Result<()> {
@@ -504,13 +499,13 @@ impl Pal for Sys {
         Err(Errno(EPERM))
     }
 
-    fn getrusage(who: c_int, r_usage: &mut rusage) -> c_int {
+    fn getrusage(who: c_int, r_usage: &mut rusage) -> Result<()> {
         //TODO
         eprintln!("relibc getrusage({}, {:p}): not implemented", who, r_usage);
-        0
+        Ok(())
     }
 
-    fn getsid(pid: pid_t) -> pid_t {
+    fn getsid(pid: pid_t) -> Result<pid_t> {
         let mut buf = [0; mem::size_of::<usize>()];
         let path = if pid == 0 {
             format!("/scheme/thisproc/current/session_id")
@@ -518,29 +513,21 @@ impl Pal for Sys {
             format!("/scheme/proc/{}/session_id", pid)
         };
         let path_c = CString::new(path).unwrap();
-        match File::open(CStr::borrow(&path_c), fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
-            Ok(mut file) => match file.read(&mut buf) {
-                Ok(_) => usize::from_ne_bytes(buf).try_into().unwrap(),
-                Err(_) => -1,
-            },
-            Err(_) => -1,
-        }
+        let mut file = File::open(CStr::borrow(&path_c), fcntl::O_RDONLY | fcntl::O_CLOEXEC)?;
+        file.read(&mut buf)
+            .map_err(|err| Errno(err.raw_os_error().unwrap_or(EIO)))?;
+        Ok(usize::from_ne_bytes(buf).try_into().unwrap())
     }
 
     fn gettid() -> pid_t {
-        //TODO
+        // TODO: TIDs do not exist on Redox, at least in a form where they can be sent to other
+        // processes and used in various syscalls from there. Should the fd be returned here?
         Self::getpid()
     }
 
-    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
+    unsafe fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> Result<()> {
         let mut redox_tp = redox_timespec::default();
-        let err = e(syscall::clock_gettime(
-            syscall::CLOCK_REALTIME,
-            &mut redox_tp,
-        )) as c_int;
-        if err < 0 {
-            return err;
-        }
+        syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut redox_tp)?;
         unsafe {
             (*tp).tv_sec = redox_tp.tv_sec as time_t;
             (*tp).tv_usec = (redox_tp.tv_nsec / 1000) as suseconds_t;
@@ -550,11 +537,11 @@ impl Pal for Sys {
                 (*tzp).tz_dsttime = 0;
             }
         }
-        0
+        Ok(())
     }
 
     fn getuid() -> uid_t {
-        e(syscall::getuid()) as pid_t
+        syscall::getuid().unwrap() as pid_t
     }
 
     fn lchown(path: CStr, owner: uid_t, group: gid_t) -> Result<()> {
@@ -612,14 +599,14 @@ impl Pal for Sys {
         Ok(())
     }
 
-    unsafe fn mlock(addr: *const c_void, len: usize) -> c_int {
+    unsafe fn mlock(addr: *const c_void, len: usize) -> Result<()> {
         // Redox never swaps
-        0
+        Ok(())
     }
 
-    fn mlockall(flags: c_int) -> c_int {
+    unsafe fn mlockall(flags: c_int) -> Result<()> {
         // Redox never swaps
-        0
+        Ok(())
     }
 
     unsafe fn mmap(
@@ -629,7 +616,7 @@ impl Pal for Sys {
         flags: c_int,
         fildes: c_int,
         off: off_t,
-    ) -> *mut c_void {
+    ) -> Result<*mut c_void> {
         let map = Map {
             offset: off as usize,
             size: round_up_to_page_size(len),
@@ -639,11 +626,11 @@ impl Pal for Sys {
             address: addr as usize,
         };
 
-        if flags & MAP_ANONYMOUS == MAP_ANONYMOUS {
-            e(syscall::fmap(!0, &map)) as *mut c_void
+        Ok(if flags & MAP_ANONYMOUS == MAP_ANONYMOUS {
+            syscall::fmap(!0, &map)?
         } else {
-            e(syscall::fmap(fildes as usize, &map)) as *mut c_void
-        }
+            syscall::fmap(fildes as usize, &map)?
+        } as *mut c_void)
     }
 
     unsafe fn mremap(
@@ -652,60 +639,59 @@ impl Pal for Sys {
         new_len: usize,
         flags: c_int,
         args: *mut c_void,
-    ) -> *mut c_void {
-        MAP_FAILED
+    ) -> Result<*mut c_void> {
+        Err(Errno(ENOSYS))
     }
 
-    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
-        e(syscall::mprotect(
+    unsafe fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> Result<()> {
+        syscall::mprotect(
             addr as usize,
             round_up_to_page_size(len),
             syscall::MapFlags::from_bits((prot as usize) << 16)
                 .expect("mprotect: invalid bit pattern"),
-        )) as c_int
+        )?;
+        Ok(())
     }
 
-    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
+    unsafe fn msync(addr: *mut c_void, len: usize, flags: c_int) -> Result<()> {
         eprintln!(
             "relibc msync({:p}, 0x{:x}, 0x{:x}): not implemented",
             addr, len, flags
         );
-        e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
+        Err(Errno(ENOSYS))
         /* TODO
-        e(syscall::msync(
+        syscall::msync(
             addr as usize,
             round_up_to_page_size(len),
             flags
-        )) as c_int
+        )?;
         */
     }
 
-    unsafe fn munlock(addr: *const c_void, len: usize) -> c_int {
+    unsafe fn munlock(addr: *const c_void, len: usize) -> Result<()> {
         // Redox never swaps
-        0
+        Ok(())
     }
 
-    fn munlockall() -> c_int {
+    unsafe fn munlockall() -> Result<()> {
         // Redox never swaps
-        0
+        Ok(())
     }
 
-    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
-        if e(syscall::funmap(addr as usize, round_up_to_page_size(len))) == !0 {
-            return !0;
-        }
-        0
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> Result<()> {
+        syscall::funmap(addr as usize, round_up_to_page_size(len))?;
+        Ok(())
     }
 
-    unsafe fn madvise(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
+    unsafe fn madvise(addr: *mut c_void, len: usize, flags: c_int) -> Result<()> {
         eprintln!(
             "relibc madvise({:p}, 0x{:x}, 0x{:x}): not implemented",
             addr, len, flags
         );
-        e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
+        Err(Errno(ENOSYS))
     }
 
-    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
+    unsafe fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> Result<()> {
         let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
         let mut redox_rmtp: redox_timespec;
         if rmtp.is_null() {
@@ -713,18 +699,14 @@ impl Pal for Sys {
         } else {
             redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
         }
-        match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int {
-            -1 => -1,
-            _ => {
-                unsafe {
-                    if !rmtp.is_null() {
-                        (*rmtp).tv_sec = redox_rmtp.tv_sec as time_t;
-                        (*rmtp).tv_nsec = redox_rmtp.tv_nsec as c_long;
-                    }
-                }
-                0
+        syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)?;
+        unsafe {
+            if !rmtp.is_null() {
+                (*rmtp).tv_sec = redox_rmtp.tv_sec as time_t;
+                (*rmtp).tv_nsec = redox_rmtp.tv_nsec as c_long;
             }
         }
+        Ok(())
     }
 
     fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
@@ -989,7 +971,7 @@ impl Pal for Sys {
         Ok(())
     }
 
-    fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
+    unsafe fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> Result<pid_t> {
         if pid == !0 {
             pid = 0;
         }
@@ -1009,16 +991,16 @@ impl Pal for Sys {
                 let mut _event = PtraceEvent::default();
                 let _ = (&mut &session.tracer).read(&mut _event);
 
-                res = Some(e(inner(
+                res = Some(inner(
                     &mut status,
                     options | sys_wait::WNOHANG | sys_wait::WUNTRACED,
-                )));
-                if res == Some(0) {
+                ));
+                if res == Some(Ok(0)) {
                     // WNOHANG, just pretend ptrace SIGSTOP:ped this
                     status = (syscall::SIGSTOP << 8) | 0x7f;
                     assert!(syscall::wifstopped(status));
                     assert_eq!(syscall::wstopsig(status), syscall::SIGSTOP);
-                    res = Some(pid as usize);
+                    res = Some(Ok(pid as usize));
                 }
             }
         }
@@ -1028,7 +1010,7 @@ impl Pal for Sys {
         // it if (and only if) a ptrace traceme was activated during
         // the wait.
         let res = res.unwrap_or_else(|| loop {
-            let res = e(inner(&mut status, options | sys_wait::WUNTRACED));
+            let res = inner(&mut status, options | sys_wait::WUNTRACED);
 
             // TODO: Also handle special PIDs here
             if !syscall::wifstopped(status)
@@ -1045,7 +1027,7 @@ impl Pal for Sys {
                 *stat_loc = status as c_int;
             }
         }
-        res as pid_t
+        Ok(res? as pid_t)
     }
 
     fn write(fd: c_int, buf: &[u8]) -> Result<ssize_t> {