Skip to content

Commit

Permalink
fix(symlink): can walk symlink path now
Browse files Browse the repository at this point in the history
  • Loading branch information
ChenRuiwei committed Aug 18, 2024
1 parent 6fedbc5 commit e7e68fd
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 274 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions kernel/src/impls.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! Impls of traits defined in other crates.
use alloc::{fmt, string::ToString};
use alloc::{fmt, string::ToString, sync::Arc};

use config::mm::VIRT_RAM_OFFSET;
use driver::KernelPageTableIf;
use log::Level;
use logging::{ColorCode, LogIf};
use memory::{KernelMappingIf, PageTable, PhysAddr, VirtAddr};
use net::HasSignalIf;
use vfs::procfs::KernelProcIf;
use vfs::{procfs::KernelProcIf, sys_root_dentry};
use vfs_core::{Dentry, SysRootDentryIf};

use crate::{
mm::kernel_page_table_mut,
Expand Down Expand Up @@ -109,3 +110,12 @@ impl KernelProcIf for KernelProcIfImpl {
current_task_ref().elf().dentry().path()
}
}

struct SysRootDentryIfImpl;

#[crate_interface::impl_interface]
impl SysRootDentryIf for SysRootDentryIfImpl {
fn sys_root_dentry() -> Arc<dyn Dentry> {
sys_root_dentry()
}
}
4 changes: 2 additions & 2 deletions kernel/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use schedule::{spawn_kernel_task, spawn_user_task};
pub use task::Task;
pub use tid::{PGid, Pid, Tid, TID_ALLOCATOR};
use vfs::sys_root_dentry;
use vfs_core::Path;
use vfs_core::{OpenFlags, Path};

use crate::{
mm::memory_space::{init_stack, MemorySpace},
Expand All @@ -29,7 +29,7 @@ pub fn spawn_init_proc() {
let envp = Vec::new();

let file = Path::new(sys_root_dentry(), sys_root_dentry(), init_proc_path)
.walk()
.walk(OpenFlags::empty())
.unwrap()
.open()
.unwrap();
Expand Down
13 changes: 8 additions & 5 deletions kernel/src/task/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ use sync::mutex::SpinNoIrqLock;
use systype::{SysError, SysResult};
use time::stat::TaskTimeStat;
use vfs::{fd_table::FdTable, sys_root_dentry};
use vfs_core::{is_absolute_path, AtFd, Dentry, File, InodeMode, InodeType, OpenFlags, Path};
use vfs_core::{
is_absolute_path, split_path, AtFd, Dentry, File, InodeMode, InodeType, OpenFlags, Path,
};

use super::{
resource::CpuMask,
Expand Down Expand Up @@ -677,11 +679,12 @@ impl Task {
}
}
};
let dentry = path.walk()?;

let dentry = path.walk(OpenFlags::empty())?;
if flags.contains(OpenFlags::O_NOFOLLOW) {
Ok(dentry)
} else {
self.resolve_dentry(dentry)
Path::resolve_dentry(dentry)
}
}

Expand All @@ -700,7 +703,7 @@ impl Task {
} else {
Path::new(sys_root_dentry(), dentry_it.parent().unwrap(), &path)
};
let new_dentry = path.walk()?;
let new_dentry = path.walk(OpenFlags::empty())?;
dentry_it = new_dentry;
}
_ => return Ok(dentry_it),
Expand All @@ -712,7 +715,7 @@ impl Task {
/// Given a path, absolute or relative, will find.
pub fn resolve_path(&self, path: &str) -> SysResult<Arc<dyn Dentry>> {
let dentry = self.at_helper(AtFd::FdCwd, path, OpenFlags::empty())?;
self.resolve_dentry(dentry)
Path::resolve_dentry(dentry)
}

/// Given a path, absolute or relative, will find.
Expand Down
2 changes: 2 additions & 0 deletions modules/vfs-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ device-core = { path = "../device-core/" }
page = { path = "../page/" }
driver = { path = "../../driver/" }
time = { path = "../time" }
async-utils = { path = "../../crates/async-utils/" }

crate_interface = "0.1"
bitflags = "2.5"
log = "0.4"
async-trait = "0.1"
Expand Down
76 changes: 62 additions & 14 deletions modules/vfs-core/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ use alloc::{
vec::Vec,
};

use async_utils::block_on;
use crate_interface::call_interface;
use systype::{SysError, SysResult};

use crate::{Dentry, InodeMode};
use crate::{dentry, Dentry, InodeMode, InodeType, OpenFlags};

#[derive(Clone)]
pub struct Path {
/// The root of the file system
root: Arc<dyn Dentry>,
pub root: Arc<dyn Dentry>,
/// The directory to start searching from
start: Arc<dyn Dentry>,
pub start: Arc<dyn Dentry>,
/// The path to search for
path: String,
pub path: String,
}

impl Eq for Path {}
Expand All @@ -36,7 +38,7 @@ impl Path {
}

/// Walk until path has been resolved.
pub fn walk(&self) -> SysResult<Arc<dyn Dentry>> {
pub fn walk(&self, flags: OpenFlags) -> SysResult<Arc<dyn Dentry>> {
let path = self.path.as_str();
let mut dentry = if is_absolute_path(path) {
self.root.clone()
Expand All @@ -50,20 +52,61 @@ impl Path {
dentry = dentry.parent().ok_or(SysError::ENOENT)?;
}
// NOTE: lookup will only create negative dentry in non-negetive dir dentry
name => match dentry.lookup(name) {
Ok(sub_dentry) => {
log::debug!("[Path::walk] sub dentry {}", sub_dentry.name());
dentry = sub_dentry
name => {
dentry = if !flags.contains(OpenFlags::O_NOFOLLOW)
&& dentry.inode()?.itype().is_symlink()
{
Path::resolve_dentry(dentry)?
} else {
dentry
};
match dentry.lookup(name) {
Ok(sub_dentry) => {
log::debug!("[Path::walk] sub dentry {}", sub_dentry.name());
dentry = sub_dentry
}
Err(e) => {
log::warn!("[Path::walk] {e:?} when walking in path {path}");
return Err(e);
}
}
Err(e) => {
log::warn!("[Path::walk] {e:?} when walking in path {path}");
return Err(e);
}
},
}
}
}
Ok(dentry)
}

pub fn resolve_dentry(dentry: Arc<dyn Dentry>) -> SysResult<Arc<dyn Dentry>> {
const MAX_RESOLVE_LINK_DEPTH: usize = 40;
let mut dentry_it = dentry;
for _ in 0..MAX_RESOLVE_LINK_DEPTH {
if dentry_it.is_negetive() {
return Ok(dentry_it);
}
match dentry_it.inode()?.itype() {
InodeType::SymLink => {
let path = block_on(async { dentry_it.open()?.readlink_string().await })?;
let path = if is_absolute_path(&path) {
Path::new(
call_interface!(SysRootDentryIf::sys_root_dentry()),
call_interface!(SysRootDentryIf::sys_root_dentry()),
&path,
)
} else {
Path::new(
call_interface!(SysRootDentryIf::sys_root_dentry()),
dentry_it.parent().unwrap(),
&path,
)
};
let new_dentry = path.walk(OpenFlags::empty())?;
dentry_it = new_dentry;
}
_ => return Ok(dentry_it),
}
}
Err(SysError::ELOOP)
}
}

pub fn is_absolute_path(path: &str) -> bool {
Expand Down Expand Up @@ -95,3 +138,8 @@ pub fn split_parent_and_name(path: &str) -> (&str, Option<&str>) {
pub fn get_name(path: &str) -> &str {
path.split('/').last().unwrap_or("/")
}

#[crate_interface::def_interface]
pub trait SysRootDentryIf {
fn sys_root_dentry() -> Arc<dyn Dentry>;
}
4 changes: 2 additions & 2 deletions modules/vfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use procfs::init_procfs;
use sockfs::SockFsType;
use spin::Once;
use sync::mutex::SpinNoIrqLock;
use vfs_core::{Dentry, DentryState, FileSystemType, InodeMode, MountFlags, Path};
use vfs_core::{Dentry, DentryState, FileSystemType, InodeMode, MountFlags, OpenFlags, Path};

use crate::{
devfs::{init_devfs, DevFsType},
Expand Down Expand Up @@ -131,7 +131,7 @@ struct FrameReleaseIfImpl;
impl FrameReleaseIf for FrameReleaseIfImpl {
fn release_frames() {
let ltp_dentry = Path::new(sys_root_dentry(), sys_root_dentry(), "/ltp/testcases/bin/")
.walk()
.walk(OpenFlags::empty())
.unwrap();
for (_, child) in ltp_dentry.children() {
if let Ok(inode) = child.inode() {
Expand Down
Loading

0 comments on commit e7e68fd

Please sign in to comment.