mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2025-12-23 22:47:55 -05:00
implement sys_fchdir
This commit is contained in:
@@ -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 |
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user