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