Add struct Path for VFS

Signed-off-by: Zhenchen Wang <m202372036@hust.edu.cn>
This commit is contained in:
plucky
2024-04-09 09:30:58 +08:00
committed by Tate, Hongliang Tian
parent bc1bf4cb53
commit 6d486c6c01
39 changed files with 561 additions and 447 deletions

View File

@ -4,7 +4,7 @@ use crate::{
fs::{
devpts::DevPts,
fs_resolver::{FsPath, FsResolver},
utils::{Dentry, Inode, InodeMode, InodeType},
utils::{Inode, InodeMode, InodeType, Path},
},
prelude::*,
};
@ -15,20 +15,29 @@ mod pty;
pub use pty::{PtyMaster, PtySlave};
use spin::Once;
static DEV_PTS: Once<Arc<Dentry>> = Once::new();
static DEV_PTS: Once<Arc<Path>> = Once::new();
pub fn init() -> Result<()> {
let fs = FsResolver::new();
let dev = fs.lookup(&FsPath::try_from("/dev")?)?;
// Create the "pts" directory and mount devpts on it.
let devpts = dev.create("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?;
let devpts_dentry =
dev.dentry()
.create("pts", InodeType::Dir, InodeMode::from_bits_truncate(0o755))?;
let devpts_mount_node =
Path::new(dev.mount_node().clone(), devpts_dentry.clone()).mount(DevPts::new())?;
let devpts = Path::new(
devpts_mount_node.clone(),
devpts_mount_node.root_dentry().clone(),
);
devpts.mount(DevPts::new())?;
DEV_PTS.call_once(|| devpts);
// Create the "ptmx" symlink.
let ptmx = dev.create(
let ptmx = dev.dentry().create(
"ptmx",
InodeType::SymLink,
InodeMode::from_bits_truncate(0o777),

View File

@ -84,13 +84,15 @@ impl From<DeviceId> for u64 {
///
/// If the parent path is not existing, `mkdir -p` the parent path.
/// This function is used in registering device.
pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<Dentry>> {
let mut dentry = {
pub fn add_node(device: Arc<dyn Device>, pathname: &str) -> Result<Arc<Dentry>> {
let mut path = {
let fs_resolver = FsResolver::new();
fs_resolver.lookup(&FsPath::try_from("/dev").unwrap())?
};
let mut dentry = path.dentry().clone();
let mut relative_path = {
let relative_path = path.trim_start_matches('/');
let relative_path = pathname.trim_start_matches('/');
if relative_path.is_empty() {
return_errno_with_message!(Errno::EINVAL, "invalid device path");
}
@ -105,24 +107,24 @@ pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<Dentry>> {
(relative_path, "")
};
match dentry.lookup(next_name) {
Ok(next_dentry) => {
match path.lookup(next_name) {
Ok(next_path) => {
if path_remain.is_empty() {
return_errno_with_message!(Errno::EEXIST, "device node is existing");
}
dentry = next_dentry;
path = next_path;
}
Err(_) => {
if path_remain.is_empty() {
// Create the device node
dentry = dentry.mknod(
dentry = path.dentry().mknod(
next_name,
InodeMode::from_bits_truncate(0o666),
device.clone(),
)?;
} else {
// Mkdir parent path
dentry = dentry.create(
dentry = path.dentry().create(
next_name,
InodeType::Dir,
InodeMode::from_bits_truncate(0o755),
@ -139,20 +141,20 @@ pub fn add_node(device: Arc<dyn Device>, path: &str) -> Result<Arc<Dentry>> {
/// Delete the device node from FS for the device.
///
/// This function is used in unregistering device.
pub fn delete_node(path: &str) -> Result<()> {
pub fn delete_node(pathname: &str) -> Result<()> {
let abs_path = {
let device_path = path.trim_start_matches('/');
let device_path = pathname.trim_start_matches('/');
if device_path.is_empty() {
return_errno_with_message!(Errno::EINVAL, "invalid device path");
}
String::from("/dev") + "/" + device_path
};
let (parent_dentry, name) = {
let (parent_path, name) = {
let fs_resolver = FsResolver::new();
fs_resolver.lookup_dir_and_base_name(&FsPath::try_from(abs_path.as_str()).unwrap())?
};
parent_dentry.unlink(&name)?;
parent_path.dentry().unlink(&name)?;
Ok(())
}

View File

@ -7,16 +7,15 @@ use super::{
inode_handle::InodeHandle,
rootfs::root_mount,
utils::{
AccessMode, CreationFlags, Dentry, InodeMode, InodeType, StatusFlags, PATH_MAX,
SYMLINKS_MAX,
AccessMode, CreationFlags, InodeMode, InodeType, Path, StatusFlags, PATH_MAX, SYMLINKS_MAX,
},
};
use crate::prelude::*;
#[derive(Debug)]
pub struct FsResolver {
root: Arc<Dentry>,
cwd: Arc<Dentry>,
root: Arc<Path>,
cwd: Arc<Path>,
}
impl Clone for FsResolver {
@ -37,33 +36,33 @@ impl Default for FsResolver {
impl FsResolver {
pub fn new() -> Self {
Self {
root: root_mount().root_dentry().clone(),
cwd: root_mount().root_dentry().clone(),
root: Path::new(root_mount().clone(), root_mount().root_dentry().clone()),
cwd: Path::new(root_mount().clone(), root_mount().root_dentry().clone()),
}
}
/// Get the root directory
pub fn root(&self) -> &Arc<Dentry> {
pub fn root(&self) -> &Arc<Path> {
&self.root
}
/// Get the current working directory
pub fn cwd(&self) -> &Arc<Dentry> {
pub fn cwd(&self) -> &Arc<Path> {
&self.cwd
}
/// Set the current working directory.
pub fn set_cwd(&mut self, dentry: Arc<Dentry>) {
self.cwd = dentry;
pub fn set_cwd(&mut self, path: Arc<Path>) {
self.cwd = path;
}
/// Set the root directory
pub fn set_root(&mut self, dentry: Arc<Dentry>) {
self.root = dentry;
pub fn set_root(&mut self, path: Arc<Path>) {
self.root = path;
}
/// Open or create a file inode handler.
pub fn open(&self, path: &FsPath, flags: u32, mode: u16) -> Result<InodeHandle> {
pub fn open(&self, pathname: &FsPath, flags: u32, mode: u16) -> Result<InodeHandle> {
let creation_flags = CreationFlags::from_bits_truncate(flags);
let status_flags = StatusFlags::from_bits_truncate(flags);
let access_mode = AccessMode::from_u32(flags)?;
@ -72,9 +71,9 @@ impl FsResolver {
let follow_tail_link = !(creation_flags.contains(CreationFlags::O_NOFOLLOW)
|| creation_flags.contains(CreationFlags::O_CREAT)
&& creation_flags.contains(CreationFlags::O_EXCL));
let dentry = match self.lookup_inner(path, follow_tail_link) {
Ok(dentry) => {
let inode = dentry.inode();
let path = match self.lookup_inner(pathname, follow_tail_link) {
Ok(path) => {
let inode = path.dentry().inode();
if inode.type_() == InodeType::SymLink
&& creation_flags.contains(CreationFlags::O_NOFOLLOW)
&& !status_flags.contains(StatusFlags::O_PATH)
@ -94,7 +93,7 @@ impl FsResolver {
"O_DIRECTORY is specified but file is not a directory"
);
}
dentry
path
}
Err(e)
if e.error() == Errno::ENOENT
@ -103,50 +102,56 @@ impl FsResolver {
if creation_flags.contains(CreationFlags::O_DIRECTORY) {
return_errno_with_message!(Errno::ENOTDIR, "cannot create directory");
}
let (dir_dentry, file_name) =
self.lookup_dir_and_base_name_inner(path, follow_tail_link)?;
let (dir_path, file_name) =
self.lookup_dir_and_base_name_inner(pathname, follow_tail_link)?;
if file_name.ends_with('/') {
return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
}
if !dir_dentry.mode()?.is_writable() {
if !dir_path.dentry().mode()?.is_writable() {
return_errno_with_message!(Errno::EACCES, "file cannot be created");
}
dir_dentry.create(&file_name, InodeType::File, inode_mode)?
let dir_dentry =
dir_path
.dentry()
.create(&file_name, InodeType::File, inode_mode)?;
Path::new(dir_path.mount_node().clone(), dir_dentry.clone())
}
Err(e) => return Err(e),
};
let inode_handle = InodeHandle::new(dentry, access_mode, status_flags)?;
let inode_handle = InodeHandle::new(path, access_mode, status_flags)?;
Ok(inode_handle)
}
/// Lookup dentry according to FsPath, always follow symlinks
pub fn lookup(&self, path: &FsPath) -> Result<Arc<Dentry>> {
self.lookup_inner(path, true)
/// Lookup path according to FsPath, always follow symlinks
pub fn lookup(&self, pathname: &FsPath) -> Result<Arc<Path>> {
self.lookup_inner(pathname, true)
}
/// Lookup dentry according to FsPath, do not follow it if last component is a symlink
pub fn lookup_no_follow(&self, path: &FsPath) -> Result<Arc<Dentry>> {
self.lookup_inner(path, false)
/// Lookup path according to FsPath, do not follow it if last component is a symlink
pub fn lookup_no_follow(&self, pathname: &FsPath) -> Result<Arc<Path>> {
self.lookup_inner(pathname, false)
}
fn lookup_inner(&self, path: &FsPath, follow_tail_link: bool) -> Result<Arc<Dentry>> {
let dentry = match path.inner {
FsPathInner::Absolute(path) => {
self.lookup_from_parent(&self.root, path.trim_start_matches('/'), follow_tail_link)?
}
FsPathInner::CwdRelative(path) => {
self.lookup_from_parent(&self.cwd, path, follow_tail_link)?
fn lookup_inner(&self, pathname: &FsPath, follow_tail_link: bool) -> Result<Arc<Path>> {
let path = match pathname.inner {
FsPathInner::Absolute(pathname) => self.lookup_from_parent(
&self.root,
pathname.trim_start_matches('/'),
follow_tail_link,
)?,
FsPathInner::CwdRelative(pathname) => {
self.lookup_from_parent(&self.cwd, pathname, follow_tail_link)?
}
FsPathInner::Cwd => self.cwd.clone(),
FsPathInner::FdRelative(fd, path) => {
FsPathInner::FdRelative(fd, pathname) => {
let parent = self.lookup_from_fd(fd)?;
self.lookup_from_parent(&parent, path, follow_tail_link)?
self.lookup_from_parent(&parent, pathname, follow_tail_link)?
}
FsPathInner::Fd(fd) => self.lookup_from_fd(fd)?,
};
Ok(dentry)
Ok(path)
}
/// Lookup dentry from parent
@ -162,10 +167,10 @@ impl FsResolver {
/// Symlinks in earlier components of the path will always be followed.
fn lookup_from_parent(
&self,
parent: &Arc<Dentry>,
parent: &Arc<Path>,
relative_path: &str,
follow_tail_link: bool,
) -> Result<Arc<Dentry>> {
) -> Result<Arc<Path>> {
debug_assert!(!relative_path.starts_with('/'));
if relative_path.len() > PATH_MAX {
@ -176,8 +181,8 @@ impl FsResolver {
let mut link_path = String::new();
let mut follows = 0;
// Initialize the first dentry and the relative path
let (mut dentry, mut relative_path) = (parent.clone(), relative_path);
// Initialize the first path and the relative path
let (mut path, mut relative_path) = (parent.clone(), relative_path);
while !relative_path.is_empty() {
let (next_name, path_remain, must_be_dir) =
@ -189,7 +194,8 @@ impl FsResolver {
};
// Iterate next dentry
let next_dentry = dentry.lookup(next_name)?;
let next_path = path.lookup(next_name)?;
let next_dentry = next_path.dentry();
let next_type = next_dentry.type_();
let next_is_tail = path_remain.is_empty();
@ -212,9 +218,9 @@ impl FsResolver {
tmp_link_path
};
// Change the dentry and relative path according to symlink
// Change the path and relative path according to symlink
if link_path_remain.starts_with('/') {
dentry = self.root.clone();
path = self.root.clone();
}
link_path.clear();
link_path.push_str(link_path_remain.trim_start_matches('/'));
@ -225,12 +231,12 @@ impl FsResolver {
if must_be_dir && next_type != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "inode is not dir");
}
dentry = next_dentry;
path = next_path;
relative_path = path_remain;
}
}
Ok(dentry)
Ok(path)
}
/// Lookup dentry from the giving fd
@ -241,38 +247,38 @@ impl FsResolver {
.get_file(fd)?
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
Ok(inode_handle.dentry().clone())
Ok(inode_handle.path().clone())
}
/// Lookup the dir dentry and base file name of the giving path.
/// Lookup the dir path and base file name of the giving pathname.
///
/// If the last component is a symlink, do not deference it
pub fn lookup_dir_and_base_name(&self, path: &FsPath) -> Result<(Arc<Dentry>, String)> {
self.lookup_dir_and_base_name_inner(path, false)
pub fn lookup_dir_and_base_name(&self, pathname: &FsPath) -> Result<(Arc<Path>, String)> {
self.lookup_dir_and_base_name_inner(pathname, false)
}
fn lookup_dir_and_base_name_inner(
&self,
path: &FsPath,
pathname: &FsPath,
follow_tail_link: bool,
) -> Result<(Arc<Dentry>, String)> {
let (mut dir_dentry, mut base_name) = match path.inner {
FsPathInner::Absolute(path) => {
let (dir, file_name) = split_path(path);
) -> Result<(Arc<Path>, String)> {
let (mut dir_path, mut base_name) = match pathname.inner {
FsPathInner::Absolute(pathname) => {
let (dir, file_name) = split_path(pathname);
(
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?,
String::from(file_name),
)
}
FsPathInner::CwdRelative(path) => {
let (dir, file_name) = split_path(path);
FsPathInner::CwdRelative(pathname) => {
let (dir, file_name) = split_path(pathname);
(
self.lookup_from_parent(&self.cwd, dir, true)?,
String::from(file_name),
)
}
FsPathInner::FdRelative(fd, path) => {
let (dir, file_name) = split_path(path);
FsPathInner::FdRelative(fd, pathname) => {
let (dir, file_name) = split_path(pathname);
let parent = self.lookup_from_fd(fd)?;
(
self.lookup_from_parent(&parent, dir, true)?,
@ -282,15 +288,15 @@ impl FsResolver {
_ => return_errno!(Errno::ENOENT),
};
if !follow_tail_link {
return Ok((dir_dentry, base_name));
return Ok((dir_path, base_name));
}
// Dereference the tail symlinks if needed
loop {
match dir_dentry.lookup(base_name.trim_end_matches('/')) {
Ok(dentry) if dentry.type_() == InodeType::SymLink => {
match dir_path.lookup(base_name.trim_end_matches('/')) {
Ok(path) if path.dentry().type_() == InodeType::SymLink => {
let link = {
let mut link = dentry.inode().read_link()?;
let mut link = path.dentry().inode().read_link()?;
if link.is_empty() {
return_errno_with_message!(Errno::ENOENT, "invalid symlink");
}
@ -301,11 +307,11 @@ impl FsResolver {
};
let (dir, file_name) = split_path(&link);
if dir.starts_with('/') {
dir_dentry =
dir_path =
self.lookup_from_parent(&self.root, dir.trim_start_matches('/'), true)?;
base_name = String::from(file_name);
} else {
dir_dentry = self.lookup_from_parent(&dir_dentry, dir, true)?;
dir_path = self.lookup_from_parent(&dir_path, dir, true)?;
base_name = String::from(file_name);
}
}
@ -313,7 +319,7 @@ impl FsResolver {
}
}
Ok((dir_dentry, base_name))
Ok((dir_path, base_name))
}
}

View File

@ -8,11 +8,11 @@ use crate::prelude::*;
impl InodeHandle<Rights> {
pub fn new(
dentry: Arc<Dentry>,
path: Arc<Path>,
access_mode: AccessMode,
status_flags: StatusFlags,
) -> Result<Self> {
let inode = dentry.inode();
let inode = path.dentry().inode();
if access_mode.is_readable() && !inode.mode()?.is_readable() {
return_errno_with_message!(Errno::EACCES, "File is not readable");
}
@ -30,7 +30,7 @@ impl InodeHandle<Rights> {
};
let inner = Arc::new(InodeHandle_ {
dentry,
path,
file_io,
offset: Mutex::new(0),
access_mode,
@ -116,6 +116,6 @@ impl FileLike for InodeHandle<Rights> {
}
fn as_device(&self) -> Option<Arc<dyn Device>> {
self.dentry().inode().as_device()
self.0.path.dentry().inode().as_device()
}
}

View File

@ -16,7 +16,7 @@ use crate::{
device::Device,
file_handle::FileLike,
utils::{
AccessMode, Dentry, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata, SeekFrom,
AccessMode, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata, Path, SeekFrom,
StatusFlags,
},
},
@ -28,7 +28,7 @@ use crate::{
pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
struct InodeHandle_ {
dentry: Arc<Dentry>,
path: Arc<Path>,
/// `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`,
/// `ioctl` will be provided by `file_io`, instead of `dentry`.
@ -47,9 +47,9 @@ impl InodeHandle_ {
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().read_direct_at(*offset, buf)?
self.path.dentry().inode().read_direct_at(*offset, buf)?
} else {
self.dentry.inode().read_at(*offset, buf)?
self.path.dentry().inode().read_at(*offset, buf)?
};
*offset += len;
@ -64,12 +64,12 @@ impl InodeHandle_ {
}
if self.status_flags().contains(StatusFlags::O_APPEND) {
*offset = self.dentry.size();
*offset = self.path.dentry().size();
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().write_direct_at(*offset, buf)?
self.path.dentry().inode().write_direct_at(*offset, buf)?
} else {
self.dentry.inode().write_at(*offset, buf)?
self.path.dentry().inode().write_at(*offset, buf)?
};
*offset += len;
@ -82,9 +82,9 @@ impl InodeHandle_ {
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().read_direct_all(buf)?
self.path.dentry().inode().read_direct_all(buf)?
} else {
self.dentry.inode().read_all(buf)?
self.path.dentry().inode().read_all(buf)?
};
Ok(len)
}
@ -99,7 +99,7 @@ impl InodeHandle_ {
off as isize
}
SeekFrom::End(off /* as isize */) => {
let file_size = self.dentry.size() as isize;
let file_size = self.path.dentry().size() as isize;
assert!(file_size >= 0);
file_size
.checked_add(off)
@ -127,7 +127,7 @@ impl InodeHandle_ {
if self.status_flags().contains(StatusFlags::O_APPEND) {
return_errno_with_message!(Errno::EPERM, "can not resize append-only file");
}
self.dentry.resize(new_size)
self.path.dentry().resize(new_size)
}
pub fn access_mode(&self) -> AccessMode {
@ -146,7 +146,7 @@ impl InodeHandle_ {
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
let mut offset = self.offset.lock();
let read_cnt = self.dentry.inode().readdir_at(*offset, visitor)?;
let read_cnt = self.path.dentry().inode().readdir_at(*offset, visitor)?;
*offset += read_cnt;
Ok(read_cnt)
}
@ -156,7 +156,7 @@ impl InodeHandle_ {
return file_io.poll(mask, poller);
}
self.dentry.inode().poll(mask, poller)
self.path.dentry().inode().poll(mask, poller)
}
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
@ -164,11 +164,11 @@ impl InodeHandle_ {
return file_io.ioctl(cmd, arg);
}
self.dentry.inode().ioctl(cmd, arg)
self.path.dentry().inode().ioctl(cmd, arg)
}
}
#[inherit_methods(from = "self.dentry")]
#[inherit_methods(from = "self.path.dentry()")]
impl InodeHandle_ {
pub fn size(&self) -> usize;
pub fn metadata(&self) -> Metadata;
@ -183,7 +183,7 @@ impl InodeHandle_ {
impl Debug for InodeHandle_ {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("InodeHandle_")
.field("dentry", &self.dentry)
.field("path", &self.path)
.field("offset", &self.offset())
.field("access_mode", &self.access_mode())
.field("status_flags", &self.status_flags())
@ -193,8 +193,8 @@ impl Debug for InodeHandle_ {
/// Methods for both dyn and static
impl<R> InodeHandle<R> {
pub fn dentry(&self) -> &Arc<Dentry> {
&self.0.dentry
pub fn path(&self) -> &Arc<Path> {
&self.0.path
}
}

View File

@ -76,12 +76,12 @@ impl FileSymOps {
impl SymOps for FileSymOps {
fn read_link(&self) -> Result<String> {
let path = if let Some(inode_handle) = self.0.downcast_ref::<InodeHandle>() {
inode_handle.dentry().abs_path()
let pathname = if let Some(inode_handle) = self.0.downcast_ref::<InodeHandle>() {
inode_handle.path().abs_path()
} else {
// TODO: get the real path for other FileLike object
String::from("/dev/tty")
};
Ok(path)
Ok(pathname)
}
}

View File

@ -54,14 +54,14 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> {
let mode = InodeMode::from_bits_truncate(metadata.permission_mode());
match metadata.file_type() {
FileType::File => {
let dentry = parent.create(name, InodeType::File, mode)?;
let dentry = parent.dentry().create(name, InodeType::File, mode)?;
entry.read_all(dentry.inode().writer(0))?;
}
FileType::Dir => {
let _ = parent.create(name, InodeType::Dir, mode)?;
let _ = parent.dentry().create(name, InodeType::Dir, mode)?;
}
FileType::Link => {
let dentry = parent.create(name, InodeType::SymLink, mode)?;
let dentry = parent.dentry().create(name, InodeType::SymLink, mode)?;
let link_content = {
let mut link_data: Vec<u8> = Vec::new();
entry.read_all(&mut link_data)?;
@ -75,11 +75,11 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> {
}
}
// Mount ProcFS
let proc_dentry = fs.lookup(&FsPath::try_from("/proc")?)?;
proc_dentry.mount(ProcFS::new())?;
let proc_path = fs.lookup(&FsPath::try_from("/proc")?)?;
proc_path.mount(ProcFS::new())?;
// Mount DevFS
let dev_dentry = fs.lookup(&FsPath::try_from("/dev")?)?;
dev_dentry.mount(RamFS::new())?;
let dev_path = fs.lookup(&FsPath::try_from("/dev")?)?;
dev_path.mount(RamFS::new())?;
println!("[kernel] rootfs is ready");
@ -87,8 +87,8 @@ pub fn init(initramfs_buf: &[u8]) -> Result<()> {
}
pub fn mount_fs_at(fs: Arc<dyn FileSystem>, fs_path: &FsPath) -> Result<()> {
let target_dentry = FsResolver::new().lookup(fs_path)?;
target_dentry.mount(fs)?;
let target_path = FsResolver::new().lookup(fs_path)?;
target_path.mount(fs)?;
Ok(())
}

View File

@ -7,7 +7,7 @@ use core::{
use inherit_methods_macro::inherit_methods;
use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, NAME_MAX};
use super::{FileSystem, Inode, InodeMode, InodeType, Metadata};
use crate::{
fs::device::Device,
prelude::*,
@ -24,7 +24,6 @@ pub struct Dentry {
name_and_parent: RwLock<Option<(String, Arc<Dentry>)>>,
this: Weak<Dentry>,
children: Mutex<Children>,
mount_node: Weak<MountNode>,
flags: AtomicU32,
}
@ -34,20 +33,23 @@ impl Dentry {
/// It is been created during the construction of MountNode struct. The MountNode
/// struct holds an arc reference to this root dentry, while this dentry holds a
/// weak reference to the MountNode struct.
pub(super) fn new_root(inode: Arc<dyn Inode>, mount: Weak<MountNode>) -> Arc<Self> {
let root = Self::new(inode, DentryOptions::Root(mount));
pub(super) fn new_root(inode: Arc<dyn Inode>) -> Arc<Self> {
let root = Self::new(inode, DentryOptions::Root);
DCACHE.lock().insert(root.key(), root.clone());
root
}
pub fn new_child(&self, inode: Arc<dyn Inode>, name: &str) -> Arc<Self> {
Dentry::new(
inode,
DentryOptions::Leaf((String::from(name), self.this())),
)
}
/// Internal constructor.
fn new(inode: Arc<dyn Inode>, options: DentryOptions) -> Arc<Self> {
Arc::new_cyclic(|weak_self| Self {
inode,
mount_node: match &options {
DentryOptions::Root(mount) => mount.clone(),
DentryOptions::Leaf(name_and_parent) => name_and_parent.1.mount_node.clone(),
},
flags: AtomicU32::new(DentryFlags::empty().bits()),
name_and_parent: match options {
DentryOptions::Leaf(name_and_parent) => RwLock::new(Some(name_and_parent)),
@ -58,69 +60,26 @@ impl Dentry {
})
}
/// Get the overlaid dentry of self.
///
/// It will jump into the child mount if it is a mountpoint.
fn overlaid_dentry(&self) -> Arc<Self> {
if !self.is_mountpoint() {
return self.this();
}
match self.mount_node().get(self) {
Some(child_mount) => child_mount.root_dentry().overlaid_dentry(),
None => self.this(),
}
}
/// Get the name of 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() {
Some(name_and_parent) => name_and_parent.0.clone(),
None => String::from("/"),
}
}
/// Get the effective name of dentry.
///
/// If it is the root of mount, it will go up to the mountpoint to get the name
/// of the mountpoint recursively.
fn effective_name(&self) -> String {
if !self.is_root_of_mount() {
return self.name();
}
match self.mount_node().mountpoint_dentry() {
Some(self_mountpoint) => self_mountpoint.effective_name(),
None => self.name(),
}
}
/// Get the parent.
///
/// Returns None if it is root dentry.
fn parent(&self) -> Option<Arc<Self>> {
pub fn parent(&self) -> Option<Arc<Self>> {
self.name_and_parent
.read()
.as_ref()
.map(|name_and_parent| name_and_parent.1.clone())
}
/// Get the effective parent of dentry.
///
/// If it is the root of mount, it will go up to the mountpoint to get the parent
/// of the mountpoint recursively.
fn effective_parent(&self) -> Option<Arc<Self>> {
if !self.is_root_of_mount() {
return self.parent();
}
match self.mount_node().mountpoint_dentry() {
Some(self_mountpoint) => self_mountpoint.effective_parent(),
None => self.parent(),
}
}
fn set_name_and_parent(&self, name: &str, parent: Arc<Self>) {
let mut name_and_parent = self.name_and_parent.write();
*name_and_parent = Some((String::from(name), parent));
@ -147,30 +106,25 @@ impl Dentry {
DentryFlags::from_bits(flags).unwrap()
}
fn is_mountpoint(&self) -> bool {
pub fn is_mountpoint(&self) -> bool {
self.flags().contains(DentryFlags::MOUNTED)
}
fn set_mountpoint(&self) {
pub fn set_mountpoint(&self) {
self.flags
.fetch_or(DentryFlags::MOUNTED.bits(), Ordering::Release);
}
fn clear_mountpoint(&self) {
pub fn clear_mountpoint(&self) {
self.flags
.fetch_and(!(DentryFlags::MOUNTED.bits()), Ordering::Release);
}
/// 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()
}
/// Get the mount node which the dentry belongs to.
pub fn mount_node(&self) -> Arc<MountNode> {
self.mount_node.upgrade().unwrap()
}
/// Create a dentry by making inode.
pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
if self.inode.type_() != InodeType::Dir {
@ -193,6 +147,29 @@ impl Dentry {
Ok(child)
}
/// Lookup a dentry from DCACHE.
pub fn lookup_fast(&self, name: &str) -> Option<Arc<Dentry>> {
let mut children = self.children.lock();
children.find_dentry(name)
}
/// Lookup a dentry from filesystem.
pub fn lookup_slow(&self, name: &str) -> Result<Arc<Dentry>> {
let mut children = self.children.lock();
let inode = self.inode.lookup(name)?;
let dentry = Self::new(
inode,
DentryOptions::Leaf((String::from(name), self.this())),
);
children.insert_dentry(&dentry);
Ok(dentry)
}
pub fn insert_dentry(&self, child_dentry: &Arc<Dentry>) {
let mut children = self.children.lock();
children.insert_dentry(child_dentry);
}
/// Create a dentry by making a device inode.
pub fn mknod(&self, name: &str, mode: InodeMode, device: Arc<dyn Device>) -> Result<Arc<Self>> {
if self.inode.type_() != InodeType::Dir {
@ -215,62 +192,6 @@ impl Dentry {
Ok(child)
}
/// Lookup a dentry.
pub fn lookup(&self, name: &str) -> Result<Arc<Self>> {
if self.inode.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if !self.inode.mode()?.is_executable() {
return_errno!(Errno::EACCES);
}
if name.len() > NAME_MAX {
return_errno!(Errno::ENAMETOOLONG);
}
let dentry = match name {
"." => self.this(),
".." => self.effective_parent().unwrap_or(self.this()),
name => {
let mut children = self.children.lock();
match children.find_dentry(name) {
Some(dentry) => dentry.overlaid_dentry(),
None => {
let inode = self.inode.lookup(name)?;
let dentry = Self::new(
inode,
DentryOptions::Leaf((String::from(name), self.this())),
);
children.insert_dentry(&dentry);
dentry
}
}
}
};
Ok(dentry)
}
/// Link a new name for the dentry by linking inode.
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
if self.inode.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let mut children = self.children.lock();
if children.find_dentry(name).is_some() {
return_errno!(Errno::EEXIST);
}
if !Arc::ptr_eq(&old.mount_node(), &self.mount_node()) {
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
}
let old_inode = old.inode();
self.inode.link(old_inode, name)?;
let dentry = Self::new(
old_inode.clone(),
DentryOptions::Leaf((String::from(name), self.this())),
);
children.insert_dentry(&dentry);
Ok(())
}
/// Delete a dentry by unlinking inode.
pub fn unlink(&self, name: &str) -> Result<()> {
if self.inode.type_() != InodeType::Dir {
@ -325,9 +246,6 @@ impl Dentry {
}
} else {
// Self and new_dir are different Dentry
if !Arc::ptr_eq(&self.mount_node(), &new_dir.mount_node()) {
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
}
let (mut self_children, mut new_dir_children) =
write_lock_children_on_two_dentries(self, new_dir);
let old_dentry = self_children.find_dentry_with_checking_mountpoint(old_name)?;
@ -346,72 +264,6 @@ impl Dentry {
}
Ok(())
}
/// Mount the fs on this dentry. It will make this dentry to be a mountpoint.
///
/// If the given mountpoint has already been mounted, then its mounted child mount
/// will be updated.
/// The root dentry cannot be mounted.
///
/// Return the mounted child mount.
pub fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountNode>> {
if self.inode.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if self.effective_parent().is_none() {
return_errno_with_message!(Errno::EINVAL, "can not mount on root");
}
let child_mount = self.mount_node().mount(fs, &self.this())?;
self.set_mountpoint();
Ok(child_mount)
}
/// Unmount and return the mounted child mount.
///
/// Note that the root mount cannot be unmounted.
pub fn umount(&self) -> Result<Arc<MountNode>> {
if !self.is_root_of_mount() {
return_errno_with_message!(Errno::EINVAL, "not mounted");
}
let mount_node = self.mount_node();
let Some(mountpoint) = mount_node.mountpoint_dentry() else {
return_errno_with_message!(Errno::EINVAL, "cannot umount root mount");
};
let child_mount = mountpoint.mount_node().umount(mountpoint)?;
mountpoint.clear_mountpoint();
Ok(child_mount)
}
/// Get the absolute path.
///
/// It will resolve the mountpoint automatically.
pub fn abs_path(&self) -> String {
let mut path = self.effective_name();
let mut dentry = self.this();
loop {
match dentry.effective_parent() {
None => break,
Some(parent_dentry) => {
path = {
let parent_name = parent_dentry.effective_name();
if parent_name != "/" {
parent_name + "/" + &path
} else {
parent_name + &path
}
};
dentry = parent_dentry;
}
}
}
debug_assert!(path.starts_with('/'));
path
}
}
#[inherit_methods(from = "self.inode")]
@ -437,7 +289,6 @@ impl Dentry {
impl Debug for Dentry {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("Dentry")
.field("abs_path", &self.abs_path())
.field("inode", &self.inode)
.field("flags", &self.flags())
.finish()
@ -475,7 +326,7 @@ bitflags! {
}
enum DentryOptions {
Root(Weak<MountNode>),
Root,
Leaf((String, Arc<Dentry>)),
}

View File

@ -14,6 +14,7 @@ pub use inode::{Inode, InodeMode, InodeType, Metadata};
pub use ioctl::IoctlCmd;
pub use mount::MountNode;
pub use page_cache::{PageCache, PageCacheBackend};
pub use path::Path;
pub use random_test::{generate_random_operation, new_fs_in_memory};
pub use status_flags::StatusFlags;
@ -29,6 +30,7 @@ mod inode;
mod ioctl;
mod mount;
mod page_cache;
mod path;
mod random_test;
mod status_flags;

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use super::{Dentry, DentryKey, FileSystem, InodeType};
use super::{Dentry, DentryKey, FileSystem, InodeType, Path};
use crate::prelude::*;
/// The MountNode can form a mount tree to maintain the mount information.
@ -12,6 +12,8 @@ pub struct MountNode {
mountpoint_dentry: Option<Arc<Dentry>>,
/// The associated FS.
fs: Arc<dyn FileSystem>,
/// The parent mount node.
parent: RwLock<Option<Weak<MountNode>>>,
/// Child mount nodes which are mounted on one dentry of self.
children: Mutex<BTreeMap<DentryKey, Arc<Self>>>,
/// Reference to self.
@ -27,16 +29,21 @@ impl MountNode {
/// 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.
pub fn new_root(fs: Arc<dyn FileSystem>) -> Arc<Self> {
Self::new(fs, None)
Self::new(fs, None, None)
}
/// The internal constructor.
///
/// Root mount node has no mountpoint which other mount nodes must have mountpoint.
fn new(fs: Arc<dyn FileSystem>, mountpoint: Option<Arc<Dentry>>) -> Arc<Self> {
fn new(
fs: Arc<dyn FileSystem>,
mountpoint: Option<Arc<Dentry>>,
parent_mount: Option<Weak<MountNode>>,
) -> Arc<Self> {
Arc::new_cyclic(|weak_self| Self {
root_dentry: Dentry::new_root(fs.root_inode(), weak_self.clone()),
root_dentry: Dentry::new_root(fs.root_inode()),
mountpoint_dentry: mountpoint,
parent: RwLock::new(parent_mount),
children: Mutex::new(BTreeMap::new()),
fs,
this: weak_self.clone(),
@ -54,16 +61,20 @@ impl MountNode {
/// mountpoint. It is the fs's responsibility to ensure the data consistency.
///
/// Return the mounted child mount.
pub fn mount(&self, fs: Arc<dyn FileSystem>, mountpoint: &Arc<Dentry>) -> Result<Arc<Self>> {
if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) {
pub fn mount(&self, fs: Arc<dyn FileSystem>, mountpoint: &Arc<Path>) -> Result<Arc<Self>> {
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
}
if mountpoint.type_() != InodeType::Dir {
if mountpoint.dentry().type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let key = mountpoint.key();
let child_mount = Self::new(fs, Some(mountpoint.clone()));
let key = mountpoint.dentry().key();
let child_mount = Self::new(
fs,
Some(mountpoint.dentry().clone()),
Some(Arc::downgrade(mountpoint.mount_node())),
);
self.children.lock().insert(key, child_mount.clone());
Ok(child_mount)
}
@ -71,25 +82,28 @@ impl MountNode {
/// Unmount a child mount node from the mountpoint and return it.
///
/// The mountpoint should belong to this mount node, or an error is returned.
pub fn umount(&self, mountpoint: &Dentry) -> Result<Arc<Self>> {
if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) {
pub fn umount(&self, mountpoint: &Path) -> Result<Arc<Self>> {
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
}
let child_mount = self
.children
.lock()
.remove(&mountpoint.key())
.remove(&mountpoint.dentry().key())
.ok_or_else(|| Error::with_message(Errno::ENOENT, "can not find child mount"))?;
Ok(child_mount)
}
/// Try to get a child mount node from the mountpoint.
pub fn get(&self, mountpoint: &Dentry) -> Option<Arc<Self>> {
if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) {
pub fn get(&self, mountpoint: &Path) -> Option<Arc<Self>> {
if !Arc::ptr_eq(mountpoint.mount_node(), &self.this()) {
return None;
}
self.children.lock().get(&mountpoint.key()).cloned()
self.children
.lock()
.get(&mountpoint.dentry().key())
.cloned()
}
/// Get the root dentry of this mount node.
@ -115,10 +129,13 @@ impl MountNode {
}
/// Try to get the parent mount node.
pub fn parent(&self) -> Option<Arc<Self>> {
self.mountpoint_dentry
.as_ref()
.map(|dentry| dentry.mount_node())
pub fn parent(&self) -> Option<Weak<Self>> {
self.parent.read().as_ref().cloned()
}
pub fn set_parent(&self, mount_node: Arc<MountNode>) {
let mut parent = self.parent.write();
*parent = Some(Arc::downgrade(&mount_node));
}
/// Get strong reference to self.

View File

@ -0,0 +1,210 @@
// SPDX-License-Identifier: MPL-2.0
use super::{Dentry, FileSystem, InodeType, MountNode, NAME_MAX};
use crate::prelude::*;
/// The Path can represent a location in the mount tree.
#[derive(Debug)]
pub struct Path {
mount_node: Arc<MountNode>,
dentry: Arc<Dentry>,
this: Weak<Path>,
}
impl Path {
pub fn new(mount_node: Arc<MountNode>, dentry: Arc<Dentry>) -> Arc<Self> {
Arc::new_cyclic(|weak_self| Self {
mount_node,
dentry,
this: weak_self.clone(),
})
}
/// Lookup a path.
pub fn lookup(&self, name: &str) -> Result<Arc<Self>> {
if self.dentry.inode().type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if !self.dentry.inode().mode()?.is_executable() {
return_errno!(Errno::EACCES);
}
if name.len() > NAME_MAX {
return_errno!(Errno::ENAMETOOLONG);
}
let path = match name {
"." => self.this(),
".." => self.effective_parent().unwrap_or(self.this()),
name => {
let children_dentry = self.dentry.lookup_fast(name);
match children_dentry {
Some(dentry) => Path::new(self.mount_node().clone(), dentry.clone()),
None => {
let slow_dentry = self.dentry.lookup_slow(name)?;
Path::new(self.mount_node().clone(), slow_dentry.clone())
}
}
}
};
let path = path.overlaid_path();
Ok(path)
}
// Get the absolute path.
//
// It will resolve the mountpoint automatically.
pub fn abs_path(&self) -> String {
let mut path = self.effective_name();
let mut dir_path = self.this();
loop {
match dir_path.effective_parent() {
None => break,
Some(parent_dir_path) => {
path = {
let parent_name = parent_dir_path.effective_name();
if parent_name != "/" {
parent_name + "/" + &path
} else {
parent_name + &path
}
};
dir_path = parent_dir_path;
}
}
}
debug_assert!(path.starts_with('/'));
path
}
/// Get the effective name of path.
///
/// If it is the root of mount, it will go up to the mountpoint to get the name
/// of the mountpoint recursively.
fn effective_name(&self) -> String {
if !self.dentry.is_root_of_mount() {
return self.dentry.name();
}
if self.mount_node.parent().is_some() & self.mount_node.mountpoint_dentry().is_some() {
let parent_path = Path::new(
self.mount_node.parent().unwrap().upgrade().unwrap().clone(),
self.mount_node.mountpoint_dentry().unwrap().clone(),
);
parent_path.effective_name()
} else {
self.dentry.name()
}
}
/// Get the effective parent of path.
///
/// If it is the root of mount, it will go up to the mountpoint to get the parent
/// of the mountpoint recursively.
fn effective_parent(&self) -> Option<Arc<Self>> {
if !self.dentry.is_root_of_mount() {
return Some(Path::new(
self.mount_node.clone(),
self.dentry.parent().unwrap().clone(),
));
}
if self.mount_node.parent().is_some() & self.mount_node.mountpoint_dentry().is_some() {
let parent_path = Path::new(
self.mount_node.parent().unwrap().upgrade().unwrap().clone(),
self.mount_node.mountpoint_dentry().unwrap().clone(),
);
parent_path.effective_parent()
} else {
None
}
}
/// Get the overlaid path of self.
///
/// It will jump into the child mount if it is a mountpoint.
fn overlaid_path(&self) -> Arc<Self> {
if !self.dentry.is_mountpoint() {
return self.this();
}
match self.mount_node.get(self) {
Some(child_mount) => {
Path::new(child_mount.clone(), child_mount.root_dentry().clone()).overlaid_path()
}
None => self.this(),
}
}
/// Mount the fs on this path. It will make this path's dentry to be a mountpoint.
///
/// If the given mountpoint has already been mounted, then its mounted child mount
/// will be updated.
/// The root dentry cannot be mounted.
///
/// Return the mounted child mount.
pub fn mount(&self, fs: Arc<dyn FileSystem>) -> Result<Arc<MountNode>> {
if self.dentry.inode().type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if self.effective_parent().is_none() {
return_errno_with_message!(Errno::EINVAL, "can not mount on root");
}
let child_mount = self.mount_node().mount(fs, &self.this())?;
self.dentry().set_mountpoint();
Ok(child_mount)
}
/// Unmount and return the mounted child mount.
///
/// Note that the root mount cannot be unmounted.
pub fn umount(&self) -> Result<Arc<MountNode>> {
if !self.dentry.is_root_of_mount() {
return_errno_with_message!(Errno::EINVAL, "not mounted");
}
let mount_node = self.mount_node.clone();
let Some(mountpoint_dentry) = mount_node.mountpoint_dentry() else {
return_errno_with_message!(Errno::EINVAL, "cannot umount root mount");
};
let mountpoint_mount_node = mount_node.parent().unwrap().upgrade().unwrap();
let mountpoint_path = Path::new(mountpoint_mount_node.clone(), mountpoint_dentry.clone());
let child_mount = mountpoint_mount_node.umount(&mountpoint_path)?;
mountpoint_dentry.clear_mountpoint();
Ok(child_mount)
}
/// Link a new name for the path's dentry by linking inode.
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
if self.dentry.inode().type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let children = self.dentry.lookup_fast(name);
if children.is_some() {
return_errno!(Errno::EEXIST);
}
if !Arc::ptr_eq(old.mount_node(), self.mount_node()) {
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
}
let old_inode = old.dentry.inode();
self.dentry.inode().link(old_inode, name)?;
let dentry = self.dentry.new_child(old_inode.clone(), name);
self.dentry.insert_dentry(&dentry);
Ok(())
}
/// Get the arc reference to self.
fn this(&self) -> Arc<Self> {
self.this.upgrade().unwrap()
}
/// Get the mount node of this path.
pub fn mount_node(&self) -> &Arc<MountNode> {
&self.mount_node
}
/// Get the dentry of this path.
pub fn dentry(&self) -> &Arc<Dentry> {
&self.dentry
}
}

View File

@ -112,7 +112,6 @@ fn init_thread() {
karg.get_initproc_envp().to_vec(),
)
.expect("Run init process failed.");
// Wait till initproc become zombie.
while !initproc.is_zombie() {
// We don't have preemptive scheduler now.

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MPL-2.0
use crate::{fs::utils::Dentry, net::socket::util::socket_addr::SocketAddr, prelude::*};
use crate::{fs::utils::Path, net::socket::util::socket_addr::SocketAddr, prelude::*};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UnixSocketAddr {
@ -10,7 +10,7 @@ pub enum UnixSocketAddr {
#[derive(Clone)]
pub(super) enum UnixSocketAddrBound {
Path(Arc<Dentry>),
Path(Arc<Path>),
Abstract(String),
}
@ -18,7 +18,9 @@ impl PartialEq for UnixSocketAddrBound {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Abstract(l0), Self::Abstract(r0)) => l0 == r0,
(Self::Path(l0), Self::Path(r0)) => Arc::ptr_eq(l0.inode(), r0.inode()),
(Self::Path(l0), Self::Path(r0)) => {
Arc::ptr_eq(l0.dentry().inode(), r0.dentry().inode())
}
_ => false,
}
}
@ -38,8 +40,8 @@ impl TryFrom<SocketAddr> for UnixSocketAddr {
impl From<UnixSocketAddrBound> for UnixSocketAddr {
fn from(value: UnixSocketAddrBound) -> Self {
match value {
UnixSocketAddrBound::Path(dentry) => {
let abs_path = dentry.abs_path();
UnixSocketAddrBound::Path(path) => {
let abs_path = path.abs_path();
Self::Path(abs_path)
}
UnixSocketAddrBound::Abstract(name) => Self::Abstract(name),

View File

@ -7,7 +7,7 @@ use crate::{
events::IoEvents,
fs::{
fs_resolver::{split_path, FsPath},
utils::{Dentry, InodeMode, InodeType},
utils::{InodeMode, InodeType, Path},
},
net::socket::unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
prelude::*,
@ -37,9 +37,9 @@ impl Init {
let bound_addr = match addr_to_bind {
UnixSocketAddr::Abstract(_) => todo!(),
UnixSocketAddr::Path(path) => {
let dentry = create_socket_file(path)?;
UnixSocketAddrBound::Path(dentry)
UnixSocketAddr::Path(pathname) => {
let path = create_socket_file(pathname)?;
UnixSocketAddrBound::Path(path)
}
};
@ -87,18 +87,19 @@ impl Init {
}
}
fn create_socket_file(path: &str) -> Result<Arc<Dentry>> {
let (parent_pathname, file_name) = split_path(path);
fn create_socket_file(pathname: &str) -> Result<Arc<Path>> {
let (parent_pathname, file_name) = split_path(pathname);
let parent = {
let current = current!();
let fs = current.fs().read();
let parent_path = FsPath::try_from(parent_pathname)?;
fs.lookup(&parent_path)?
};
let dentry = parent.create(
let dentry = parent.dentry().create(
file_name,
InodeType::Socket,
InodeMode::S_IRUSR | InodeMode::S_IWUSR,
)?;
Ok(dentry)
let path = Path::new(parent.mount_node().clone(), dentry.clone());
Ok(path)
}

View File

@ -9,7 +9,7 @@ use crate::{
events::IoEvents,
fs::{
file_handle::FileLike,
utils::{Dentry, Inode},
utils::{Inode, Path},
},
net::socket::{
unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
@ -91,10 +91,10 @@ impl BacklogTable {
fn add_backlog(&self, addr: &UnixSocketAddrBound, backlog: usize) -> Result<()> {
let inode = {
let UnixSocketAddrBound::Path(dentry) = addr else {
let UnixSocketAddrBound::Path(path) = addr else {
todo!()
};
create_keyable_inode(dentry)
create_keyable_inode(path)
};
let mut backlog_sockets = self.backlog_sockets.write();
@ -108,10 +108,10 @@ impl BacklogTable {
fn get_backlog(&self, addr: &UnixSocketAddrBound) -> Result<Arc<Backlog>> {
let inode = {
let UnixSocketAddrBound::Path(dentry) = addr else {
let UnixSocketAddrBound::Path(path) = addr else {
todo!()
};
create_keyable_inode(dentry)
create_keyable_inode(path)
};
let backlog_sockets = self.backlog_sockets.read();
@ -212,8 +212,8 @@ impl Backlog {
}
}
fn create_keyable_inode(dentry: &Arc<Dentry>) -> KeyableWeak<dyn Inode> {
let weak_inode = Arc::downgrade(dentry.inode());
fn create_keyable_inode(path: &Arc<Path>) -> KeyableWeak<dyn Inode> {
let weak_inode = Arc::downgrade(path.dentry().inode());
KeyableWeak::from(weak_inode)
}

View File

@ -11,7 +11,7 @@ use crate::{
fs::{
file_handle::FileLike,
fs_resolver::FsPath,
utils::{Dentry, InodeType, StatusFlags},
utils::{InodeType, Path, StatusFlags},
},
net::socket::{
unix::{addr::UnixSocketAddrBound, UnixSocketAddr},
@ -161,9 +161,9 @@ impl Socket for UnixStreamSocket {
UnixSocketAddr::Abstract(abstract_name) => {
UnixSocketAddrBound::Abstract(abstract_name)
}
UnixSocketAddr::Path(path) => {
let dentry = lookup_socket_file(&path)?;
UnixSocketAddrBound::Path(dentry)
UnixSocketAddr::Path(pathname) => {
let path = lookup_socket_file(&pathname)?;
UnixSocketAddrBound::Path(path)
}
}
};
@ -287,20 +287,20 @@ impl Drop for UnixStreamSocket {
}
}
fn lookup_socket_file(path: &str) -> Result<Arc<Dentry>> {
let dentry = {
fn lookup_socket_file(pathname: &str) -> Result<Arc<Path>> {
let path = {
let current = current!();
let fs = current.fs().read();
let fs_path = FsPath::try_from(path)?;
let fs_path = FsPath::try_from(pathname)?;
fs.lookup(&fs_path)?
};
if dentry.type_() != InodeType::Socket {
if path.dentry().type_() != InodeType::Socket {
return_errno_with_message!(Errno::ENOTSOCK, "not a socket file")
}
if !dentry.mode()?.is_readable() || !dentry.mode()?.is_writable() {
if !path.dentry().mode()?.is_readable() || !path.dentry().mode()?.is_writable() {
return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written")
}
Ok(dentry)
Ok(path)
}

View File

@ -41,7 +41,7 @@ impl PosixThreadExt for Thread {
fs_resolver.lookup(&fs_path)?
};
let (_, elf_load_info) =
load_program_to_vm(process_vm, elf_file, argv, envp, fs_resolver, 1)?;
load_program_to_vm(process_vm, elf_file.clone(), argv, envp, fs_resolver, 1)?;
let vm_space = process_vm.root_vmar().vm_space().clone();
let mut cpu_ctx = UserContext::default();

View File

@ -12,7 +12,7 @@ use super::elf_file::Elf;
use crate::{
fs::{
fs_resolver::{FsPath, FsResolver, AT_FDCWD},
utils::Dentry,
utils::{Dentry, Path},
},
prelude::*,
process::{
@ -35,7 +35,7 @@ use crate::{
pub fn load_elf_to_vm(
process_vm: &ProcessVm,
file_header: &[u8],
elf_file: Arc<Dentry>,
elf_file: Arc<Path>,
fs_resolver: &FsResolver,
argv: Vec<CString>,
envp: Vec<CString>,
@ -101,11 +101,11 @@ fn lookup_and_parse_ldso(
};
let ldso_elf = {
let mut buf = Box::new([0u8; PAGE_SIZE]);
let inode = ldso_file.inode();
let inode = ldso_file.dentry().inode();
inode.read_at(0, &mut *buf)?;
Elf::parse_elf(&*buf)?
};
Ok((ldso_file, ldso_elf))
Ok((ldso_file.dentry().clone(), ldso_elf))
}
fn load_ldso(root_vmar: &Vmar<Full>, ldso_file: &Dentry, ldso_elf: &Elf) -> Result<LdsoLoadInfo> {

View File

@ -11,7 +11,7 @@ use super::process_vm::ProcessVm;
use crate::{
fs::{
fs_resolver::{FsPath, FsResolver, AT_FDCWD},
utils::Dentry,
utils::{Dentry, Path},
},
prelude::*,
};
@ -25,14 +25,14 @@ use crate::{
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
pub fn load_program_to_vm(
process_vm: &ProcessVm,
elf_file: Arc<Dentry>,
elf_file: Arc<Path>,
argv: Vec<CString>,
envp: Vec<CString>,
fs_resolver: &FsResolver,
recursion_limit: usize,
) -> Result<(String, ElfLoadInfo)> {
let abs_path = elf_file.abs_path();
let inode = elf_file.inode();
let inode = elf_file.dentry().inode();
let file_header = {
// read the first page of file header
let mut file_header_buffer = Box::new([0u8; PAGE_SIZE]);
@ -49,7 +49,7 @@ pub fn load_program_to_vm(
let fs_path = FsPath::new(AT_FDCWD, &filename)?;
fs_resolver.lookup(&fs_path)?
};
check_executable_file(&interpreter)?;
check_executable_file(interpreter.dentry())?;
return load_program_to_vm(
process_vm,
interpreter,

View File

@ -16,7 +16,7 @@ pub fn sys_chdir(pathname_addr: Vaddr) -> Result<SyscallReturn> {
let current = current!();
let mut fs = current.fs().write();
let dentry = {
let path = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
@ -24,10 +24,10 @@ pub fn sys_chdir(pathname_addr: Vaddr) -> Result<SyscallReturn> {
let fs_path = FsPath::try_from(pathname.as_ref())?;
fs.lookup(&fs_path)?
};
if dentry.type_() != InodeType::Dir {
if path.dentry().type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
}
fs.set_cwd(dentry);
fs.set_cwd(path);
Ok(SyscallReturn::Return(0))
}
@ -36,17 +36,17 @@ pub fn sys_fchdir(fd: FileDesc) -> Result<SyscallReturn> {
debug!("fd = {}", fd);
let current = current!();
let dentry = {
let path = {
let file_table = current.file_table().lock();
let file = file_table.get_file(fd)?;
let inode_handle = file
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
inode_handle.dentry().clone()
inode_handle.path().clone()
};
if dentry.type_() != InodeType::Dir {
if path.dentry().type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
}
current.fs().write().set_cwd(dentry);
current.fs().write().set_cwd(path);
Ok(SyscallReturn::Return(0))
}

View File

@ -35,18 +35,22 @@ pub fn sys_fchmodat(
/* flags: u32, */
) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCHMODAT);
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!("dirfd = {}, path = {:?}, mode = 0o{:o}", dirfd, path, mode,);
let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!(
"dirfd = {}, path = {:?}, mode = 0o{:o}",
dirfd, pathname, mode,
);
let current = current!();
let dentry = {
let path = path.to_string_lossy();
if path.is_empty() {
let path = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
current.fs().read().lookup(&fs_path)?
};
dentry.set_mode(InodeMode::from_bits_truncate(mode))?;
path.dentry()
.set_mode(InodeMode::from_bits_truncate(mode))?;
Ok(SyscallReturn::Return(0))
}

View File

@ -57,15 +57,15 @@ pub fn sys_fchownat(
flags: u32,
) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCHOWNAT);
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?;
let flags = ChownFlags::from_bits(flags)
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid flags"))?;
debug!(
"dirfd = {}, path = {:?}, uid = {}, gid = {}, flags = {:?}",
dirfd, path, uid, gid, flags
dirfd, pathname, uid, gid, flags
);
if path.is_empty() {
if pathname.is_empty() {
if !flags.contains(ChownFlags::AT_EMPTY_PATH) {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
@ -79,9 +79,9 @@ pub fn sys_fchownat(
}
let current = current!();
let dentry = {
let path = path.to_string_lossy();
let fs_path = FsPath::new(dirfd, path.as_ref())?;
let path = {
let pathname = pathname.to_string_lossy();
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
let fs = current.fs().read();
if flags.contains(ChownFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
@ -90,10 +90,10 @@ pub fn sys_fchownat(
}
};
if let Some(uid) = uid {
dentry.set_owner(uid)?;
path.dentry().set_owner(uid)?;
}
if let Some(gid) = gid {
dentry.set_group(gid)?;
path.dentry().set_group(gid)?;
}
Ok(SyscallReturn::Return(0))
}

View File

@ -16,7 +16,7 @@ pub fn sys_chroot(pathname_addr: Vaddr) -> Result<SyscallReturn> {
let current = current!();
let mut fs = current.fs().write();
let dentry = {
let path = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
@ -24,9 +24,9 @@ pub fn sys_chroot(pathname_addr: Vaddr) -> Result<SyscallReturn> {
let fs_path = FsPath::try_from(pathname.as_ref())?;
fs.lookup(&fs_path)?
};
if dentry.type_() != InodeType::Dir {
if path.dentry().type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
}
fs.set_root(dentry);
fs.set_root(path);
Ok(SyscallReturn::Return(0))
}

View File

@ -8,7 +8,7 @@ use crate::{
fs::{
file_table::FileDesc,
fs_resolver::{FsPath, AT_FDCWD},
utils::{Dentry, InodeType},
utils::{Dentry, InodeType, Path},
},
log_syscall_entry,
prelude::*,
@ -61,29 +61,29 @@ fn lookup_executable_file(
dfd: FileDesc,
filename: String,
flags: OpenFlags,
) -> Result<Arc<Dentry>> {
) -> Result<Arc<Path>> {
let current = current!();
let fs_resolver = current.fs().read();
let dentry = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() {
let path = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() {
fs_resolver.lookup_from_fd(dfd)
} else {
let fs_path = FsPath::new(dfd, &filename)?;
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
let dentry = fs_resolver.lookup_no_follow(&fs_path)?;
if dentry.type_() == InodeType::SymLink {
let path = fs_resolver.lookup_no_follow(&fs_path)?;
if path.dentry().type_() == InodeType::SymLink {
return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink");
}
Ok(dentry)
Ok(path)
} else {
fs_resolver.lookup(&fs_path)
}
}?;
check_executable_file(&dentry)?;
Ok(dentry)
check_executable_file(path.dentry())?;
Ok(path)
}
fn do_execve(
elf_file: Arc<Dentry>,
elf_file: Arc<Path>,
argv_ptr_ptr: Vaddr,
envp_ptr_ptr: Vaddr,
context: &mut UserContext,
@ -121,8 +121,8 @@ fn do_execve(
debug!("load elf in execve succeeds");
let credentials = credentials_mut();
set_uid_from_elf(&credentials, &elf_file)?;
set_gid_from_elf(&credentials, &elf_file)?;
set_uid_from_elf(&credentials, elf_file.dentry())?;
set_gid_from_elf(&credentials, elf_file.dentry())?;
// set executable path
current.set_executable_path(new_executable_path);

View File

@ -18,7 +18,7 @@ pub fn sys_fsync(fd: FileDesc) -> Result<SyscallReturn> {
let inode_handle = file
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EINVAL, "not inode"))?;
inode_handle.dentry().clone()
inode_handle.path().dentry().clone()
};
dentry.sync()?;
Ok(SyscallReturn::Return(0))

View File

@ -29,7 +29,7 @@ pub fn sys_getdents64(fd: FileDesc, buf_addr: Vaddr, buf_len: usize) -> Result<S
let inode_handle = file
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
if inode_handle.dentry().type_() != InodeType::Dir {
if inode_handle.path().dentry().type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let mut buffer = vec![0u8; buf_len];

View File

@ -30,7 +30,7 @@ pub fn sys_linkat(
);
let current = current!();
let (old_dentry, new_dir_dentry, new_name) = {
let (old_path, new_dir_path, new_name) = {
let old_pathname = old_pathname.to_string_lossy();
if old_pathname.ends_with('/') {
return_errno_with_message!(Errno::EPERM, "oldpath is dir");
@ -46,15 +46,15 @@ pub fn sys_linkat(
let old_fs_path = FsPath::new(old_dirfd, old_pathname.as_ref())?;
let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref())?;
let fs = current.fs().read();
let old_dentry = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) {
let old_path = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) {
fs.lookup(&old_fs_path)?
} else {
fs.lookup_no_follow(&old_fs_path)?
};
let (new_dir_dentry, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?;
(old_dentry, new_dir_dentry, new_name)
let (new_dir_path, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?;
(old_path, new_dir_path, new_name)
};
new_dir_dentry.link(&old_dentry, &new_name)?;
new_dir_path.link(&old_path, &new_name)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -22,7 +22,7 @@ pub fn sys_mkdirat(dirfd: FileDesc, pathname_addr: Vaddr, mode: u16) -> Result<S
);
let current = current!();
let (dir_dentry, name) = {
let (dir_path, name) = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
@ -35,7 +35,9 @@ pub fn sys_mkdirat(dirfd: FileDesc, pathname_addr: Vaddr, mode: u16) -> Result<S
let mask_mode = mode & !current.umask().read().get();
InodeMode::from_bits_truncate(mask_mode)
};
let _ = dir_dentry.create(name.trim_end_matches('/'), InodeType::Dir, inode_mode)?;
let _ = dir_path
.dentry()
.create(name.trim_end_matches('/'), InodeType::Dir, inode_mode)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -100,8 +100,8 @@ fn alloc_filebacked_vmo(
let current = current!();
let page_cache_vmo = {
let fs_resolver = current.fs().read();
let dentry = fs_resolver.lookup_from_fd(fd)?;
let inode = dentry.inode();
let path = fs_resolver.lookup_from_fd(fd)?;
let inode = path.dentry().inode();
inode
.page_cache()
.ok_or(Error::with_message(

View File

@ -26,7 +26,7 @@ pub fn sys_readlinkat(
);
let current = current!();
let dentry = {
let path = {
let pathname = pathname.to_string_lossy();
if pathname.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, pathname.as_ref())?;
current.fs().read().lookup_no_follow(&fs_path)?
};
let linkpath = dentry.inode().read_link()?;
let linkpath = path.dentry().inode().read_link()?;
let bytes = linkpath.as_bytes();
let write_len = bytes.len().min(usr_buf_len);
write_bytes_to_user(usr_buf_addr, &bytes[..write_len])?;

View File

@ -30,7 +30,7 @@ pub fn sys_renameat(
let current = current!();
let fs = current.fs().read();
let (old_dir_dentry, old_name) = {
let (old_dir_path, old_name) = {
let old_pathname = old_pathname.to_string_lossy();
if old_pathname.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_pathname.as_ref())?;
fs.lookup_dir_and_base_name(&old_fs_path)?
};
let old_dentry = old_dir_dentry.lookup(&old_name)?;
let old_path = old_dir_path.lookup(&old_name)?;
let (new_dir_dentry, new_name) = {
let (new_dir_path, new_name) = {
let new_pathname = new_pathname.to_string_lossy();
if new_pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "newpath is empty");
}
if new_pathname.ends_with('/') && old_dentry.type_() != InodeType::Dir {
if new_pathname.ends_with('/') && old_path.dentry().type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir");
}
let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref().trim_end_matches('/'))?;
@ -53,8 +53,8 @@ pub fn sys_renameat(
};
// Check abs_path
let old_abs_path = old_dentry.abs_path();
let new_abs_path = new_dir_dentry.abs_path() + "/" + &new_name;
let old_abs_path = old_path.abs_path();
let new_abs_path = new_dir_path.abs_path() + "/" + &new_name;
if new_abs_path.starts_with(&old_abs_path) {
if new_abs_path.len() == old_abs_path.len() {
return Ok(SyscallReturn::Return(0));
@ -66,7 +66,13 @@ pub fn sys_renameat(
}
}
old_dir_dentry.rename(&old_name, &new_dir_dentry, &new_name)?;
if !Arc::ptr_eq(old_dir_path.mount_node(), new_dir_path.mount_node()) {
return_errno_with_message!(Errno::EXDEV, "cannot cross mount");
}
old_dir_path
.dentry()
.rename(&old_name, new_dir_path.dentry(), &new_name)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -22,7 +22,7 @@ pub(super) fn sys_rmdirat(dirfd: FileDesc, pathname_addr: Vaddr) -> Result<Sysca
debug!("dirfd = {}, pathname = {:?}", dirfd, pathname);
let current = current!();
let (dir_dentry, name) = {
let (dir_path, name) = {
let pathname = pathname.to_string_lossy();
if pathname == "/" {
return_errno_with_message!(Errno::EBUSY, "is root directory");
@ -30,6 +30,6 @@ pub(super) fn sys_rmdirat(dirfd: FileDesc, pathname_addr: Vaddr) -> Result<Sysca
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
current.fs().read().lookup_dir_and_base_name(&fs_path)?
};
dir_dentry.rmdir(name.trim_end_matches('/'))?;
dir_path.dentry().rmdir(name.trim_end_matches('/'))?;
Ok(SyscallReturn::Return(0))
}

View File

@ -63,7 +63,7 @@ pub fn sys_fstatat(
}
let current = current!();
let dentry = {
let path = {
let filename = filename.to_string_lossy();
let fs_path = FsPath::new(dirfd, filename.as_ref())?;
let fs = current.fs().read();
@ -73,7 +73,7 @@ pub fn sys_fstatat(
fs.lookup(&fs_path)?
}
};
let stat = Stat::from(dentry.metadata());
let stat = Stat::from(path.dentry().metadata());
write_val_to_user(stat_buf_ptr, &stat)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -15,16 +15,19 @@ use crate::{
pub fn sys_statfs(path_ptr: Vaddr, statfs_buf_ptr: Vaddr) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_STATFS);
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!("path = {:?}, statfs_buf_ptr = 0x{:x}", path, statfs_buf_ptr,);
let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!(
"pathname = {:?}, statfs_buf_ptr = 0x{:x}",
pathname, statfs_buf_ptr,
);
let current = current!();
let dentry = {
let path = path.to_string_lossy();
let fs_path = FsPath::try_from(path.as_ref())?;
let path = {
let pathname = pathname.to_string_lossy();
let fs_path = FsPath::try_from(pathname.as_ref())?;
current.fs().read().lookup(&fs_path)?
};
let statfs = Statfs::from(dentry.fs().sb());
let statfs = Statfs::from(path.dentry().fs().sb());
write_val_to_user(statfs_buf_ptr, &statfs)?;
Ok(SyscallReturn::Return(0))
}
@ -39,7 +42,7 @@ pub fn sys_fstatfs(fd: FileDesc, statfs_buf_ptr: Vaddr) -> Result<SyscallReturn>
let inode_handle = file
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
let dentry = inode_handle.dentry();
let dentry = inode_handle.path().dentry();
let statfs = Statfs::from(dentry.fs().sb());
write_val_to_user(statfs_buf_ptr, &statfs)?;
Ok(SyscallReturn::Return(0))

View File

@ -31,7 +31,7 @@ pub fn sys_symlinkat(
if target.is_empty() {
return_errno_with_message!(Errno::ENOENT, "target is empty");
}
let (dir_dentry, link_name) = {
let (dir_path, link_name) = {
let linkpath = linkpath.to_string_lossy();
if 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)?
};
let new_dentry = dir_dentry.create(
let new_dentry = dir_path.dentry().create(
&link_name,
InodeType::SymLink,
InodeMode::from_bits_truncate(0o777),

View File

@ -28,21 +28,21 @@ pub fn sys_ftruncate(fd: FileDesc, len: isize) -> Result<SyscallReturn> {
pub fn sys_truncate(path_ptr: Vaddr, len: isize) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_TRUNCATE);
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!("path = {:?}, length = {}", path, len);
let pathname = read_cstring_from_user(path_ptr, PATH_MAX)?;
debug!("pathname = {:?}, length = {}", pathname, len);
check_length(len)?;
let current = current!();
let dentry = {
let path = path.to_string_lossy();
if path.is_empty() {
let path = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
let fs_path = FsPath::new(AT_FDCWD, pathname.as_ref())?;
current.fs().read().lookup(&fs_path)?
};
dentry.resize(len as usize)?;
path.dentry().resize(len as usize)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -24,7 +24,7 @@ pub fn sys_unlinkat(dirfd: FileDesc, pathname_addr: Vaddr, flags: u32) -> Result
debug!("dirfd = {}, pathname = {:?}", dirfd, pathname);
let current = current!();
let (dir_dentry, name) = {
let (dir_path, name) = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
@ -35,7 +35,7 @@ pub fn sys_unlinkat(dirfd: FileDesc, pathname_addr: Vaddr, flags: u32) -> Result
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
current.fs().read().lookup_dir_and_base_name(&fs_path)?
};
dir_dentry.unlink(&name)?;
dir_path.dentry().unlink(&name)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -61,7 +61,7 @@ pub fn sys_utimensat(
return Ok(SyscallReturn::Return(0));
}
let current = current!();
let dentry = {
let path = {
let pathname = pathname.to_string_lossy();
if pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "pathname is empty");
@ -75,10 +75,10 @@ pub fn sys_utimensat(
}
};
if let Some(time) = atime {
dentry.set_atime(Duration::from(time));
path.dentry().set_atime(Duration::from(time));
}
if let Some(time) = mtime {
dentry.set_mtime(Duration::from(time));
path.dentry().set_mtime(Duration::from(time));
}
Ok(SyscallReturn::Return(0))
}

View File

@ -220,7 +220,7 @@ impl Vdso {
let vdso_path = FsPath::new(AT_FDCWD, "/lib/x86_64-linux-gnu/vdso64.so").unwrap();
let fs_resolver = FsResolver::new();
let vdso_lib = fs_resolver.lookup(&vdso_path).unwrap();
vdso_lib.inode().page_cache().unwrap()
vdso_lib.dentry().inode().page_cache().unwrap()
};
let mut vdso_text = Box::new([0u8; PAGE_SIZE]);
vdso_lib_vmo.read_bytes(0, &mut *vdso_text).unwrap();