implement sys_fchdir

This commit is contained in:
ootinnyoo
2025-12-22 18:34:22 -05:00
parent 1dd1811f34
commit 8f00af7587
8 changed files with 95 additions and 19 deletions

View File

@@ -50,7 +50,7 @@
| 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 |
| 0x32 (50) | fchdir | (unsigned int fd) | __arm64_sys_fchdir | false |
| 0x32 (50) | fchdir | (unsigned int fd) | __arm64_sys_fchdir | true |
| 0x33 (51) | chroot | (const char *filename) | __arm64_sys_chroot | true |
| 0x34 (52) | fchmod | (unsigned int fd, umode_t mode) | __arm64_sys_fchmod | false |
| 0x35 (53) | fchmodat | (int dfd, const char *filename, umode_t mode) | __arm64_sys_fchmodat | false |

View File

@@ -3,7 +3,7 @@
//! This module provides a `Path` struct that is a thin wrapper around `&str`,
//! offering various methods for path inspection and manipulation.
use alloc::vec::Vec;
use alloc::{borrow::ToOwned, vec::Vec};
use super::pathbuf::PathBuf;
@@ -217,6 +217,14 @@ impl AsRef<Path> for str {
}
}
impl ToOwned for Path {
type Owned = PathBuf;
fn to_owned(&self) -> Self::Owned {
PathBuf::from(self.as_str())
}
}
/// An iterator over the components of a `Path`.
#[derive(Clone, Debug)]
pub struct Components<'a> {

View File

@@ -6,7 +6,7 @@
use super::path::Path;
use alloc::string::String;
use core::ops::Deref;
use core::{borrow::Borrow, ops::Deref};
/// An owned, mutable path, akin to `String`.
///
@@ -164,6 +164,12 @@ impl Deref for PathBuf {
}
}
impl Borrow<Path> for PathBuf {
fn borrow(&self) -> &Path {
self
}
}
#[cfg(test)]
mod tests {
use super::PathBuf;

View File

@@ -1,8 +1,3 @@
use crate::fs::syscalls::chdir::sys_chroot;
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;
use crate::{
arch::{Arch, ArchImpl},
clock::{gettime::sys_clock_gettime, timeofday::sys_gettimeofday},
@@ -18,7 +13,7 @@ use crate::{
stat::sys_newfstatat,
unlink::sys_unlinkat,
},
chdir::{sys_chdir, sys_getcwd},
chdir::{sys_chdir, sys_chroot, sys_fchdir, sys_getcwd},
close::sys_close,
ioctl::sys_ioctl,
iov::{sys_readv, sys_writev},
@@ -27,13 +22,13 @@ use crate::{
splice::sys_sendfile,
stat::sys_fstat,
sync::sys_sync,
trunc::sys_ftruncate,
},
},
kernel::sysinfo::sys_sysinfo,
kernel::uname::sys_uname,
kernel::{power::sys_reboot, rand::sys_getrandom, sysinfo::sys_sysinfo, uname::sys_uname},
memory::{
brk::sys_brk,
mmap::{sys_mmap, sys_munmap},
mmap::{sys_mmap, sys_mprotect, sys_munmap},
},
process::{
clone::sys_clone,
@@ -101,6 +96,7 @@ pub async fn handle_syscall() {
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,
0x32 => sys_fchdir(arg1.into()).await,
0x33 => sys_chroot(TUA::from_value(arg1 as _)).await,
0x38 => {
sys_openat(

View File

@@ -1,3 +1,4 @@
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::{collections::btree_map::BTreeMap, sync::Arc};
use async_trait::async_trait;
@@ -337,14 +338,14 @@ impl VFS {
FileType::File => {
let mut open_file =
OpenFile::new(Box::new(RegFile::new(target_inode.clone())), flags);
open_file.set_inode(target_inode);
open_file.update(target_inode, path.to_owned());
Ok(Arc::new(open_file))
}
FileType::Directory => {
let mut open_file =
OpenFile::new(Box::new(DirFile::new(target_inode.clone())), flags);
open_file.set_inode(target_inode);
open_file.update(target_inode, path.to_owned());
Ok(Arc::new(open_file))
}

View File

@@ -7,7 +7,7 @@ use alloc::{boxed::Box, sync::Arc, vec::Vec};
use core::{future, pin::Pin, task::Poll};
use libkernel::{
error::Result,
fs::{Inode, OpenFlags},
fs::{Inode, OpenFlags, path::Path, pathbuf::PathBuf},
};
pub struct FileCtx {
@@ -23,6 +23,7 @@ impl FileCtx {
pub struct OpenFile {
inode: Option<Arc<dyn Inode>>,
path: Option<PathBuf>,
state: Mutex<(Box<dyn FileOps>, FileCtx)>,
}
@@ -31,17 +32,23 @@ impl OpenFile {
Self {
state: Mutex::new((ops, FileCtx::new(flags))),
inode: None,
path: None,
}
}
pub fn set_inode(&mut self, inode: Arc<dyn Inode>) {
self.inode = Some(inode)
pub fn update(&mut self, inode: Arc<dyn Inode>, path: PathBuf) {
self.inode = Some(inode);
self.path = Some(path);
}
pub fn inode(&self) -> Option<Arc<dyn Inode>> {
self.inode.clone()
}
pub fn path(&self) -> Option<&Path> {
self.path.as_deref()
}
pub async fn flags(&self) -> OpenFlags {
self.state.lock().await.1.flags
}

View File

@@ -1,9 +1,10 @@
use crate::{
fs::VFS,
memory::uaccess::{copy_to_user_slice, cstr::UserCStr},
process::fd_table::Fd,
sched::current_task,
};
use alloc::{ffi::CString, string::ToString};
use alloc::{borrow::ToOwned, ffi::CString, string::ToString};
use core::{ffi::c_char, str::FromStr};
use libkernel::{
error::{KernelError, Result},
@@ -55,3 +56,19 @@ pub async fn sys_chroot(path: TUA<c_char>) -> Result<usize> {
Ok(0)
}
pub async fn sys_fchdir(fd: Fd) -> Result<usize> {
let task = current_task();
let file = task
.fd_table
.lock_save_irq()
.get(fd)
.ok_or(KernelError::BadFd)?;
*task.cwd.lock_save_irq() = (
file.inode().ok_or(KernelError::BadFd)?,
file.path().ok_or(KernelError::BadFd)?.to_owned(),
);
Ok(0)
}

View File

@@ -47,11 +47,51 @@ fn test_readdir() {
fn test_chdir() {
print!("Testing chdir syscall ...");
let path = std::ffi::CString::new("/").unwrap();
let path = std::ffi::CString::new("/dev").unwrap();
let mut buffer = [1u8; 16];
unsafe {
if libc::chdir(path.as_ptr()) != 0 {
panic!("chdir failed");
}
if libc::getcwd(
buffer.as_mut_ptr() as *mut libc::c_char,
buffer.len() as libc::size_t,
)
.is_null()
{
panic!("getcwd failed");
}
if std::ffi::CStr::from_ptr(buffer.as_ptr()).to_string_lossy() != "/dev" {
panic!("chdir failed");
}
}
println!(" OK");
}
fn test_fchdir() {
print!("Testing fchdir syscall ...");
let path = std::ffi::CString::new("/dev").unwrap();
let mut buffer = [1u8; 16];
unsafe {
let fd = libc::open(path.as_ptr(), libc::O_RDONLY);
if fd == -1 {
panic!("open failed");
}
if libc::fchdir(fd) != 0 {
panic!("fchdir failed");
}
if libc::getcwd(
buffer.as_mut_ptr() as *mut libc::c_char,
buffer.len() as libc::size_t,
)
.is_null()
{
panic!("getcwd failed");
}
if std::ffi::CStr::from_ptr(buffer.as_ptr()).to_string_lossy() != "/dev" {
panic!("fchdir failed");
}
libc::close(fd);
}
println!(" OK");
}
@@ -240,6 +280,7 @@ fn main() {
run_test(test_opendir);
run_test(test_readdir);
run_test(test_chdir);
run_test(test_fchdir);
run_test(test_chroot);
run_test(test_fork);
run_test(test_read);