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 | | 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 | | 0x30 (48) | faccessat | (int dfd, const char *filename, int mode) | __arm64_sys_faccessat | true |
| 0x31 (49) | chdir | (const char *filename) | __arm64_sys_chdir | 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 | | 0x33 (51) | chroot | (const char *filename) | __arm64_sys_chroot | true |
| 0x34 (52) | fchmod | (unsigned int fd, umode_t mode) | __arm64_sys_fchmod | false | | 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 | | 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`, //! This module provides a `Path` struct that is a thin wrapper around `&str`,
//! offering various methods for path inspection and manipulation. //! offering various methods for path inspection and manipulation.
use alloc::vec::Vec; use alloc::{borrow::ToOwned, vec::Vec};
use super::pathbuf::PathBuf; 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`. /// An iterator over the components of a `Path`.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Components<'a> { pub struct Components<'a> {

View File

@@ -6,7 +6,7 @@
use super::path::Path; use super::path::Path;
use alloc::string::String; use alloc::string::String;
use core::ops::Deref; use core::{borrow::Borrow, ops::Deref};
/// An owned, mutable path, akin to `String`. /// 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)] #[cfg(test)]
mod tests { mod tests {
use super::PathBuf; 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::{ use crate::{
arch::{Arch, ArchImpl}, arch::{Arch, ArchImpl},
clock::{gettime::sys_clock_gettime, timeofday::sys_gettimeofday}, clock::{gettime::sys_clock_gettime, timeofday::sys_gettimeofday},
@@ -18,7 +13,7 @@ use crate::{
stat::sys_newfstatat, stat::sys_newfstatat,
unlink::sys_unlinkat, unlink::sys_unlinkat,
}, },
chdir::{sys_chdir, sys_getcwd}, chdir::{sys_chdir, sys_chroot, sys_fchdir, sys_getcwd},
close::sys_close, close::sys_close,
ioctl::sys_ioctl, ioctl::sys_ioctl,
iov::{sys_readv, sys_writev}, iov::{sys_readv, sys_writev},
@@ -27,13 +22,13 @@ use crate::{
splice::sys_sendfile, splice::sys_sendfile,
stat::sys_fstat, stat::sys_fstat,
sync::sys_sync, sync::sys_sync,
trunc::sys_ftruncate,
}, },
}, },
kernel::sysinfo::sys_sysinfo, kernel::{power::sys_reboot, rand::sys_getrandom, sysinfo::sys_sysinfo, uname::sys_uname},
kernel::uname::sys_uname,
memory::{ memory::{
brk::sys_brk, brk::sys_brk,
mmap::{sys_mmap, sys_munmap}, mmap::{sys_mmap, sys_mprotect, sys_munmap},
}, },
process::{ process::{
clone::sys_clone, clone::sys_clone,
@@ -101,6 +96,7 @@ pub async fn handle_syscall() {
0x2e => sys_ftruncate(arg1.into(), arg2 as _).await, 0x2e => sys_ftruncate(arg1.into(), arg2 as _).await,
0x30 => sys_faccessat(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await, 0x30 => sys_faccessat(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
0x31 => sys_chdir(TUA::from_value(arg1 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, 0x33 => sys_chroot(TUA::from_value(arg1 as _)).await,
0x38 => { 0x38 => {
sys_openat( sys_openat(

View File

@@ -1,3 +1,4 @@
use alloc::borrow::ToOwned;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::{collections::btree_map::BTreeMap, sync::Arc}; use alloc::{collections::btree_map::BTreeMap, sync::Arc};
use async_trait::async_trait; use async_trait::async_trait;
@@ -337,14 +338,14 @@ impl VFS {
FileType::File => { FileType::File => {
let mut open_file = let mut open_file =
OpenFile::new(Box::new(RegFile::new(target_inode.clone())), flags); 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)) Ok(Arc::new(open_file))
} }
FileType::Directory => { FileType::Directory => {
let mut open_file = let mut open_file =
OpenFile::new(Box::new(DirFile::new(target_inode.clone())), flags); 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)) 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 core::{future, pin::Pin, task::Poll};
use libkernel::{ use libkernel::{
error::Result, error::Result,
fs::{Inode, OpenFlags}, fs::{Inode, OpenFlags, path::Path, pathbuf::PathBuf},
}; };
pub struct FileCtx { pub struct FileCtx {
@@ -23,6 +23,7 @@ impl FileCtx {
pub struct OpenFile { pub struct OpenFile {
inode: Option<Arc<dyn Inode>>, inode: Option<Arc<dyn Inode>>,
path: Option<PathBuf>,
state: Mutex<(Box<dyn FileOps>, FileCtx)>, state: Mutex<(Box<dyn FileOps>, FileCtx)>,
} }
@@ -31,17 +32,23 @@ impl OpenFile {
Self { Self {
state: Mutex::new((ops, FileCtx::new(flags))), state: Mutex::new((ops, FileCtx::new(flags))),
inode: None, inode: None,
path: None,
} }
} }
pub fn set_inode(&mut self, inode: Arc<dyn Inode>) { pub fn update(&mut self, inode: Arc<dyn Inode>, path: PathBuf) {
self.inode = Some(inode) self.inode = Some(inode);
self.path = Some(path);
} }
pub fn inode(&self) -> Option<Arc<dyn Inode>> { pub fn inode(&self) -> Option<Arc<dyn Inode>> {
self.inode.clone() self.inode.clone()
} }
pub fn path(&self) -> Option<&Path> {
self.path.as_deref()
}
pub async fn flags(&self) -> OpenFlags { pub async fn flags(&self) -> OpenFlags {
self.state.lock().await.1.flags self.state.lock().await.1.flags
} }

View File

@@ -1,9 +1,10 @@
use crate::{ use crate::{
fs::VFS, fs::VFS,
memory::uaccess::{copy_to_user_slice, cstr::UserCStr}, memory::uaccess::{copy_to_user_slice, cstr::UserCStr},
process::fd_table::Fd,
sched::current_task, 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 core::{ffi::c_char, str::FromStr};
use libkernel::{ use libkernel::{
error::{KernelError, Result}, error::{KernelError, Result},
@@ -55,3 +56,19 @@ pub async fn sys_chroot(path: TUA<c_char>) -> Result<usize> {
Ok(0) 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() { fn test_chdir() {
print!("Testing chdir syscall ..."); 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 { unsafe {
if libc::chdir(path.as_ptr()) != 0 { if libc::chdir(path.as_ptr()) != 0 {
panic!("chdir failed"); 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"); println!(" OK");
} }
@@ -240,6 +280,7 @@ fn main() {
run_test(test_opendir); run_test(test_opendir);
run_test(test_readdir); run_test(test_readdir);
run_test(test_chdir); run_test(test_chdir);
run_test(test_fchdir);
run_test(test_chroot); run_test(test_chroot);
run_test(test_fork); run_test(test_fork);
run_test(test_read); run_test(test_read);