access.rs 1.8 KB

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