xref: /relibc/src/ld_so/access.rs (revision 7016e5c833af9fe4182462e6a86e498cd5e8c738)
1 // Wrapper over the access syscall that doesn't touch errno variable,
2 // Do not use outside of ld_so
3 
4 #[cfg(target_os = "redox")]
5 use crate::header::unistd::{F_OK, R_OK, W_OK, X_OK};
6 use crate::{
7     c_str::{CStr, CString},
8     platform::types::*,
9 };
10 
accessible(path: &str, mode: c_int) -> c_int11 pub fn accessible(path: &str, mode: c_int) -> c_int {
12     let path_c = CString::new(path.as_bytes()).unwrap(); /*.map_err(|err| {
13                                                              Error::Malformed(format!("invalid path '{}': {}", path, err))
14                                                          })?;*/
15     unsafe { access(path_c.as_ptr(), mode) }
16 }
17 
18 #[cfg(target_os = "linux")]
access(path: *const c_char, mode: c_int) -> c_int19 unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
20     let path = CStr::from_ptr(path);
21     syscall!(ACCESS, (path).as_ptr(), mode) as c_int
22 }
23 
24 #[cfg(target_os = "dragonos")]
access(path: *const c_char, mode: c_int) -> c_int25 unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
26     // let path = CStr::from_ptr(path);
27     // syscall!(ACCESS, (path).as_ptr(), mode) as c_int
28     return -1;
29 }
30 
31 // Wrapper over the systemcall, Do not use outside of ld_so
32 #[cfg(target_os = "redox")]
access(path: *const c_char, mode: c_int) -> c_int33 unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
34     use core::str;
35     let path = match str::from_utf8(CStr::from_ptr(path).to_bytes()) {
36         Ok(ok) => ok,
37         Err(_) => return -1,
38     };
39     let fd = match crate::platform::sys::path::open(path, syscall::O_CLOEXEC) {
40         Ok(fd) => fd,
41         _ => return -1,
42     };
43     if mode == F_OK {
44         return 0;
45     }
46     let mut stat = syscall::Stat::default();
47     if syscall::fstat(fd, &mut stat).is_err() {
48         return -1;
49     }
50     let _ = syscall::close(fd);
51     let uid = match syscall::getuid() {
52         Ok(uid) => uid,
53         Err(_) => return -1,
54     };
55     let gid = match syscall::getgid() {
56         Ok(gid) => gid,
57         Err(_) => return -1,
58     };
59 
60     let perms = if stat.st_uid as usize == uid {
61         stat.st_mode >> (3 * 2 & 0o7)
62     } else if stat.st_gid as usize == gid {
63         stat.st_mode >> (3 * 1 & 0o7)
64     } else {
65         stat.st_mode & 0o7
66     };
67     if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
68         || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
69         || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
70     {
71         return -1;
72     }
73     0
74 }
75