|
@@ -8,6 +8,7 @@ use bindings::{
|
|
|
use crate::{
|
|
|
io::{Buffer, BufferFill},
|
|
|
kernel::{
|
|
|
+ constants::AT_EMPTY_PATH,
|
|
|
task::Thread,
|
|
|
user::{
|
|
|
dataflow::{CheckedUserPointer, UserBuffer, UserString},
|
|
@@ -99,23 +100,36 @@ fn do_statx(dirfd: u32, path: *const u8, flags: u32, mask: u32, buffer: *mut u8)
|
|
|
unimplemented!("AT_STATX_SYNC_TYPE={:x}", flags & AT_STATX_SYNC_TYPE);
|
|
|
}
|
|
|
|
|
|
- if dirfd != AT_FDCWD as u32 {
|
|
|
- unimplemented!("dirfd={}", dirfd);
|
|
|
- }
|
|
|
-
|
|
|
- let path = UserString::new(path)?;
|
|
|
- let path = Path::new(path.as_cstr().to_bytes())?;
|
|
|
+ let mut stat: statx = unsafe { MaybeUninit::zeroed().assume_init() };
|
|
|
let mut buffer = UserBuffer::new(buffer, core::mem::size_of::<statx>())?;
|
|
|
|
|
|
- let file = Dentry::open(
|
|
|
- &FsContext::get_current(),
|
|
|
- path,
|
|
|
- (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
|
|
|
- )?;
|
|
|
+ if (flags & AT_EMPTY_PATH) != 0 {
|
|
|
+ let file = FileArray::get_current().get(dirfd).ok_or(EBADF)?;
|
|
|
+ file.statx(&mut stat, mask)?;
|
|
|
+ } else {
|
|
|
+ let path = UserString::new(path)?;
|
|
|
+ let path = Path::new(path.as_cstr().to_bytes())?;
|
|
|
+
|
|
|
+ let file;
|
|
|
+ if dirfd != AT_FDCWD as u32 && !path.is_absolute() {
|
|
|
+ let at = FileArray::get_current().get(dirfd).ok_or(EBADF)?;
|
|
|
+ file = Dentry::open_at(
|
|
|
+ &FsContext::get_current(),
|
|
|
+ at.as_path().ok_or(EBADF)?,
|
|
|
+ path,
|
|
|
+ (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
|
|
|
+ )?;
|
|
|
+ } else {
|
|
|
+ file = Dentry::open(
|
|
|
+ &FsContext::get_current(),
|
|
|
+ path,
|
|
|
+ (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
|
|
|
+ )?;
|
|
|
+ }
|
|
|
|
|
|
- let mut stat: statx = unsafe { MaybeUninit::zeroed().assume_init() };
|
|
|
+ file.statx(&mut stat, mask)?;
|
|
|
+ }
|
|
|
|
|
|
- file.statx(&mut stat, mask)?;
|
|
|
buffer.copy(&stat)?.ok_or(EFAULT)
|
|
|
}
|
|
|
|