Browse Source

Implement access

jD91mZM2 6 years ago
parent
commit
daf65c7a46

+ 1 - 0
include/math.h

@@ -1,2 +1,3 @@
 #define OPENLIBM_USE_HOST_FENV_H 1
 #include <openlibm.h>
+#undef I

+ 4 - 0
src/platform/src/linux/mod.rs

@@ -25,6 +25,10 @@ pub unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut so
     e(syscall!(ACCEPT, socket, address, address_len)) as c_int
 }
 
+pub fn access(path: *const c_char, mode: c_int) -> c_int {
+    e(unsafe { syscall!(ACCESS, path, mode) }) as c_int
+}
+
 pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
     e(syscall!(BIND, socket, address, address_len)) as c_int
 }

+ 50 - 3
src/platform/src/redox/mod.rs

@@ -12,6 +12,8 @@ use syscall::{self, Result};
 use types::*;
 use *;
 
+const EINVAL: c_int = 22;
+
 #[thread_local]
 static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
 
@@ -82,6 +84,51 @@ pub unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut so
     stream
 }
 
+pub fn access(path: *const c_char, mode: c_int) -> c_int {
+    let fd = match RawFile::open(path, 0, 0) {
+        Ok(fd) => fd,
+        Err(_) => return -1
+    };
+    if mode == F_OK {
+        return 0;
+    }
+
+    let mut stat = syscall::Stat::default();
+
+    if e(syscall::fstat(*fd as usize, &mut stat)) == !0 {
+        return -1;
+    }
+
+    let uid = e(syscall::getuid());
+    if uid == !0 {
+        return -1;
+    }
+    let gid = e(syscall::getgid());
+    if gid == !0 {
+        return -1;
+    }
+
+    let perms = if stat.st_uid as usize == uid {
+        // octal has max 7 characters, binary has max two. And we're interested
+        // in the 3rd digit
+        stat.st_mode >> ((7 / 2) * 2 & 0o7)
+    } else if stat.st_gid as usize == gid {
+        stat.st_mode >> ((7 / 2) & 0o7)
+    } else {
+        stat.st_mode & 0o7
+    };
+    if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
+            || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
+            || (mode & X_OK == X_OK && perms & 0o1 != 0o1) {
+        unsafe {
+            errno = EINVAL;
+        }
+        return -1;
+    }
+
+    0
+}
+
 pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
     bind_or_connect!(bind socket, address, address_len)
 }
@@ -253,15 +300,15 @@ pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
                     (*buf).st_blksize = redox_buf.st_blksize as blksize_t;
                     (*buf).st_atim = timespec {
                         tv_sec: redox_buf.st_atime as time_t,
-                        tv_nsec: 0,
+                        tv_nsec: redox_buf.st_atime_nsec as c_long,
                     };
                     (*buf).st_mtim = timespec {
                         tv_sec: redox_buf.st_mtime as time_t,
-                        tv_nsec: 0,
+                        tv_nsec: redox_buf.st_mtime_nsec as c_long,
                     };
                     (*buf).st_ctim = timespec {
                         tv_sec: redox_buf.st_ctime as time_t,
-                        tv_nsec: 0,
+                        tv_nsec: redox_buf.st_ctime_nsec as c_long,
                     };
                 }
             }

+ 5 - 0
src/platform/src/types.rs

@@ -236,3 +236,8 @@ pub const FD_SETSIZE: usize = 1024;
 pub struct fd_set {
     pub fds_bits: [c_ulong; FD_SETSIZE / (8 * mem::size_of::<c_ulong>())],
 }
+
+pub const F_OK: c_int = 0;
+pub const R_OK: c_int = 4;
+pub const W_OK: c_int = 2;
+pub const X_OK: c_int = 1;

+ 3 - 3
src/sys_file/src/lib.rs

@@ -7,9 +7,9 @@ extern crate platform;
 use platform::types::*;
 
 pub const LOCK_SH: usize = 1;
-pub const LOCK_EX: usize = 1 << 1;
-pub const LOCK_NB: usize = 1 << 2;
-pub const LOCK_UN: usize = 1 << 3;
+pub const LOCK_EX: usize = 2;
+pub const LOCK_NB: usize = 4;
+pub const LOCK_UN: usize = 8;
 
 pub const L_SET: usize = 0;
 pub const L_INCR: usize = 1;

+ 6 - 6
src/sys_socket/src/constants.rs

@@ -43,13 +43,13 @@ pub const SO_DOMAIN: c_int = 39;
 
 pub const SOMAXCONN: c_int = 128;
 
-pub const MSG_CTRUNC: c_int = 1 << 3;
-pub const MSG_DONTROUTE: c_int = 1 << 2;
-pub const MSG_EOR: c_int = 1 << 7;
+pub const MSG_CTRUNC: c_int = 8;
+pub const MSG_DONTROUTE: c_int = 4;
+pub const MSG_EOR: c_int = 128;
 pub const MSG_OOB: c_int = 1;
-pub const MSG_PEEK: c_int = 1 << 1;
-pub const MSG_TRUNC: c_int = 1 << 5;
-pub const MSG_WAITALL: c_int = 1 << 8;
+pub const MSG_PEEK: c_int = 2;
+pub const MSG_TRUNC: c_int = 32;
+pub const MSG_WAITALL: c_int = 256;
 
 pub const AF_INET6: c_int = 10;
 pub const AF_UNIX: c_int = 1;

+ 6 - 6
src/unistd/src/lib.rs

@@ -20,10 +20,10 @@ mod brk;
 mod getopt;
 mod pathconf;
 
-pub const R_OK: c_int = 1;
+pub const F_OK: c_int = 0;
+pub const R_OK: c_int = 4;
 pub const W_OK: c_int = 2;
-pub const X_OK: c_int = 4;
-pub const F_OK: c_int = 8;
+pub const X_OK: c_int = 1;
 
 pub const SEEK_SET: c_int = 0;
 pub const SEEK_CUR: c_int = 1;
@@ -43,9 +43,9 @@ pub extern "C" fn _exit(status: c_int) {
     platform::exit(status)
 }
 
-// #[no_mangle]
-pub extern "C" fn access(path: *const c_char, amode: c_int) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
+    platform::access(path, mode)
 }
 
 #[no_mangle]

+ 1 - 0
tests/Makefile

@@ -46,6 +46,7 @@ EXPECT_BINS=\
 	time/mktime \
 	time/strftime \
 	time/time \
+	unistd/access \
 	unistd/brk \
 	unistd/dup \
 	unistd/exec \

+ 0 - 0
tests/expected/unistd/access.stderr


+ 0 - 0
tests/expected/unistd/access.stdout


+ 14 - 0
tests/unistd/access.c

@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <unistd.h>
+
+int main() {
+    if (access("example_dir/1-never-gonna-give-you-up", R_OK | W_OK)) {
+        perror("access");
+        return 1;
+    }
+    if (!access("example_dir/1-never-gonna-give-you-up", X_OK)) {
+        puts("Accessing a file with X_OK worked even though it... probably... shouldn't?");
+        puts("Please run `chmod 644 example_dir/*` and try again.");
+        return 1;
+    }
+}