Implement access
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
#define OPENLIBM_USE_HOST_FENV_H 1
|
||||
#include <openlibm.h>
|
||||
#undef I
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -46,6 +46,7 @@ EXPECT_BINS=\
|
||||
time/mktime \
|
||||
time/strftime \
|
||||
time/time \
|
||||
unistd/access \
|
||||
unistd/brk \
|
||||
unistd/dup \
|
||||
unistd/exec \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user