Implement sys_truncate (#86)

This commit is contained in:
someone
2025-12-24 06:08:16 +00:00
committed by GitHub
parent 3aef9a4e15
commit 877dc9bf2e
4 changed files with 88 additions and 4 deletions

View File

@@ -45,7 +45,7 @@
| 0x29 (41) | pivot_root | (const char *new_root, const char *put_old) | __arm64_sys_pivot_root | false |
| 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 |
| 0x2d (45) | truncate | (const char *path, long length) | __arm64_sys_truncate | true |
| 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 |

View File

@@ -26,7 +26,7 @@ use crate::{
splice::sys_sendfile,
stat::sys_fstat,
sync::sys_sync,
trunc::sys_ftruncate,
trunc::{sys_ftruncate, sys_truncate},
},
},
kernel::{power::sys_reboot, rand::sys_getrandom, sysinfo::sys_sysinfo, uname::sys_uname},
@@ -97,6 +97,7 @@ pub async fn handle_syscall() {
0x1d => sys_ioctl(arg1.into(), arg2 as _, arg3 as _).await,
0x22 => sys_mkdirat(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
0x23 => sys_unlinkat(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
0x2d => sys_truncate(TUA::from_value(arg1 as _), arg2 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,

View File

@@ -1,5 +1,33 @@
use crate::{process::fd_table::Fd, sched::current_task};
use libkernel::error::{KernelError, Result};
use core::ffi::c_char;
use crate::{fs::VFS, memory::uaccess::cstr::UserCStr, process::fd_table::Fd, sched::current_task};
use libkernel::{
error::{KernelError, Result},
fs::{OpenFlags, attr::FilePermissions, path::Path},
memory::address::TUA,
};
pub async fn sys_truncate(path: TUA<c_char>, new_size: usize) -> Result<usize> {
let mut buf = [0; 1024];
let task = current_task();
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
let root = task.root.lock_save_irq().0.clone();
let file = VFS
.open(
path,
OpenFlags::O_WRONLY,
root,
FilePermissions::empty(),
task,
)
.await?;
let (ops, ctx) = &mut *file.lock().await;
ops.truncate(ctx, new_size).await.map(|_| 0)
}
pub async fn sys_ftruncate(fd: Fd, new_size: usize) -> Result<usize> {
let fd = current_task()

View File

@@ -319,6 +319,59 @@ fn test_futex() {
println!(" OK");
}
fn test_truncate() {
print!("Testing truncate syscall ...");
use std::fs::{self, File};
use std::io::{Read, Seek, Write};
let path = "/tmp/truncate_test.txt";
let mut file = File::create_new(path).expect("Failed to create file");
file.write_all(b"Hello, world!")
.expect("Failed to write to file");
unsafe {
libc::truncate(std::ffi::CString::new(path).unwrap().as_ptr(), 5);
}
let mut string = String::new();
file.rewind().expect("Failed to rewind file");
file.read_to_string(&mut string)
.expect("Failed to read from file");
if string != "Hello" {
println!("{string}");
panic!("truncate failed");
}
fs::remove_file(path).expect("Failed to delete file");
println!(" OK");
}
fn test_ftruncate() {
print!("Testing ftruncate syscall ...");
let file = "/tmp/ftruncate_test.txt";
let c_file = std::ffi::CString::new(file).unwrap();
let data = b"Hello, world!";
let mut buffer = [1u8; 5];
unsafe {
let fd = libc::open(c_file.as_ptr(), libc::O_RDWR | libc::O_CREAT, 0o777);
let ret = libc::write(fd, data.as_ptr() as *const libc::c_void, data.len());
if ret < 0 || ret as usize != data.len() {
panic!("write failed");
}
libc::ftruncate(fd, 5);
libc::lseek(fd, 0, libc::SEEK_SET);
let ret = libc::read(fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len());
if ret < 0 || ret as usize != 5 {
panic!("read failed");
}
if &buffer != b"Hello" {
panic!("ftruncate failed");
}
libc::close(fd);
}
fs::remove_file(file).expect("Failed to delete file");
println!(" OK");
}
fn test_rust_file() {
print!("Testing rust file operations ...");
use std::fs::{self, File};
@@ -436,6 +489,8 @@ fn main() {
run_test(test_read);
run_test(test_write);
run_test(test_futex);
run_test(test_truncate);
run_test(test_ftruncate);
run_test(test_rust_file);
run_test(test_rust_dir);
run_test(test_rust_thread);