diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs
index 5f57298db7e1faacb1908029f3449b491e7d674e..63732fbf61129c399658e8488e78c2ce0711e735 100644
--- a/src/platform/src/lib.rs
+++ b/src/platform/src/lib.rs
@@ -54,6 +54,10 @@ pub unsafe fn c_str_n(s: *const c_char, n: usize) -> &'static [u8] {
     slice::from_raw_parts(s as *const u8, size as usize)
 }
 
+pub unsafe fn cstr_from_bytes_with_nul_unchecked(bytes: &[u8]) -> *const c_char {
+    &*(bytes as *const [u8] as *const c_char)
+}
+
 pub struct FileWriter(pub c_int);
 
 impl FileWriter {
diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
index 96db8eb18b4423197db41805ba1dde3221e5ca68..01d4fa232b2d6f0bb11693cc646bbd2d25de103b 100644
--- a/src/platform/src/linux/mod.rs
+++ b/src/platform/src/linux/mod.rs
@@ -4,7 +4,9 @@ use errno;
 use types::*;
 
 const AT_FDCWD: c_int = -100;
+const AT_EMPTY_PATH: c_int = 0x1000;
 const AT_REMOVEDIR: c_int = 0x200;
+const AT_SYMLINK_NOFOLLOW: c_int = 0x100;
 
 pub fn e(sys: usize) -> usize {
     if (sys as isize) < 0 && (sys as isize) >= -256 {
@@ -71,6 +73,11 @@ pub fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
     e(unsafe { syscall!(FCHOWN, fildes, owner, group) }) as c_int
 }
 
+pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+    let empty_cstr: *const c_char = unsafe { ::cstr_from_bytes_with_nul_unchecked(b"\0") };
+    e(unsafe { syscall!(NEWFSTATAT, fildes, empty_cstr, buf, AT_EMPTY_PATH) }) as c_int
+}
+
 pub fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
     e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
 }
@@ -127,6 +134,10 @@ pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
     e(unsafe { syscall!(LINKAT, AT_FDCWD, path1, AT_FDCWD, path2, 0) }) as c_int
 }
 
+pub fn lstat(file: *const c_char, buf: *mut stat) -> c_int {
+    e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW) }) as c_int
+}
+
 pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
     e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path, mode) }) as c_int
 }
@@ -163,6 +174,10 @@ pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
     e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int
 }
 
+pub fn stat(file: *const c_char, buf: *mut stat) -> c_int {
+    e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, 0) }) as c_int
+}
+
 pub fn unlink(path: *const c_char) -> c_int {
     e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, 0) }) as c_int
 }
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
index 87910d06cce9a808f77f58b1f611ddf6629463f5..ac09922c7e9ce0a676b49d855dfae4f18799d613 100644
--- a/src/platform/src/redox/mod.rs
+++ b/src/platform/src/redox/mod.rs
@@ -4,6 +4,7 @@ use core::mem;
 use syscall;
 use syscall::flag::*;
 use syscall::data::TimeSpec as redox_timespec;
+use syscall::data::Stat as redox_stat;
 
 use c_str;
 use errno;
@@ -32,8 +33,7 @@ pub fn chdir(path: *const c_char) -> c_int {
 
 pub fn chmod(path: *const c_char, mode: mode_t) -> c_int {
     let path = unsafe { c_str(path) };
-    let result = syscall::open(path, 0x0001);
-    match result {
+    match syscall::open(path, O_WRONLY) {
         Err(err) => e(Err(err)) as c_int,
         Ok(fd) => e(syscall::fchmod(fd as usize, mode)) as c_int,
     }
@@ -41,8 +41,7 @@ pub fn chmod(path: *const c_char, mode: mode_t) -> c_int {
 
 pub fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
     let path = unsafe { c_str(path) };
-    let result = syscall::open(path, 0x0001);
-    match result {
+    match syscall::open(path, O_WRONLY) {
         Err(err) => e(Err(err)) as c_int,
         Ok(fd) => e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int,
     }
@@ -90,6 +89,33 @@ pub fn fork() -> pid_t {
     e(unsafe { syscall::clone(0) }) as pid_t
 }
 
+pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+    let mut redox_buf: redox_stat = redox_stat::default(); 
+    match e(syscall::fstat(fildes as usize, &mut redox_buf)) {
+       0 => {
+                unsafe {
+                    if !buf.is_null() {
+                        (*buf).st_dev = redox_buf.st_dev as dev_t;
+                        (*buf).st_ino = redox_buf.st_ino as ino_t;
+                        (*buf).st_nlink = redox_buf.st_nlink as nlink_t;
+                        (*buf).st_mode = redox_buf.st_mode;
+                        (*buf).st_uid = redox_buf.st_uid as uid_t;
+                        (*buf).st_gid = redox_buf.st_gid as gid_t;
+                        // TODO st_rdev
+                        (*buf).st_rdev = 0;
+                        (*buf).st_size = redox_buf.st_size as off_t;
+                        (*buf).st_blksize = redox_buf.st_blksize as blksize_t;
+                        (*buf).st_atim = redox_buf.st_atime as time_t;
+                        (*buf).st_mtim = redox_buf.st_mtime as time_t;
+                        (*buf).st_ctim = redox_buf.st_ctime as time_t;
+                    }
+                }
+                0
+            },
+        _ => -1,
+    }
+}
+
 pub fn fsync(fd: c_int) -> c_int {
     e(syscall::fsync(fd as usize)) as c_int
 }
@@ -141,6 +167,14 @@ pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
     e(unsafe { syscall::link(path1.as_ptr(), path2.as_ptr()) }) as c_int
 }
 
+pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
+    let path = unsafe { c_str(path) };
+    match syscall::open(path, O_RDONLY | O_NOFOLLOW) {
+        Err(err) => e(Err(err)) as c_int,
+        Ok(fd) => fstat(fd as i32, buf), 
+    }
+}
+
 pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
     let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | mode as usize & 0o777;
     let path = unsafe { c_str(path) };
@@ -209,6 +243,14 @@ pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
     e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
 }
 
+pub fn stat(path: *const c_char, buf: *mut stat) -> c_int {
+    let path = unsafe { c_str(path) };
+    match syscall::open(path, O_RDONLY) {
+        Err(err) => e(Err(err)) as c_int,
+        Ok(fd) => fstat(fd as i32, buf), 
+    }
+}
+
 pub fn unlink(path: *const c_char) -> c_int {
     let path = unsafe { c_str(path) };
     e(syscall::unlink(path)) as c_int
diff --git a/src/platform/src/types.rs b/src/platform/src/types.rs
index d6e19dbd580c8ad2b5bbbe1934cacabacc1bfc22..f721d674e0b7449ff3ee141ea91f31f29de9aece 100644
--- a/src/platform/src/types.rs
+++ b/src/platform/src/types.rs
@@ -82,3 +82,19 @@ impl<'a> From<&'a timespec> for redox_timespec {
         }
     }
 }
+
+#[repr(C)]
+pub struct stat {
+    pub st_dev: dev_t,
+    pub st_ino: ino_t,
+    pub st_nlink: nlink_t,
+    pub st_mode: mode_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_size: off_t,
+    pub st_blksize: blksize_t,
+    pub st_atim: time_t,
+    pub st_mtim: time_t,
+    pub st_ctim: time_t,
+}
diff --git a/src/stat/src/lib.rs b/src/stat/src/lib.rs
index 7e40fbbaa6102c1df70b4b6ac92ad1f364cdadd8..6e4232cd5477413fc841e517e0da942485d26fed 100644
--- a/src/stat/src/lib.rs
+++ b/src/stat/src/lib.rs
@@ -34,12 +34,12 @@ 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 {
-    unimplemented!();
+    platform::fstat(fildes, buf)
 }
 
 #[no_mangle]
 pub extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
-    unimplemented!();
+    platform::lstat(path, buf)
 }
 
 #[no_mangle]
@@ -59,7 +59,7 @@ pub extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int
 
 #[no_mangle]
 pub extern "C" fn stat(file: *const c_char, buf: *mut stat) -> c_int {
-    unimplemented!();
+    platform::stat(file, buf)
 }
 
 #[no_mangle]