diff --git a/src/services/libs/jinux-std/src/fs/utils/vnode.rs b/src/services/libs/jinux-std/src/fs/utils/vnode.rs index c690a9f0..1673a973 100644 --- a/src/services/libs/jinux-std/src/fs/utils/vnode.rs +++ b/src/services/libs/jinux-std/src/fs/utils/vnode.rs @@ -1,5 +1,5 @@ -use crate::prelude::*; use super::{DirentWriterContext, Inode, InodeMode, InodeType, Metadata, PageCacheManager}; +use crate::prelude::*; use crate::rights::Rights; use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions}; use alloc::string::String; @@ -21,7 +21,7 @@ struct Inner { impl Vnode { pub fn new(inode: Arc) -> Result { let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode))); - let page_cache = VmoOptions::::new(inode.metadata().size) + let page_cache = VmoOptions::::new(inode.len()) .flags(VmoFlags::RESIZABLE) .pager(page_cache_manager.clone()) .alloc()?; diff --git a/src/services/libs/jinux-std/src/syscall/chdir.rs b/src/services/libs/jinux-std/src/syscall/chdir.rs new file mode 100644 index 00000000..bf306f33 --- /dev/null +++ b/src/services/libs/jinux-std/src/syscall/chdir.rs @@ -0,0 +1,50 @@ +use crate::fs::{file_table::FileDescripter, fs_resolver::FsPath, utils::InodeType}; +use crate::log_syscall_entry; +use crate::prelude::*; +use crate::syscall::constants::MAX_FILENAME_LEN; +use crate::util::read_cstring_from_user; + +use super::SyscallReturn; +use super::{SYS_CHDIR, SYS_FCHDIR}; + +pub fn sys_chdir(pathname_addr: Vaddr) -> Result { + log_syscall_entry!(SYS_CHDIR); + let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?; + debug!("pathname = {:?}", pathname); + + let current = current!(); + let mut fs = current.fs().write(); + let dentry = { + let pathname = pathname.to_string_lossy(); + if pathname.is_empty() { + return_errno_with_message!(Errno::ENOENT, "path is empty"); + } + let fs_path = FsPath::try_from(pathname.as_ref())?; + fs.lookup(&fs_path)? + }; + if dentry.inode_type() != InodeType::Dir { + return_errno_with_message!(Errno::ENOTDIR, "must be directory"); + } + fs.set_cwd(dentry); + Ok(SyscallReturn::Return(0)) +} + +pub fn sys_fchdir(fd: FileDescripter) -> Result { + log_syscall_entry!(SYS_FCHDIR); + debug!("fd = {}", fd); + + let current = current!(); + let dentry = { + let file_table = current.file_table().lock(); + let file = file_table.get_file(fd)?; + let inode_handle = file + .as_inode_handle() + .ok_or(Error::with_message(Errno::EBADE, "not inode"))?; + inode_handle.dentry().clone() + }; + if dentry.inode_type() != InodeType::Dir { + return_errno_with_message!(Errno::ENOTDIR, "must be directory"); + } + current.fs().write().set_cwd(dentry); + Ok(SyscallReturn::Return(0)) +} diff --git a/src/services/libs/jinux-std/src/syscall/mod.rs b/src/services/libs/jinux-std/src/syscall/mod.rs index a4e0335c..4dc16447 100644 --- a/src/services/libs/jinux-std/src/syscall/mod.rs +++ b/src/services/libs/jinux-std/src/syscall/mod.rs @@ -4,6 +4,7 @@ use crate::prelude::*; use crate::syscall::access::sys_access; use crate::syscall::arch_prctl::sys_arch_prctl; use crate::syscall::brk::sys_brk; +use crate::syscall::chdir::{sys_chdir, sys_fchdir}; use crate::syscall::clock_nanosleep::sys_clock_nanosleep; use crate::syscall::clone::sys_clone; use crate::syscall::close::sys_close; @@ -60,6 +61,7 @@ use jinux_frame::cpu::CpuContext; mod access; mod arch_prctl; mod brk; +mod chdir; mod clock_nanosleep; mod clone; mod close; @@ -175,6 +177,8 @@ define_syscall_nums!( SYS_UNAME = 63, SYS_FCNTL = 72, SYS_GETCWD = 79, + SYS_CHDIR = 80, + SYS_FCHDIR = 81, SYS_RENAME = 82, SYS_MKDIR = 83, SYS_RMDIR = 84, @@ -297,6 +301,8 @@ pub fn syscall_dispatch( SYS_UNAME => syscall_handler!(1, sys_uname, args), SYS_FCNTL => syscall_handler!(3, sys_fcntl, args), SYS_GETCWD => syscall_handler!(2, sys_getcwd, args), + SYS_CHDIR => syscall_handler!(1, sys_chdir, args), + SYS_FCHDIR => syscall_handler!(1, sys_fchdir, args), SYS_RENAME => syscall_handler!(2, sys_rename, args), SYS_MKDIR => syscall_handler!(2, sys_mkdir, args), SYS_RMDIR => syscall_handler!(1, sys_rmdir, args),