diff --git a/src/services/libs/jinux-std/src/fs/file.rs b/src/services/libs/jinux-std/src/fs/file_handle/file.rs similarity index 89% rename from src/services/libs/jinux-std/src/fs/file.rs rename to src/services/libs/jinux-std/src/fs/file_handle/file.rs index 70cd30b0..85a6ac82 100644 --- a/src/services/libs/jinux-std/src/fs/file.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/file.rs @@ -2,10 +2,7 @@ use crate::prelude::*; use crate::tty::get_n_tty; use core::any::Any; -use super::events::IoEvents; -use super::ioctl::IoctlCmd; - -pub type FileDescripter = i32; +use crate::fs::utils::{IoEvents, IoctlCmd}; /// The basic operations defined on a file pub trait File: Send + Sync + Any { diff --git a/src/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs similarity index 97% rename from src/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs rename to src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs index b3a18a2d..e131d0f4 100644 --- a/src/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/dyn_cap.rs @@ -1,5 +1,4 @@ use crate::prelude::*; - use crate::rights::{Rights, TRights}; use super::*; @@ -10,7 +9,7 @@ impl InodeHandle { access_mode: AccessMode, status_flags: StatusFlags, ) -> Result { - let inode_info = dentry.inode().raw_inode().metadata(); + let inode_info = dentry.vnode().inode().metadata(); if access_mode.is_readable() && !inode_info.mode.is_readable() { return_errno_with_message!(Errno::EACCES, "File is not readable"); } diff --git a/src/services/libs/jinux-std/src/fs/inode_handle/mod.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs similarity index 86% rename from src/services/libs/jinux-std/src/fs/inode_handle/mod.rs rename to src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs index 048c4d79..11b8c568 100644 --- a/src/services/libs/jinux-std/src/fs/inode_handle/mod.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/mod.rs @@ -1,9 +1,9 @@ -//! Opend File Handle +//! Opend Inode-backed File Handle mod dyn_cap; mod static_cap; -use super::utils::{ +use crate::fs::utils::{ AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags, }; use crate::prelude::*; @@ -23,17 +23,17 @@ struct InodeHandle_ { impl InodeHandle_ { pub fn read(&self, buf: &mut [u8]) -> Result { let mut offset = self.offset.lock(); - let file_size = self.dentry.inode().raw_inode().metadata().size; + let file_size = self.dentry.vnode().inode().metadata().size; let start = file_size.min(*offset); let end = file_size.min(*offset + buf.len()); let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { self.dentry + .vnode() .inode() - .raw_inode() .read_at(start, &mut buf[0..end - start])? } else { self.dentry - .inode() + .vnode() .pages() .read_bytes(start, &mut buf[0..end - start])?; end - start @@ -45,24 +45,21 @@ impl InodeHandle_ { pub fn write(&self, buf: &[u8]) -> Result { let mut offset = self.offset.lock(); - let file_size = self.dentry.inode().raw_inode().metadata().size; + let file_size = self.dentry.vnode().inode().metadata().size; if self.status_flags.lock().contains(StatusFlags::O_APPEND) { *offset = file_size; } let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { - self.dentry.inode().raw_inode().write_at(*offset, buf)? + self.dentry.vnode().inode().write_at(*offset, buf)? } else { - let pages = self.dentry.inode().pages(); + let pages = self.dentry.vnode().pages(); let should_expand_size = *offset + buf.len() > file_size; if should_expand_size { pages.resize(*offset + buf.len())?; } pages.write_bytes(*offset, buf)?; if should_expand_size { - self.dentry - .inode() - .raw_inode() - .resize(*offset + buf.len())?; + self.dentry.vnode().inode().resize(*offset + buf.len())?; } buf.len() }; @@ -81,7 +78,7 @@ impl InodeHandle_ { off as i64 } SeekFrom::End(off /* as i64 */) => { - let file_size = self.dentry.inode().raw_inode().metadata().size as i64; + let file_size = self.dentry.vnode().inode().metadata().size as i64; assert!(file_size >= 0); file_size .checked_add(off) @@ -128,11 +125,7 @@ impl InodeHandle_ { pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result { let mut offset = self.offset.lock(); let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer); - let written_size = self - .dentry - .inode() - .raw_inode() - .readdir(&mut dir_writer_ctx)?; + let written_size = self.dentry.vnode().inode().readdir(&mut dir_writer_ctx)?; *offset = dir_writer_ctx.pos(); Ok(written_size) } diff --git a/src/services/libs/jinux-std/src/fs/inode_handle/static_cap.rs b/src/services/libs/jinux-std/src/fs/file_handle/inode_handle/static_cap.rs similarity index 100% rename from src/services/libs/jinux-std/src/fs/inode_handle/static_cap.rs rename to src/services/libs/jinux-std/src/fs/file_handle/inode_handle/static_cap.rs diff --git a/src/services/libs/jinux-std/src/fs/file_handle.rs b/src/services/libs/jinux-std/src/fs/file_handle/mod.rs similarity index 92% rename from src/services/libs/jinux-std/src/fs/file_handle.rs rename to src/services/libs/jinux-std/src/fs/file_handle/mod.rs index 680cc513..d6d2f092 100644 --- a/src/services/libs/jinux-std/src/fs/file_handle.rs +++ b/src/services/libs/jinux-std/src/fs/file_handle/mod.rs @@ -1,9 +1,14 @@ +//! Opend File Handle + +mod file; +mod inode_handle; + use crate::prelude::*; use crate::rights::{ReadOp, WriteOp}; use alloc::sync::Arc; -use super::file::File; -use super::inode_handle::InodeHandle; +pub use self::file::File; +pub use self::inode_handle::InodeHandle; #[derive(Clone)] pub struct FileHandle { diff --git a/src/services/libs/jinux-std/src/fs/file_table.rs b/src/services/libs/jinux-std/src/fs/file_table.rs index a533015c..6b3dfd7c 100644 --- a/src/services/libs/jinux-std/src/fs/file_table.rs +++ b/src/services/libs/jinux-std/src/fs/file_table.rs @@ -1,11 +1,12 @@ use crate::prelude::*; use super::{ - file::FileDescripter, file_handle::FileHandle, stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT}, }; +pub type FileDescripter = i32; + #[derive(Clone)] pub struct FileTable { table: BTreeMap, diff --git a/src/services/libs/jinux-std/src/fs/fs_resolver.rs b/src/services/libs/jinux-std/src/fs/fs_resolver.rs index 0669344f..cbf88b2c 100644 --- a/src/services/libs/jinux-std/src/fs/fs_resolver.rs +++ b/src/services/libs/jinux-std/src/fs/fs_resolver.rs @@ -2,14 +2,13 @@ use crate::prelude::*; use alloc::str; use alloc::string::String; -use super::file::FileDescripter; -use super::inode_handle::InodeHandle; +use super::file_handle::InodeHandle; +use super::file_table::FileDescripter; use super::ramfs::RamFS; use super::utils::{ - AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, PATH_MAX, - SYMLINKS_MAX, + AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, Vnode, + PATH_MAX, SYMLINKS_MAX, }; -use super::vfs_inode::VfsInode; lazy_static! { static ref ROOT_FS: Arc = RamFS::new(); @@ -32,8 +31,8 @@ impl Clone for FsResolver { impl FsResolver { pub fn new() -> Result { let root = { - let root_inode = VfsInode::new(ROOT_FS.root_inode())?; - Dentry::new_root(root_inode) + let root_vnode = Vnode::new(ROOT_FS.root_inode())?; + Dentry::new_root(root_vnode) }; Ok(Self { root: root.clone(), @@ -64,9 +63,9 @@ impl FsResolver { let inode_mode = InodeMode::from_bits_truncate(mode); let follow_tail_link = !creation_flags.contains(CreationFlags::O_NOFOLLOW); - let dentry = match self.lookup(path, follow_tail_link) { + let dentry = match self.lookup_inner(path, follow_tail_link) { Ok(dentry) => { - let inode = dentry.inode().raw_inode(); + let inode = dentry.vnode().inode(); if inode.metadata().type_ == InodeType::SymLink && !status_flags.contains(StatusFlags::O_PATH) { @@ -94,15 +93,15 @@ impl FsResolver { if creation_flags.contains(CreationFlags::O_DIRECTORY) { return_errno_with_message!(Errno::ENOTDIR, "cannot create directory"); } - let (dir_dentry, file_name) = self.lookup_dir_and_base_name(path)?; + let (dir_dentry, file_name) = + self.lookup_dir_and_base_name_inner(path, follow_tail_link)?; if file_name.ends_with("/") { return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); } - if !dir_dentry.inode().raw_inode().metadata().mode.is_writable() { + if !dir_dentry.vnode().inode().metadata().mode.is_writable() { return_errno_with_message!(Errno::EPERM, "file cannot be created"); } - let new_dentry = - dir_dentry.create_child(&file_name, InodeType::File, inode_mode)?; + let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?; new_dentry } Err(e) => return Err(e), @@ -112,8 +111,17 @@ impl FsResolver { Ok(inode_handle) } - /// Lookup dentry according to FsPath - pub fn lookup(&self, path: &FsPath, follow_tail_link: bool) -> Result> { + /// Lookup dentry according to FsPath, always follow symlinks + pub fn lookup(&self, path: &FsPath) -> Result> { + self.lookup_inner(path, true) + } + + /// Lookup dentry according to FsPath, do not follow it if last component is a symlink + pub fn lookup_no_follow(&self, path: &FsPath) -> Result> { + self.lookup_inner(path, false) + } + + fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result> { let dentry = match path.inner { FsPathInner::Absolute(path) => { self.lookup_from_parent(&self.root, path.trim_start_matches('/'), follow_tail_link)? @@ -123,75 +131,15 @@ impl FsResolver { } FsPathInner::Cwd => self.cwd.clone(), FsPathInner::FdRelative(fd, path) => { - let parent = self.lookup_dentry_from_fd(fd)?; + let parent = self.lookup_from_fd(fd)?; self.lookup_from_parent(&parent, path, follow_tail_link)? } - FsPathInner::Fd(fd) => self.lookup_dentry_from_fd(fd)?, + FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?, }; Ok(dentry) } - /// Lookup the dir dentry and base file name of the giving path. - /// - /// If encounters symlinks, should deference them. - fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc, String)> { - let (mut dir_dentry, mut base_name) = match path.inner { - FsPathInner::Absolute(path) => { - let (dir, file_name) = split_path(path); - ( - self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?, - String::from(file_name), - ) - } - FsPathInner::CwdRelative(path) => { - let (dir, file_name) = split_path(path); - ( - self.lookup_from_parent(&self.cwd, path, true)?, - String::from(file_name), - ) - } - FsPathInner::FdRelative(fd, path) => { - let (dir, file_name) = split_path(path); - let parent = self.lookup_dentry_from_fd(fd)?; - ( - self.lookup_from_parent(&parent, path, true)?, - String::from(file_name), - ) - } - _ => return_errno!(Errno::ENOENT), - }; - - loop { - match dir_dentry.get(&base_name.trim_end_matches('/')) { - Ok(dentry) if dentry.inode().raw_inode().metadata().type_ == InodeType::SymLink => { - let link = { - let mut link = dentry.inode().raw_inode().read_link()?; - if link.is_empty() { - return_errno_with_message!(Errno::ENOENT, "invalid symlink"); - } - if base_name.ends_with("/") && !link.ends_with("/") { - link += "/"; - } - link - }; - let (dir, file_name) = split_path(&link); - if dir.starts_with("/") { - dir_dentry = - self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?; - base_name = String::from(file_name); - } else { - dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?; - base_name = String::from(file_name); - } - } - _ => break, - } - } - - Ok((dir_dentry, base_name)) - } - /// Lookup dentry from parent /// /// The length of `path` cannot exceed PATH_MAX. @@ -232,8 +180,8 @@ impl FsResolver { }; // Iterate next dentry - let next_dentry = dentry.get(next_name)?; - let next_type = next_dentry.inode().raw_inode().metadata().type_; + let next_dentry = dentry.lookup(next_name)?; + let next_type = next_dentry.vnode().inode().metadata().type_; let next_is_tail = path_remain.is_empty(); // If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times. @@ -242,7 +190,7 @@ impl FsResolver { return_errno_with_message!(Errno::ELOOP, "too many symlinks"); } let link_path_remain = { - let mut tmp_link_path = next_dentry.inode().raw_inode().read_link()?; + let mut tmp_link_path = next_dentry.vnode().inode().read_link()?; if tmp_link_path.is_empty() { return_errno_with_message!(Errno::ENOENT, "empty symlink"); } @@ -277,7 +225,7 @@ impl FsResolver { } /// Lookup dentry from the giving fd - fn lookup_dentry_from_fd(&self, fd: FileDescripter) -> Result> { + fn lookup_from_fd(&self, fd: FileDescripter) -> Result> { let current = current!(); let file_table = current.file_table().lock(); let inode_handle = file_table @@ -286,6 +234,78 @@ impl FsResolver { .ok_or(Error::with_message(Errno::EBADE, "not inode"))?; Ok(inode_handle.dentry().clone()) } + + /// Lookup the dir dentry and base file name of the giving path. + /// + /// If the last component is a symlink, do not deference it + pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc, String)> { + self.lookup_dir_and_base_name_inner(path, false) + } + + fn lookup_dir_and_base_name_inner( + &self, + path: &FsPath, + follow_tail_link: bool, + ) -> Result<(Arc, String)> { + let (mut dir_dentry, mut base_name) = match path.inner { + FsPathInner::Absolute(path) => { + let (dir, file_name) = split_path(path); + ( + self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?, + String::from(file_name), + ) + } + FsPathInner::CwdRelative(path) => { + let (dir, file_name) = split_path(path); + ( + self.lookup_from_parent(&self.cwd, path, true)?, + String::from(file_name), + ) + } + FsPathInner::FdRelative(fd, path) => { + let (dir, file_name) = split_path(path); + let parent = self.lookup_from_fd(fd)?; + ( + self.lookup_from_parent(&parent, path, true)?, + String::from(file_name), + ) + } + _ => return_errno!(Errno::ENOENT), + }; + if !follow_tail_link { + return Ok((dir_dentry, base_name)); + } + + // Dereference the tail symlinks if needed + loop { + match dir_dentry.lookup(&base_name.trim_end_matches('/')) { + Ok(dentry) if dentry.vnode().inode().metadata().type_ == InodeType::SymLink => { + let link = { + let mut link = dentry.vnode().inode().read_link()?; + if link.is_empty() { + return_errno_with_message!(Errno::ENOENT, "invalid symlink"); + } + if base_name.ends_with("/") && !link.ends_with("/") { + link += "/"; + } + link + }; + let (dir, file_name) = split_path(&link); + if dir.starts_with("/") { + dir_dentry = + self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?; + base_name = String::from(file_name); + } else { + dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?; + base_name = String::from(file_name); + } + } + _ => break, + } + } + + Ok((dir_dentry, base_name)) + } } pub const AT_FDCWD: FileDescripter = -100; diff --git a/src/services/libs/jinux-std/src/fs/mod.rs b/src/services/libs/jinux-std/src/fs/mod.rs index b52b3a6b..77018bc5 100644 --- a/src/services/libs/jinux-std/src/fs/mod.rs +++ b/src/services/libs/jinux-std/src/fs/mod.rs @@ -1,14 +1,6 @@ -pub mod events; -pub mod fcntl; -pub mod file; pub mod file_handle; pub mod file_table; pub mod fs_resolver; -pub mod inode_handle; -pub mod ioctl; -pub mod poll; pub mod ramfs; -pub mod stat; pub mod stdio; pub mod utils; -pub mod vfs_inode; diff --git a/src/services/libs/jinux-std/src/fs/ramfs/fs.rs b/src/services/libs/jinux-std/src/fs/ramfs/fs.rs index cd4d6d69..52918948 100644 --- a/src/services/libs/jinux-std/src/fs/ramfs/fs.rs +++ b/src/services/libs/jinux-std/src/fs/ramfs/fs.rs @@ -7,9 +7,8 @@ use jinux_frame::vm::VmFrame; use spin::{RwLock, RwLockWriteGuard}; use super::*; -use crate::fs::ioctl::IoctlCmd; use crate::fs::utils::{ - DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, Metadata, SuperBlock, + DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock, }; pub struct RamFS { diff --git a/src/services/libs/jinux-std/src/fs/stdio.rs b/src/services/libs/jinux-std/src/fs/stdio.rs index 6538c201..3bcfa739 100644 --- a/src/services/libs/jinux-std/src/fs/stdio.rs +++ b/src/services/libs/jinux-std/src/fs/stdio.rs @@ -1,8 +1,9 @@ -use super::events::IoEvents; use crate::prelude::*; use crate::tty::{get_n_tty, Tty}; -use super::file::{File, FileDescripter}; +use super::file_handle::File; +use super::file_table::FileDescripter; +use super::utils::IoEvents; pub const FD_STDIN: FileDescripter = 0; pub const FD_STDOUT: FileDescripter = 1; @@ -37,7 +38,7 @@ impl File for Stdin { } } - fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result { + fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result { if let Some(console) = self.console.as_ref() { console.ioctl(cmd, arg) } else { @@ -46,7 +47,7 @@ impl File for Stdin { } } impl File for Stdout { - fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result { + fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result { if let Some(console) = self.console.as_ref() { console.ioctl(cmd, arg) } else { @@ -64,7 +65,7 @@ impl File for Stdout { } impl File for Stderr { - fn ioctl(&self, cmd: super::ioctl::IoctlCmd, arg: usize) -> Result { + fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result { if let Some(console) = self.console.as_ref() { console.ioctl(cmd, arg) } else { diff --git a/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs b/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs index 412241a2..b0839b2b 100644 --- a/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs +++ b/src/services/libs/jinux-std/src/fs/utils/dentry_cache.rs @@ -1,12 +1,11 @@ use crate::prelude::*; use alloc::string::String; -use super::{InodeMode, InodeType, NAME_MAX}; -use crate::fs::vfs_inode::VfsInode; +use super::{InodeMode, InodeType, Vnode, NAME_MAX}; pub struct Dentry { inner: RwLock, - inode: VfsInode, + vnode: Vnode, } struct Dentry_ { @@ -29,16 +28,16 @@ impl Dentry_ { impl Dentry { /// Create a new dentry cache with root inode - pub fn new_root(inode: VfsInode) -> Arc { - let root = Self::new("/", inode, None); + pub fn new_root(root_vnode: Vnode) -> Arc { + let root = Self::new("/", root_vnode, None); root } /// Internal constructor - fn new(name: &str, inode: VfsInode, parent: Option>) -> Arc { + fn new(name: &str, vnode: Vnode, parent: Option>) -> Arc { let dentry = { let inner = RwLock::new(Dentry_::new(name, parent)); - Arc::new(Self { inner, inode }) + Arc::new(Self { inner, vnode }) }; dentry.inner.write().this = Arc::downgrade(&dentry); dentry @@ -48,20 +47,6 @@ impl Dentry { self.inner.read().name.clone() } - pub fn inode(&self) -> &VfsInode { - &self.inode - } - - pub fn create_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { - let mut inner = self.inner.write(); - let child = { - let inode = VfsInode::new(self.inode().raw_inode().mknod(name, type_, mode)?)?; - Dentry::new(name, inode, Some(inner.this.clone())) - }; - inner.children.insert(String::from(name), child.clone()); - Ok(child) - } - fn this(&self) -> Arc { self.inner.read().this.upgrade().unwrap() } @@ -74,8 +59,22 @@ impl Dentry { .map(|p| p.upgrade().unwrap()) } - pub fn get(&self, name: &str) -> Result> { - if self.inode.raw_inode().metadata().type_ != InodeType::Dir { + pub fn vnode(&self) -> &Vnode { + &self.vnode + } + + pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result> { + let mut inner = self.inner.write(); + let child = { + let vnode = Vnode::new(self.vnode.inode().mknod(name, type_, mode)?)?; + Dentry::new(name, vnode, Some(inner.this.clone())) + }; + inner.children.insert(String::from(name), child.clone()); + Ok(child) + } + + pub fn lookup(&self, name: &str) -> Result> { + if self.vnode.inode().metadata().type_ != InodeType::Dir { return_errno!(Errno::ENOTDIR); } if name.len() > NAME_MAX { @@ -90,8 +89,8 @@ impl Dentry { if let Some(dentry) = inner.children.get(name) { dentry.clone() } else { - let inode = VfsInode::new(self.inode.raw_inode().lookup(name)?)?; - let dentry = Dentry::new(name, inode, Some(inner.this.clone())); + let vnode = Vnode::new(self.vnode.inode().lookup(name)?)?; + let dentry = Dentry::new(name, vnode, Some(inner.this.clone())); inner.children.insert(String::from(name), dentry.clone()); dentry } diff --git a/src/services/libs/jinux-std/src/fs/events.rs b/src/services/libs/jinux-std/src/fs/utils/events.rs similarity index 100% rename from src/services/libs/jinux-std/src/fs/events.rs rename to src/services/libs/jinux-std/src/fs/utils/events.rs diff --git a/src/services/libs/jinux-std/src/fs/fcntl.rs b/src/services/libs/jinux-std/src/fs/utils/fcntl.rs similarity index 100% rename from src/services/libs/jinux-std/src/fs/fcntl.rs rename to src/services/libs/jinux-std/src/fs/utils/fcntl.rs diff --git a/src/services/libs/jinux-std/src/fs/utils/inode.rs b/src/services/libs/jinux-std/src/fs/utils/inode.rs index d3ac45c2..faf5ee80 100644 --- a/src/services/libs/jinux-std/src/fs/utils/inode.rs +++ b/src/services/libs/jinux-std/src/fs/utils/inode.rs @@ -4,8 +4,7 @@ use bitflags::bitflags; use core::any::Any; use jinux_frame::vm::VmFrame; -use super::{DirentWriterContext, FileSystem}; -use crate::fs::ioctl::IoctlCmd; +use super::{DirentWriterContext, FileSystem, IoctlCmd}; use crate::prelude::*; #[repr(u32)] diff --git a/src/services/libs/jinux-std/src/fs/ioctl/mod.rs b/src/services/libs/jinux-std/src/fs/utils/ioctl.rs similarity index 100% rename from src/services/libs/jinux-std/src/fs/ioctl/mod.rs rename to src/services/libs/jinux-std/src/fs/utils/ioctl.rs diff --git a/src/services/libs/jinux-std/src/fs/utils/mod.rs b/src/services/libs/jinux-std/src/fs/utils/mod.rs index bf6cb42a..99461d92 100644 --- a/src/services/libs/jinux-std/src/fs/utils/mod.rs +++ b/src/services/libs/jinux-std/src/fs/utils/mod.rs @@ -4,19 +4,31 @@ pub use access_mode::AccessMode; pub use creation_flags::CreationFlags; pub use dentry_cache::Dentry; pub use dirent_writer::{DirentWriter, DirentWriterContext}; +pub use events::IoEvents; +pub use fcntl::FcntlCmd; pub use fs::{FileSystem, SuperBlock}; pub use inode::{Inode, InodeMode, InodeType, Metadata, Timespec}; +pub use ioctl::IoctlCmd; pub use page_cache::PageCacheManager; +pub use poll::{c_nfds, c_pollfd, PollFd}; +pub use stat::Stat; pub use status_flags::StatusFlags; +pub use vnode::Vnode; mod access_mode; mod creation_flags; mod dentry_cache; mod dirent_writer; +mod events; +mod fcntl; mod fs; mod inode; +mod ioctl; mod page_cache; +mod poll; +mod stat; mod status_flags; +mod vnode; #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum SeekFrom { diff --git a/src/services/libs/jinux-std/src/fs/poll.rs b/src/services/libs/jinux-std/src/fs/utils/poll.rs similarity index 93% rename from src/services/libs/jinux-std/src/fs/poll.rs rename to src/services/libs/jinux-std/src/fs/utils/poll.rs index 8f64fa61..9c99d45b 100644 --- a/src/services/libs/jinux-std/src/fs/poll.rs +++ b/src/services/libs/jinux-std/src/fs/utils/poll.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] -use super::events::IoEvents; -use super::file::FileDescripter; +use super::IoEvents; +use crate::fs::file_table::FileDescripter; pub type c_nfds = u64; // https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h diff --git a/src/services/libs/jinux-std/src/fs/stat.rs b/src/services/libs/jinux-std/src/fs/utils/stat.rs similarity index 100% rename from src/services/libs/jinux-std/src/fs/stat.rs rename to src/services/libs/jinux-std/src/fs/utils/stat.rs diff --git a/src/services/libs/jinux-std/src/fs/utils/vnode.rs b/src/services/libs/jinux-std/src/fs/utils/vnode.rs new file mode 100644 index 00000000..29494edb --- /dev/null +++ b/src/services/libs/jinux-std/src/fs/utils/vnode.rs @@ -0,0 +1,31 @@ +use crate::prelude::*; + +use super::{Inode, PageCacheManager}; +use crate::rights::Rights; +use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions}; + +/// VFS-level representation of an inode +#[derive(Clone)] +pub struct Vnode { + inode: Arc, + pages: Vmo, +} + +impl Vnode { + pub fn new(inode: Arc) -> Result { + let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode))); + let pages = VmoOptions::::new(inode.metadata().size) + .flags(VmoFlags::RESIZABLE) + .pager(page_cache_manager) + .alloc()?; + Ok(Self { inode, pages }) + } + + pub fn pages(&self) -> &Vmo { + &self.pages + } + + pub fn inode(&self) -> &Arc { + &self.inode + } +} diff --git a/src/services/libs/jinux-std/src/fs/vfs_inode.rs b/src/services/libs/jinux-std/src/fs/vfs_inode.rs deleted file mode 100644 index 7618d71e..00000000 --- a/src/services/libs/jinux-std/src/fs/vfs_inode.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::prelude::*; - -use super::utils::{Inode, PageCacheManager}; -use crate::rights::Rights; -use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions}; - -#[derive(Clone)] -pub struct VfsInode { - raw_inode: Arc, - pages: Vmo, -} - -impl VfsInode { - pub fn new(raw_inode: Arc) -> Result { - let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&raw_inode))); - let pages = VmoOptions::::new(raw_inode.metadata().size) - .flags(VmoFlags::RESIZABLE) - .pager(page_cache_manager) - .alloc()?; - Ok(Self { raw_inode, pages }) - } - - pub fn pages(&self) -> &Vmo { - &self.pages - } - - pub fn raw_inode(&self) -> &Arc { - &self.raw_inode - } -} diff --git a/src/services/libs/jinux-std/src/process/clone.rs b/src/services/libs/jinux-std/src/process/clone.rs index 3171990a..7041a134 100644 --- a/src/services/libs/jinux-std/src/process/clone.rs +++ b/src/services/libs/jinux-std/src/process/clone.rs @@ -7,6 +7,7 @@ use jinux_frame::{ use crate::{ current_thread, fs::file_table::FileTable, + fs::fs_resolver::FsResolver, prelude::*, process::{ posix_thread::{ @@ -209,6 +210,8 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res // clone file table let child_file_table = clone_files(current.file_table(), clone_flags); + // clone fs + let child_fs = clone_fs(current.fs(), clone_flags); // clone sig dispositions let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags); // clone system V semaphore @@ -240,6 +243,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res child_root_vmar.clone(), Weak::new(), child_file_table, + child_fs, child_sig_dispositions, ) }); @@ -337,11 +341,15 @@ fn clone_cpu_context( child_context } -fn clone_fs(clone_flags: CloneFlags) -> Result<()> { +fn clone_fs( + parent_fs: &Arc>, + clone_flags: CloneFlags, +) -> Arc> { if clone_flags.contains(CloneFlags::CLONE_FS) { - warn!("CLONE_FS is not supported now") + parent_fs.clone() + } else { + Arc::new(RwLock::new(parent_fs.read().clone())) } - Ok(()) } fn clone_files( diff --git a/src/services/libs/jinux-std/src/process/mod.rs b/src/services/libs/jinux-std/src/process/mod.rs index ddcc52e0..1c07324d 100644 --- a/src/services/libs/jinux-std/src/process/mod.rs +++ b/src/services/libs/jinux-std/src/process/mod.rs @@ -11,6 +11,7 @@ use self::signal::sig_queues::SigQueues; use self::signal::signals::kernel::KernelSignal; use self::status::ProcessStatus; use crate::fs::file_table::FileTable; +use crate::fs::fs_resolver::FsResolver; use crate::prelude::*; use crate::rights::Full; use crate::thread::kernel_thread::KernelThreadExt; @@ -65,6 +66,8 @@ pub struct Process { process_group: Mutex>, /// File table file_table: Arc>, + /// FsResolver + fs: Arc>, /// resource limits resource_limits: Mutex, @@ -99,6 +102,7 @@ impl Process { root_vmar: Arc>, process_group: Weak, file_table: Arc>, + fs: Arc>, sig_dispositions: Arc>, ) -> Self { let parent = if pid == 0 { @@ -125,6 +129,7 @@ impl Process { children: Mutex::new(children), process_group: Mutex::new(process_group), file_table, + fs, sig_dispositions, sig_queues: Mutex::new(SigQueues::new()), resource_limits: Mutex::new(resource_limits), @@ -191,6 +196,7 @@ impl Process { let pid = thread.tid(); let user_vm = UserVm::new(); let file_table = FileTable::new_with_stdio(); + let fs = FsResolver::new().unwrap(); let sig_dispositions = SigDispositions::new(); let process = Process::new( @@ -201,6 +207,7 @@ impl Process { Arc::new(root_vmar), Weak::new(), Arc::new(Mutex::new(file_table)), + Arc::new(RwLock::new(fs)), Arc::new(Mutex::new(sig_dispositions)), ); process @@ -224,6 +231,7 @@ impl Process { let thread = Thread::new_kernel_thread(task_fn, weak_process_ref.clone()); let pid = thread.tid(); let file_table = FileTable::new(); + let fs = FsResolver::new().unwrap(); let sig_dispositions = SigDispositions::new(); // FIXME: kernel process does not need root vmar let root_vmar = Vmar::::new_root().unwrap(); @@ -235,6 +243,7 @@ impl Process { Arc::new(root_vmar), Weak::new(), Arc::new(Mutex::new(file_table)), + Arc::new(RwLock::new(fs)), Arc::new(Mutex::new(sig_dispositions)), ) }); @@ -287,6 +296,10 @@ impl Process { &self.file_table } + pub fn fs(&self) -> &Arc> { + &self.fs + } + /// create a new process group for the process and add it to globle table. /// Then set the process group for current process. fn create_and_set_process_group(self: &Arc) { diff --git a/src/services/libs/jinux-std/src/syscall/close.rs b/src/services/libs/jinux-std/src/syscall/close.rs index 9b9c81f5..3e3ca756 100644 --- a/src/services/libs/jinux-std/src/syscall/close.rs +++ b/src/services/libs/jinux-std/src/syscall/close.rs @@ -1,7 +1,7 @@ use super::SyscallReturn; use super::SYS_CLOSE; use crate::log_syscall_entry; -use crate::{fs::file::FileDescripter, prelude::*}; +use crate::{fs::file_table::FileDescripter, prelude::*}; pub fn sys_close(fd: FileDescripter) -> Result { log_syscall_entry!(SYS_CLOSE); diff --git a/src/services/libs/jinux-std/src/syscall/fcntl.rs b/src/services/libs/jinux-std/src/syscall/fcntl.rs index a82f0ec1..835081bf 100644 --- a/src/services/libs/jinux-std/src/syscall/fcntl.rs +++ b/src/services/libs/jinux-std/src/syscall/fcntl.rs @@ -1,7 +1,7 @@ use super::{SyscallReturn, SYS_FCNTL}; -use crate::fs::fcntl::FcntlCmd; +use crate::fs::utils::FcntlCmd; use crate::log_syscall_entry; -use crate::{fs::file::FileDescripter, prelude::*}; +use crate::{fs::file_table::FileDescripter, prelude::*}; pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result { log_syscall_entry!(SYS_FCNTL); diff --git a/src/services/libs/jinux-std/src/syscall/fstat.rs b/src/services/libs/jinux-std/src/syscall/fstat.rs index dece7b80..f61bf144 100644 --- a/src/services/libs/jinux-std/src/syscall/fstat.rs +++ b/src/services/libs/jinux-std/src/syscall/fstat.rs @@ -1,6 +1,6 @@ use jinux_frame::vm::VmIo; -use crate::fs::stat::Stat; +use crate::fs::utils::Stat; use crate::{log_syscall_entry, prelude::*}; use crate::syscall::{SyscallReturn, SYS_FSTAT}; diff --git a/src/services/libs/jinux-std/src/syscall/ioctl.rs b/src/services/libs/jinux-std/src/syscall/ioctl.rs index 67be4ece..61219a67 100644 --- a/src/services/libs/jinux-std/src/syscall/ioctl.rs +++ b/src/services/libs/jinux-std/src/syscall/ioctl.rs @@ -1,5 +1,5 @@ -use crate::fs::file::FileDescripter; -use crate::fs::ioctl::IoctlCmd; +use crate::fs::file_table::FileDescripter; +use crate::fs::utils::IoctlCmd; use crate::log_syscall_entry; use crate::prelude::*; diff --git a/src/services/libs/jinux-std/src/syscall/lseek.rs b/src/services/libs/jinux-std/src/syscall/lseek.rs index 5adfb2e4..6cf8b897 100644 --- a/src/services/libs/jinux-std/src/syscall/lseek.rs +++ b/src/services/libs/jinux-std/src/syscall/lseek.rs @@ -1,5 +1,5 @@ use crate::log_syscall_entry; -use crate::{fs::file::FileDescripter, prelude::*}; +use crate::{fs::file_table::FileDescripter, prelude::*}; use super::SyscallReturn; use super::SYS_LSEEK; diff --git a/src/services/libs/jinux-std/src/syscall/lstat.rs b/src/services/libs/jinux-std/src/syscall/lstat.rs index 0b226d75..c8bdf9ef 100644 --- a/src/services/libs/jinux-std/src/syscall/lstat.rs +++ b/src/services/libs/jinux-std/src/syscall/lstat.rs @@ -1,4 +1,4 @@ -use crate::fs::stat::Stat; +use crate::fs::utils::Stat; use crate::log_syscall_entry; use crate::prelude::*; use crate::syscall::constants::MAX_FILENAME_LEN; diff --git a/src/services/libs/jinux-std/src/syscall/mmap.rs b/src/services/libs/jinux-std/src/syscall/mmap.rs index 374b06ba..00ff3963 100644 --- a/src/services/libs/jinux-std/src/syscall/mmap.rs +++ b/src/services/libs/jinux-std/src/syscall/mmap.rs @@ -1,6 +1,6 @@ //! This mod defines mmap flags and the handler to syscall mmap -use crate::fs::file::FileDescripter; +use crate::fs::file_table::FileDescripter; use crate::process::process_vm::mmap_flags::MMapFlags; use crate::rights::Rights; use crate::vm::perms::VmPerms; diff --git a/src/services/libs/jinux-std/src/syscall/openat.rs b/src/services/libs/jinux-std/src/syscall/openat.rs index 299ce271..0f63238f 100644 --- a/src/services/libs/jinux-std/src/syscall/openat.rs +++ b/src/services/libs/jinux-std/src/syscall/openat.rs @@ -1,6 +1,8 @@ -use crate::fs::file::File; -use crate::fs::file::FileDescripter; -use crate::fs::file_handle::FileHandle; +use crate::fs::{ + file_handle::{File, FileHandle}, + file_table::FileDescripter, + fs_resolver::{FsPath, AT_FDCWD}, +}; use crate::log_syscall_entry; use crate::prelude::*; use crate::syscall::constants::MAX_FILENAME_LEN; @@ -10,12 +12,10 @@ use crate::util::read_cstring_from_user; use super::SyscallReturn; use super::SYS_OPENAT; -const AT_FDCWD: FileDescripter = -100; - pub fn sys_openat( dirfd: FileDescripter, pathname_addr: Vaddr, - flags: i32, + flags: u32, mode: u16, ) -> Result { log_syscall_entry!(SYS_OPENAT); @@ -53,7 +53,18 @@ pub fn sys_openat( let fd = file_table.insert(tty_file); return Ok(SyscallReturn::Return(fd as _)); } - todo!() + + // The common path + let current = current!(); + let file_handle = { + let pathname = pathname.to_string_lossy(); + let fs_path = FsPath::new(dirfd, pathname.as_ref())?; + let inode_handle = current.fs().read().open(&fs_path, flags, mode)?; + FileHandle::new_inode_handle(inode_handle) + }; + let mut file_table = current.file_table().lock(); + let fd = file_table.insert(file_handle); + Ok(SyscallReturn::Return(fd as _)) } /// File for output busybox ash log. diff --git a/src/services/libs/jinux-std/src/syscall/poll.rs b/src/services/libs/jinux-std/src/syscall/poll.rs index 77bd2a8c..15096c6c 100644 --- a/src/services/libs/jinux-std/src/syscall/poll.rs +++ b/src/services/libs/jinux-std/src/syscall/poll.rs @@ -1,9 +1,9 @@ use core::time::Duration; -use crate::fs::poll::{c_pollfd, PollFd}; +use crate::fs::utils::{c_pollfd, PollFd}; use crate::log_syscall_entry; use crate::util::{read_val_from_user, write_val_to_user}; -use crate::{fs::poll::c_nfds, prelude::*}; +use crate::{fs::utils::c_nfds, prelude::*}; use super::SyscallReturn; use super::SYS_POLL; diff --git a/src/services/libs/jinux-std/src/syscall/read.rs b/src/services/libs/jinux-std/src/syscall/read.rs index ee98fa58..5a37e1f8 100644 --- a/src/services/libs/jinux-std/src/syscall/read.rs +++ b/src/services/libs/jinux-std/src/syscall/read.rs @@ -1,6 +1,6 @@ use crate::log_syscall_entry; use crate::util::write_bytes_to_user; -use crate::{fs::file::FileDescripter, prelude::*}; +use crate::{fs::file_table::FileDescripter, prelude::*}; use super::SyscallReturn; use super::SYS_READ; diff --git a/src/services/libs/jinux-std/src/syscall/write.rs b/src/services/libs/jinux-std/src/syscall/write.rs index 2472ce40..d1ffcb57 100644 --- a/src/services/libs/jinux-std/src/syscall/write.rs +++ b/src/services/libs/jinux-std/src/syscall/write.rs @@ -1,4 +1,4 @@ -use crate::fs::file::FileDescripter; +use crate::fs::file_table::FileDescripter; use crate::{log_syscall_entry, prelude::*}; use crate::syscall::SYS_WRITE; diff --git a/src/services/libs/jinux-std/src/tty/line_discipline.rs b/src/services/libs/jinux-std/src/tty/line_discipline.rs index 4a62ae51..e632e6f3 100644 --- a/src/services/libs/jinux-std/src/tty/line_discipline.rs +++ b/src/services/libs/jinux-std/src/tty/line_discipline.rs @@ -1,4 +1,4 @@ -use crate::fs::events::IoEvents; +use crate::fs::utils::IoEvents; use crate::process::signal::constants::{SIGINT, SIGQUIT}; use crate::{ prelude::*, diff --git a/src/services/libs/jinux-std/src/tty/mod.rs b/src/services/libs/jinux-std/src/tty/mod.rs index 6c30e0fc..0f9b4789 100644 --- a/src/services/libs/jinux-std/src/tty/mod.rs +++ b/src/services/libs/jinux-std/src/tty/mod.rs @@ -1,11 +1,12 @@ use self::line_discipline::LineDiscipline; use crate::driver::tty::TtyDriver; -use crate::fs::events::IoEvents; - -use crate::fs::ioctl::IoctlCmd; +use crate::fs::{ + file_handle::File, + utils::{IoEvents, IoctlCmd}, +}; +use crate::prelude::*; use crate::process::{process_table, Pgid}; use crate::util::{read_val_from_user, write_val_to_user}; -use crate::{fs::file::File, prelude::*}; pub mod line_discipline; pub mod termio;