diff --git a/include/math.h b/include/math.h index 5ce9f25af7bb3ffa55b39cfee699360b541a50a2..071e3daa7cf21b98119f06d262deca1655807b8d 100644 --- a/include/math.h +++ b/include/math.h @@ -1,2 +1,3 @@ #define OPENLIBM_USE_HOST_FENV_H 1 #include <openlibm.h> +#undef I diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs index f4b0116cb91792bd2a656d4472263f8949379b59..14765b6c5a5bfa5d61860f74d7d28ec5303a3461 100644 --- a/src/platform/src/linux/mod.rs +++ b/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 } diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 80a29e95bb4545774c8c971994be26df519cf18a..75cbc771fa6de89e534e48a8d644b639d07066d0 100644 --- a/src/platform/src/redox/mod.rs +++ b/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, }; } } diff --git a/src/platform/src/types.rs b/src/platform/src/types.rs index dbd5364b57c719011ceee36f5eb22544f9f7d4cc..5ac9ab3a3071b2f65e389ace02988575e69df2c3 100644 --- a/src/platform/src/types.rs +++ b/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; diff --git a/src/sys_file/src/lib.rs b/src/sys_file/src/lib.rs index 2ffb3e04bcdf2cd93fbf0428e30d9e6b555200f5..a12bcc2a0bee2b1a3b71c543389df10d0a3e1c7b 100644 --- a/src/sys_file/src/lib.rs +++ b/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; diff --git a/src/sys_socket/src/constants.rs b/src/sys_socket/src/constants.rs index 6abb1b8e64daaeaf6b79a35fb8c405d2d23e23c7..38a791c156c6ffc0de120def4832ac0cd28636db 100644 --- a/src/sys_socket/src/constants.rs +++ b/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; diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index 76dbb27b1f4ed737f3fb4e6ffb5ee77bb5fbf24f..95c3eac42228e5aca3fcee80a0bf1cb6187fe416 100644 --- a/src/unistd/src/lib.rs +++ b/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] diff --git a/tests/Makefile b/tests/Makefile index b2bee9f19439987db2a2557b6a450d1819ac649e..cad834e36194176af396e60b0f53f15b6fd68521 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -46,6 +46,7 @@ EXPECT_BINS=\ time/mktime \ time/strftime \ time/time \ + unistd/access \ unistd/brk \ unistd/dup \ unistd/exec \ diff --git a/tests/expected/unistd/access.stderr b/tests/expected/unistd/access.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/unistd/access.stdout b/tests/expected/unistd/access.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/unistd/access.c b/tests/unistd/access.c new file mode 100644 index 0000000000000000000000000000000000000000..9491aa5f5de4648cdea9248af6ee04b34298b3f5 --- /dev/null +++ b/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; + } +}