1use crate::CoreError;
11use crate::error::syscall_ret;
12use std::ffi::CString;
13use std::os::unix::ffi::OsStrExt;
14use std::path::Path;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct PathStat {
19 pub uid: u32,
21 pub inode: u64,
23 pub ctime_sec: i64,
25 pub ctime_nsec: i64,
27 pub mtime_sec: i64,
29 pub mtime_nsec: i64,
31}
32
33pub fn path_uid(path: impl AsRef<Path>) -> Result<u32, CoreError> {
39 Ok(path_stat(path)?.uid)
40}
41
42pub fn path_stat(path: impl AsRef<Path>) -> Result<PathStat, CoreError> {
48 stat_path(path.as_ref(), "stat", true)
49}
50
51pub fn path_lstat(path: impl AsRef<Path>) -> Result<PathStat, CoreError> {
53 stat_path(path.as_ref(), "lstat", false)
54}
55
56pub fn proc_uid(pid: i32) -> Result<u32, CoreError> {
62 proc_uid_at("/proc", pid)
63}
64
65pub fn proc_uid_at(proc_root: impl AsRef<Path>, pid: i32) -> Result<u32, CoreError> {
70 Ok(proc_stat_at(proc_root, pid)?.uid)
71}
72
73pub fn proc_stat(pid: i32) -> Result<PathStat, CoreError> {
75 proc_stat_at("/proc", pid)
76}
77
78pub fn proc_stat_at(proc_root: impl AsRef<Path>, pid: i32) -> Result<PathStat, CoreError> {
80 let path = proc_root.as_ref().join(pid.to_string());
81 stat_path(&path, "stat", true)
82}
83
84#[inline(always)]
86pub fn effective_uid() -> u32 {
87 unsafe { libc::geteuid() }
88}
89
90pub fn chown_path(path: impl AsRef<Path>, uid: u32, gid: Option<u32>) -> Result<(), CoreError> {
92 let path = CString::new(path.as_ref().as_os_str().as_bytes())
93 .map_err(|_| CoreError::sys(libc::EINVAL, "chown"))?;
94 let gid = gid.unwrap_or(u32::MAX);
95 let ret = unsafe { libc::chown(path.as_ptr(), uid, gid) };
96 syscall_ret(ret, "chown")
97}
98
99fn stat_path(path: &Path, op: &'static str, follow_symlink: bool) -> Result<PathStat, CoreError> {
100 let path =
101 CString::new(path.as_os_str().as_bytes()).map_err(|_| CoreError::sys(libc::EINVAL, op))?;
102 let mut stat_buf: libc::stat = unsafe { std::mem::zeroed() };
103 let ret = if follow_symlink {
104 unsafe { libc::stat(path.as_ptr(), &mut stat_buf) }
105 } else {
106 unsafe { libc::lstat(path.as_ptr(), &mut stat_buf) }
107 };
108 syscall_ret(ret, op)?;
109 Ok(PathStat {
110 uid: stat_buf.st_uid,
111 inode: stat_buf.st_ino as _,
112 ctime_sec: stat_buf.st_ctime as _,
113 ctime_nsec: stat_buf.st_ctime_nsec as _,
114 mtime_sec: stat_buf.st_mtime as _,
115 mtime_nsec: stat_buf.st_mtime_nsec as _,
116 })
117}