starry_api/imp/fs/
stat.rs1use core::ffi::{c_char, c_int};
2
3use axerrno::{AxError, LinuxError, LinuxResult};
4use axfs::fops::OpenOptions;
5use linux_raw_sys::general::{AT_EMPTY_PATH, stat, statx};
6
7use crate::{
8 file::{Directory, File, FileLike, Kstat, get_file_like},
9 path::handle_file_path,
10 ptr::{UserConstPtr, UserPtr, nullable},
11};
12
13fn stat_at_path(path: &str) -> LinuxResult<Kstat> {
14 let opts = OpenOptions::new().set_read(true);
15 match axfs::fops::File::open(path, &opts) {
16 Ok(file) => File::new(file, path.into()).stat(),
17 Err(AxError::IsADirectory) => {
18 let dir = axfs::fops::Directory::open_dir(path, &opts)?;
19 Directory::new(dir, path.into()).stat()
20 }
21 Err(e) => Err(e.into()),
22 }
23}
24
25pub fn sys_stat(path: UserConstPtr<c_char>, statbuf: UserPtr<stat>) -> LinuxResult<isize> {
29 let path = path.get_as_str()?;
30 debug!("sys_stat <= path: {}", path);
31
32 *statbuf.get_as_mut()? = stat_at_path(path)?.into();
33
34 Ok(0)
35}
36
37pub fn sys_fstat(fd: i32, statbuf: UserPtr<stat>) -> LinuxResult<isize> {
41 debug!("sys_fstat <= fd: {}", fd);
42 *statbuf.get_as_mut()? = get_file_like(fd)?.stat()?.into();
43 Ok(0)
44}
45
46pub fn sys_lstat(path: UserConstPtr<c_char>, statbuf: UserPtr<stat>) -> LinuxResult<isize> {
50 sys_stat(path, statbuf)
52}
53
54pub fn sys_fstatat(
55 dirfd: c_int,
56 path: UserConstPtr<c_char>,
57 statbuf: UserPtr<stat>,
58 flags: u32,
59) -> LinuxResult<isize> {
60 let path = nullable!(path.get_as_str())?;
61 debug!(
62 "sys_fstatat <= dirfd: {}, path: {:?}, flags: {}",
63 dirfd, path, flags
64 );
65
66 *statbuf.get_as_mut()? = if path.is_none_or(|s| s.is_empty()) {
67 if (flags & AT_EMPTY_PATH) == 0 {
68 return Err(LinuxError::ENOENT);
69 }
70 let f = get_file_like(dirfd)?;
71 f.stat()?.into()
72 } else {
73 let path = handle_file_path(dirfd, path.unwrap_or_default())?;
74 stat_at_path(path.as_str())?.into()
75 };
76
77 Ok(0)
78}
79
80pub fn sys_statx(
81 dirfd: c_int,
82 path: UserConstPtr<c_char>,
83 flags: u32,
84 _mask: u32,
85 statxbuf: UserPtr<statx>,
86) -> LinuxResult<isize> {
87 let path = nullable!(path.get_as_str())?;
115 debug!(
116 "sys_statx <= dirfd: {}, path: {:?}, flags: {}",
117 dirfd, path, flags
118 );
119
120 *statxbuf.get_as_mut()? = if path.is_none_or(|s| s.is_empty()) {
121 if (flags & AT_EMPTY_PATH) == 0 {
122 return Err(LinuxError::ENOENT);
123 }
124 let f = get_file_like(dirfd)?;
125 f.stat()?.into()
126 } else {
127 let path = handle_file_path(dirfd, path.unwrap_or_default())?;
128 stat_at_path(path.as_str())?.into()
129 };
130
131 Ok(0)
132}