Browse Source

feat: temp. impl for sys_times, update sys_statx

greatbridf 3 months ago
parent
commit
e9ec2880b8

+ 1 - 1
Cargo.toml

@@ -7,7 +7,7 @@ edition = "2021"
 crate-type = ["staticlib"]
 
 [dependencies]
-arch = { path="./arch" }
+arch = { path = "./arch" }
 bitflags = "2.6.0"
 itertools = { version = "0.13.0", default-features = false }
 lazy_static = { version = "1.5.0", features = ["spin_no_std"] }

+ 2 - 0
src/kernel/constants.rs

@@ -33,6 +33,8 @@ pub const S_IFLNK: u32 = 0o120000;
 
 pub const RLIMIT_STACK: u32 = 0x3;
 
+pub const AT_EMPTY_PATH: u32 = 0x1000;
+
 bitflags! {
     #[derive(Debug, Clone, Copy)]
     pub struct UserMmapFlags: u32 {

+ 27 - 13
src/kernel/syscall/file_rw.rs

@@ -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)
 }
 

+ 21 - 0
src/kernel/syscall/sysinfo.rs

@@ -130,12 +130,33 @@ fn do_sysinfo(info: *mut Sysinfo) -> KResult<()> {
     })
 }
 
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct TMS {
+    tms_utime: u32,
+    tms_stime: u32,
+    tms_cutime: u32,
+    tms_cstime: u32,
+}
+
+fn do_times(tms: *mut TMS) -> KResult<()> {
+    let tms = UserPointerMut::new(tms)?;
+    tms.write(TMS {
+        tms_utime: 0,
+        tms_stime: 0,
+        tms_cutime: 0,
+        tms_cstime: 0,
+    })
+}
+
 define_syscall32!(sys_newuname, do_newuname, buffer: *mut NewUTSName);
 define_syscall32!(sys_gettimeofday, do_gettimeofday, timeval: *mut TimeVal, timezone: *mut ());
 define_syscall32!(sys_clock_gettime64, do_clock_gettime64, clock_id: u32, timespec: *mut TimeSpec);
 define_syscall32!(sys_sysinfo, do_sysinfo, info: *mut Sysinfo);
+define_syscall32!(sys_times, do_times, tms: *mut TMS);
 
 pub(super) fn register() {
+    register_syscall!(0x2b, times);
     register_syscall!(0x4e, gettimeofday);
     register_syscall!(0x74, sysinfo);
     register_syscall!(0x7a, newuname);

+ 9 - 0
src/kernel/vfs/dentry.rs

@@ -311,6 +311,15 @@ impl Dentry {
         Dentry::open_recursive(context, &cwd, path, follow_symlinks, 0)
     }
 
+    pub fn open_at(
+        context: &FsContext,
+        at: &Arc<Self>,
+        path: Path,
+        follow_symlinks: bool,
+    ) -> KResult<Arc<Self>> {
+        Dentry::open_recursive(context, at, path, follow_symlinks, 0)
+    }
+
     pub fn get_path(
         self: &Arc<Dentry>,
         context: &FsContext,

+ 18 - 2
src/kernel/vfs/file.rs

@@ -15,13 +15,15 @@ use crate::{
 };
 
 use alloc::{collections::vec_deque::VecDeque, sync::Arc};
-use bindings::{EBADF, EFAULT, EINTR, EINVAL, ENOTDIR, ENOTTY, EOVERFLOW, EPIPE, ESPIPE, S_IFMT};
+use bindings::{
+    statx, EBADF, EFAULT, EINTR, EINVAL, ENOTDIR, ENOTTY, EOVERFLOW, EPIPE, ESPIPE, S_IFMT,
+};
 use bitflags::bitflags;
 
 use super::{
     dentry::Dentry,
     inode::{Mode, WriteOffset},
-    s_isblk, s_isreg,
+    s_isblk, s_isdir, s_isreg,
 };
 
 pub struct InodeFile {
@@ -547,4 +549,18 @@ impl File {
             _ => unimplemented!("Poll event not supported."),
         }
     }
+
+    pub fn statx(&self, buffer: &mut statx, mask: u32) -> KResult<()> {
+        match self {
+            File::Inode(inode) => inode.dentry.statx(buffer, mask),
+            _ => Err(EBADF),
+        }
+    }
+
+    pub fn as_path(&self) -> Option<&Arc<Dentry>> {
+        match self {
+            File::Inode(inode_file) if s_isdir(inode_file.mode) => Some(&inode_file.dentry),
+            _ => None,
+        }
+    }
 }

+ 8 - 0
src/path.rs

@@ -2,6 +2,8 @@ use crate::prelude::*;
 
 use bindings::ENOENT;
 
+use core::fmt::{self, Debug, Formatter};
+
 pub struct Path<'lt> {
     all: &'lt [u8],
 }
@@ -79,3 +81,9 @@ impl<'lt> Iterator for PathIterator<'lt> {
         }
     }
 }
+
+impl Debug for Path<'_> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        write!(f, "Path({:?})", self.all)
+    }
+}