mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-15 16:26: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 crate::tty::get_n_tty;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
|
|
||||||
use super::events::IoEvents;
|
use crate::fs::utils::{IoEvents, IoctlCmd};
|
||||||
use super::ioctl::IoctlCmd;
|
|
||||||
|
|
||||||
pub type FileDescripter = i32;
|
|
||||||
|
|
||||||
/// The basic operations defined on a file
|
/// The basic operations defined on a file
|
||||||
pub trait File: Send + Sync + Any {
|
pub trait File: Send + Sync + Any {
|
@ -1,5 +1,4 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::rights::{Rights, TRights};
|
use crate::rights::{Rights, TRights};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -10,7 +9,7 @@ impl InodeHandle<Rights> {
|
|||||||
access_mode: AccessMode,
|
access_mode: AccessMode,
|
||||||
status_flags: StatusFlags,
|
status_flags: StatusFlags,
|
||||||
) -> Result<Self> {
|
) -> 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() {
|
if access_mode.is_readable() && !inode_info.mode.is_readable() {
|
||||||
return_errno_with_message!(Errno::EACCES, "File is not 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 dyn_cap;
|
||||||
mod static_cap;
|
mod static_cap;
|
||||||
|
|
||||||
use super::utils::{
|
use crate::fs::utils::{
|
||||||
AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags,
|
AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags,
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@ -23,17 +23,17 @@ struct InodeHandle_ {
|
|||||||
impl InodeHandle_ {
|
impl InodeHandle_ {
|
||||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
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 start = file_size.min(*offset);
|
||||||
let end = file_size.min(*offset + buf.len());
|
let end = file_size.min(*offset + buf.len());
|
||||||
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentry
|
self.dentry
|
||||||
|
.vnode()
|
||||||
.inode()
|
.inode()
|
||||||
.raw_inode()
|
|
||||||
.read_at(start, &mut buf[0..end - start])?
|
.read_at(start, &mut buf[0..end - start])?
|
||||||
} else {
|
} else {
|
||||||
self.dentry
|
self.dentry
|
||||||
.inode()
|
.vnode()
|
||||||
.pages()
|
.pages()
|
||||||
.read_bytes(start, &mut buf[0..end - start])?;
|
.read_bytes(start, &mut buf[0..end - start])?;
|
||||||
end - start
|
end - start
|
||||||
@ -45,24 +45,21 @@ impl InodeHandle_ {
|
|||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
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) {
|
if self.status_flags.lock().contains(StatusFlags::O_APPEND) {
|
||||||
*offset = file_size;
|
*offset = file_size;
|
||||||
}
|
}
|
||||||
let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) {
|
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 {
|
} else {
|
||||||
let pages = self.dentry.inode().pages();
|
let pages = self.dentry.vnode().pages();
|
||||||
let should_expand_size = *offset + buf.len() > file_size;
|
let should_expand_size = *offset + buf.len() > file_size;
|
||||||
if should_expand_size {
|
if should_expand_size {
|
||||||
pages.resize(*offset + buf.len())?;
|
pages.resize(*offset + buf.len())?;
|
||||||
}
|
}
|
||||||
pages.write_bytes(*offset, buf)?;
|
pages.write_bytes(*offset, buf)?;
|
||||||
if should_expand_size {
|
if should_expand_size {
|
||||||
self.dentry
|
self.dentry.vnode().inode().resize(*offset + buf.len())?;
|
||||||
.inode()
|
|
||||||
.raw_inode()
|
|
||||||
.resize(*offset + buf.len())?;
|
|
||||||
}
|
}
|
||||||
buf.len()
|
buf.len()
|
||||||
};
|
};
|
||||||
@ -81,7 +78,7 @@ impl InodeHandle_ {
|
|||||||
off as i64
|
off as i64
|
||||||
}
|
}
|
||||||
SeekFrom::End(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);
|
assert!(file_size >= 0);
|
||||||
file_size
|
file_size
|
||||||
.checked_add(off)
|
.checked_add(off)
|
||||||
@ -128,11 +125,7 @@ impl InodeHandle_ {
|
|||||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
let mut offset = self.offset.lock();
|
||||||
let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer);
|
let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer);
|
||||||
let written_size = self
|
let written_size = self.dentry.vnode().inode().readdir(&mut dir_writer_ctx)?;
|
||||||
.dentry
|
|
||||||
.inode()
|
|
||||||
.raw_inode()
|
|
||||||
.readdir(&mut dir_writer_ctx)?;
|
|
||||||
*offset = dir_writer_ctx.pos();
|
*offset = dir_writer_ctx.pos();
|
||||||
Ok(written_size)
|
Ok(written_size)
|
||||||
}
|
}
|
@ -1,9 +1,14 @@
|
|||||||
|
//! Opend File Handle
|
||||||
|
|
||||||
|
mod file;
|
||||||
|
mod inode_handle;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::{ReadOp, WriteOp};
|
use crate::rights::{ReadOp, WriteOp};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
use super::file::File;
|
pub use self::file::File;
|
||||||
use super::inode_handle::InodeHandle;
|
pub use self::inode_handle::InodeHandle;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FileHandle {
|
pub struct FileHandle {
|
@ -1,11 +1,12 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
file::FileDescripter,
|
|
||||||
file_handle::FileHandle,
|
file_handle::FileHandle,
|
||||||
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
stdio::{Stderr, Stdin, Stdout, FD_STDERR, FD_STDIN, FD_STDOUT},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub type FileDescripter = i32;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FileTable {
|
pub struct FileTable {
|
||||||
table: BTreeMap<FileDescripter, FileHandle>,
|
table: BTreeMap<FileDescripter, FileHandle>,
|
||||||
|
@ -2,14 +2,13 @@ use crate::prelude::*;
|
|||||||
use alloc::str;
|
use alloc::str;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
|
||||||
use super::file::FileDescripter;
|
use super::file_handle::InodeHandle;
|
||||||
use super::inode_handle::InodeHandle;
|
use super::file_table::FileDescripter;
|
||||||
use super::ramfs::RamFS;
|
use super::ramfs::RamFS;
|
||||||
use super::utils::{
|
use super::utils::{
|
||||||
AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, PATH_MAX,
|
AccessMode, CreationFlags, Dentry, FileSystem, InodeMode, InodeType, StatusFlags, Vnode,
|
||||||
SYMLINKS_MAX,
|
PATH_MAX, SYMLINKS_MAX,
|
||||||
};
|
};
|
||||||
use super::vfs_inode::VfsInode;
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref ROOT_FS: Arc<dyn FileSystem> = RamFS::new();
|
static ref ROOT_FS: Arc<dyn FileSystem> = RamFS::new();
|
||||||
@ -32,8 +31,8 @@ impl Clone for FsResolver {
|
|||||||
impl FsResolver {
|
impl FsResolver {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let root = {
|
let root = {
|
||||||
let root_inode = VfsInode::new(ROOT_FS.root_inode())?;
|
let root_vnode = Vnode::new(ROOT_FS.root_inode())?;
|
||||||
Dentry::new_root(root_inode)
|
Dentry::new_root(root_vnode)
|
||||||
};
|
};
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
root: root.clone(),
|
root: root.clone(),
|
||||||
@ -64,9 +63,9 @@ impl FsResolver {
|
|||||||
let inode_mode = InodeMode::from_bits_truncate(mode);
|
let inode_mode = InodeMode::from_bits_truncate(mode);
|
||||||
|
|
||||||
let follow_tail_link = !creation_flags.contains(CreationFlags::O_NOFOLLOW);
|
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) => {
|
Ok(dentry) => {
|
||||||
let inode = dentry.inode().raw_inode();
|
let inode = dentry.vnode().inode();
|
||||||
if inode.metadata().type_ == InodeType::SymLink
|
if inode.metadata().type_ == InodeType::SymLink
|
||||||
&& !status_flags.contains(StatusFlags::O_PATH)
|
&& !status_flags.contains(StatusFlags::O_PATH)
|
||||||
{
|
{
|
||||||
@ -94,15 +93,15 @@ impl FsResolver {
|
|||||||
if creation_flags.contains(CreationFlags::O_DIRECTORY) {
|
if creation_flags.contains(CreationFlags::O_DIRECTORY) {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "cannot create 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("/") {
|
if file_name.ends_with("/") {
|
||||||
return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
|
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");
|
return_errno_with_message!(Errno::EPERM, "file cannot be created");
|
||||||
}
|
}
|
||||||
let new_dentry =
|
let new_dentry = dir_dentry.create(&file_name, InodeType::File, inode_mode)?;
|
||||||
dir_dentry.create_child(&file_name, InodeType::File, inode_mode)?;
|
|
||||||
new_dentry
|
new_dentry
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
@ -112,8 +111,17 @@ impl FsResolver {
|
|||||||
Ok(inode_handle)
|
Ok(inode_handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup dentry according to FsPath
|
/// Lookup dentry according to FsPath, always follow symlinks
|
||||||
pub fn lookup(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> {
|
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 {
|
let dentry = match path.inner {
|
||||||
FsPathInner::Absolute(path) => {
|
FsPathInner::Absolute(path) => {
|
||||||
self.lookup_from_parent(&self.root, path.trim_start_matches('/'), follow_tail_link)?
|
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::Cwd => self.cwd.clone(),
|
||||||
FsPathInner::FdRelative(fd, path) => {
|
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)?
|
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)
|
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
|
/// Lookup dentry from parent
|
||||||
///
|
///
|
||||||
/// The length of `path` cannot exceed PATH_MAX.
|
/// The length of `path` cannot exceed PATH_MAX.
|
||||||
@ -232,8 +180,8 @@ impl FsResolver {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Iterate next dentry
|
// Iterate next dentry
|
||||||
let next_dentry = dentry.get(next_name)?;
|
let next_dentry = dentry.lookup(next_name)?;
|
||||||
let next_type = next_dentry.inode().raw_inode().metadata().type_;
|
let next_type = next_dentry.vnode().inode().metadata().type_;
|
||||||
let next_is_tail = path_remain.is_empty();
|
let next_is_tail = path_remain.is_empty();
|
||||||
|
|
||||||
// If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times.
|
// 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");
|
return_errno_with_message!(Errno::ELOOP, "too many symlinks");
|
||||||
}
|
}
|
||||||
let link_path_remain = {
|
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() {
|
if tmp_link_path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "empty symlink");
|
return_errno_with_message!(Errno::ENOENT, "empty symlink");
|
||||||
}
|
}
|
||||||
@ -277,7 +225,7 @@ impl FsResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup dentry from the giving fd
|
/// 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 current = current!();
|
||||||
let file_table = current.file_table().lock();
|
let file_table = current.file_table().lock();
|
||||||
let inode_handle = file_table
|
let inode_handle = file_table
|
||||||
@ -286,6 +234,78 @@ impl FsResolver {
|
|||||||
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?;
|
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?;
|
||||||
Ok(inode_handle.dentry().clone())
|
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;
|
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_handle;
|
||||||
pub mod file_table;
|
pub mod file_table;
|
||||||
pub mod fs_resolver;
|
pub mod fs_resolver;
|
||||||
pub mod inode_handle;
|
|
||||||
pub mod ioctl;
|
|
||||||
pub mod poll;
|
|
||||||
pub mod ramfs;
|
pub mod ramfs;
|
||||||
pub mod stat;
|
|
||||||
pub mod stdio;
|
pub mod stdio;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod vfs_inode;
|
|
||||||
|
@ -7,9 +7,8 @@ use jinux_frame::vm::VmFrame;
|
|||||||
use spin::{RwLock, RwLockWriteGuard};
|
use spin::{RwLock, RwLockWriteGuard};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fs::ioctl::IoctlCmd;
|
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, Metadata, SuperBlock,
|
DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RamFS {
|
pub struct RamFS {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use super::events::IoEvents;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::tty::{get_n_tty, Tty};
|
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_STDIN: FileDescripter = 0;
|
||||||
pub const FD_STDOUT: FileDescripter = 1;
|
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() {
|
if let Some(console) = self.console.as_ref() {
|
||||||
console.ioctl(cmd, arg)
|
console.ioctl(cmd, arg)
|
||||||
} else {
|
} else {
|
||||||
@ -46,7 +47,7 @@ impl File for Stdin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl File for Stdout {
|
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() {
|
if let Some(console) = self.console.as_ref() {
|
||||||
console.ioctl(cmd, arg)
|
console.ioctl(cmd, arg)
|
||||||
} else {
|
} else {
|
||||||
@ -64,7 +65,7 @@ impl File for Stdout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl File for Stderr {
|
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() {
|
if let Some(console) = self.console.as_ref() {
|
||||||
console.ioctl(cmd, arg)
|
console.ioctl(cmd, arg)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
|
||||||
use super::{InodeMode, InodeType, NAME_MAX};
|
use super::{InodeMode, InodeType, Vnode, NAME_MAX};
|
||||||
use crate::fs::vfs_inode::VfsInode;
|
|
||||||
|
|
||||||
pub struct Dentry {
|
pub struct Dentry {
|
||||||
inner: RwLock<Dentry_>,
|
inner: RwLock<Dentry_>,
|
||||||
inode: VfsInode,
|
vnode: Vnode,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Dentry_ {
|
struct Dentry_ {
|
||||||
@ -29,16 +28,16 @@ impl Dentry_ {
|
|||||||
|
|
||||||
impl Dentry {
|
impl Dentry {
|
||||||
/// Create a new dentry cache with root inode
|
/// Create a new dentry cache with root inode
|
||||||
pub fn new_root(inode: VfsInode) -> Arc<Self> {
|
pub fn new_root(root_vnode: Vnode) -> Arc<Self> {
|
||||||
let root = Self::new("/", inode, None);
|
let root = Self::new("/", root_vnode, None);
|
||||||
root
|
root
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal constructor
|
/// 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 dentry = {
|
||||||
let inner = RwLock::new(Dentry_::new(name, parent));
|
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.inner.write().this = Arc::downgrade(&dentry);
|
||||||
dentry
|
dentry
|
||||||
@ -48,20 +47,6 @@ impl Dentry {
|
|||||||
self.inner.read().name.clone()
|
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> {
|
fn this(&self) -> Arc<Dentry> {
|
||||||
self.inner.read().this.upgrade().unwrap()
|
self.inner.read().this.upgrade().unwrap()
|
||||||
}
|
}
|
||||||
@ -74,8 +59,22 @@ impl Dentry {
|
|||||||
.map(|p| p.upgrade().unwrap())
|
.map(|p| p.upgrade().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, name: &str) -> Result<Arc<Dentry>> {
|
pub fn vnode(&self) -> &Vnode {
|
||||||
if self.inode.raw_inode().metadata().type_ != InodeType::Dir {
|
&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);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
@ -90,8 +89,8 @@ impl Dentry {
|
|||||||
if let Some(dentry) = inner.children.get(name) {
|
if let Some(dentry) = inner.children.get(name) {
|
||||||
dentry.clone()
|
dentry.clone()
|
||||||
} else {
|
} else {
|
||||||
let inode = VfsInode::new(self.inode.raw_inode().lookup(name)?)?;
|
let vnode = Vnode::new(self.vnode.inode().lookup(name)?)?;
|
||||||
let dentry = Dentry::new(name, inode, Some(inner.this.clone()));
|
let dentry = Dentry::new(name, vnode, Some(inner.this.clone()));
|
||||||
inner.children.insert(String::from(name), dentry.clone());
|
inner.children.insert(String::from(name), dentry.clone());
|
||||||
dentry
|
dentry
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ use bitflags::bitflags;
|
|||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
|
||||||
use super::{DirentWriterContext, FileSystem};
|
use super::{DirentWriterContext, FileSystem, IoctlCmd};
|
||||||
use crate::fs::ioctl::IoctlCmd;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
@ -4,19 +4,31 @@ pub use access_mode::AccessMode;
|
|||||||
pub use creation_flags::CreationFlags;
|
pub use creation_flags::CreationFlags;
|
||||||
pub use dentry_cache::Dentry;
|
pub use dentry_cache::Dentry;
|
||||||
pub use dirent_writer::{DirentWriter, DirentWriterContext};
|
pub use dirent_writer::{DirentWriter, DirentWriterContext};
|
||||||
|
pub use events::IoEvents;
|
||||||
|
pub use fcntl::FcntlCmd;
|
||||||
pub use fs::{FileSystem, SuperBlock};
|
pub use fs::{FileSystem, SuperBlock};
|
||||||
pub use inode::{Inode, InodeMode, InodeType, Metadata, Timespec};
|
pub use inode::{Inode, InodeMode, InodeType, Metadata, Timespec};
|
||||||
|
pub use ioctl::IoctlCmd;
|
||||||
pub use page_cache::PageCacheManager;
|
pub use page_cache::PageCacheManager;
|
||||||
|
pub use poll::{c_nfds, c_pollfd, PollFd};
|
||||||
|
pub use stat::Stat;
|
||||||
pub use status_flags::StatusFlags;
|
pub use status_flags::StatusFlags;
|
||||||
|
pub use vnode::Vnode;
|
||||||
|
|
||||||
mod access_mode;
|
mod access_mode;
|
||||||
mod creation_flags;
|
mod creation_flags;
|
||||||
mod dentry_cache;
|
mod dentry_cache;
|
||||||
mod dirent_writer;
|
mod dirent_writer;
|
||||||
|
mod events;
|
||||||
|
mod fcntl;
|
||||||
mod fs;
|
mod fs;
|
||||||
mod inode;
|
mod inode;
|
||||||
|
mod ioctl;
|
||||||
mod page_cache;
|
mod page_cache;
|
||||||
|
mod poll;
|
||||||
|
mod stat;
|
||||||
mod status_flags;
|
mod status_flags;
|
||||||
|
mod vnode;
|
||||||
|
|
||||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||||
pub enum SeekFrom {
|
pub enum SeekFrom {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
use super::events::IoEvents;
|
use super::IoEvents;
|
||||||
use super::file::FileDescripter;
|
use crate::fs::file_table::FileDescripter;
|
||||||
pub type c_nfds = u64;
|
pub type c_nfds = u64;
|
||||||
|
|
||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h
|
// 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::{
|
use crate::{
|
||||||
current_thread,
|
current_thread,
|
||||||
fs::file_table::FileTable,
|
fs::file_table::FileTable,
|
||||||
|
fs::fs_resolver::FsResolver,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{
|
process::{
|
||||||
posix_thread::{
|
posix_thread::{
|
||||||
@ -209,6 +210,8 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
|
|||||||
|
|
||||||
// clone file table
|
// clone file table
|
||||||
let child_file_table = clone_files(current.file_table(), clone_flags);
|
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
|
// clone sig dispositions
|
||||||
let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags);
|
let child_sig_dispositions = clone_sighand(current.sig_dispositions(), clone_flags);
|
||||||
// clone system V semaphore
|
// clone system V semaphore
|
||||||
@ -240,6 +243,7 @@ fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Res
|
|||||||
child_root_vmar.clone(),
|
child_root_vmar.clone(),
|
||||||
Weak::new(),
|
Weak::new(),
|
||||||
child_file_table,
|
child_file_table,
|
||||||
|
child_fs,
|
||||||
child_sig_dispositions,
|
child_sig_dispositions,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -337,11 +341,15 @@ fn clone_cpu_context(
|
|||||||
child_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) {
|
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(
|
fn clone_files(
|
||||||
|
@ -11,6 +11,7 @@ use self::signal::sig_queues::SigQueues;
|
|||||||
use self::signal::signals::kernel::KernelSignal;
|
use self::signal::signals::kernel::KernelSignal;
|
||||||
use self::status::ProcessStatus;
|
use self::status::ProcessStatus;
|
||||||
use crate::fs::file_table::FileTable;
|
use crate::fs::file_table::FileTable;
|
||||||
|
use crate::fs::fs_resolver::FsResolver;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Full;
|
use crate::rights::Full;
|
||||||
use crate::thread::kernel_thread::KernelThreadExt;
|
use crate::thread::kernel_thread::KernelThreadExt;
|
||||||
@ -65,6 +66,8 @@ pub struct Process {
|
|||||||
process_group: Mutex<Weak<ProcessGroup>>,
|
process_group: Mutex<Weak<ProcessGroup>>,
|
||||||
/// File table
|
/// File table
|
||||||
file_table: Arc<Mutex<FileTable>>,
|
file_table: Arc<Mutex<FileTable>>,
|
||||||
|
/// FsResolver
|
||||||
|
fs: Arc<RwLock<FsResolver>>,
|
||||||
/// resource limits
|
/// resource limits
|
||||||
resource_limits: Mutex<ResourceLimits>,
|
resource_limits: Mutex<ResourceLimits>,
|
||||||
|
|
||||||
@ -99,6 +102,7 @@ impl Process {
|
|||||||
root_vmar: Arc<Vmar<Full>>,
|
root_vmar: Arc<Vmar<Full>>,
|
||||||
process_group: Weak<ProcessGroup>,
|
process_group: Weak<ProcessGroup>,
|
||||||
file_table: Arc<Mutex<FileTable>>,
|
file_table: Arc<Mutex<FileTable>>,
|
||||||
|
fs: Arc<RwLock<FsResolver>>,
|
||||||
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
sig_dispositions: Arc<Mutex<SigDispositions>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let parent = if pid == 0 {
|
let parent = if pid == 0 {
|
||||||
@ -125,6 +129,7 @@ impl Process {
|
|||||||
children: Mutex::new(children),
|
children: Mutex::new(children),
|
||||||
process_group: Mutex::new(process_group),
|
process_group: Mutex::new(process_group),
|
||||||
file_table,
|
file_table,
|
||||||
|
fs,
|
||||||
sig_dispositions,
|
sig_dispositions,
|
||||||
sig_queues: Mutex::new(SigQueues::new()),
|
sig_queues: Mutex::new(SigQueues::new()),
|
||||||
resource_limits: Mutex::new(resource_limits),
|
resource_limits: Mutex::new(resource_limits),
|
||||||
@ -191,6 +196,7 @@ impl Process {
|
|||||||
let pid = thread.tid();
|
let pid = thread.tid();
|
||||||
let user_vm = UserVm::new();
|
let user_vm = UserVm::new();
|
||||||
let file_table = FileTable::new_with_stdio();
|
let file_table = FileTable::new_with_stdio();
|
||||||
|
let fs = FsResolver::new().unwrap();
|
||||||
let sig_dispositions = SigDispositions::new();
|
let sig_dispositions = SigDispositions::new();
|
||||||
|
|
||||||
let process = Process::new(
|
let process = Process::new(
|
||||||
@ -201,6 +207,7 @@ impl Process {
|
|||||||
Arc::new(root_vmar),
|
Arc::new(root_vmar),
|
||||||
Weak::new(),
|
Weak::new(),
|
||||||
Arc::new(Mutex::new(file_table)),
|
Arc::new(Mutex::new(file_table)),
|
||||||
|
Arc::new(RwLock::new(fs)),
|
||||||
Arc::new(Mutex::new(sig_dispositions)),
|
Arc::new(Mutex::new(sig_dispositions)),
|
||||||
);
|
);
|
||||||
process
|
process
|
||||||
@ -224,6 +231,7 @@ impl Process {
|
|||||||
let thread = Thread::new_kernel_thread(task_fn, weak_process_ref.clone());
|
let thread = Thread::new_kernel_thread(task_fn, weak_process_ref.clone());
|
||||||
let pid = thread.tid();
|
let pid = thread.tid();
|
||||||
let file_table = FileTable::new();
|
let file_table = FileTable::new();
|
||||||
|
let fs = FsResolver::new().unwrap();
|
||||||
let sig_dispositions = SigDispositions::new();
|
let sig_dispositions = SigDispositions::new();
|
||||||
// FIXME: kernel process does not need root vmar
|
// FIXME: kernel process does not need root vmar
|
||||||
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
let root_vmar = Vmar::<Full>::new_root().unwrap();
|
||||||
@ -235,6 +243,7 @@ impl Process {
|
|||||||
Arc::new(root_vmar),
|
Arc::new(root_vmar),
|
||||||
Weak::new(),
|
Weak::new(),
|
||||||
Arc::new(Mutex::new(file_table)),
|
Arc::new(Mutex::new(file_table)),
|
||||||
|
Arc::new(RwLock::new(fs)),
|
||||||
Arc::new(Mutex::new(sig_dispositions)),
|
Arc::new(Mutex::new(sig_dispositions)),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -287,6 +296,10 @@ impl Process {
|
|||||||
&self.file_table
|
&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.
|
/// create a new process group for the process and add it to globle table.
|
||||||
/// Then set the process group for current process.
|
/// Then set the process group for current process.
|
||||||
fn create_and_set_process_group(self: &Arc<Self>) {
|
fn create_and_set_process_group(self: &Arc<Self>) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use super::SYS_CLOSE;
|
use super::SYS_CLOSE;
|
||||||
use crate::log_syscall_entry;
|
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> {
|
pub fn sys_close(fd: FileDescripter) -> Result<SyscallReturn> {
|
||||||
log_syscall_entry!(SYS_CLOSE);
|
log_syscall_entry!(SYS_CLOSE);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{SyscallReturn, SYS_FCNTL};
|
use super::{SyscallReturn, SYS_FCNTL};
|
||||||
use crate::fs::fcntl::FcntlCmd;
|
use crate::fs::utils::FcntlCmd;
|
||||||
use crate::log_syscall_entry;
|
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> {
|
pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn> {
|
||||||
log_syscall_entry!(SYS_FCNTL);
|
log_syscall_entry!(SYS_FCNTL);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use jinux_frame::vm::VmIo;
|
use jinux_frame::vm::VmIo;
|
||||||
|
|
||||||
use crate::fs::stat::Stat;
|
use crate::fs::utils::Stat;
|
||||||
use crate::{log_syscall_entry, prelude::*};
|
use crate::{log_syscall_entry, prelude::*};
|
||||||
|
|
||||||
use crate::syscall::{SyscallReturn, SYS_FSTAT};
|
use crate::syscall::{SyscallReturn, SYS_FSTAT};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::fs::file::FileDescripter;
|
use crate::fs::file_table::FileDescripter;
|
||||||
use crate::fs::ioctl::IoctlCmd;
|
use crate::fs::utils::IoctlCmd;
|
||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::{fs::file::FileDescripter, prelude::*};
|
use crate::{fs::file_table::FileDescripter, prelude::*};
|
||||||
|
|
||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use super::SYS_LSEEK;
|
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::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This mod defines mmap flags and the handler to syscall mmap
|
//! 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::process::process_vm::mmap_flags::MMapFlags;
|
||||||
use crate::rights::Rights;
|
use crate::rights::Rights;
|
||||||
use crate::vm::perms::VmPerms;
|
use crate::vm::perms::VmPerms;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use crate::fs::file::File;
|
use crate::fs::{
|
||||||
use crate::fs::file::FileDescripter;
|
file_handle::{File, FileHandle},
|
||||||
use crate::fs::file_handle::FileHandle;
|
file_table::FileDescripter,
|
||||||
|
fs_resolver::{FsPath, AT_FDCWD},
|
||||||
|
};
|
||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||||
@ -10,12 +12,10 @@ use crate::util::read_cstring_from_user;
|
|||||||
use super::SyscallReturn;
|
use super::SyscallReturn;
|
||||||
use super::SYS_OPENAT;
|
use super::SYS_OPENAT;
|
||||||
|
|
||||||
const AT_FDCWD: FileDescripter = -100;
|
|
||||||
|
|
||||||
pub fn sys_openat(
|
pub fn sys_openat(
|
||||||
dirfd: FileDescripter,
|
dirfd: FileDescripter,
|
||||||
pathname_addr: Vaddr,
|
pathname_addr: Vaddr,
|
||||||
flags: i32,
|
flags: u32,
|
||||||
mode: u16,
|
mode: u16,
|
||||||
) -> Result<SyscallReturn> {
|
) -> Result<SyscallReturn> {
|
||||||
log_syscall_entry!(SYS_OPENAT);
|
log_syscall_entry!(SYS_OPENAT);
|
||||||
@ -53,7 +53,18 @@ pub fn sys_openat(
|
|||||||
let fd = file_table.insert(tty_file);
|
let fd = file_table.insert(tty_file);
|
||||||
return Ok(SyscallReturn::Return(fd as _));
|
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.
|
/// File for output busybox ash log.
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use core::time::Duration;
|
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::log_syscall_entry;
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
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::SyscallReturn;
|
||||||
use super::SYS_POLL;
|
use super::SYS_POLL;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::util::write_bytes_to_user;
|
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::SyscallReturn;
|
||||||
use super::SYS_READ;
|
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::{log_syscall_entry, prelude::*};
|
||||||
|
|
||||||
use crate::syscall::SYS_WRITE;
|
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::process::signal::constants::{SIGINT, SIGQUIT};
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use self::line_discipline::LineDiscipline;
|
use self::line_discipline::LineDiscipline;
|
||||||
use crate::driver::tty::TtyDriver;
|
use crate::driver::tty::TtyDriver;
|
||||||
use crate::fs::events::IoEvents;
|
use crate::fs::{
|
||||||
|
file_handle::File,
|
||||||
use crate::fs::ioctl::IoctlCmd;
|
utils::{IoEvents, IoctlCmd},
|
||||||
|
};
|
||||||
|
use crate::prelude::*;
|
||||||
use crate::process::{process_table, Pgid};
|
use crate::process::{process_table, Pgid};
|
||||||
use crate::util::{read_val_from_user, write_val_to_user};
|
use crate::util::{read_val_from_user, write_val_to_user};
|
||||||
use crate::{fs::file::File, prelude::*};
|
|
||||||
|
|
||||||
pub mod line_discipline;
|
pub mod line_discipline;
|
||||||
pub mod termio;
|
pub mod termio;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user