Skip to content

Commit

Permalink
fs: implement directory relative ops (openat)
Browse files Browse the repository at this point in the history
  • Loading branch information
equation314 committed Apr 6, 2023
1 parent f2dbc95 commit f4b2bf9
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 24 deletions.
2 changes: 1 addition & 1 deletion modules/axfs/src/api/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl DirBuilder {
if self.recursive {
self.create_dir_all(path)
} else {
crate::root::create_dir(path)
crate::root::create_dir(None, path)
}
}

Expand Down
4 changes: 2 additions & 2 deletions modules/axfs/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ pub fn create_dir_all(path: &str) -> io::Result<()> {

/// Removes an empty directory.
pub fn remove_dir(path: &str) -> io::Result<()> {
crate::root::remove_dir(path)
crate::root::remove_dir(None, path)
}

/// Removes a file from the filesystem.
pub fn remove_file(path: &str) -> io::Result<()> {
crate::root::remove_file(path)
crate::root::remove_file(None, path)
}
50 changes: 45 additions & 5 deletions modules/axfs/src/fops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ impl OpenOptions {
}

impl File {
pub fn open(path: &str, opts: &OpenOptions) -> AxResult<Self> {
fn _open_at(dir: Option<&VfsNodeRef>, path: &str, opts: &OpenOptions) -> AxResult<Self> {
debug!("open file: {} {:?}", path, opts);
if !opts.is_valid() {
return ax_err!(InvalidInput);
}

let node_option = crate::root::lookup(path);
let node_option = crate::root::lookup(dir, path);
let node = if opts.create || opts.create_new {
match node_option {
Ok(node) => {
Expand All @@ -108,7 +108,7 @@ impl File {
node
}
// not exists, create new
Err(VfsError::NotFound) => crate::root::create_file(path)?,
Err(VfsError::NotFound) => crate::root::create_file(dir, path)?,
Err(e) => return Err(e),
}
} else {
Expand Down Expand Up @@ -138,6 +138,10 @@ impl File {
})
}

pub fn open(path: &str, opts: &OpenOptions) -> AxResult<Self> {
Self::_open_at(None, path, opts)
}

pub fn truncate(&self, size: u64) -> AxResult {
self.node.access(Cap::WRITE)?.truncate(size)?;
Ok(())
Expand Down Expand Up @@ -171,7 +175,7 @@ impl File {
}

impl Directory {
pub fn open_dir(path: &str, opts: &OpenOptions) -> AxResult<Self> {
fn _open_dir_at(dir: Option<&VfsNodeRef>, path: &str, opts: &OpenOptions) -> AxResult<Self> {
debug!("open dir: {}", path);
if !opts.read {
return ax_err!(InvalidInput);
Expand All @@ -180,7 +184,7 @@ impl Directory {
return ax_err!(InvalidInput);
}

let node = crate::root::lookup(path)?;
let node = crate::root::lookup(dir, path)?;
let attr = node.get_attr()?;
if !attr.is_dir() {
return ax_err!(NotADirectory);
Expand All @@ -197,6 +201,42 @@ impl Directory {
})
}

fn access_at(&self, path: &str) -> AxResult<Option<&VfsNodeRef>> {
if path.starts_with('/') {
Ok(None)
} else {
Ok(Some(self.node.access(Cap::EXECUTE)?))
}
}

pub fn open_dir(path: &str, opts: &OpenOptions) -> AxResult<Self> {
Self::_open_dir_at(None, path, opts)
}

pub fn open_dir_at(&self, path: &str, opts: &OpenOptions) -> AxResult<Self> {
Self::_open_dir_at(self.access_at(path)?, path, opts)
}

pub fn open_file_at(&self, path: &str, opts: &OpenOptions) -> AxResult<File> {
File::_open_at(self.access_at(path)?, path, opts)
}

pub fn create_file(&self, path: &str) -> AxResult<VfsNodeRef> {
crate::root::create_file(self.access_at(path)?, path)
}

pub fn create_dir(&self, path: &str) -> AxResult {
crate::root::create_dir(self.access_at(path)?, path)
}

pub fn remove_file(&self, path: &str) -> AxResult {
crate::root::remove_file(self.access_at(path)?, path)
}

pub fn remove_dir(&self, path: &str) -> AxResult {
crate::root::remove_dir(self.access_at(path)?, path)
}

pub fn read_dir(&mut self, dirents: &mut [DirEntry]) -> AxResult<usize> {
let n = self
.node
Expand Down
32 changes: 16 additions & 16 deletions modules/axfs/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,58 +164,58 @@ pub(crate) fn init_rootfs(disk: crate::dev::Disk) {
*CURRENT_DIR_PATH.lock() = "/".into();
}

fn parent_node_of(path: &str) -> VfsNodeRef {
fn parent_node_of(dir: Option<&VfsNodeRef>, path: &str) -> VfsNodeRef {
if path.starts_with('/') {
ROOT_DIR.clone()
} else {
CURRENT_DIR.lock().clone()
dir.cloned().unwrap_or_else(|| CURRENT_DIR.lock().clone())
}
}

pub(crate) fn lookup(path: &str) -> AxResult<VfsNodeRef> {
pub(crate) fn lookup(dir: Option<&VfsNodeRef>, path: &str) -> AxResult<VfsNodeRef> {
if path.is_empty() {
return ax_err!(NotFound);
}
let node = parent_node_of(path).lookup(path)?;
let node = parent_node_of(dir, path).lookup(path)?;
if path.ends_with('/') && !node.get_attr()?.is_dir() {
ax_err!(NotADirectory)
} else {
Ok(node)
}
}

pub(crate) fn create_file(path: &str) -> AxResult<VfsNodeRef> {
pub(crate) fn create_file(dir: Option<&VfsNodeRef>, path: &str) -> AxResult<VfsNodeRef> {
if path.is_empty() {
return ax_err!(NotFound);
} else if path.ends_with('/') {
return ax_err!(NotADirectory);
}
let parent = parent_node_of(path);
let parent = parent_node_of(dir, path);
parent.create(path, VfsNodeType::File)?;
parent.lookup(path)
}

pub(crate) fn create_dir(path: &str) -> AxResult {
match lookup(path) {
pub(crate) fn create_dir(dir: Option<&VfsNodeRef>, path: &str) -> AxResult {
match lookup(dir, path) {
Ok(_) => ax_err!(AlreadyExists),
Err(AxError::NotFound) => parent_node_of(path).create(path, VfsNodeType::Dir),
Err(AxError::NotFound) => parent_node_of(dir, path).create(path, VfsNodeType::Dir),
Err(e) => Err(e),
}
}

pub(crate) fn remove_file(path: &str) -> AxResult {
let node = lookup(path)?;
pub(crate) fn remove_file(dir: Option<&VfsNodeRef>, path: &str) -> AxResult {
let node = lookup(dir, path)?;
let attr = node.get_attr()?;
if attr.is_dir() {
ax_err!(IsADirectory)
} else if !attr.perm().owner_writable() {
ax_err!(PermissionDenied)
} else {
parent_node_of(path).remove(path)
parent_node_of(dir, path).remove(path)
}
}

pub(crate) fn remove_dir(path: &str) -> AxResult {
pub(crate) fn remove_dir(dir: Option<&VfsNodeRef>, path: &str) -> AxResult {
// TODO: canonicalize path to avoid bypassing checks for removeing mount points
if path.is_empty() {
return ax_err!(NotFound);
Expand All @@ -231,14 +231,14 @@ pub(crate) fn remove_dir(path: &str) -> AxResult {
return ax_err!(InvalidInput);
}

let node = lookup(path)?;
let node = lookup(dir, path)?;
let attr = node.get_attr()?;
if !attr.is_dir() {
ax_err!(NotADirectory)
} else if !attr.perm().owner_writable() {
ax_err!(PermissionDenied)
} else {
parent_node_of(path).remove(path)
parent_node_of(dir, path).remove(path)
}
}

Expand All @@ -247,7 +247,7 @@ pub(crate) fn current_dir() -> AxResult<String> {
}

pub(crate) fn set_current_dir(path: &str) -> AxResult {
let node = lookup(path)?;
let node = lookup(None, path)?;
let attr = node.get_attr()?;
if !attr.is_dir() {
ax_err!(NotADirectory)
Expand Down

0 comments on commit f4b2bf9

Please sign in to comment.