From 5511e28b728c0ffd5935305156f26dc6de59707d Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Wed, 17 Dec 2025 22:16:52 +0000 Subject: [PATCH] syscalls: implement ftruncate --- etc/syscalls_linux_aarch64.md | 2 +- src/arch/arm64/exceptions/syscall.rs | 2 ++ src/fs/fops.rs | 5 +++++ src/fs/reg.rs | 4 ++++ src/fs/syscalls/mod.rs | 1 + src/fs/syscalls/trunc.rs | 16 ++++++++++++++++ 6 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/fs/syscalls/trunc.rs diff --git a/etc/syscalls_linux_aarch64.md b/etc/syscalls_linux_aarch64.md index 829b6da..e6d76f0 100644 --- a/etc/syscalls_linux_aarch64.md +++ b/etc/syscalls_linux_aarch64.md @@ -46,7 +46,7 @@ | 0x2b (43) | statfs | (const char *pathname, struct statfs *buf) | __arm64_sys_statfs | false | | 0x2c (44) | fstatfs | (unsigned int fd, struct statfs *buf) | __arm64_sys_fstatfs | false | | 0x2d (45) | truncate | (const char *path, long length) | __arm64_sys_truncate | false | -| 0x2e (46) | ftruncate | (unsigned int fd, off_t length) | __arm64_sys_ftruncate | false | +| 0x2e (46) | ftruncate | (unsigned int fd, off_t length) | __arm64_sys_ftruncate | true | | 0x2f (47) | fallocate | (int fd, int mode, loff_t offset, loff_t len) | __arm64_sys_fallocate | false | | 0x30 (48) | faccessat | (int dfd, const char *filename, int mode) | __arm64_sys_faccessat | true | | 0x31 (49) | chdir | (const char *filename) | __arm64_sys_chdir | true | diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index ee61b5b..f2f2272 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -1,3 +1,4 @@ +use crate::fs::syscalls::trunc::sys_ftruncate; use crate::kernel::power::sys_reboot; use crate::kernel::rand::sys_getrandom; use crate::memory::mmap::sys_mprotect; @@ -91,6 +92,7 @@ pub async fn handle_syscall() { 0x18 => sys_dup3(arg1.into(), arg2.into(), arg3 as _), 0x19 => sys_fcntl(arg1.into(), arg2 as _, arg3 as _).await, 0x1d => sys_ioctl(arg1.into(), arg2 as _, arg3 as _).await, + 0x2e => sys_ftruncate(arg1.into(), arg2 as _).await, 0x30 => sys_faccessat(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await, 0x31 => sys_chdir(TUA::from_value(arg1 as _)).await, 0x38 => { diff --git a/src/fs/fops.rs b/src/fs/fops.rs index 135df94..0b340aa 100644 --- a/src/fs/fops.rs +++ b/src/fs/fops.rs @@ -84,6 +84,11 @@ pub trait FileOps: Send + Sync { Err(KernelError::NotATty) } + /// Truncate a file to a specified length + async fn truncate(&mut self, _ctx: &FileCtx, _new_size: usize) -> Result<()> { + Err(KernelError::InvalidValue) + } + /// Flushes any pending writes to the hardware. async fn flush(&self, _ctx: &FileCtx) -> Result<()> { Ok(()) diff --git a/src/fs/reg.rs b/src/fs/reg.rs index 04f86c9..2a93f46 100644 --- a/src/fs/reg.rs +++ b/src/fs/reg.rs @@ -91,6 +91,10 @@ impl FileOps for RegFile { Ok(total_bytes_written) } + async fn truncate(&mut self, _ctx: &FileCtx, new_size: usize) -> Result<()> { + self.inode.truncate(new_size as _).await + } + fn poll_read_ready(&self) -> Pin> + 'static + Send>> { // For regular files, polling just returns ready. Box::pin(async { Ok(()) }) diff --git a/src/fs/syscalls/mod.rs b/src/fs/syscalls/mod.rs index 85412d8..1192675 100644 --- a/src/fs/syscalls/mod.rs +++ b/src/fs/syscalls/mod.rs @@ -9,3 +9,4 @@ pub mod seek; pub mod splice; pub mod stat; pub mod sync; +pub mod trunc; diff --git a/src/fs/syscalls/trunc.rs b/src/fs/syscalls/trunc.rs new file mode 100644 index 0000000..df89488 --- /dev/null +++ b/src/fs/syscalls/trunc.rs @@ -0,0 +1,16 @@ +use crate::{process::fd_table::Fd, sched::current_task}; +use libkernel::{ + error::{KernelError, Result}, +}; + +pub async fn sys_ftruncate(fd: Fd, new_size: usize) -> Result { + let fd = current_task() + .fd_table + .lock_save_irq() + .get(fd) + .ok_or(KernelError::BadFd)?; + + let (ops, ctx) = &mut *fd.lock().await; + + ops.truncate(ctx, new_size).await.map(|_| 0) +}