From 29a6d24309bf9a6b2401b81dfd41ed16659d4408 Mon Sep 17 00:00:00 2001
From: Paul Sajna <paulsajna@gmail.com>
Date: Thu, 22 Mar 2018 17:40:52 -0700
Subject: [PATCH] chmod and fchmod

---
 src/platform/src/linux/mod.rs | 16 ++++++++++++----
 src/platform/src/redox/mod.rs | 28 ++++++++++++++++++++++------
 src/stat/src/lib.rs           |  4 ++--
 3 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
index f26076e6c..96db8eb18 100644
--- a/src/platform/src/linux/mod.rs
+++ b/src/platform/src/linux/mod.rs
@@ -32,6 +32,10 @@ pub fn chdir(path: *const c_char) -> c_int {
     e(unsafe { syscall!(CHDIR, path) }) as c_int
 }
 
+pub fn chmod(path: *const c_char, mode: mode_t) -> c_int {
+    e(unsafe { syscall!(FCHMODAT, AT_FDCWD, path, mode, 0) }) as c_int
+}
+
 pub fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
     e(unsafe { syscall!(FCHOWNAT, AT_FDCWD, path, owner as u32, group as u32) }) as c_int
 }
@@ -55,14 +59,18 @@ pub fn exit(status: c_int) -> ! {
     loop {}
 }
 
-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 fchdir(fildes: c_int) -> c_int {
     e(unsafe { syscall!(FCHDIR, fildes) }) as c_int
 }
 
+pub fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
+    e(unsafe { syscall!(FCHMOD, fildes, mode) }) as c_int
+}
+
+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 fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
     e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
 }
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
index f125166fa..87910d06c 100644
--- a/src/platform/src/redox/mod.rs
+++ b/src/platform/src/redox/mod.rs
@@ -30,10 +30,22 @@ pub fn chdir(path: *const c_char) -> c_int {
     e(syscall::chdir(path)) as 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 {
+        Err(err) => e(Err(err)) as c_int,
+        Ok(fd) => e(syscall::fchmod(fd as usize, mode)) as c_int,
+    }
+}
+
 pub fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
     let path = unsafe { c_str(path) };
-    let fd = syscall::open(path, 0x0001).unwrap();
-    e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
+    let result = syscall::open(path, 0x0001);
+    match result {
+        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,
+    }
 }
 
 pub fn close(fd: c_int) -> c_int {
@@ -53,10 +65,6 @@ pub fn exit(status: c_int) -> ! {
     loop {}
 }
 
-pub fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
-    e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
-}
-
 pub fn fchdir(fd: c_int) -> c_int {
     let path: &mut [u8] = &mut [0; 4096];
     if e(syscall::fpath(fd as usize, path)) == !0 {
@@ -66,6 +74,14 @@ pub fn fchdir(fd: c_int) -> c_int {
     }
 }
 
+pub fn fchmod(fd: c_int, mode: mode_t) -> c_int {
+    e(syscall::fchmod(fd as usize, mode)) as c_int
+}
+
+pub fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
+    e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
+}
+
 pub fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
     e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
 }
diff --git a/src/stat/src/lib.rs b/src/stat/src/lib.rs
index b8e2db574..7e40fbbaa 100644
--- a/src/stat/src/lib.rs
+++ b/src/stat/src/lib.rs
@@ -24,12 +24,12 @@ pub struct stat {
 
 #[no_mangle]
 pub extern "C" fn chmod(path: *const c_char, mode: mode_t) -> c_int {
-    unimplemented!();
+    platform::chmod(path, mode)
 }
 
 #[no_mangle]
 pub extern "C" fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
-    unimplemented!();
+    platform::fchmod(fildes, mode)
 }
 
 #[no_mangle]
-- 
GitLab