mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 18:03:25 +00:00
Extract dentry.rs and mount.rs to path module, rename Dentry and DentryMnt and check usage of pub.
Signed-off-by: Zhenchen Wang <m202372036@hust.edu.cn>
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
8d18a12385
commit
8bcadee540
@ -4,7 +4,8 @@ use crate::{
|
|||||||
fs::{
|
fs::{
|
||||||
devpts::DevPts,
|
devpts::DevPts,
|
||||||
fs_resolver::{FsPath, FsResolver},
|
fs_resolver::{FsPath, FsResolver},
|
||||||
utils::{DentryMnt, Inode, InodeMode, InodeType},
|
path::Dentry,
|
||||||
|
utils::{Inode, InodeMode, InodeType},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
@ -15,17 +16,17 @@ mod pty;
|
|||||||
pub use pty::{PtyMaster, PtySlave};
|
pub use pty::{PtyMaster, PtySlave};
|
||||||
use spin::Once;
|
use spin::Once;
|
||||||
|
|
||||||
static DEV_PTS: Once<Arc<DentryMnt>> = Once::new();
|
static DEV_PTS: Once<Arc<Dentry>> = Once::new();
|
||||||
|
|
||||||
pub fn init() -> Result<()> {
|
pub fn init() -> Result<()> {
|
||||||
let fs = FsResolver::new();
|
let fs = FsResolver::new();
|
||||||
|
|
||||||
let dev = fs.lookup(&FsPath::try_from("/dev")?)?;
|
let dev = fs.lookup(&FsPath::try_from("/dev")?)?;
|
||||||
// Create the "pts" directory and mount devpts on it.
|
// Create the "pts" directory and mount devpts on it.
|
||||||
let devpts_dentrymnt =
|
let devpts_dentry =
|
||||||
dev.new_fs_child("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?;
|
dev.new_fs_child("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?;
|
||||||
let devpts_mount_node = devpts_dentrymnt.mount(DevPts::new())?;
|
let devpts_mount_node = devpts_dentry.mount(DevPts::new())?;
|
||||||
let devpts = DentryMnt::new_fs_root(devpts_mount_node.clone());
|
let devpts = Dentry::new_fs_root(devpts_mount_node.clone());
|
||||||
|
|
||||||
DEV_PTS.call_once(|| devpts);
|
DEV_PTS.call_once(|| devpts);
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use super::{inode_handle::FileIo, utils::DentryMnt};
|
use super::inode_handle::FileIo;
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{
|
fs::{
|
||||||
fs_resolver::{FsPath, FsResolver},
|
fs_resolver::{FsPath, FsResolver},
|
||||||
|
path::Dentry,
|
||||||
utils::{InodeMode, InodeType},
|
utils::{InodeMode, InodeType},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -84,12 +85,11 @@ impl From<DeviceId> for u64 {
|
|||||||
///
|
///
|
||||||
/// If the parent path is not existing, `mkdir -p` the parent path.
|
/// If the parent path is not existing, `mkdir -p` the parent path.
|
||||||
/// This function is used in registering device.
|
/// This function is used in registering device.
|
||||||
pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<DentryMnt>> {
|
pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<Dentry>> {
|
||||||
let mut dentrymnt = {
|
let mut dentry = {
|
||||||
let fs_resolver = FsResolver::new();
|
let fs_resolver = FsResolver::new();
|
||||||
fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())?
|
fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())?
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut relative_path = {
|
let mut relative_path = {
|
||||||
let relative_path = path.trim_start_matches('/');
|
let relative_path = path.trim_start_matches('/');
|
||||||
if relative_path.is_empty() {
|
if relative_path.is_empty() {
|
||||||
@ -106,24 +106,24 @@ pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<DentryMnt>> {
|
|||||||
(relative_path, "")
|
(relative_path, "")
|
||||||
};
|
};
|
||||||
|
|
||||||
match dentrymnt.lookup(next_name) {
|
match dentry.lookup(next_name) {
|
||||||
Ok(next_dentrymnt) => {
|
Ok(next_dentry) => {
|
||||||
if path_remain.is_empty() {
|
if path_remain.is_empty() {
|
||||||
return_errno_with_message!(Errno::EEXIST, "device node is existing");
|
return_errno_with_message!(Errno::EEXIST, "device node is existing");
|
||||||
}
|
}
|
||||||
dentrymnt = next_dentrymnt;
|
dentry = next_dentry;
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
if path_remain.is_empty() {
|
if path_remain.is_empty() {
|
||||||
// Create the device node
|
// Create the device node
|
||||||
dentrymnt = dentrymnt.mknod(
|
dentry = dentry.mknod(
|
||||||
next_name,
|
next_name,
|
||||||
InodeMode::from_bits_truncate(0o666),
|
InodeMode::from_bits_truncate(0o666),
|
||||||
device.clone(),
|
device.clone(),
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
// Mkdir parent path
|
// Mkdir parent path
|
||||||
dentrymnt = dentrymnt.new_fs_child(
|
dentry = dentry.new_fs_child(
|
||||||
next_name,
|
next_name,
|
||||||
InodeType::Dir,
|
InodeType::Dir,
|
||||||
InodeMode::from_bits_truncate(0o755),
|
InodeMode::from_bits_truncate(0o755),
|
||||||
@ -134,7 +134,7 @@ pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<DentryMnt>> {
|
|||||||
relative_path = path_remain;
|
relative_path = path_remain;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete the device node from FS for the device.
|
/// Delete the device node from FS for the device.
|
||||||
@ -149,11 +149,11 @@ pub fn delete_node(path: &str) -> Result<()> {
|
|||||||
String::from("/dev") + "/" + device_path
|
String::from("/dev") + "/" + device_path
|
||||||
};
|
};
|
||||||
|
|
||||||
let (parent_dentrymnt, name) = {
|
let (parent_dentry, name) = {
|
||||||
let fs_resolver = FsResolver::new();
|
let fs_resolver = FsResolver::new();
|
||||||
fs_resolver.lookup_dir_and_base_name(&FsPath::try_from(abs_path.as_str()).unwrap())?
|
fs_resolver.lookup_dir_and_base_name(&FsPath::try_from(abs_path.as_str()).unwrap())?
|
||||||
};
|
};
|
||||||
|
|
||||||
parent_dentrymnt.unlink(&name)?;
|
parent_dentry.unlink(&name)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -5,18 +5,16 @@ use alloc::str;
|
|||||||
use super::{
|
use super::{
|
||||||
file_table::FileDesc,
|
file_table::FileDesc,
|
||||||
inode_handle::InodeHandle,
|
inode_handle::InodeHandle,
|
||||||
|
path::Dentry,
|
||||||
rootfs::root_mount,
|
rootfs::root_mount,
|
||||||
utils::{
|
utils::{AccessMode, CreationFlags, InodeMode, InodeType, StatusFlags, PATH_MAX, SYMLINKS_MAX},
|
||||||
AccessMode, CreationFlags, DentryMnt, InodeMode, InodeType, StatusFlags, PATH_MAX,
|
|
||||||
SYMLINKS_MAX,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FsResolver {
|
pub struct FsResolver {
|
||||||
root: Arc<DentryMnt>,
|
root: Arc<Dentry>,
|
||||||
cwd: Arc<DentryMnt>,
|
cwd: Arc<Dentry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for FsResolver {
|
impl Clone for FsResolver {
|
||||||
@ -37,29 +35,29 @@ impl Default for FsResolver {
|
|||||||
impl FsResolver {
|
impl FsResolver {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
root: DentryMnt::new_fs_root(root_mount().clone()),
|
root: Dentry::new_fs_root(root_mount().clone()),
|
||||||
cwd: DentryMnt::new_fs_root(root_mount().clone()),
|
cwd: Dentry::new_fs_root(root_mount().clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the root directory
|
/// Get the root directory
|
||||||
pub fn root(&self) -> &Arc<DentryMnt> {
|
pub fn root(&self) -> &Arc<Dentry> {
|
||||||
&self.root
|
&self.root
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current working directory
|
/// Get the current working directory
|
||||||
pub fn cwd(&self) -> &Arc<DentryMnt> {
|
pub fn cwd(&self) -> &Arc<Dentry> {
|
||||||
&self.cwd
|
&self.cwd
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the current working directory.
|
/// Set the current working directory.
|
||||||
pub fn set_cwd(&mut self, dentrymnt: Arc<DentryMnt>) {
|
pub fn set_cwd(&mut self, dentry: Arc<Dentry>) {
|
||||||
self.cwd = dentrymnt;
|
self.cwd = dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the root directory
|
/// Set the root directory
|
||||||
pub fn set_root(&mut self, dentrymnt: Arc<DentryMnt>) {
|
pub fn set_root(&mut self, dentry: Arc<Dentry>) {
|
||||||
self.root = dentrymnt;
|
self.root = dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open or create a file inode handler.
|
/// Open or create a file inode handler.
|
||||||
@ -72,9 +70,9 @@ impl FsResolver {
|
|||||||
let follow_tail_link = !(creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
let follow_tail_link = !(creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
||||||
|| creation_flags.contains(CreationFlags::O_CREAT)
|
|| creation_flags.contains(CreationFlags::O_CREAT)
|
||||||
&& creation_flags.contains(CreationFlags::O_EXCL));
|
&& creation_flags.contains(CreationFlags::O_EXCL));
|
||||||
let dentrymnt = match self.lookup_inner(path, follow_tail_link) {
|
let dentry = match self.lookup_inner(path, follow_tail_link) {
|
||||||
Ok(dentrymnt) => {
|
Ok(dentry) => {
|
||||||
let inode = dentrymnt.inode();
|
let inode = dentry.inode();
|
||||||
if inode.type_() == InodeType::SymLink
|
if inode.type_() == InodeType::SymLink
|
||||||
&& creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
&& creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
||||||
&& !status_flags.contains(StatusFlags::O_PATH)
|
&& !status_flags.contains(StatusFlags::O_PATH)
|
||||||
@ -94,7 +92,7 @@ impl FsResolver {
|
|||||||
"O_DIRECTORY is specified but file is not a directory"
|
"O_DIRECTORY is specified but file is not a directory"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
dentrymnt
|
dentry
|
||||||
}
|
}
|
||||||
Err(e)
|
Err(e)
|
||||||
if e.error() == Errno::ENOENT
|
if e.error() == Errno::ENOENT
|
||||||
@ -103,35 +101,35 @@ 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_dentrymnt, file_name) =
|
let (dir_dentry, file_name) =
|
||||||
self.lookup_dir_and_base_name_inner(path, follow_tail_link)?;
|
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_dentrymnt.mode()?.is_writable() {
|
if !dir_dentry.mode()?.is_writable() {
|
||||||
return_errno_with_message!(Errno::EACCES, "file cannot be created");
|
return_errno_with_message!(Errno::EACCES, "file cannot be created");
|
||||||
}
|
}
|
||||||
dir_dentrymnt.new_fs_child(&file_name, InodeType::File, inode_mode)?
|
dir_dentry.new_fs_child(&file_name, InodeType::File, inode_mode)?
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
let inode_handle = InodeHandle::new(dentrymnt, access_mode, status_flags)?;
|
let inode_handle = InodeHandle::new(dentry, access_mode, status_flags)?;
|
||||||
Ok(inode_handle)
|
Ok(inode_handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup dentrymnt according to FsPath, always follow symlinks
|
/// Lookup dentry according to FsPath, always follow symlinks
|
||||||
pub fn lookup(&self, path: &FsPath) -> Result<Arc<DentryMnt>> {
|
pub fn lookup(&self, path: &FsPath) -> Result<Arc<Dentry>> {
|
||||||
self.lookup_inner(path, true)
|
self.lookup_inner(path, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup dentrymnt according to FsPath, do not follow it if last component is a symlink
|
/// 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<DentryMnt>> {
|
pub fn lookup_no_follow(&self, path: &FsPath) -> Result<Arc<Dentry>> {
|
||||||
self.lookup_inner(path, false)
|
self.lookup_inner(path, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<DentryMnt>> {
|
fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> {
|
||||||
let dentrymnt = 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)?
|
||||||
}
|
}
|
||||||
@ -146,7 +144,7 @@ impl FsResolver {
|
|||||||
FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?,
|
FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup dentry from parent
|
/// Lookup dentry from parent
|
||||||
@ -162,10 +160,10 @@ impl FsResolver {
|
|||||||
/// Symlinks in earlier components of the path will always be followed.
|
/// Symlinks in earlier components of the path will always be followed.
|
||||||
fn lookup_from_parent(
|
fn lookup_from_parent(
|
||||||
&self,
|
&self,
|
||||||
parent: &Arc<DentryMnt>,
|
parent: &Arc<Dentry>,
|
||||||
relative_path: &str,
|
relative_path: &str,
|
||||||
follow_tail_link: bool,
|
follow_tail_link: bool,
|
||||||
) -> Result<Arc<DentryMnt>> {
|
) -> Result<Arc<Dentry>> {
|
||||||
debug_assert!(!relative_path.starts_with('/'));
|
debug_assert!(!relative_path.starts_with('/'));
|
||||||
|
|
||||||
if relative_path.len() > PATH_MAX {
|
if relative_path.len() > PATH_MAX {
|
||||||
@ -176,8 +174,8 @@ impl FsResolver {
|
|||||||
let mut link_path = String::new();
|
let mut link_path = String::new();
|
||||||
let mut follows = 0;
|
let mut follows = 0;
|
||||||
|
|
||||||
// Initialize the first dentrymnt and the relative path
|
// Initialize the first dentry and the relative path
|
||||||
let (mut dentrymnt, mut relative_path) = (parent.clone(), relative_path);
|
let (mut dentry, mut relative_path) = (parent.clone(), relative_path);
|
||||||
|
|
||||||
while !relative_path.is_empty() {
|
while !relative_path.is_empty() {
|
||||||
let (next_name, path_remain, must_be_dir) =
|
let (next_name, path_remain, must_be_dir) =
|
||||||
@ -189,8 +187,8 @@ impl FsResolver {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Iterate next dentry
|
// Iterate next dentry
|
||||||
let next_dentrymnt = dentrymnt.lookup(next_name)?;
|
let next_dentry = dentry.lookup(next_name)?;
|
||||||
let next_type = next_dentrymnt.type_();
|
let next_type = next_dentry.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.
|
||||||
@ -199,7 +197,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_dentrymnt.inode().read_link()?;
|
let mut tmp_link_path = next_dentry.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");
|
||||||
}
|
}
|
||||||
@ -212,9 +210,9 @@ impl FsResolver {
|
|||||||
tmp_link_path
|
tmp_link_path
|
||||||
};
|
};
|
||||||
|
|
||||||
// Change the dentrymnt and relative path according to symlink
|
// Change the dentry and relative path according to symlink
|
||||||
if link_path_remain.starts_with('/') {
|
if link_path_remain.starts_with('/') {
|
||||||
dentrymnt = self.root.clone();
|
dentry = self.root.clone();
|
||||||
}
|
}
|
||||||
link_path.clear();
|
link_path.clear();
|
||||||
link_path.push_str(link_path_remain.trim_start_matches('/'));
|
link_path.push_str(link_path_remain.trim_start_matches('/'));
|
||||||
@ -225,29 +223,29 @@ impl FsResolver {
|
|||||||
if must_be_dir && next_type != InodeType::Dir {
|
if must_be_dir && next_type != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "inode is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "inode is not dir");
|
||||||
}
|
}
|
||||||
dentrymnt = next_dentrymnt;
|
dentry = next_dentry;
|
||||||
relative_path = path_remain;
|
relative_path = path_remain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup dentry from the giving fd
|
/// Lookup dentry from the giving fd
|
||||||
pub fn lookup_from_fd(&self, fd: FileDesc) -> Result<Arc<DentryMnt>> {
|
pub fn lookup_from_fd(&self, fd: FileDesc) -> 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
|
||||||
.get_file(fd)?
|
.get_file(fd)?
|
||||||
.downcast_ref::<InodeHandle>()
|
.downcast_ref::<InodeHandle>()
|
||||||
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
||||||
Ok(inode_handle.dentrymnt().clone())
|
Ok(inode_handle.dentry().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup the dir dentrymnt and base file name of the giving path.
|
/// Lookup the dir dentry and base file name of the giving path.
|
||||||
///
|
///
|
||||||
/// If the last component is a symlink, do not deference it
|
/// If the last component is a symlink, do not deference it
|
||||||
pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc<DentryMnt>, String)> {
|
pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc<Dentry>, String)> {
|
||||||
self.lookup_dir_and_base_name_inner(path, false)
|
self.lookup_dir_and_base_name_inner(path, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,8 +253,8 @@ impl FsResolver {
|
|||||||
&self,
|
&self,
|
||||||
path: &FsPath,
|
path: &FsPath,
|
||||||
follow_tail_link: bool,
|
follow_tail_link: bool,
|
||||||
) -> Result<(Arc<DentryMnt>, String)> {
|
) -> Result<(Arc<Dentry>, String)> {
|
||||||
let (mut dir_dentrymnt, mut base_name) = match path.inner {
|
let (mut dir_dentry, mut base_name) = match path.inner {
|
||||||
FsPathInner::Absolute(path) => {
|
FsPathInner::Absolute(path) => {
|
||||||
let (dir, file_name) = split_path(path);
|
let (dir, file_name) = split_path(path);
|
||||||
(
|
(
|
||||||
@ -282,15 +280,15 @@ impl FsResolver {
|
|||||||
_ => return_errno!(Errno::ENOENT),
|
_ => return_errno!(Errno::ENOENT),
|
||||||
};
|
};
|
||||||
if !follow_tail_link {
|
if !follow_tail_link {
|
||||||
return Ok((dir_dentrymnt, base_name));
|
return Ok((dir_dentry, base_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dereference the tail symlinks if needed
|
// Dereference the tail symlinks if needed
|
||||||
loop {
|
loop {
|
||||||
match dir_dentrymnt.lookup(base_name.trim_end_matches('/')) {
|
match dir_dentry.lookup(base_name.trim_end_matches('/')) {
|
||||||
Ok(dentrymnt) if dentrymnt.type_() == InodeType::SymLink => {
|
Ok(dentry) if dentry.type_() == InodeType::SymLink => {
|
||||||
let link = {
|
let link = {
|
||||||
let mut link = dentrymnt.inode().read_link()?;
|
let mut link = dentry.inode().read_link()?;
|
||||||
if link.is_empty() {
|
if link.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "invalid symlink");
|
return_errno_with_message!(Errno::ENOENT, "invalid symlink");
|
||||||
}
|
}
|
||||||
@ -301,11 +299,11 @@ impl FsResolver {
|
|||||||
};
|
};
|
||||||
let (dir, file_name) = split_path(&link);
|
let (dir, file_name) = split_path(&link);
|
||||||
if dir.starts_with('/') {
|
if dir.starts_with('/') {
|
||||||
dir_dentrymnt =
|
dir_dentry =
|
||||||
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?;
|
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?;
|
||||||
base_name = String::from(file_name);
|
base_name = String::from(file_name);
|
||||||
} else {
|
} else {
|
||||||
dir_dentrymnt = self.lookup_from_parent(&dir_dentrymnt, dir, true)?;
|
dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?;
|
||||||
base_name = String::from(file_name);
|
base_name = String::from(file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +311,7 @@ impl FsResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((dir_dentrymnt, base_name))
|
Ok((dir_dentry, base_name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
impl InodeHandle<Rights> {
|
impl InodeHandle<Rights> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
dentrymnt: Arc<DentryMnt>,
|
dentry: Arc<Dentry>,
|
||||||
access_mode: AccessMode,
|
access_mode: AccessMode,
|
||||||
status_flags: StatusFlags,
|
status_flags: StatusFlags,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let inode = dentrymnt.inode();
|
let inode = dentry.inode();
|
||||||
if access_mode.is_readable() && !inode.mode()?.is_readable() {
|
if access_mode.is_readable() && !inode.mode()?.is_readable() {
|
||||||
return_errno_with_message!(Errno::EACCES, "File is not readable");
|
return_errno_with_message!(Errno::EACCES, "File is not readable");
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ impl InodeHandle<Rights> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let inner = Arc::new(InodeHandle_ {
|
let inner = Arc::new(InodeHandle_ {
|
||||||
dentrymnt,
|
dentry,
|
||||||
file_io,
|
file_io,
|
||||||
offset: Mutex::new(0),
|
offset: Mutex::new(0),
|
||||||
access_mode,
|
access_mode,
|
||||||
@ -116,6 +116,6 @@ impl FileLike for InodeHandle<Rights> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
||||||
self.0.dentrymnt.inode().as_device()
|
self.dentry().inode().as_device()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,10 @@ use crate::{
|
|||||||
fs::{
|
fs::{
|
||||||
device::Device,
|
device::Device,
|
||||||
file_handle::FileLike,
|
file_handle::FileLike,
|
||||||
|
path::Dentry,
|
||||||
utils::{
|
utils::{
|
||||||
AccessMode, DentryMnt, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata,
|
AccessMode, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata, SeekFrom,
|
||||||
SeekFrom, StatusFlags,
|
StatusFlags,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -28,7 +29,7 @@ use crate::{
|
|||||||
pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
|
pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
|
||||||
|
|
||||||
struct InodeHandle_ {
|
struct InodeHandle_ {
|
||||||
dentrymnt: Arc<DentryMnt>,
|
dentry: Arc<Dentry>,
|
||||||
/// `file_io` is Similar to `file_private` field in `file` structure in linux. If
|
/// `file_io` is Similar to `file_private` field in `file` structure in linux. If
|
||||||
/// `file_io` is Some, typical file operations including `read`, `write`, `poll`,
|
/// `file_io` is Some, typical file operations including `read`, `write`, `poll`,
|
||||||
/// `ioctl` will be provided by `file_io`, instead of `dentry`.
|
/// `ioctl` will be provided by `file_io`, instead of `dentry`.
|
||||||
@ -47,9 +48,9 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentrymnt.inode().read_direct_at(*offset, buf)?
|
self.dentry.inode().read_direct_at(*offset, buf)?
|
||||||
} else {
|
} else {
|
||||||
self.dentrymnt.inode().read_at(*offset, buf)?
|
self.dentry.inode().read_at(*offset, buf)?
|
||||||
};
|
};
|
||||||
|
|
||||||
*offset += len;
|
*offset += len;
|
||||||
@ -64,12 +65,12 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
||||||
*offset = self.dentrymnt.size();
|
*offset = self.dentry.size();
|
||||||
}
|
}
|
||||||
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentrymnt.inode().write_direct_at(*offset, buf)?
|
self.dentry.inode().write_direct_at(*offset, buf)?
|
||||||
} else {
|
} else {
|
||||||
self.dentrymnt.inode().write_at(*offset, buf)?
|
self.dentry.inode().write_at(*offset, buf)?
|
||||||
};
|
};
|
||||||
|
|
||||||
*offset += len;
|
*offset += len;
|
||||||
@ -82,9 +83,9 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentrymnt.inode().read_direct_all(buf)?
|
self.dentry.inode().read_direct_all(buf)?
|
||||||
} else {
|
} else {
|
||||||
self.dentrymnt.inode().read_all(buf)?
|
self.dentry.inode().read_all(buf)?
|
||||||
};
|
};
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
@ -99,7 +100,7 @@ impl InodeHandle_ {
|
|||||||
off as isize
|
off as isize
|
||||||
}
|
}
|
||||||
SeekFrom::End(off /* as isize */) => {
|
SeekFrom::End(off /* as isize */) => {
|
||||||
let file_size = self.dentrymnt.size() as isize;
|
let file_size = self.dentry.size() as isize;
|
||||||
assert!(file_size >= 0);
|
assert!(file_size >= 0);
|
||||||
file_size
|
file_size
|
||||||
.checked_add(off)
|
.checked_add(off)
|
||||||
@ -127,7 +128,7 @@ impl InodeHandle_ {
|
|||||||
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
||||||
return_errno_with_message!(Errno::EPERM, "can not resize append-only file");
|
return_errno_with_message!(Errno::EPERM, "can not resize append-only file");
|
||||||
}
|
}
|
||||||
self.dentrymnt.resize(new_size)
|
self.dentry.resize(new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn access_mode(&self) -> AccessMode {
|
pub fn access_mode(&self) -> AccessMode {
|
||||||
@ -146,7 +147,7 @@ impl InodeHandle_ {
|
|||||||
|
|
||||||
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
let mut offset = self.offset.lock();
|
||||||
let read_cnt = self.dentrymnt.inode().readdir_at(*offset, visitor)?;
|
let read_cnt = self.dentry.inode().readdir_at(*offset, visitor)?;
|
||||||
*offset += read_cnt;
|
*offset += read_cnt;
|
||||||
Ok(read_cnt)
|
Ok(read_cnt)
|
||||||
}
|
}
|
||||||
@ -156,7 +157,7 @@ impl InodeHandle_ {
|
|||||||
return file_io.poll(mask, poller);
|
return file_io.poll(mask, poller);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dentrymnt.inode().poll(mask, poller)
|
self.dentry.inode().poll(mask, poller)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
@ -164,11 +165,11 @@ impl InodeHandle_ {
|
|||||||
return file_io.ioctl(cmd, arg);
|
return file_io.ioctl(cmd, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dentrymnt.inode().ioctl(cmd, arg)
|
self.dentry.inode().ioctl(cmd, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inherit_methods(from = "self.dentrymnt")]
|
#[inherit_methods(from = "self.dentry")]
|
||||||
impl InodeHandle_ {
|
impl InodeHandle_ {
|
||||||
pub fn size(&self) -> usize;
|
pub fn size(&self) -> usize;
|
||||||
pub fn metadata(&self) -> Metadata;
|
pub fn metadata(&self) -> Metadata;
|
||||||
@ -183,7 +184,7 @@ impl InodeHandle_ {
|
|||||||
impl Debug for InodeHandle_ {
|
impl Debug for InodeHandle_ {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
f.debug_struct("InodeHandle_")
|
f.debug_struct("InodeHandle_")
|
||||||
.field("dentrymnt", &self.dentrymnt)
|
.field("dentry", &self.dentry)
|
||||||
.field("offset", &self.offset())
|
.field("offset", &self.offset())
|
||||||
.field("access_mode", &self.access_mode())
|
.field("access_mode", &self.access_mode())
|
||||||
.field("status_flags", &self.status_flags())
|
.field("status_flags", &self.status_flags())
|
||||||
@ -193,8 +194,8 @@ impl Debug for InodeHandle_ {
|
|||||||
|
|
||||||
/// Methods for both dyn and static
|
/// Methods for both dyn and static
|
||||||
impl<R> InodeHandle<R> {
|
impl<R> InodeHandle<R> {
|
||||||
pub fn dentrymnt(&self) -> &Arc<DentryMnt> {
|
pub fn dentry(&self) -> &Arc<Dentry> {
|
||||||
&self.0.dentrymnt
|
&self.0.dentry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ 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 inode_handle;
|
||||||
|
pub mod path;
|
||||||
pub mod pipe;
|
pub mod pipe;
|
||||||
pub mod procfs;
|
pub mod procfs;
|
||||||
pub mod ramfs;
|
pub mod ramfs;
|
||||||
|
@ -7,34 +7,34 @@ use core::{
|
|||||||
|
|
||||||
use inherit_methods_macro::inherit_methods;
|
use inherit_methods_macro::inherit_methods;
|
||||||
|
|
||||||
use super::{FileSystem, Inode, InodeMode, InodeType, Metadata};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{
|
fs::{
|
||||||
device::Device,
|
device::Device,
|
||||||
utils::{MountNode, NAME_MAX},
|
path::mount::MountNode,
|
||||||
|
utils::{FileSystem, Inode, InodeMode, InodeType, Metadata, NAME_MAX},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{Gid, Uid},
|
process::{Gid, Uid},
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref DCACHE: Mutex<BTreeMap<DentryKey, Arc<Dentry>>> = Mutex::new(BTreeMap::new());
|
static ref DCACHE: Mutex<BTreeMap<DentryKey, Arc<Dentry_>>> = Mutex::new(BTreeMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The dentry cache to accelerate path lookup
|
/// The Dentry_ cache to accelerate path lookup
|
||||||
pub struct Dentry {
|
pub struct Dentry_ {
|
||||||
inode: Arc<dyn Inode>,
|
inode: Arc<dyn Inode>,
|
||||||
name_and_parent: RwLock<Option<(String, Arc<Dentry>)>>,
|
name_and_parent: RwLock<Option<(String, Arc<Dentry_>)>>,
|
||||||
this: Weak<Dentry>,
|
this: Weak<Dentry_>,
|
||||||
children: Mutex<Children>,
|
children: Mutex<Children>,
|
||||||
flags: AtomicU32,
|
flags: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dentry {
|
impl Dentry_ {
|
||||||
/// Create a new root dentry with the giving inode.
|
/// Create a new root Dentry_ with the giving inode.
|
||||||
///
|
///
|
||||||
/// It is been created during the construction of MountNode struct. The MountNode
|
/// It is been created during the construction of MountNode struct. The MountNode
|
||||||
/// struct holds an arc reference to this root dentry.
|
/// struct holds an arc reference to this root Dentry_.
|
||||||
pub(super) fn new_root(inode: Arc<dyn Inode>) -> Arc<Self> {
|
pub(super) fn new_root(inode: Arc<dyn Inode>) -> Arc<Self> {
|
||||||
let root = Self::new(inode, DentryOptions::Root);
|
let root = Self::new(inode, DentryOptions::Root);
|
||||||
DCACHE.lock().insert(root.key(), root.clone());
|
DCACHE.lock().insert(root.key(), root.clone());
|
||||||
@ -55,10 +55,10 @@ impl Dentry {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the name of dentry.
|
/// Get the name of Dentry_.
|
||||||
///
|
///
|
||||||
/// Returns "/" if it is a root dentry.
|
/// Returns "/" if it is a root Dentry_.
|
||||||
fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
match self.name_and_parent.read().as_ref() {
|
match self.name_and_parent.read().as_ref() {
|
||||||
Some(name_and_parent) => name_and_parent.0.clone(),
|
Some(name_and_parent) => name_and_parent.0.clone(),
|
||||||
None => String::from("/"),
|
None => String::from("/"),
|
||||||
@ -67,8 +67,8 @@ impl Dentry {
|
|||||||
|
|
||||||
/// Get the parent.
|
/// Get the parent.
|
||||||
///
|
///
|
||||||
/// Returns None if it is root dentry.
|
/// Returns None if it is root Dentry_.
|
||||||
fn parent(&self) -> Option<Arc<Self>> {
|
pub fn parent(&self) -> Option<Arc<Self>> {
|
||||||
self.name_and_parent
|
self.name_and_parent
|
||||||
.read()
|
.read()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -86,7 +86,7 @@ impl Dentry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the DentryKey.
|
/// Get the DentryKey.
|
||||||
fn key(&self) -> DentryKey {
|
pub fn key(&self) -> DentryKey {
|
||||||
DentryKey::new(self)
|
DentryKey::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,27 +101,27 @@ impl Dentry {
|
|||||||
DentryFlags::from_bits(flags).unwrap()
|
DentryFlags::from_bits(flags).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_mountpoint(&self) -> bool {
|
pub fn is_mountpoint(&self) -> bool {
|
||||||
self.flags().contains(DentryFlags::MOUNTED)
|
self.flags().contains(DentryFlags::MOUNTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_mountpoint(&self) {
|
pub fn set_mountpoint_dentry(&self) {
|
||||||
self.flags
|
self.flags
|
||||||
.fetch_or(DentryFlags::MOUNTED.bits(), Ordering::Release);
|
.fetch_or(DentryFlags::MOUNTED.bits(), Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_mountpoint(&self) {
|
pub fn clear_mountpoint(&self) {
|
||||||
self.flags
|
self.flags
|
||||||
.fetch_and(!(DentryFlags::MOUNTED.bits()), Ordering::Release);
|
.fetch_and(!(DentryFlags::MOUNTED.bits()), Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Currently, the root dentry of a fs is the root of a mount.
|
/// Currently, the root Dentry_ of a fs is the root of a mount.
|
||||||
fn is_root_of_mount(&self) -> bool {
|
pub fn is_root_of_mount(&self) -> bool {
|
||||||
self.name_and_parent.read().as_ref().is_none()
|
self.name_and_parent.read().as_ref().is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a dentry by making inode.
|
/// Create a Dentry_ by making inode.
|
||||||
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
|
pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
|
||||||
if self.inode.type_() != InodeType::Dir {
|
if self.inode.type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
@ -142,31 +142,31 @@ impl Dentry {
|
|||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a dentry from DCACHE.
|
/// Lookup a Dentry_ from DCACHE.
|
||||||
fn lookup_via_cache(&self, name: &str) -> Option<Arc<Dentry>> {
|
pub fn lookup_via_cache(&self, name: &str) -> Option<Arc<Dentry_>> {
|
||||||
let mut children = self.children.lock();
|
let mut children = self.children.lock();
|
||||||
children.find_dentry(name)
|
children.find_dentry(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a dentry from filesystem.
|
/// Lookup a Dentry_ from filesystem.
|
||||||
fn lookuop_via_fs(&self, name: &str) -> Result<Arc<Dentry>> {
|
pub fn lookuop_via_fs(&self, name: &str) -> Result<Arc<Dentry_>> {
|
||||||
let mut children = self.children.lock();
|
let mut children = self.children.lock();
|
||||||
let inode = self.inode.lookup(name)?;
|
let inode = self.inode.lookup(name)?;
|
||||||
let dentry = Self::new(
|
let inner = Self::new(
|
||||||
inode,
|
inode,
|
||||||
DentryOptions::Leaf((String::from(name), self.this())),
|
DentryOptions::Leaf((String::from(name), self.this())),
|
||||||
);
|
);
|
||||||
children.insert_dentry(&dentry);
|
children.insert_dentry(&inner);
|
||||||
Ok(dentry)
|
Ok(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_dentry(&self, child_dentry: &Arc<Dentry>) {
|
fn insert_dentry(&self, child_dentry: &Arc<Dentry_>) {
|
||||||
let mut children = self.children.lock();
|
let mut children = self.children.lock();
|
||||||
children.insert_dentry(child_dentry);
|
children.insert_dentry(child_dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a dentry by making a device inode.
|
/// Create a Dentry_ by making a device inode.
|
||||||
fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Arc<Self>> {
|
pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Arc<Self>> {
|
||||||
if self.inode.type_() != InodeType::Dir {
|
if self.inode.type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
@ -187,8 +187,8 @@ impl Dentry {
|
|||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Link a new name for the dentry by linking inode.
|
/// Link a new name for the Dentry_ by linking inode.
|
||||||
fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
|
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
|
||||||
if self.inode.type_() != InodeType::Dir {
|
if self.inode.type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
@ -206,8 +206,8 @@ impl Dentry {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a dentry by unlinking inode.
|
/// Delete a Dentry_ by unlinking inode.
|
||||||
fn unlink(&self, name: &str) -> Result<()> {
|
pub fn unlink(&self, name: &str) -> Result<()> {
|
||||||
if self.inode.type_() != InodeType::Dir {
|
if self.inode.type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
@ -218,8 +218,8 @@ impl Dentry {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a directory dentry by rmdiring inode.
|
/// Delete a directory Dentry_ by rmdiring inode.
|
||||||
fn rmdir(&self, name: &str) -> Result<()> {
|
pub fn rmdir(&self, name: &str) -> Result<()> {
|
||||||
if self.inode.type_() != InodeType::Dir {
|
if self.inode.type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
@ -230,8 +230,8 @@ impl Dentry {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename a dentry to the new dentry by renaming inode.
|
/// Rename a Dentry_ to the new Dentry_ by renaming inode.
|
||||||
fn rename(&self, old_name: &str, new_dir: &Arc<Self>, new_name: &str) -> Result<()> {
|
pub fn rename(&self, old_name: &str, new_dir: &Arc<Self>, new_name: &str) -> Result<()> {
|
||||||
if old_name == "." || old_name == ".." || new_name == "." || new_name == ".." {
|
if old_name == "." || old_name == ".." || new_name == "." || new_name == ".." {
|
||||||
return_errno_with_message!(Errno::EISDIR, "old_name or new_name is a directory");
|
return_errno_with_message!(Errno::EISDIR, "old_name or new_name is a directory");
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ impl Dentry {
|
|||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Self and new_dir are same Dentry, just modify name
|
// Self and new_dir are same Dentry_, just modify name
|
||||||
if Arc::ptr_eq(&self.this(), new_dir) {
|
if Arc::ptr_eq(&self.this(), new_dir) {
|
||||||
if old_name == new_name {
|
if old_name == new_name {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -259,7 +259,7 @@ impl Dentry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Self and new_dir are different Dentry
|
// Self and new_dir are different Dentry_
|
||||||
let (mut self_children, mut new_dir_children) =
|
let (mut self_children, mut new_dir_children) =
|
||||||
write_lock_children_on_two_dentries(self, new_dir);
|
write_lock_children_on_two_dentries(self, new_dir);
|
||||||
let old_dentry = self_children.find_dentry_with_checking_mountpoint(old_name)?;
|
let old_dentry = self_children.find_dentry_with_checking_mountpoint(old_name)?;
|
||||||
@ -281,38 +281,38 @@ impl Dentry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inherit_methods(from = "self.inode")]
|
#[inherit_methods(from = "self.inode")]
|
||||||
impl Dentry {
|
impl Dentry_ {
|
||||||
fn fs(&self) -> Arc<dyn FileSystem>;
|
pub fn fs(&self) -> Arc<dyn FileSystem>;
|
||||||
fn sync(&self) -> Result<()>;
|
pub fn sync(&self) -> Result<()>;
|
||||||
fn metadata(&self) -> Metadata;
|
pub fn metadata(&self) -> Metadata;
|
||||||
fn type_(&self) -> InodeType;
|
pub fn type_(&self) -> InodeType;
|
||||||
fn mode(&self) -> Result<InodeMode>;
|
pub fn mode(&self) -> Result<InodeMode>;
|
||||||
fn set_mode(&self, mode: InodeMode) -> Result<()>;
|
pub fn set_mode(&self, mode: InodeMode) -> Result<()>;
|
||||||
fn size(&self) -> usize;
|
pub fn size(&self) -> usize;
|
||||||
fn resize(&self, size: usize) -> Result<()>;
|
pub fn resize(&self, size: usize) -> Result<()>;
|
||||||
fn owner(&self) -> Result<Uid>;
|
pub fn owner(&self) -> Result<Uid>;
|
||||||
fn set_owner(&self, uid: Uid) -> Result<()>;
|
pub fn set_owner(&self, uid: Uid) -> Result<()>;
|
||||||
fn group(&self) -> Result<Gid>;
|
pub fn group(&self) -> Result<Gid>;
|
||||||
fn set_group(&self, gid: Gid) -> Result<()>;
|
pub fn set_group(&self, gid: Gid) -> Result<()>;
|
||||||
fn atime(&self) -> Duration;
|
pub fn atime(&self) -> Duration;
|
||||||
fn set_atime(&self, time: Duration);
|
pub fn set_atime(&self, time: Duration);
|
||||||
fn mtime(&self) -> Duration;
|
pub fn mtime(&self) -> Duration;
|
||||||
fn set_mtime(&self, time: Duration);
|
pub fn set_mtime(&self, time: Duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Dentry {
|
impl Debug for Dentry_ {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
f.debug_struct("Dentry")
|
f.debug_struct("Dentry_")
|
||||||
.field("inode", &self.inode)
|
.field("inode", &self.inode)
|
||||||
.field("flags", &self.flags())
|
.field("flags", &self.flags())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DentryKey is the unique identifier for Dentry in DCACHE.
|
/// DentryKey is the unique identifier for Dentry_ in DCACHE.
|
||||||
///
|
///
|
||||||
/// For none-root dentries, it uses self's name and parent's pointer to form the key,
|
/// For none-root dentries, it uses self's name and parent's pointer to form the key,
|
||||||
/// meanwhile, the root dentry uses "/" and self's pointer to form the key.
|
/// meanwhile, the root Dentry_ uses "/" and self's pointer to form the key.
|
||||||
#[derive(Debug, Clone, Hash, PartialOrd, Ord, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, PartialOrd, Ord, Eq, PartialEq)]
|
||||||
pub struct DentryKey {
|
pub struct DentryKey {
|
||||||
name: String,
|
name: String,
|
||||||
@ -320,8 +320,8 @@ pub struct DentryKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DentryKey {
|
impl DentryKey {
|
||||||
/// Form the DentryKey for the dentry.
|
/// Form the DentryKey for the Dentry_.
|
||||||
fn new(dentry: &Dentry) -> Self {
|
pub fn new(dentry: &Dentry_) -> Self {
|
||||||
let (name, parent) = match dentry.name_and_parent.read().as_ref() {
|
let (name, parent) = match dentry.name_and_parent.read().as_ref() {
|
||||||
Some(name_and_parent) => name_and_parent.clone(),
|
Some(name_and_parent) => name_and_parent.clone(),
|
||||||
None => (String::from("/"), dentry.this()),
|
None => (String::from("/"), dentry.this()),
|
||||||
@ -341,21 +341,21 @@ bitflags! {
|
|||||||
|
|
||||||
enum DentryOptions {
|
enum DentryOptions {
|
||||||
Root,
|
Root,
|
||||||
Leaf((String, Arc<Dentry>)),
|
Leaf((String, Arc<Dentry_>)),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Children {
|
struct Children {
|
||||||
inner: BTreeMap<String, Weak<Dentry>>,
|
inner: BTreeMap<String, Weak<Dentry_>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Children {
|
impl Children {
|
||||||
fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: BTreeMap::new(),
|
inner: BTreeMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_dentry(&mut self, dentry: &Arc<Dentry>) {
|
pub fn insert_dentry(&mut self, dentry: &Arc<Dentry_>) {
|
||||||
// Do not cache it in DCACHE and children if is not cacheable.
|
// Do not cache it in DCACHE and children if is not cacheable.
|
||||||
// When we look up it from the parent, it will always be newly created.
|
// When we look up it from the parent, it will always be newly created.
|
||||||
if !dentry.inode().is_dentry_cacheable() {
|
if !dentry.inode().is_dentry_cacheable() {
|
||||||
@ -366,14 +366,14 @@ impl Children {
|
|||||||
self.inner.insert(dentry.name(), Arc::downgrade(dentry));
|
self.inner.insert(dentry.name(), Arc::downgrade(dentry));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_dentry(&mut self, name: &str) -> Option<Arc<Dentry>> {
|
pub fn delete_dentry(&mut self, name: &str) -> Option<Arc<Dentry_>> {
|
||||||
self.inner
|
self.inner
|
||||||
.remove(name)
|
.remove(name)
|
||||||
.and_then(|d| d.upgrade())
|
.and_then(|d| d.upgrade())
|
||||||
.and_then(|d| DCACHE.lock().remove(&d.key()))
|
.and_then(|d| DCACHE.lock().remove(&d.key()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_dentry(&mut self, name: &str) -> Option<Arc<Dentry>> {
|
pub fn find_dentry(&mut self, name: &str) -> Option<Arc<Dentry_>> {
|
||||||
if let Some(dentry) = self.inner.get(name) {
|
if let Some(dentry) = self.inner.get(name) {
|
||||||
dentry.upgrade().or_else(|| {
|
dentry.upgrade().or_else(|| {
|
||||||
self.inner.remove(name);
|
self.inner.remove(name);
|
||||||
@ -384,7 +384,10 @@ impl Children {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_dentry_with_checking_mountpoint(&mut self, name: &str) -> Result<Option<Arc<Dentry>>> {
|
pub fn find_dentry_with_checking_mountpoint(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<Option<Arc<Dentry_>>> {
|
||||||
let dentry = self.find_dentry(name);
|
let dentry = self.find_dentry(name);
|
||||||
if let Some(dentry) = dentry.as_ref() {
|
if let Some(dentry) = dentry.as_ref() {
|
||||||
if dentry.is_mountpoint() {
|
if dentry.is_mountpoint() {
|
||||||
@ -396,8 +399,8 @@ impl Children {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_lock_children_on_two_dentries<'a>(
|
fn write_lock_children_on_two_dentries<'a>(
|
||||||
this: &'a Dentry,
|
this: &'a Dentry_,
|
||||||
other: &'a Dentry,
|
other: &'a Dentry_,
|
||||||
) -> (MutexGuard<'a, Children>, MutexGuard<'a, Children>) {
|
) -> (MutexGuard<'a, Children>, MutexGuard<'a, Children>) {
|
||||||
let this_key = this.key();
|
let this_key = this.key();
|
||||||
let other_key = other.key();
|
let other_key = other.key();
|
||||||
@ -412,63 +415,63 @@ fn write_lock_children_on_two_dentries<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The DentryMnt can represent a location in the mount tree.
|
/// The Dentry can represent a location in the mount tree.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DentryMnt {
|
pub struct Dentry {
|
||||||
mount_node: Arc<MountNode>,
|
mount_node: Arc<MountNode>,
|
||||||
dentry: Arc<Dentry>,
|
inner: Arc<Dentry_>,
|
||||||
this: Weak<DentryMnt>,
|
this: Weak<Dentry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DentryMnt {
|
impl Dentry {
|
||||||
/// Create a new DentryMnt to represent the root directory of a file system.
|
/// Create a new Dentry to represent the root directory of a file system.
|
||||||
pub fn new_fs_root(mount_node: Arc<MountNode>) -> Arc<Self> {
|
pub fn new_fs_root(mount_node: Arc<MountNode>) -> Arc<Self> {
|
||||||
Self::new(mount_node.clone(), mount_node.root_dentry().clone())
|
Self::new(mount_node.clone(), mount_node.root_dentry().clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Crete a new DentryMnt to represent the child directory of a file system.
|
/// Crete a new Dentry to represent the child directory of a file system.
|
||||||
pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
|
pub fn new_fs_child(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
|
||||||
let new_child_dentry = self.dentry.create(name, type_, mode)?;
|
let new_child_dentry = self.inner.create(name, type_, mode)?;
|
||||||
Ok(Self::new(self.mount_node.clone(), new_child_dentry.clone()))
|
Ok(Self::new(self.mount_node.clone(), new_child_dentry.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal constructor.
|
/// Internal constructor.
|
||||||
fn new(mount_node: Arc<MountNode>, dentry: Arc<Dentry>) -> Arc<Self> {
|
fn new(mount_node: Arc<MountNode>, inner: Arc<Dentry_>) -> Arc<Self> {
|
||||||
Arc::new_cyclic(|weak_self| Self {
|
Arc::new_cyclic(|weak_self| Self {
|
||||||
mount_node,
|
mount_node,
|
||||||
dentry,
|
inner,
|
||||||
this: weak_self.clone(),
|
this: weak_self.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup a dentrymnt.
|
/// Lookup a Dentry.
|
||||||
pub fn lookup(&self, name: &str) -> Result<Arc<Self>> {
|
pub fn lookup(&self, name: &str) -> Result<Arc<Self>> {
|
||||||
if self.dentry.inode().type_() != InodeType::Dir {
|
if self.inner.inode().type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
if !self.dentry.inode().mode()?.is_executable() {
|
if !self.inner.inode().mode()?.is_executable() {
|
||||||
return_errno!(Errno::EACCES);
|
return_errno!(Errno::EACCES);
|
||||||
}
|
}
|
||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
return_errno!(Errno::ENAMETOOLONG);
|
return_errno!(Errno::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dentrymnt = match name {
|
let dentry = match name {
|
||||||
"." => self.this(),
|
"." => self.this(),
|
||||||
".." => self.effective_parent().unwrap_or_else(|| self.this()),
|
".." => self.effective_parent().unwrap_or_else(|| self.this()),
|
||||||
name => {
|
name => {
|
||||||
let children_dentry = self.dentry.lookup_via_cache(name);
|
let children_inner = self.inner.lookup_via_cache(name);
|
||||||
match children_dentry {
|
match children_inner {
|
||||||
Some(dentry) => Self::new(self.mount_node().clone(), dentry.clone()),
|
Some(inner) => Self::new(self.mount_node().clone(), inner.clone()),
|
||||||
None => {
|
None => {
|
||||||
let slow_dentry = self.dentry.lookuop_via_fs(name)?;
|
let fs_inner = self.inner.lookuop_via_fs(name)?;
|
||||||
Self::new(self.mount_node().clone(), slow_dentry.clone())
|
Self::new(self.mount_node().clone(), fs_inner.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let dentrymnt = dentrymnt.get_top_dentrymnt();
|
let dentry = dentry.get_top_dentry();
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the absolute path.
|
/// Get the absolute path.
|
||||||
@ -476,98 +479,99 @@ impl DentryMnt {
|
|||||||
/// It will resolve the mountpoint automatically.
|
/// It will resolve the mountpoint automatically.
|
||||||
pub fn abs_path(&self) -> String {
|
pub fn abs_path(&self) -> String {
|
||||||
let mut path = self.effective_name();
|
let mut path = self.effective_name();
|
||||||
let mut dir_dentrymnt = self.this();
|
let mut dir_dentry = self.this();
|
||||||
|
|
||||||
while let Some(parent_dir_dentrymnt) = dir_dentrymnt.effective_parent() {
|
while let Some(parent_dir_dentry) = dir_dentry.effective_parent() {
|
||||||
path = {
|
path = {
|
||||||
let parent_name = parent_dir_dentrymnt.effective_name();
|
let parent_name = parent_dir_dentry.effective_name();
|
||||||
if parent_name != "/" {
|
if parent_name != "/" {
|
||||||
parent_name + "/" + &path
|
parent_name + "/" + &path
|
||||||
} else {
|
} else {
|
||||||
parent_name + &path
|
parent_name + &path
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
dir_dentrymnt = parent_dir_dentrymnt;
|
dir_dentry = parent_dir_dentry;
|
||||||
}
|
}
|
||||||
debug_assert!(path.starts_with('/'));
|
debug_assert!(path.starts_with('/'));
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the effective name of dentrymnt.
|
/// Get the effective name of Dentry.
|
||||||
///
|
///
|
||||||
/// If it is the root of mount, it will go up to the mountpoint to get the name
|
/// If it is the root of mount, it will go up to the mountpoint to get the name
|
||||||
/// of the mountpoint recursively.
|
/// of the mountpoint recursively.
|
||||||
fn effective_name(&self) -> String {
|
fn effective_name(&self) -> String {
|
||||||
if !self.dentry.is_root_of_mount() {
|
if !self.inner.is_root_of_mount() {
|
||||||
return self.dentry.name();
|
return self.inner.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(parent) = self.mount_node.parent() else {
|
let Some(parent) = self.mount_node.parent() else {
|
||||||
return self.dentry.name();
|
return self.inner.name();
|
||||||
};
|
};
|
||||||
let Some(mountpoint) = self.mount_node.mountpoint_dentry() else {
|
let Some(mountpoint) = self.mount_node.mountpoint_dentry() else {
|
||||||
return self.dentry.name();
|
return self.inner.name();
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_dentrymnt = Self::new(
|
let parent_inner = Self::new(
|
||||||
self.mount_node.parent().unwrap().upgrade().unwrap().clone(),
|
self.mount_node.parent().unwrap().upgrade().unwrap().clone(),
|
||||||
self.mount_node.mountpoint_dentry().unwrap().clone(),
|
self.mount_node.mountpoint_dentry().unwrap().clone(),
|
||||||
);
|
);
|
||||||
parent_dentrymnt.effective_name()
|
parent_inner.effective_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the effective parent of dentrymnt.
|
/// Get the effective parent of Dentry.
|
||||||
///
|
///
|
||||||
/// If it is the root of mount, it will go up to the mountpoint to get the parent
|
/// If it is the root of mount, it will go up to the mountpoint to get the parent
|
||||||
/// of the mountpoint recursively.
|
/// of the mountpoint recursively.
|
||||||
fn effective_parent(&self) -> Option<Arc<Self>> {
|
fn effective_parent(&self) -> Option<Arc<Self>> {
|
||||||
if !self.dentry.is_root_of_mount() {
|
if !self.inner.is_root_of_mount() {
|
||||||
return Some(Self::new(
|
return Some(Self::new(
|
||||||
self.mount_node.clone(),
|
self.mount_node.clone(),
|
||||||
self.dentry.parent().unwrap().clone(),
|
self.inner.parent().unwrap().clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let parent = self.mount_node.parent()?;
|
let parent = self.mount_node.parent()?;
|
||||||
let mountpoint = self.mount_node.mountpoint_dentry()?;
|
let mountpoint = self.mount_node.mountpoint_dentry()?;
|
||||||
|
|
||||||
let parent_dentrymnt = Self::new(parent.upgrade().unwrap(), mountpoint.clone());
|
let parent_dentry = Self::new(parent.upgrade().unwrap(), mountpoint.clone());
|
||||||
parent_dentrymnt.effective_parent()
|
parent_dentry.effective_parent()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the top DentryMnt of self.
|
/// Get the top Dentry of self.
|
||||||
///
|
///
|
||||||
/// When different file systems are mounted on the same mount point.
|
/// When different file systems are mounted on the same mount point.
|
||||||
/// For example, first `mount /dev/sda1 /mnt` and then `mount /dev/sda2 /mnt`.
|
/// For example, first `mount /dev/sda1 /mnt` and then `mount /dev/sda2 /mnt`.
|
||||||
/// After the second mount is completed, the content of the first mount will be overridden.
|
/// After the second mount is completed, the content of the first mount will be overridden.
|
||||||
/// We need to recursively obtain the top DentryMnt.
|
/// We need to recursively obtain the top Dentry.
|
||||||
fn get_top_dentrymnt(&self) -> Arc<Self> {
|
fn get_top_dentry(&self) -> Arc<Self> {
|
||||||
if !self.dentry.is_mountpoint() {
|
if !self.inner.is_mountpoint() {
|
||||||
return self.this();
|
return self.this();
|
||||||
}
|
}
|
||||||
match self.mount_node.get(self) {
|
match self.mount_node.get(self) {
|
||||||
Some(child_mount) => Self::new(child_mount.clone(), child_mount.root_dentry().clone())
|
Some(child_mount) => {
|
||||||
.get_top_dentrymnt(),
|
Self::new(child_mount.clone(), child_mount.root_dentry().clone()).get_top_dentry()
|
||||||
|
}
|
||||||
None => self.this(),
|
None => self.this(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make this DentryMnt's dentry to be a mountpoint,
|
/// Make this Dentry' inner to be a mountpoint,
|
||||||
/// and set the mountpoint of the child mount to this DentryMnt's dentry.
|
/// and set the mountpoint of the child mount to this Dentry's inner.
|
||||||
fn set_mountpoint(&self, child_mount: Arc<MountNode>) {
|
fn set_mountpoint(&self, child_mount: Arc<MountNode>) {
|
||||||
child_mount.set_mountpoint_dentry(self.dentry.clone());
|
child_mount.set_mountpoint_dentry(self.inner.clone());
|
||||||
self.dentry.set_mountpoint();
|
self.inner.set_mountpoint_dentry();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mount the fs on this DentryMnt. It will make this DentryMnt's dentry to be a mountpoint.
|
/// Mount the fs on this Dentry. It will make this Dentry's inner to be a mountpoint.
|
||||||
///
|
///
|
||||||
/// If the given mountpoint has already been mounted, then its mounted child mount
|
/// If the given mountpoint has already been mounted, then its mounted child mount
|
||||||
/// will be updated.
|
/// will be updated.
|
||||||
/// The root dentry cannot be mounted.
|
/// The root Dentry cannot be mounted.
|
||||||
///
|
///
|
||||||
/// Return the mounted child mount.
|
/// Return the mounted child mount.
|
||||||
pub fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountNode>> {
|
pub fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountNode>> {
|
||||||
if self.dentry.inode().type_() != InodeType::Dir {
|
if self.inner.inode().type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
if self.effective_parent().is_none() {
|
if self.effective_parent().is_none() {
|
||||||
@ -582,7 +586,7 @@ impl DentryMnt {
|
|||||||
///
|
///
|
||||||
/// Note that the root mount cannot be unmounted.
|
/// Note that the root mount cannot be unmounted.
|
||||||
pub fn umount(&self) -> Result<Arc<MountNode>> {
|
pub fn umount(&self) -> Result<Arc<MountNode>> {
|
||||||
if !self.dentry.is_root_of_mount() {
|
if !self.inner.is_root_of_mount() {
|
||||||
return_errno_with_message!(Errno::EINVAL, "not mounted");
|
return_errno_with_message!(Errno::EINVAL, "not mounted");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,44 +596,43 @@ impl DentryMnt {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mountpoint_mount_node = mount_node.parent().unwrap().upgrade().unwrap();
|
let mountpoint_mount_node = mount_node.parent().unwrap().upgrade().unwrap();
|
||||||
let mountpoint_dentrymnt =
|
let mountpoint = Self::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone());
|
||||||
Self::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone());
|
|
||||||
|
|
||||||
let child_mount = mountpoint_mount_node.umount(&mountpoint_dentrymnt)?;
|
let child_mount = mountpoint_mount_node.umount(&mountpoint)?;
|
||||||
mountpoint_dentry.clear_mountpoint();
|
mountpoint_dentry.clear_mountpoint();
|
||||||
Ok(child_mount)
|
Ok(child_mount)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a DentryMnt by making a device inode.
|
/// Create a Dentry by making a device inode.
|
||||||
pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Arc<Self>> {
|
pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Arc<Self>> {
|
||||||
let dentry = self.dentry.mknod(name, mode, device)?;
|
let inner = self.inner.mknod(name, mode, device)?;
|
||||||
Ok(Self::new(self.mount_node.clone(), dentry.clone()))
|
Ok(Self::new(self.mount_node.clone(), inner.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Link a new name for the DentryMnt by linking inode.
|
/// Link a new name for the Dentry by linking inode.
|
||||||
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
|
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
|
||||||
if !Arc::ptr_eq(&old.mount_node, &self.mount_node) {
|
if !Arc::ptr_eq(&old.mount_node, &self.mount_node) {
|
||||||
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
|
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
|
||||||
}
|
}
|
||||||
self.dentry.link(&old.dentry, name)
|
self.inner.link(&old.inner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a DentryMnt by unlinking inode.
|
/// Delete a Dentry by unlinking inode.
|
||||||
pub fn unlink(&self, name: &str) -> Result<()> {
|
pub fn unlink(&self, name: &str) -> Result<()> {
|
||||||
self.dentry.unlink(name)
|
self.inner.unlink(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a directory dentry by rmdiring inode.
|
/// Delete a directory Dentry by rmdiring inode.
|
||||||
pub fn rmdir(&self, name: &str) -> Result<()> {
|
pub fn rmdir(&self, name: &str) -> Result<()> {
|
||||||
self.dentry.rmdir(name)
|
self.inner.rmdir(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename a dentry to the new dentry by renaming inode.
|
/// Rename a Dentry to the new Dentry by renaming inode.
|
||||||
pub fn rename(&self, old_name: &str, new_dir: &Arc<Self>, new_name: &str) -> Result<()> {
|
pub fn rename(&self, old_name: &str, new_dir: &Arc<Self>, new_name: &str) -> Result<()> {
|
||||||
if !Arc::ptr_eq(&self.mount_node, &new_dir.mount_node) {
|
if !Arc::ptr_eq(&self.mount_node, &new_dir.mount_node) {
|
||||||
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
|
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
|
||||||
}
|
}
|
||||||
self.dentry.rename(old_name, &new_dir.dentry, new_name)
|
self.inner.rename(old_name, &new_dir.inner, new_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the arc reference to self.
|
/// Get the arc reference to self.
|
||||||
@ -637,14 +640,14 @@ impl DentryMnt {
|
|||||||
self.this.upgrade().unwrap()
|
self.this.upgrade().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the mount node of this dentrymnt.
|
/// Get the mount node of this Dentry.
|
||||||
pub fn mount_node(&self) -> &Arc<MountNode> {
|
pub fn mount_node(&self) -> &Arc<MountNode> {
|
||||||
&self.mount_node
|
&self.mount_node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inherit_methods(from = "self.dentry")]
|
#[inherit_methods(from = "self.inner")]
|
||||||
impl DentryMnt {
|
impl Dentry {
|
||||||
pub fn fs(&self) -> Arc<dyn FileSystem>;
|
pub fn fs(&self) -> Arc<dyn FileSystem>;
|
||||||
pub fn sync(&self) -> Result<()>;
|
pub fn sync(&self) -> Result<()>;
|
||||||
pub fn metadata(&self) -> Metadata;
|
pub fn metadata(&self) -> Metadata;
|
9
kernel/aster-nix/src/fs/path/mod.rs
Normal file
9
kernel/aster-nix/src/fs/path/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
//! Form file paths within and across FSes with dentries and mount points.
|
||||||
|
|
||||||
|
pub use dentry::{Dentry, DentryKey};
|
||||||
|
pub use mount::MountNode;
|
||||||
|
|
||||||
|
mod dentry;
|
||||||
|
mod mount;
|
@ -1,15 +1,20 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use super::{Dentry, DentryKey, DentryMnt, FileSystem, InodeType};
|
use crate::{
|
||||||
use crate::prelude::*;
|
fs::{
|
||||||
|
path::dentry::{Dentry, DentryKey, Dentry_},
|
||||||
|
utils::{FileSystem, InodeType},
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
/// The MountNode can form a mount tree to maintain the mount information.
|
/// The MountNode can form a mount tree to maintain the mount information.
|
||||||
pub struct MountNode {
|
pub struct MountNode {
|
||||||
/// Root dentry.
|
/// Root Dentry_.
|
||||||
root_dentry: Arc<Dentry>,
|
root_dentry: Arc<Dentry_>,
|
||||||
/// Mountpoint dentry. A mount node can be mounted on one dentry of another mount node,
|
/// Mountpoint Dentry_. A mount node can be mounted on one dentry of another mount node,
|
||||||
/// which makes the mount being the child of the mount node.
|
/// which makes the mount being the child of the mount node.
|
||||||
mountpoint_dentry: RwLock<Option<Arc<Dentry>>>,
|
mountpoint_dentry: RwLock<Option<Arc<Dentry_>>>,
|
||||||
/// The associated FS.
|
/// The associated FS.
|
||||||
fs: Arc<dyn FileSystem>,
|
fs: Arc<dyn FileSystem>,
|
||||||
/// The parent mount node.
|
/// The parent mount node.
|
||||||
@ -24,7 +29,7 @@ impl MountNode {
|
|||||||
/// Create a root mount node with an associated FS.
|
/// Create a root mount node with an associated FS.
|
||||||
///
|
///
|
||||||
/// The root mount node is not mounted on other mount nodes(which means it has no
|
/// The root mount node is not mounted on other mount nodes(which means it has no
|
||||||
/// parent). The root inode of the fs will form the root dentry of it.
|
/// parent). The root inode of the fs will form the root dentryinner of it.
|
||||||
///
|
///
|
||||||
/// It is allowed to create a mount node even if the fs has been provided to another
|
/// It is allowed to create a mount node even if the fs has been provided to another
|
||||||
/// mount node. It is the fs's responsibility to ensure the data consistency.
|
/// mount node. It is the fs's responsibility to ensure the data consistency.
|
||||||
@ -42,7 +47,7 @@ impl MountNode {
|
|||||||
/// mount nodes must be explicitly assigned a mountpoint to maintain structural integrity.
|
/// mount nodes must be explicitly assigned a mountpoint to maintain structural integrity.
|
||||||
fn new(fs: Arc<dyn FileSystem>, parent_mount: Option<Weak<MountNode>>) -> Arc<Self> {
|
fn new(fs: Arc<dyn FileSystem>, parent_mount: Option<Weak<MountNode>>) -> Arc<Self> {
|
||||||
Arc::new_cyclic(|weak_self| Self {
|
Arc::new_cyclic(|weak_self| Self {
|
||||||
root_dentry: Dentry::new_root(fs.root_inode()),
|
root_dentry: Dentry_::new_root(fs.root_inode()),
|
||||||
mountpoint_dentry: RwLock::new(None),
|
mountpoint_dentry: RwLock::new(None),
|
||||||
parent: RwLock::new(parent_mount),
|
parent: RwLock::new(parent_mount),
|
||||||
children: Mutex::new(BTreeMap::new()),
|
children: Mutex::new(BTreeMap::new()),
|
||||||
@ -62,7 +67,7 @@ impl MountNode {
|
|||||||
/// mountpoint. It is the fs's responsibility to ensure the data consistency.
|
/// mountpoint. It is the fs's responsibility to ensure the data consistency.
|
||||||
///
|
///
|
||||||
/// Return the mounted child mount.
|
/// Return the mounted child mount.
|
||||||
pub fn mount(&self, fs: Arc<dyn FileSystem>, mountpoint: &Arc<DentryMnt>) -> Result<Arc<Self>> {
|
pub fn mount(&self, fs: Arc<dyn FileSystem>, mountpoint: &Arc<Dentry>) -> Result<Arc<Self>> {
|
||||||
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
||||||
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
|
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
|
||||||
}
|
}
|
||||||
@ -79,7 +84,7 @@ impl MountNode {
|
|||||||
/// Unmount a child mount node from the mountpoint and return it.
|
/// Unmount a child mount node from the mountpoint and return it.
|
||||||
///
|
///
|
||||||
/// The mountpoint should belong to this mount node, or an error is returned.
|
/// The mountpoint should belong to this mount node, or an error is returned.
|
||||||
pub fn umount(&self, mountpoint: &DentryMnt) -> Result<Arc<Self>> {
|
pub fn umount(&self, mountpoint: &Dentry) -> Result<Arc<Self>> {
|
||||||
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
||||||
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
|
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
|
||||||
}
|
}
|
||||||
@ -93,20 +98,20 @@ impl MountNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Try to get a child mount node from the mountpoint.
|
/// Try to get a child mount node from the mountpoint.
|
||||||
pub fn get(&self, mountpoint: &DentryMnt) -> Option<Arc<Self>> {
|
pub fn get(&self, mountpoint: &Dentry) -> Option<Arc<Self>> {
|
||||||
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.children.lock().get(&mountpoint.key()).cloned()
|
self.children.lock().get(&mountpoint.key()).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the root dentry of this mount node.
|
/// Get the root Dentry_ of this mount node.
|
||||||
pub fn root_dentry(&self) -> &Arc<Dentry> {
|
pub fn root_dentry(&self) -> &Arc<Dentry_> {
|
||||||
&self.root_dentry
|
&self.root_dentry
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to get the mountpoint dentry of this mount node.
|
/// Try to get the mountpoint Dentry_ of this mount node.
|
||||||
pub fn mountpoint_dentry(&self) -> Option<Arc<Dentry>> {
|
pub fn mountpoint_dentry(&self) -> Option<Arc<Dentry_>> {
|
||||||
self.mountpoint_dentry.read().clone()
|
self.mountpoint_dentry.read().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,9 +119,9 @@ impl MountNode {
|
|||||||
///
|
///
|
||||||
/// In some cases we may need to reset the mountpoint of
|
/// In some cases we may need to reset the mountpoint of
|
||||||
/// the created MountNode, such as move mount.
|
/// the created MountNode, such as move mount.
|
||||||
pub fn set_mountpoint_dentry(&self, dentry: Arc<Dentry>) {
|
pub fn set_mountpoint_dentry(&self, inner: Arc<Dentry_>) {
|
||||||
let mut mountpoint_dentry = self.mountpoint_dentry.write();
|
let mut mountpoint_dentry = self.mountpoint_dentry.write();
|
||||||
*mountpoint_dentry = Some(dentry);
|
*mountpoint_dentry = Some(inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flushes all pending filesystem metadata and cached file data to the device.
|
/// Flushes all pending filesystem metadata and cached file data to the device.
|
@ -77,7 +77,7 @@ impl FileSymOps {
|
|||||||
impl SymOps for FileSymOps {
|
impl SymOps for FileSymOps {
|
||||||
fn read_link(&self) -> Result<String> {
|
fn read_link(&self) -> Result<String> {
|
||||||
let path = if let Some(inode_handle) = self.0.downcast_ref::<InodeHandle>() {
|
let path = if let Some(inode_handle) = self.0.downcast_ref::<InodeHandle>() {
|
||||||
inode_handle.dentrymnt().abs_path()
|
inode_handle.dentry().abs_path()
|
||||||
} else {
|
} else {
|
||||||
// TODO: get the real path for other FileLike object
|
// TODO: get the real path for other FileLike object
|
||||||
String::from("/dev/tty")
|
String::from("/dev/tty")
|
||||||
|
@ -7,9 +7,10 @@ use spin::Once;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
fs_resolver::{FsPath, FsResolver},
|
fs_resolver::{FsPath, FsResolver},
|
||||||
|
path::MountNode,
|
||||||
procfs::ProcFS,
|
procfs::ProcFS,
|
||||||
ramfs::RamFS,
|
ramfs::RamFS,
|
||||||
utils::{FileSystem, InodeMode, InodeType, MountNode},
|
utils::{FileSystem, InodeMode, InodeType},
|
||||||
};
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
@ -54,20 +55,20 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> {
|
|||||||
let mode = InodeMode::from_bits_truncate(metadata.permission_mode());
|
let mode = InodeMode::from_bits_truncate(metadata.permission_mode());
|
||||||
match metadata.file_type() {
|
match metadata.file_type() {
|
||||||
FileType::File => {
|
FileType::File => {
|
||||||
let dentrymnt = parent.new_fs_child(name, InodeType::File, mode)?;
|
let dentry = parent.new_fs_child(name, InodeType::File, mode)?;
|
||||||
entry.read_all(dentrymnt.inode().writer(0))?;
|
entry.read_all(dentry.inode().writer(0))?;
|
||||||
}
|
}
|
||||||
FileType::Dir => {
|
FileType::Dir => {
|
||||||
let _ = parent.new_fs_child(name, InodeType::Dir, mode)?;
|
let _ = parent.new_fs_child(name, InodeType::Dir, mode)?;
|
||||||
}
|
}
|
||||||
FileType::Link => {
|
FileType::Link => {
|
||||||
let dentrymnt = parent.new_fs_child(name, InodeType::SymLink, mode)?;
|
let dentry = parent.new_fs_child(name, InodeType::SymLink, mode)?;
|
||||||
let link_content = {
|
let link_content = {
|
||||||
let mut link_data: Vec<u8> = Vec::new();
|
let mut link_data: Vec<u8> = Vec::new();
|
||||||
entry.read_all(&mut link_data)?;
|
entry.read_all(&mut link_data)?;
|
||||||
core::str::from_utf8(&link_data)?.to_string()
|
core::str::from_utf8(&link_data)?.to_string()
|
||||||
};
|
};
|
||||||
dentrymnt.inode().write_link(&link_content)?;
|
dentry.inode().write_link(&link_content)?;
|
||||||
}
|
}
|
||||||
type_ => {
|
type_ => {
|
||||||
panic!("unsupported file type = {:?} in initramfs", type_);
|
panic!("unsupported file type = {:?} in initramfs", type_);
|
||||||
@ -75,11 +76,11 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Mount ProcFS
|
// Mount ProcFS
|
||||||
let proc_dentrymnt = fs.lookup(&FsPath::try_from("/proc")?)?;
|
let proc_dentry = fs.lookup(&FsPath::try_from("/proc")?)?;
|
||||||
proc_dentrymnt.mount(ProcFS::new())?;
|
proc_dentry.mount(ProcFS::new())?;
|
||||||
// Mount DevFS
|
// Mount DevFS
|
||||||
let dev_dentrymnt = fs.lookup(&FsPath::try_from("/dev")?)?;
|
let dev_dentry = fs.lookup(&FsPath::try_from("/dev")?)?;
|
||||||
dev_dentrymnt.mount(RamFS::new())?;
|
dev_dentry.mount(RamFS::new())?;
|
||||||
|
|
||||||
println!("[kernel] rootfs is ready");
|
println!("[kernel] rootfs is ready");
|
||||||
|
|
||||||
@ -87,8 +88,8 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount_fs_at(fs: Arc<dyn FileSystem>, fs_path: &FsPath) -> Result<()> {
|
pub fn mount_fs_at(fs: Arc<dyn FileSystem>, fs_path: &FsPath) -> Result<()> {
|
||||||
let target_dentrymnt = FsResolver::new().lookup(fs_path)?;
|
let target_dentry = FsResolver::new().lookup(fs_path)?;
|
||||||
target_dentrymnt.mount(fs)?;
|
target_dentry.mount(fs)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,14 +5,12 @@
|
|||||||
pub use access_mode::AccessMode;
|
pub use access_mode::AccessMode;
|
||||||
pub use channel::{Channel, Consumer, Producer};
|
pub use channel::{Channel, Consumer, Producer};
|
||||||
pub use creation_flags::CreationFlags;
|
pub use creation_flags::CreationFlags;
|
||||||
pub use dentry::{Dentry, DentryKey, DentryMnt};
|
|
||||||
pub use dirent_visitor::DirentVisitor;
|
pub use dirent_visitor::DirentVisitor;
|
||||||
pub use direntry_vec::DirEntryVecExt;
|
pub use direntry_vec::DirEntryVecExt;
|
||||||
pub use file_creation_mask::FileCreationMask;
|
pub use file_creation_mask::FileCreationMask;
|
||||||
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
||||||
pub use inode::{Inode, InodeMode, InodeType, Metadata};
|
pub use inode::{Inode, InodeMode, InodeType, Metadata};
|
||||||
pub use ioctl::IoctlCmd;
|
pub use ioctl::IoctlCmd;
|
||||||
pub use mount::MountNode;
|
|
||||||
pub use page_cache::{PageCache, PageCacheBackend};
|
pub use page_cache::{PageCache, PageCacheBackend};
|
||||||
pub use random_test::{generate_random_operation, new_fs_in_memory};
|
pub use random_test::{generate_random_operation, new_fs_in_memory};
|
||||||
pub use status_flags::StatusFlags;
|
pub use status_flags::StatusFlags;
|
||||||
@ -20,14 +18,12 @@ pub use status_flags::StatusFlags;
|
|||||||
mod access_mode;
|
mod access_mode;
|
||||||
mod channel;
|
mod channel;
|
||||||
mod creation_flags;
|
mod creation_flags;
|
||||||
mod dentry;
|
|
||||||
mod dirent_visitor;
|
mod dirent_visitor;
|
||||||
mod direntry_vec;
|
mod direntry_vec;
|
||||||
mod file_creation_mask;
|
mod file_creation_mask;
|
||||||
mod fs;
|
mod fs;
|
||||||
mod inode;
|
mod inode;
|
||||||
mod ioctl;
|
mod ioctl;
|
||||||
mod mount;
|
|
||||||
mod page_cache;
|
mod page_cache;
|
||||||
mod random_test;
|
mod random_test;
|
||||||
mod status_flags;
|
mod status_flags;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use crate::{fs::utils::DentryMnt, net::socket::util::socket_addr::SocketAddr, prelude::*};
|
use crate::{fs::path::Dentry, net::socket::util::socket_addr::SocketAddr, prelude::*};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum UnixSocketAddr {
|
pub enum UnixSocketAddr {
|
||||||
@ -10,7 +10,7 @@ pub enum UnixSocketAddr {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(super) enum UnixSocketAddrBound {
|
pub(super) enum UnixSocketAddrBound {
|
||||||
Path(Arc<DentryMnt>),
|
Path(Arc<Dentry>),
|
||||||
Abstract(String),
|
Abstract(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ impl TryFrom<SocketAddr> for UnixSocketAddr {
|
|||||||
impl From<UnixSocketAddrBound> for UnixSocketAddr {
|
impl From<UnixSocketAddrBound> for UnixSocketAddr {
|
||||||
fn from(value: UnixSocketAddrBound) -> Self {
|
fn from(value: UnixSocketAddrBound) -> Self {
|
||||||
match value {
|
match value {
|
||||||
UnixSocketAddrBound::Path(dentrymnt) => {
|
UnixSocketAddrBound::Path(dentry) => {
|
||||||
let abs_path = dentrymnt.abs_path();
|
let abs_path = dentry.abs_path();
|
||||||
Self::Path(abs_path)
|
Self::Path(abs_path)
|
||||||
}
|
}
|
||||||
UnixSocketAddrBound::Abstract(name) => Self::Abstract(name),
|
UnixSocketAddrBound::Abstract(name) => Self::Abstract(name),
|
||||||
|
@ -7,7 +7,8 @@ use crate::{
|
|||||||
events::IoEvents,
|
events::IoEvents,
|
||||||
fs::{
|
fs::{
|
||||||
fs_resolver::{split_path, FsPath},
|
fs_resolver::{split_path, FsPath},
|
||||||
utils::{DentryMnt, InodeMode, InodeType},
|
path::Dentry,
|
||||||
|
utils::{InodeMode, InodeType},
|
||||||
},
|
},
|
||||||
net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
|
net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -38,8 +39,8 @@ impl Init {
|
|||||||
let bound_addr = match addr_to_bind {
|
let bound_addr = match addr_to_bind {
|
||||||
UnixSocketAddr::Abstract(_) => todo!(),
|
UnixSocketAddr::Abstract(_) => todo!(),
|
||||||
UnixSocketAddr::Path(path) => {
|
UnixSocketAddr::Path(path) => {
|
||||||
let dentrymnt = create_socket_file(path)?;
|
let dentry = create_socket_file(path)?;
|
||||||
UnixSocketAddrBound::Path(dentrymnt)
|
UnixSocketAddrBound::Path(dentry)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ impl Init {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_socket_file(path: &str) -> Result<Arc<DentryMnt>> {
|
fn create_socket_file(path: &str) -> Result<Arc<Dentry>> {
|
||||||
let (parent_pathname, file_name) = split_path(path);
|
let (parent_pathname, file_name) = split_path(path);
|
||||||
let parent = {
|
let parent = {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
@ -95,10 +96,10 @@ fn create_socket_file(path: &str) -> Result<Arc<DentryMnt>> {
|
|||||||
let parent_path = FsPath::try_from(parent_pathname)?;
|
let parent_path = FsPath::try_from(parent_pathname)?;
|
||||||
fs.lookup(&parent_path)?
|
fs.lookup(&parent_path)?
|
||||||
};
|
};
|
||||||
let dentrymnt = parent.new_fs_child(
|
let dentry = parent.new_fs_child(
|
||||||
file_name,
|
file_name,
|
||||||
InodeType::Socket,
|
InodeType::Socket,
|
||||||
InodeMode::S_IRUSR | InodeMode::S_IWUSR,
|
InodeMode::S_IRUSR | InodeMode::S_IWUSR,
|
||||||
)?;
|
)?;
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,7 @@ use keyable_arc::KeyableWeak;
|
|||||||
use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket};
|
use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket};
|
||||||
use crate::{
|
use crate::{
|
||||||
events::IoEvents,
|
events::IoEvents,
|
||||||
fs::{
|
fs::{file_handle::FileLike, path::Dentry, utils::Inode},
|
||||||
file_handle::FileLike,
|
|
||||||
utils::{DentryMnt, Inode},
|
|
||||||
},
|
|
||||||
net::socket::{
|
net::socket::{
|
||||||
unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
|
unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
|
||||||
SocketAddr,
|
SocketAddr,
|
||||||
@ -91,10 +88,10 @@ impl BacklogTable {
|
|||||||
|
|
||||||
fn add_backlog(&self, addr: &UnixSocketAddrBound, backlog: usize) -> Result<()> {
|
fn add_backlog(&self, addr: &UnixSocketAddrBound, backlog: usize) -> Result<()> {
|
||||||
let inode = {
|
let inode = {
|
||||||
let UnixSocketAddrBound::Path(dentrymnt) = addr else {
|
let UnixSocketAddrBound::Path(dentry) = addr else {
|
||||||
todo!()
|
todo!()
|
||||||
};
|
};
|
||||||
create_keyable_inode(dentrymnt)
|
create_keyable_inode(dentry)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut backlog_sockets = self.backlog_sockets.write();
|
let mut backlog_sockets = self.backlog_sockets.write();
|
||||||
@ -108,10 +105,10 @@ impl BacklogTable {
|
|||||||
|
|
||||||
fn get_backlog(&self, addr: &UnixSocketAddrBound) -> Result<Arc<Backlog>> {
|
fn get_backlog(&self, addr: &UnixSocketAddrBound) -> Result<Arc<Backlog>> {
|
||||||
let inode = {
|
let inode = {
|
||||||
let UnixSocketAddrBound::Path(dentrymnt) = addr else {
|
let UnixSocketAddrBound::Path(dentry) = addr else {
|
||||||
todo!()
|
todo!()
|
||||||
};
|
};
|
||||||
create_keyable_inode(dentrymnt)
|
create_keyable_inode(dentry)
|
||||||
};
|
};
|
||||||
|
|
||||||
let backlog_sockets = self.backlog_sockets.read();
|
let backlog_sockets = self.backlog_sockets.read();
|
||||||
@ -162,11 +159,11 @@ impl BacklogTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn remove_backlog(&self, addr: &UnixSocketAddrBound) {
|
fn remove_backlog(&self, addr: &UnixSocketAddrBound) {
|
||||||
let UnixSocketAddrBound::Path(dentrymnt) = addr else {
|
let UnixSocketAddrBound::Path(dentry) = addr else {
|
||||||
todo!()
|
todo!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let inode = create_keyable_inode(dentrymnt);
|
let inode = create_keyable_inode(dentry);
|
||||||
self.backlog_sockets.write().remove(&inode);
|
self.backlog_sockets.write().remove(&inode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,8 +209,8 @@ impl Backlog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_keyable_inode(dentrymnt: &Arc<DentryMnt>) -> KeyableWeak<dyn Inode> {
|
fn create_keyable_inode(dentry: &Arc<Dentry>) -> KeyableWeak<dyn Inode> {
|
||||||
let weak_inode = Arc::downgrade(dentrymnt.inode());
|
let weak_inode = Arc::downgrade(dentry.inode());
|
||||||
KeyableWeak::from(weak_inode)
|
KeyableWeak::from(weak_inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,8 @@ use crate::{
|
|||||||
fs::{
|
fs::{
|
||||||
file_handle::FileLike,
|
file_handle::FileLike,
|
||||||
fs_resolver::FsPath,
|
fs_resolver::FsPath,
|
||||||
utils::{DentryMnt, InodeType, StatusFlags},
|
path::Dentry,
|
||||||
|
utils::{InodeType, StatusFlags},
|
||||||
},
|
},
|
||||||
net::socket::{
|
net::socket::{
|
||||||
unix::{addr::UnixSocketAddrBound, UnixSocketAddr},
|
unix::{addr::UnixSocketAddrBound, UnixSocketAddr},
|
||||||
@ -162,8 +163,8 @@ impl Socket for UnixStreamSocket {
|
|||||||
UnixSocketAddrBound::Abstract(abstract_name)
|
UnixSocketAddrBound::Abstract(abstract_name)
|
||||||
}
|
}
|
||||||
UnixSocketAddr::Path(path) => {
|
UnixSocketAddr::Path(path) => {
|
||||||
let dentrymnt = lookup_socket_file(&path)?;
|
let dentry = lookup_socket_file(&path)?;
|
||||||
UnixSocketAddrBound::Path(dentrymnt)
|
UnixSocketAddrBound::Path(dentry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -287,20 +288,20 @@ impl Drop for UnixStreamSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_socket_file(path: &str) -> Result<Arc<DentryMnt>> {
|
fn lookup_socket_file(path: &str) -> Result<Arc<Dentry>> {
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let fs = current.fs().read();
|
let fs = current.fs().read();
|
||||||
let fs_path = FsPath::try_from(path)?;
|
let fs_path = FsPath::try_from(path)?;
|
||||||
fs.lookup(&fs_path)?
|
fs.lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
|
|
||||||
if dentrymnt.type_() != InodeType::Socket {
|
if dentry.type_() != InodeType::Socket {
|
||||||
return_errno_with_message!(Errno::ENOTSOCK, "not a socket file")
|
return_errno_with_message!(Errno::ENOTSOCK, "not a socket file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dentrymnt.mode()?.is_readable() || !dentrymnt.mode()?.is_writable() {
|
if !dentry.mode()?.is_readable() || !dentry.mode()?.is_writable() {
|
||||||
return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written")
|
return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written")
|
||||||
}
|
}
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ impl PosixThreadExt for Thread {
|
|||||||
fs_resolver.lookup(&fs_path)?
|
fs_resolver.lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
let (_, elf_load_info) =
|
let (_, elf_load_info) =
|
||||||
load_program_to_vm(process_vm, elf_file.clone(), argv, envp, fs_resolver, 1)?;
|
load_program_to_vm(process_vm, elf_file, argv, envp, fs_resolver, 1)?;
|
||||||
|
|
||||||
let vm_space = process_vm.root_vmar().vm_space().clone();
|
let vm_space = process_vm.root_vmar().vm_space().clone();
|
||||||
let mut cpu_ctx = UserContext::default();
|
let mut cpu_ctx = UserContext::default();
|
||||||
|
@ -12,7 +12,7 @@ use super::elf_file::Elf;
|
|||||||
use crate::{
|
use crate::{
|
||||||
fs::{
|
fs::{
|
||||||
fs_resolver::{FsPath, FsResolver, AT_FDCWD},
|
fs_resolver::{FsPath, FsResolver, AT_FDCWD},
|
||||||
utils::DentryMnt,
|
path::Dentry,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{
|
process::{
|
||||||
@ -35,7 +35,7 @@ use crate::{
|
|||||||
pub fn load_elf_to_vm(
|
pub fn load_elf_to_vm(
|
||||||
process_vm: &ProcessVm,
|
process_vm: &ProcessVm,
|
||||||
file_header: &[u8],
|
file_header: &[u8],
|
||||||
elf_file: Arc<DentryMnt>,
|
elf_file: Arc<Dentry>,
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
@ -93,7 +93,7 @@ fn lookup_and_parse_ldso(
|
|||||||
elf: &Elf,
|
elf: &Elf,
|
||||||
file_header: &[u8],
|
file_header: &[u8],
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
) -> Result<(Arc<DentryMnt>, Elf)> {
|
) -> Result<(Arc<Dentry>, Elf)> {
|
||||||
let ldso_file = {
|
let ldso_file = {
|
||||||
let ldso_path = elf.ldso_path(file_header)?;
|
let ldso_path = elf.ldso_path(file_header)?;
|
||||||
let fs_path = FsPath::new(AT_FDCWD, &ldso_path)?;
|
let fs_path = FsPath::new(AT_FDCWD, &ldso_path)?;
|
||||||
@ -105,14 +105,10 @@ fn lookup_and_parse_ldso(
|
|||||||
inode.read_at(0, &mut *buf)?;
|
inode.read_at(0, &mut *buf)?;
|
||||||
Elf::parse_elf(&*buf)?
|
Elf::parse_elf(&*buf)?
|
||||||
};
|
};
|
||||||
Ok((ldso_file.clone(), ldso_elf))
|
Ok((ldso_file, ldso_elf))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_ldso(
|
fn load_ldso(root_vmar: &Vmar<Full>, ldso_file: &Dentry, ldso_elf: &Elf) -> Result<LdsoLoadInfo> {
|
||||||
root_vmar: &Vmar<Full>,
|
|
||||||
ldso_file: &DentryMnt,
|
|
||||||
ldso_elf: &Elf,
|
|
||||||
) -> Result<LdsoLoadInfo> {
|
|
||||||
let map_addr = map_segment_vmos(ldso_elf, root_vmar, ldso_file)?;
|
let map_addr = map_segment_vmos(ldso_elf, root_vmar, ldso_file)?;
|
||||||
Ok(LdsoLoadInfo::new(
|
Ok(LdsoLoadInfo::new(
|
||||||
ldso_elf.entry_point() + map_addr,
|
ldso_elf.entry_point() + map_addr,
|
||||||
@ -122,9 +118,9 @@ fn load_ldso(
|
|||||||
|
|
||||||
fn init_and_map_vmos(
|
fn init_and_map_vmos(
|
||||||
process_vm: &ProcessVm,
|
process_vm: &ProcessVm,
|
||||||
ldso: Option<(Arc<DentryMnt>, Elf)>,
|
ldso: Option<(Arc<Dentry>, Elf)>,
|
||||||
parsed_elf: &Elf,
|
parsed_elf: &Elf,
|
||||||
elf_file: &DentryMnt,
|
elf_file: &Dentry,
|
||||||
) -> Result<(Vaddr, AuxVec)> {
|
) -> Result<(Vaddr, AuxVec)> {
|
||||||
let root_vmar = process_vm.root_vmar();
|
let root_vmar = process_vm.root_vmar();
|
||||||
|
|
||||||
@ -203,7 +199,7 @@ impl ElfLoadInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// init vmo for each segment and then map segment to root vmar
|
/// init vmo for each segment and then map segment to root vmar
|
||||||
pub fn map_segment_vmos(elf: &Elf, root_vmar: &Vmar<Full>, elf_file: &DentryMnt) -> Result<Vaddr> {
|
pub fn map_segment_vmos(elf: &Elf, root_vmar: &Vmar<Full>, elf_file: &Dentry) -> Result<Vaddr> {
|
||||||
// all segments of the shared object must be mapped to a continuous vm range
|
// all segments of the shared object must be mapped to a continuous vm range
|
||||||
// to ensure the relative offset of each segment not changed.
|
// to ensure the relative offset of each segment not changed.
|
||||||
let base_addr = if elf.is_shared_object() {
|
let base_addr = if elf.is_shared_object() {
|
||||||
@ -292,10 +288,7 @@ fn map_segment_vmo(
|
|||||||
|
|
||||||
/// Create VMO for each segment. Return the segment VMO and the size of
|
/// Create VMO for each segment. Return the segment VMO and the size of
|
||||||
/// additional anonymous mapping it needs.
|
/// additional anonymous mapping it needs.
|
||||||
fn init_segment_vmo(
|
fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result<(Vmo, usize)> {
|
||||||
program_header: &ProgramHeader64,
|
|
||||||
elf_file: &DentryMnt,
|
|
||||||
) -> Result<(Vmo, usize)> {
|
|
||||||
trace!(
|
trace!(
|
||||||
"mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}",
|
"mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}",
|
||||||
program_header.virtual_addr,
|
program_header.virtual_addr,
|
||||||
|
@ -11,7 +11,7 @@ use super::process_vm::ProcessVm;
|
|||||||
use crate::{
|
use crate::{
|
||||||
fs::{
|
fs::{
|
||||||
fs_resolver::{FsPath, FsResolver, AT_FDCWD},
|
fs_resolver::{FsPath, FsResolver, AT_FDCWD},
|
||||||
utils::DentryMnt,
|
path::Dentry,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
@ -25,7 +25,7 @@ use crate::{
|
|||||||
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
|
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
|
||||||
pub fn load_program_to_vm(
|
pub fn load_program_to_vm(
|
||||||
process_vm: &ProcessVm,
|
process_vm: &ProcessVm,
|
||||||
elf_file: Arc<DentryMnt>,
|
elf_file: Arc<Dentry>,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
@ -68,16 +68,16 @@ pub fn load_program_to_vm(
|
|||||||
Ok((abs_path, elf_load_info))
|
Ok((abs_path, elf_load_info))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_executable_file(dentrymnt: &Arc<DentryMnt>) -> Result<()> {
|
pub fn check_executable_file(dentry: &Arc<Dentry>) -> Result<()> {
|
||||||
if dentrymnt.type_().is_directory() {
|
if dentry.type_().is_directory() {
|
||||||
return_errno_with_message!(Errno::EISDIR, "the file is a directory");
|
return_errno_with_message!(Errno::EISDIR, "the file is a directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dentrymnt.type_().is_reguler_file() {
|
if !dentry.type_().is_reguler_file() {
|
||||||
return_errno_with_message!(Errno::EACCES, "the dentry is not a regular file");
|
return_errno_with_message!(Errno::EACCES, "the dentry is not a regular file");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dentrymnt.mode()?.is_executable() {
|
if !dentry.mode()?.is_executable() {
|
||||||
return_errno_with_message!(Errno::EACCES, "the dentry is not executable");
|
return_errno_with_message!(Errno::EACCES, "the dentry is not executable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ pub fn sys_chdir(path_ptr: Vaddr) -> Result<SyscallReturn> {
|
|||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let mut fs = current.fs().write();
|
let mut fs = current.fs().write();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -24,10 +24,10 @@ pub fn sys_chdir(path_ptr: Vaddr) -> Result<SyscallReturn> {
|
|||||||
let fs_path = FsPath::try_from(path.as_ref())?;
|
let fs_path = FsPath::try_from(path.as_ref())?;
|
||||||
fs.lookup(&fs_path)?
|
fs.lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
if dentrymnt.type_() != InodeType::Dir {
|
if dentry.type_() != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
||||||
}
|
}
|
||||||
fs.set_cwd(dentrymnt);
|
fs.set_cwd(dentry);
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,17 +36,17 @@ pub fn sys_fchdir(fd: FileDesc) -> Result<SyscallReturn> {
|
|||||||
debug!("fd = {}", fd);
|
debug!("fd = {}", fd);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let file_table = current.file_table().lock();
|
let file_table = current.file_table().lock();
|
||||||
let file = file_table.get_file(fd)?;
|
let file = file_table.get_file(fd)?;
|
||||||
let inode_handle = file
|
let inode_handle = file
|
||||||
.downcast_ref::<InodeHandle>()
|
.downcast_ref::<InodeHandle>()
|
||||||
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
||||||
inode_handle.dentrymnt().clone()
|
inode_handle.dentry().clone()
|
||||||
};
|
};
|
||||||
if dentrymnt.type_() != InodeType::Dir {
|
if dentry.type_() != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
||||||
}
|
}
|
||||||
current.fs().write().set_cwd(dentrymnt);
|
current.fs().write().set_cwd(dentry);
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ pub fn sys_fchmodat(
|
|||||||
debug!("dirfd = {}, path = {:?}, mode = 0o{:o}", dirfd, path, mode,);
|
debug!("dirfd = {}, path = {:?}, mode = 0o{:o}", dirfd, path, mode,);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -47,6 +47,6 @@ pub fn sys_fchmodat(
|
|||||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||||
current.fs().read().lookup(&fs_path)?
|
current.fs().read().lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
dentrymnt.set_mode(InodeMode::from_bits_truncate(mode))?;
|
dentry.set_mode(InodeMode::from_bits_truncate(mode))?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ pub fn sys_fchownat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||||
let fs = current.fs().read();
|
let fs = current.fs().read();
|
||||||
@ -90,10 +90,10 @@ pub fn sys_fchownat(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(uid) = uid {
|
if let Some(uid) = uid {
|
||||||
dentrymnt.set_owner(uid)?;
|
dentry.set_owner(uid)?;
|
||||||
}
|
}
|
||||||
if let Some(gid) = gid {
|
if let Some(gid) = gid {
|
||||||
dentrymnt.set_group(gid)?;
|
dentry.set_group(gid)?;
|
||||||
}
|
}
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ pub fn sys_chroot(path_ptr: Vaddr) -> Result<SyscallReturn> {
|
|||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let mut fs = current.fs().write();
|
let mut fs = current.fs().write();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -24,9 +24,9 @@ pub fn sys_chroot(path_ptr: Vaddr) -> Result<SyscallReturn> {
|
|||||||
let fs_path = FsPath::try_from(path.as_ref())?;
|
let fs_path = FsPath::try_from(path.as_ref())?;
|
||||||
fs.lookup(&fs_path)?
|
fs.lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
if dentrymnt.type_() != InodeType::Dir {
|
if dentry.type_() != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
||||||
}
|
}
|
||||||
fs.set_root(dentrymnt);
|
fs.set_root(dentry);
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@ use crate::{
|
|||||||
fs::{
|
fs::{
|
||||||
file_table::FileDesc,
|
file_table::FileDesc,
|
||||||
fs_resolver::{FsPath, AT_FDCWD},
|
fs_resolver::{FsPath, AT_FDCWD},
|
||||||
utils::{DentryMnt, InodeType},
|
path::Dentry,
|
||||||
|
utils::InodeType,
|
||||||
},
|
},
|
||||||
log_syscall_entry,
|
log_syscall_entry,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -61,29 +62,29 @@ fn lookup_executable_file(
|
|||||||
dfd: FileDesc,
|
dfd: FileDesc,
|
||||||
filename: String,
|
filename: String,
|
||||||
flags: OpenFlags,
|
flags: OpenFlags,
|
||||||
) -> Result<Arc<DentryMnt>> {
|
) -> Result<Arc<Dentry>> {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let fs_resolver = current.fs().read();
|
let fs_resolver = current.fs().read();
|
||||||
let dentrymnt = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() {
|
let dentry = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() {
|
||||||
fs_resolver.lookup_from_fd(dfd)
|
fs_resolver.lookup_from_fd(dfd)
|
||||||
} else {
|
} else {
|
||||||
let fs_path = FsPath::new(dfd, &filename)?;
|
let fs_path = FsPath::new(dfd, &filename)?;
|
||||||
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
|
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
|
||||||
let dentrymnt = fs_resolver.lookup_no_follow(&fs_path)?;
|
let dentry = fs_resolver.lookup_no_follow(&fs_path)?;
|
||||||
if dentrymnt.type_() == InodeType::SymLink {
|
if dentry.type_() == InodeType::SymLink {
|
||||||
return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink");
|
return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink");
|
||||||
}
|
}
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
} else {
|
} else {
|
||||||
fs_resolver.lookup(&fs_path)
|
fs_resolver.lookup(&fs_path)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
check_executable_file(&dentrymnt)?;
|
check_executable_file(&dentry)?;
|
||||||
Ok(dentrymnt)
|
Ok(dentry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_execve(
|
fn do_execve(
|
||||||
elf_file: Arc<DentryMnt>,
|
elf_file: Arc<Dentry>,
|
||||||
argv_ptr_ptr: Vaddr,
|
argv_ptr_ptr: Vaddr,
|
||||||
envp_ptr_ptr: Vaddr,
|
envp_ptr_ptr: Vaddr,
|
||||||
context: &mut UserContext,
|
context: &mut UserContext,
|
||||||
@ -180,7 +181,7 @@ fn read_cstring_vec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit.
|
/// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit.
|
||||||
fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<DentryMnt>) -> Result<()> {
|
fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) -> Result<()> {
|
||||||
if elf_file.mode()?.has_set_uid() {
|
if elf_file.mode()?.has_set_uid() {
|
||||||
let uid = elf_file.owner()?;
|
let uid = elf_file.owner()?;
|
||||||
credentials.set_euid(uid);
|
credentials.set_euid(uid);
|
||||||
@ -192,7 +193,7 @@ fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<DentryMnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit.
|
/// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit.
|
||||||
fn set_gid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<DentryMnt>) -> Result<()> {
|
fn set_gid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) -> Result<()> {
|
||||||
if elf_file.mode()?.has_set_gid() {
|
if elf_file.mode()?.has_set_gid() {
|
||||||
let gid = elf_file.group()?;
|
let gid = elf_file.group()?;
|
||||||
credentials.set_egid(gid);
|
credentials.set_egid(gid);
|
||||||
|
@ -11,15 +11,15 @@ pub fn sys_fsync(fd: FileDesc) -> Result<SyscallReturn> {
|
|||||||
log_syscall_entry!(SYS_FSYNC);
|
log_syscall_entry!(SYS_FSYNC);
|
||||||
debug!("fd = {}", fd);
|
debug!("fd = {}", fd);
|
||||||
|
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let file_table = current.file_table().lock();
|
let file_table = current.file_table().lock();
|
||||||
let file = file_table.get_file(fd)?;
|
let file = file_table.get_file(fd)?;
|
||||||
let inode_handle = file
|
let inode_handle = file
|
||||||
.downcast_ref::<InodeHandle>()
|
.downcast_ref::<InodeHandle>()
|
||||||
.ok_or(Error::with_message(Errno::EINVAL, "not inode"))?;
|
.ok_or(Error::with_message(Errno::EINVAL, "not inode"))?;
|
||||||
inode_handle.dentrymnt().clone()
|
inode_handle.dentry().clone()
|
||||||
};
|
};
|
||||||
dentrymnt.sync()?;
|
dentry.sync()?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub fn sys_getdents64(fd: FileDesc, buf_addr: Vaddr, buf_len: usize) -> Result<S
|
|||||||
let inode_handle = file
|
let inode_handle = file
|
||||||
.downcast_ref::<InodeHandle>()
|
.downcast_ref::<InodeHandle>()
|
||||||
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
||||||
if inode_handle.dentrymnt().type_() != InodeType::Dir {
|
if inode_handle.dentry().type_() != InodeType::Dir {
|
||||||
return_errno!(Errno::ENOTDIR);
|
return_errno!(Errno::ENOTDIR);
|
||||||
}
|
}
|
||||||
let mut buffer = vec![0u8; buf_len];
|
let mut buffer = vec![0u8; buf_len];
|
||||||
|
@ -30,7 +30,7 @@ pub fn sys_linkat(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let (old_dentrymnt, new_dir_dentrymnt, new_name) = {
|
let (old_dentry, new_dir_dentry, new_name) = {
|
||||||
let old_path = old_path.to_string_lossy();
|
let old_path = old_path.to_string_lossy();
|
||||||
if old_path.ends_with('/') {
|
if old_path.ends_with('/') {
|
||||||
return_errno_with_message!(Errno::EPERM, "oldpath is dir");
|
return_errno_with_message!(Errno::EPERM, "oldpath is dir");
|
||||||
@ -46,16 +46,16 @@ pub fn sys_linkat(
|
|||||||
let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?;
|
let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?;
|
||||||
let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref())?;
|
let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref())?;
|
||||||
let fs = current.fs().read();
|
let fs = current.fs().read();
|
||||||
let old_dentrymnt = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) {
|
let old_dentry = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) {
|
||||||
fs.lookup(&old_fs_path)?
|
fs.lookup(&old_fs_path)?
|
||||||
} else {
|
} else {
|
||||||
fs.lookup_no_follow(&old_fs_path)?
|
fs.lookup_no_follow(&old_fs_path)?
|
||||||
};
|
};
|
||||||
let (new_dir_dentrymnt, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?;
|
let (new_dir_dentry, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?;
|
||||||
(old_dentrymnt, new_dir_dentrymnt, new_name)
|
(old_dentry, new_dir_dentry, new_name)
|
||||||
};
|
};
|
||||||
|
|
||||||
new_dir_dentrymnt.link(&old_dentrymnt, &new_name)?;
|
new_dir_dentry.link(&old_dentry, &new_name)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ pub fn sys_mkdirat(dirfd: FileDesc, path_addr: Vaddr, mode: u16) -> Result<Sysca
|
|||||||
debug!("dirfd = {}, path = {:?}, mode = {}", dirfd, path, mode);
|
debug!("dirfd = {}, path = {:?}, mode = {}", dirfd, path, mode);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let (dir_dentrymnt, name) = {
|
let (dir_dentry, name) = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -32,7 +32,7 @@ pub fn sys_mkdirat(dirfd: FileDesc, path_addr: Vaddr, mode: u16) -> Result<Sysca
|
|||||||
let mask_mode = mode & !current.umask().read().get();
|
let mask_mode = mode & !current.umask().read().get();
|
||||||
InodeMode::from_bits_truncate(mask_mode)
|
InodeMode::from_bits_truncate(mask_mode)
|
||||||
};
|
};
|
||||||
let _ = dir_dentrymnt.new_fs_child(name.trim_end_matches('/'), InodeType::Dir, inode_mode)?;
|
let _ = dir_dentry.new_fs_child(name.trim_end_matches('/'), InodeType::Dir, inode_mode)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ fn alloc_filebacked_vmo(
|
|||||||
let current = current!();
|
let current = current!();
|
||||||
let page_cache_vmo = {
|
let page_cache_vmo = {
|
||||||
let fs_resolver = current.fs().read();
|
let fs_resolver = current.fs().read();
|
||||||
let dentrymnt = fs_resolver.lookup_from_fd(fd)?;
|
let dentry = fs_resolver.lookup_from_fd(fd)?;
|
||||||
let inode = dentrymnt.inode();
|
let inode = dentry.inode();
|
||||||
inode
|
inode
|
||||||
.page_cache()
|
.page_cache()
|
||||||
.ok_or(Error::with_message(
|
.ok_or(Error::with_message(
|
||||||
|
@ -26,7 +26,7 @@ pub fn sys_readlinkat(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -34,7 +34,7 @@ pub fn sys_readlinkat(
|
|||||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||||
current.fs().read().lookup_no_follow(&fs_path)?
|
current.fs().read().lookup_no_follow(&fs_path)?
|
||||||
};
|
};
|
||||||
let linkpath = dentrymnt.inode().read_link()?;
|
let linkpath = dentry.inode().read_link()?;
|
||||||
let bytes = linkpath.as_bytes();
|
let bytes = linkpath.as_bytes();
|
||||||
let write_len = bytes.len().min(usr_buf_len);
|
let write_len = bytes.len().min(usr_buf_len);
|
||||||
write_bytes_to_user(usr_buf_addr, &bytes[..write_len])?;
|
write_bytes_to_user(usr_buf_addr, &bytes[..write_len])?;
|
||||||
|
@ -30,7 +30,7 @@ pub fn sys_renameat(
|
|||||||
let current = current!();
|
let current = current!();
|
||||||
let fs = current.fs().read();
|
let fs = current.fs().read();
|
||||||
|
|
||||||
let (old_dir_dentrymnt, old_name) = {
|
let (old_dir_dentry, old_name) = {
|
||||||
let old_path = old_path.to_string_lossy();
|
let old_path = old_path.to_string_lossy();
|
||||||
if old_path.is_empty() {
|
if old_path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "oldpath is empty");
|
return_errno_with_message!(Errno::ENOENT, "oldpath is empty");
|
||||||
@ -38,14 +38,14 @@ pub fn sys_renameat(
|
|||||||
let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?;
|
let old_fs_path = FsPath::new(old_dirfd, old_path.as_ref())?;
|
||||||
fs.lookup_dir_and_base_name(&old_fs_path)?
|
fs.lookup_dir_and_base_name(&old_fs_path)?
|
||||||
};
|
};
|
||||||
let old_dentrymnt = old_dir_dentrymnt.lookup(&old_name)?;
|
let old_dentry = old_dir_dentry.lookup(&old_name)?;
|
||||||
|
|
||||||
let (new_dir_dentrymnt, new_name) = {
|
let (new_dir_dentry, new_name) = {
|
||||||
let new_path = new_path.to_string_lossy();
|
let new_path = new_path.to_string_lossy();
|
||||||
if new_path.is_empty() {
|
if new_path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "newpath is empty");
|
return_errno_with_message!(Errno::ENOENT, "newpath is empty");
|
||||||
}
|
}
|
||||||
if new_path.ends_with('/') && old_dentrymnt.type_() != InodeType::Dir {
|
if new_path.ends_with('/') && old_dentry.type_() != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir");
|
||||||
}
|
}
|
||||||
let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref().trim_end_matches('/'))?;
|
let new_fs_path = FsPath::new(new_dirfd, new_path.as_ref().trim_end_matches('/'))?;
|
||||||
@ -53,8 +53,8 @@ pub fn sys_renameat(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Check abs_path
|
// Check abs_path
|
||||||
let old_abs_path = old_dentrymnt.abs_path();
|
let old_abs_path = old_dentry.abs_path();
|
||||||
let new_abs_path = new_dir_dentrymnt.abs_path() + "/" + &new_name;
|
let new_abs_path = new_dir_dentry.abs_path() + "/" + &new_name;
|
||||||
if new_abs_path.starts_with(&old_abs_path) {
|
if new_abs_path.starts_with(&old_abs_path) {
|
||||||
if new_abs_path.len() == old_abs_path.len() {
|
if new_abs_path.len() == old_abs_path.len() {
|
||||||
return Ok(SyscallReturn::Return(0));
|
return Ok(SyscallReturn::Return(0));
|
||||||
@ -66,7 +66,7 @@ pub fn sys_renameat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
old_dir_dentrymnt.rename(&old_name, &new_dir_dentrymnt, &new_name)?;
|
old_dir_dentry.rename(&old_name, &new_dir_dentry, &new_name)?;
|
||||||
|
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ pub(super) fn sys_rmdirat(dirfd: FileDesc, path_addr: Vaddr) -> Result<SyscallRe
|
|||||||
debug!("dirfd = {}, path_addr = {:?}", dirfd, path_addr);
|
debug!("dirfd = {}, path_addr = {:?}", dirfd, path_addr);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let (dir_dentrymnt, name) = {
|
let (dir_dentry, name) = {
|
||||||
let path_addr = path_addr.to_string_lossy();
|
let path_addr = path_addr.to_string_lossy();
|
||||||
if path_addr == "/" {
|
if path_addr == "/" {
|
||||||
return_errno_with_message!(Errno::EBUSY, "is root directory");
|
return_errno_with_message!(Errno::EBUSY, "is root directory");
|
||||||
@ -30,6 +30,6 @@ pub(super) fn sys_rmdirat(dirfd: FileDesc, path_addr: Vaddr) -> Result<SyscallRe
|
|||||||
let fs_path = FsPath::new(dirfd, path_addr.as_ref())?;
|
let fs_path = FsPath::new(dirfd, path_addr.as_ref())?;
|
||||||
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
||||||
};
|
};
|
||||||
dir_dentrymnt.rmdir(name.trim_end_matches('/'))?;
|
dir_dentry.rmdir(name.trim_end_matches('/'))?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ pub fn sys_fstatat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let filename = filename.to_string_lossy();
|
let filename = filename.to_string_lossy();
|
||||||
let fs_path = FsPath::new(dirfd, filename.as_ref())?;
|
let fs_path = FsPath::new(dirfd, filename.as_ref())?;
|
||||||
let fs = current.fs().read();
|
let fs = current.fs().read();
|
||||||
@ -73,7 +73,7 @@ pub fn sys_fstatat(
|
|||||||
fs.lookup(&fs_path)?
|
fs.lookup(&fs_path)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let stat = Stat::from(dentrymnt.metadata());
|
let stat = Stat::from(dentry.metadata());
|
||||||
write_val_to_user(stat_buf_ptr, &stat)?;
|
write_val_to_user(stat_buf_ptr, &stat)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@ pub fn sys_statfs(path_ptr: Vaddr, statfs_buf_ptr: Vaddr) -> Result<SyscallRetur
|
|||||||
debug!("path = {:?}, statfs_buf_ptr = 0x{:x}", path, statfs_buf_ptr,);
|
debug!("path = {:?}, statfs_buf_ptr = 0x{:x}", path, statfs_buf_ptr,);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
let fs_path = FsPath::try_from(path.as_ref())?;
|
let fs_path = FsPath::try_from(path.as_ref())?;
|
||||||
current.fs().read().lookup(&fs_path)?
|
current.fs().read().lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
let statfs = Statfs::from(dentrymnt.fs().sb());
|
let statfs = Statfs::from(dentry.fs().sb());
|
||||||
write_val_to_user(statfs_buf_ptr, &statfs)?;
|
write_val_to_user(statfs_buf_ptr, &statfs)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
@ -39,8 +39,8 @@ pub fn sys_fstatfs(fd: FileDesc, statfs_buf_ptr: Vaddr) -> Result<SyscallReturn>
|
|||||||
let inode_handle = file
|
let inode_handle = file
|
||||||
.downcast_ref::<InodeHandle>()
|
.downcast_ref::<InodeHandle>()
|
||||||
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
|
||||||
let dentrymnt = inode_handle.dentrymnt();
|
let dentry = inode_handle.dentry();
|
||||||
let statfs = Statfs::from(dentrymnt.fs().sb());
|
let statfs = Statfs::from(dentry.fs().sb());
|
||||||
write_val_to_user(statfs_buf_ptr, &statfs)?;
|
write_val_to_user(statfs_buf_ptr, &statfs)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ pub fn sys_symlinkat(
|
|||||||
if target.is_empty() {
|
if target.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "target is empty");
|
return_errno_with_message!(Errno::ENOENT, "target is empty");
|
||||||
}
|
}
|
||||||
let (dir_dentrymnt, link_name) = {
|
let (dir_dentry, link_name) = {
|
||||||
let linkpath = linkpath.to_string_lossy();
|
let linkpath = linkpath.to_string_lossy();
|
||||||
if linkpath.is_empty() {
|
if linkpath.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "linkpath is empty");
|
return_errno_with_message!(Errno::ENOENT, "linkpath is empty");
|
||||||
@ -43,7 +43,7 @@ pub fn sys_symlinkat(
|
|||||||
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let new_dentry = dir_dentrymnt.new_fs_child(
|
let new_dentry = dir_dentry.new_fs_child(
|
||||||
&link_name,
|
&link_name,
|
||||||
InodeType::SymLink,
|
InodeType::SymLink,
|
||||||
InodeMode::from_bits_truncate(0o777),
|
InodeMode::from_bits_truncate(0o777),
|
||||||
|
@ -34,7 +34,7 @@ pub fn sys_truncate(path_ptr: Vaddr, len: isize) -> Result<SyscallReturn> {
|
|||||||
check_length(len)?;
|
check_length(len)?;
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dir_dentrymnt = {
|
let dir_dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -42,7 +42,7 @@ pub fn sys_truncate(path_ptr: Vaddr, len: isize) -> Result<SyscallReturn> {
|
|||||||
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
|
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
|
||||||
current.fs().read().lookup(&fs_path)?
|
current.fs().read().lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
dir_dentrymnt.resize(len as usize)?;
|
dir_dentry.resize(len as usize)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ pub fn sys_unlinkat(dirfd: FileDesc, path_addr: Vaddr, flags: u32) -> Result<Sys
|
|||||||
debug!("dirfd = {}, path = {:?}", dirfd, path);
|
debug!("dirfd = {}, path = {:?}", dirfd, path);
|
||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let (dir_dentrymnt, name) = {
|
let (dir_dentry, name) = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -35,7 +35,7 @@ pub fn sys_unlinkat(dirfd: FileDesc, path_addr: Vaddr, flags: u32) -> Result<Sys
|
|||||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||||
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
||||||
};
|
};
|
||||||
dir_dentrymnt.unlink(&name)?;
|
dir_dentry.unlink(&name)?;
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ pub fn sys_utimensat(
|
|||||||
return Ok(SyscallReturn::Return(0));
|
return Ok(SyscallReturn::Return(0));
|
||||||
}
|
}
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let dentrymnt = {
|
let dentry = {
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
@ -75,10 +75,10 @@ pub fn sys_utimensat(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(time) = atime {
|
if let Some(time) = atime {
|
||||||
dentrymnt.set_atime(Duration::from(time));
|
dentry.set_atime(Duration::from(time));
|
||||||
}
|
}
|
||||||
if let Some(time) = mtime {
|
if let Some(time) = mtime {
|
||||||
dentrymnt.set_mtime(Duration::from(time));
|
dentry.set_mtime(Duration::from(time));
|
||||||
}
|
}
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user