소스 검색

feat(syscall): impl fch{own, mod}at and utimensat

greatbridf 7 달 전
부모
커밋
98ac37c635
5개의 변경된 파일70개의 추가작업 그리고 14개의 파일을 삭제
  1. 1 1
      crates/posix_types/src/syscall_no/riscv64.rs
  2. 61 0
      src/kernel/syscall/file_rw.rs
  3. 0 13
      src/kernel/syscall/procops.rs
  4. 4 0
      src/kernel/vfs/dentry.rs
  5. 4 0
      src/kernel/vfs/inode.rs

+ 1 - 1
crates/posix_types/src/syscall_no/riscv64.rs

@@ -88,7 +88,7 @@ pub const SYS_SYNC_FILE_RANGE: usize = 84;
 pub const SYS_TIMERFD_CREATE: usize = 85;
 pub const SYS_TIMERFD_SETTIME: usize = 411;
 pub const SYS_TIMERFD_GETTIME: usize = 410;
-pub const SYS_UTIMENSAT: usize = 412;
+pub const SYS_UTIMENSAT: usize = 88;
 pub const SYS_ACCT: usize = 89;
 pub const SYS_CAPGET: usize = 90;
 pub const SYS_CAPSET: usize = 91;

+ 61 - 0
src/kernel/syscall/file_rw.rs

@@ -476,4 +476,65 @@ fn poll(fds: *mut UserPollFd, nfds: u32, timeout: u32) -> KResult<u32> {
     do_poll(thread, fds, nfds, timeout)
 }
 
+#[eonix_macros::define_syscall(SYS_FCHOWNAT)]
+fn fchownat(dirfd: FD, pathname: *const u8, uid: u32, gid: u32, flags: AtFlags) -> KResult<()> {
+    let dentry = dentry_from(thread, dirfd, pathname, !flags.no_follow())?;
+    if !dentry.is_valid() {
+        return Err(ENOENT);
+    }
+
+    dentry.chown(uid, gid)
+}
+
+#[eonix_macros::define_syscall(SYS_FCHMODAT)]
+fn fchmodat(dirfd: FD, pathname: *const u8, mode: u32, flags: AtFlags) -> KResult<()> {
+    let dentry = if flags.at_empty_path() {
+        let file = thread.files.get(dirfd).ok_or(EBADF)?;
+        file.as_path().ok_or(EBADF)?.clone()
+    } else {
+        dentry_from(thread, dirfd, pathname, !flags.no_follow())?
+    };
+
+    if !dentry.is_valid() {
+        return Err(ENOENT);
+    }
+
+    dentry.chmod(mode)
+}
+
+#[eonix_macros::define_syscall(SYS_FCHMOD)]
+fn chmod(pathname: *const u8, mode: u32) -> KResult<()> {
+    sys_fchmodat(thread, FD::AT_FDCWD, pathname, mode, AtFlags::empty())
+}
+
+#[eonix_macros::define_syscall(SYS_UTIMENSAT)]
+fn utimensat(
+    dirfd: FD,
+    pathname: *const u8,
+    times: *const TimeSpec,
+    flags: AtFlags,
+) -> KResult<()> {
+    let dentry = if flags.at_empty_path() {
+        let file = thread.files.get(dirfd).ok_or(EBADF)?;
+        file.as_path().ok_or(EBADF)?.clone()
+    } else {
+        dentry_from(thread, dirfd, pathname, !flags.no_follow())?
+    };
+
+    if !dentry.is_valid() {
+        return Err(ENOENT);
+    }
+
+    let _times = if times.is_null() {
+        [TimeSpec::default(), TimeSpec::default()]
+    } else {
+        let times = UserPointer::new(times)?;
+        [times.read()?, times.offset(1)?.read()?]
+    };
+
+    // TODO: Implement utimensat
+    // dentry.utimens(&times)
+    Ok(())
+}
+
 pub fn keep_alive() {}

+ 0 - 13
src/kernel/syscall/procops.rs

@@ -684,19 +684,6 @@ fn getrusage(who: u32, rusage: *mut RUsage) -> KResult<()> {
     Ok(())
 }
 
-#[eonix_macros::define_syscall(SYS_FCHMOD)]
-fn chmod(pathname: *const u8, mode: u32) -> KResult<()> {
-    let path = UserString::new(pathname)?;
-    let path = Path::new(path.as_cstr().to_bytes())?;
-
-    let dentry = Dentry::open(&thread.fs_context, path, true)?;
-    if !dentry.is_valid() {
-        return Err(ENOENT);
-    }
-
-    dentry.chmod(mode)
-}
-
 #[cfg(target_arch = "x86_64")]
 #[eonix_macros::define_syscall(SYS_VFORK)]
 fn vfork() -> KResult<u32> {

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

@@ -453,4 +453,8 @@ impl Dentry {
     pub fn chmod(&self, mode: Mode) -> KResult<()> {
         self.get_inode()?.chmod(mode)
     }
+
+    pub fn chown(&self, uid: u32, gid: u32) -> KResult<()> {
+        self.get_inode()?.chown(uid, gid)
+    }
 }

+ 4 - 0
src/kernel/vfs/inode.rs

@@ -144,6 +144,10 @@ pub trait Inode: Send + Sync + InodeInner {
         Err(EPERM)
     }
 
+    fn chown(&self, uid: u32, gid: u32) -> KResult<()> {
+        Err(EPERM)
+    }
+
     fn statx(&self, stat: &mut StatX, mask: u32) -> KResult<()> {
         // Safety: ffi should have checked reference
         let vfs = self.vfs.upgrade().expect("Vfs is dropped");