access.rs 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. // Wrapper over the access syscall that doesn't touch errno variable,
  2. // Do not use outside of ld_so
  3. use crate::{c_str::CStr, platform::types::*};
  4. #[cfg(target_os = "redox")]
  5. use crate::header::unistd::{F_OK, R_OK, W_OK, X_OK};
  6. #[cfg(target_os = "linux")]
  7. pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
  8. let path = CStr::from_ptr(path);
  9. syscall!(ACCESS, (path).as_ptr(), mode) as c_int
  10. }
  11. // Wrapper over the systemcall, Do not use outside of ld_so
  12. #[cfg(target_os = "redox")]
  13. pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
  14. let path = CStr::from_ptr(path).to_bytes();
  15. let fd = match syscall::open(path, syscall::O_CLOEXEC) {
  16. Ok(fd) => fd,
  17. _ => return -1,
  18. };
  19. if mode == F_OK {
  20. return 0;
  21. }
  22. let mut stat = syscall::Stat::default();
  23. if syscall::fstat(fd, &mut stat).is_err() {
  24. return -1;
  25. }
  26. let uid = match syscall::getuid() {
  27. Ok(uid) => uid,
  28. Err(_) => return -1,
  29. };
  30. let gid = match syscall::getgid() {
  31. Ok(gid) => gid,
  32. Err(_) => return -1,
  33. };
  34. let perms = if stat.st_uid as usize == uid {
  35. stat.st_mode >> (3 * 2 & 0o7)
  36. } else if stat.st_gid as usize == gid {
  37. stat.st_mode >> (3 * 1 & 0o7)
  38. } else {
  39. stat.st_mode & 0o7
  40. };
  41. if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
  42. || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
  43. || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
  44. {
  45. return -1;
  46. }
  47. 0
  48. }