mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Merge pull request #71 from liqinggd/dev-fs-impl
Enhance the fs code in std
This commit is contained in:
commit
551406b9f4
@ -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 {
|
@ -1,5 +1,4 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::rights::{Rights, TRights};
|
||||
|
||||
use super::*;
|
||||
@ -10,7 +9,7 @@ impl InodeHandle<Rights> {
|
||||
access_mode: AccessMode,
|
||||
status_flags: StatusFlags,
|
||||
) -> Result<Self> {
|
||||
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");
|
||||
}
|
@ -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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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)
|
||||
}
|
@ -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 {
|
@ -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<FileDescripter, FileHandle>,
|
||||
|
@ -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<dyn FileSystem> = RamFS::new();
|
||||
@ -32,8 +31,8 @@ impl Clone for FsResolver {
|
||||
impl FsResolver {
|
||||
pub fn new() -> Result<Self> {
|
||||
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<Arc<Dentry>> {
|
||||
/// Lookup dentry according to FsPath, always follow symlinks
|
||||
pub fn lookup(&self, path: &FsPath) -> Result<Arc<Dentry>> {
|
||||
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<Arc<Dentry>> {
|
||||
self.lookup_inner(path, false)
|
||||
}
|
||||
|
||||
fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> {
|
||||
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<Dentry>, 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<Arc<Dentry>> {
|
||||
fn lookup_from_fd(&self, fd: FileDescripter) -> Result<Arc<Dentry>> {
|
||||
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<Dentry>, 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<Dentry>, 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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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<i32> {
|
||||
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
|
||||
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<i32> {
|
||||
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
|
||||
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<i32> {
|
||||
fn ioctl(&self, cmd: super::utils::IoctlCmd, arg: usize) -> Result<i32> {
|
||||
if let Some(console) = self.console.as_ref() {
|
||||
console.ioctl(cmd, arg)
|
||||
} else {
|
||||
|
@ -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<Dentry_>,
|
||||
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<Self> {
|
||||
let root = Self::new("/", inode, None);
|
||||
pub fn new_root(root_vnode: Vnode) -> Arc<Self> {
|
||||
let root = Self::new("/", root_vnode, None);
|
||||
root
|
||||
}
|
||||
|
||||
/// Internal constructor
|
||||
fn new(name: &str, inode: VfsInode, parent: Option<Weak<Dentry>>) -> Arc<Self> {
|
||||
fn new(name: &str, vnode: Vnode, parent: Option<Weak<Dentry>>) -> Arc<Self> {
|
||||
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<Arc<Self>> {
|
||||
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<Dentry> {
|
||||
self.inner.read().this.upgrade().unwrap()
|
||||
}
|
||||
@ -74,8 +59,22 @@ impl Dentry {
|
||||
.map(|p| p.upgrade().unwrap())
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Result<Arc<Dentry>> {
|
||||
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<Arc<Self>> {
|
||||
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<Arc<Dentry>> {
|
||||
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
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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
|
31
src/services/libs/jinux-std/src/fs/utils/vnode.rs
Normal file
31
src/services/libs/jinux-std/src/fs/utils/vnode.rs
Normal file
@ -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<dyn Inode>,
|
||||
pages: Vmo,
|
||||
}
|
||||
|
||||
impl Vnode {
|
||||
pub fn new(inode: Arc<dyn Inode>) -> Result<Self> {
|
||||
let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&inode)));
|
||||
let pages = VmoOptions::<Rights>::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<dyn Inode> {
|
||||
&self.inode
|
||||
}
|
||||
}
|
@ -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<dyn Inode>,
|
||||
pages: Vmo,
|
||||
}
|
||||
|
||||
impl VfsInode {
|
||||
pub fn new(raw_inode: Arc<dyn Inode>) -> Result<Self> {
|
||||
let page_cache_manager = Arc::new(PageCacheManager::new(&Arc::downgrade(&raw_inode)));
|
||||
let pages = VmoOptions::<Rights>::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<dyn Inode> {
|
||||
&self.raw_inode
|
||||
}
|
||||
}
|
@ -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<RwLock<FsResolver>>,
|
||||
clone_flags: CloneFlags,
|
||||
) -> Arc<RwLock<FsResolver>> {
|
||||
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(
|
||||
|
@ -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<Weak<ProcessGroup>>,
|
||||
/// File table
|
||||
file_table: Arc<Mutex<FileTable>>,
|
||||
/// FsResolver
|
||||
fs: Arc<RwLock<FsResolver>>,
|
||||
/// resource limits
|
||||
resource_limits: Mutex<ResourceLimits>,
|
||||
|
||||
@ -99,6 +102,7 @@ impl Process {
|
||||
root_vmar: Arc<Vmar<Full>>,
|
||||
process_group: Weak<ProcessGroup>,
|
||||
file_table: Arc<Mutex<FileTable>>,
|
||||
fs: Arc<RwLock<FsResolver>>,
|
||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||
) -> 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::<Full>::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<RwLock<FsResolver>> {
|
||||
&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<Self>) {
|
||||
|
@ -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<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_CLOSE);
|
||||
|
@ -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<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_FCNTL);
|
||||
|
@ -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};
|
||||
|
@ -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::*;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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<SyscallReturn> {
|
||||
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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::fs::events::IoEvents;
|
||||
use crate::fs::utils::IoEvents;
|
||||
use crate::process::signal::constants::{SIGINT, SIGQUIT};
|
||||
use crate::{
|
||||
prelude::*,
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user