summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/disk/allocation.rs10
-rw-r--r--src/disk/inode.rs10
-rw-r--r--src/filesystem/trait_impl.rs332
-rw-r--r--src/memory/cached_inode.rs10
-rw-r--r--src/memory/dir_entry.rs100
5 files changed, 371 insertions, 91 deletions
diff --git a/src/disk/allocation.rs b/src/disk/allocation.rs
index d4ad397..d0142c9 100644
--- a/src/disk/allocation.rs
+++ b/src/disk/allocation.rs
@@ -404,7 +404,10 @@ impl AyaFS {
inode: &Inode,
mut block_index_within_inode: usize,
) -> Option<usize> {
- debug!("get_block_index(block_index_within_inode: {})", block_index_within_inode);
+ debug!(
+ "get_block_index(block_index_within_inode: {})",
+ block_index_within_inode
+ );
// direct block
if block_index_within_inode < DIRECT_NUMBER {
let block_index = inode.direct[block_index_within_inode] as usize;
@@ -525,7 +528,10 @@ impl AyaFS {
) -> Option<&mut CachedBlock<T>> {
self.get_block_index(inode, block_index_within_inode)
.map(|block_index| {
- debug!("access_block_mut(index: {}) found", block_index_within_inode);
+ debug!(
+ "access_block_mut(index: {}) found",
+ block_index_within_inode
+ );
self.get_block_mut::<T>(block_index).unwrap() // 可以 unwrap 吧这里 ??
})
}
diff --git a/src/disk/inode.rs b/src/disk/inode.rs
index 1f5e54e..e686d01 100644
--- a/src/disk/inode.rs
+++ b/src/disk/inode.rs
@@ -82,7 +82,9 @@ impl InodeMode {
(self.0 & 0xF000) == Self::IFDIR.0
}
- pub(crate) fn is_symlink(&self) -> bool { self.0 & 0xF000 == Self::IFLNK.0 }
+ pub(crate) fn is_symlink(&self) -> bool {
+ self.0 & 0xF000 == Self::IFLNK.0
+ }
pub(crate) fn validate(mode_value: u16) -> Option<Self> {
let valid_flags: [u16; 7] = [0x1000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000];
@@ -274,8 +276,10 @@ impl Inode {
self.mode.is_dir()
}
- pub(crate) fn is_symlink(&self) -> bool { self.mode.is_symlink() }
-
+ pub(crate) fn is_symlink(&self) -> bool {
+ self.mode.is_symlink()
+ }
+
pub(crate) fn file_type(&self) -> FileType {
self.mode.into()
}
diff --git a/src/filesystem/trait_impl.rs b/src/filesystem/trait_impl.rs
index 5523c8c..e030f04 100644
--- a/src/filesystem/trait_impl.rs
+++ b/src/filesystem/trait_impl.rs
@@ -1,19 +1,22 @@
+use crate::block_device::BLOCK_SIZE;
+use crate::disk::block::DataBlock;
use crate::disk::inode::InodeMode;
use crate::utils::permissions::get_groups;
use crate::utils::permissions::{check_access, clear_suid_sgid};
use crate::utils::{from_filetype, from_systime, time_now, to_fileattr, to_filetype};
use crate::{AyaFS, TTL};
use fuser::TimeOrNow::{Now, SpecificTime};
-use fuser::{Filesystem, FileType, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, ReplyWrite, Request, TimeOrNow};
-use libc::{c_int, EACCES, EBADF, EEXIST, EFAULT, EINVAL, EIO, EISDIR, ENAMETOOLONG, ENOENT, ENOSPC, ENOSYS, ENOTDIR, ENOTEMPTY, EPERM, IPOPT_OFFSET, link, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY, R_OK, S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK, write};
+use fuser::{
+ FileType, Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty,
+ ReplyEntry, ReplyOpen, ReplyWrite, Request, TimeOrNow,
+};
+use libc::{c_int, link, write, EACCES, EBADF, EEXIST, EFAULT, EINVAL, EIO, EISDIR, ENAMETOOLONG, ENOENT, ENOSPC, ENOSYS, ENOTDIR, ENOTEMPTY, EPERM, IPOPT_OFFSET, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY, R_OK, S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK, RENAME_NOREPLACE, RENAME_EXCHANGE};
use log::debug;
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::slice;
use std::time::SystemTime;
-use crate::block_device::BLOCK_SIZE;
-use crate::disk::block::DataBlock;
impl AyaFS {}
@@ -79,11 +82,11 @@ impl Filesystem for AyaFS {
atime: Option<TimeOrNow>,
mtime: Option<TimeOrNow>,
_ctime: Option<SystemTime>,
- fh: Option<u64>, // 当 setattr 被 ftruncate invoke 时会提供 fh
- _crtime: Option<SystemTime>, // 忽略
- _chgtime: Option<SystemTime>, // 忽略
+ fh: Option<u64>, // 当 setattr 被 ftruncate invoke 时会提供 fh
+ _crtime: Option<SystemTime>, // 忽略
+ _chgtime: Option<SystemTime>, // 忽略
_bkuptime: Option<SystemTime>, // 忽略
- _flags: Option<u32>, // 忽略
+ _flags: Option<u32>, // 忽略
reply: ReplyAttr,
) {
if let Some(inode) = self.get_inode_mut(ino as usize) {
@@ -160,7 +163,8 @@ impl Filesystem for AyaFS {
debug!("ftruncate on inode {:#x?} size {:?}", ino, size);
if let Some(file_handle) = fh {
let mut inode = inode.clone();
- let (inode_index, _read, write) = self.file_handle_map.get(&file_handle).unwrap();
+ let (inode_index, _read, write) =
+ self.file_handle_map.get(&file_handle).unwrap();
assert_eq!(ino as usize, *inode_index);
if !write {
reply.error(EACCES);
@@ -170,14 +174,7 @@ impl Filesystem for AyaFS {
self.update_inode(*inode_index, inode);
}
} else {
- if !check_access(
- req.uid(),
- req.gid(),
- inode.uid,
- inode.gid,
- inode.mode,
- W_OK,
- ) {
+ if !check_access(req.uid(), req.gid(), inode.uid, inode.gid, inode.mode, W_OK) {
reply.error(EACCES);
} else {
inode.size = size as u32;
@@ -256,7 +253,14 @@ impl Filesystem for AyaFS {
}
}
- fn symlink(&mut self, req: &Request<'_>, parent: u64, link_name: &OsStr, target: &Path, reply: ReplyEntry) {
+ fn symlink(
+ &mut self,
+ req: &Request<'_>,
+ parent: u64,
+ link_name: &OsStr,
+ target: &Path,
+ reply: ReplyEntry,
+ ) {
debug!(
"symlink(parent: {}, name: {:?}, target: {:?})",
parent, link_name, target
@@ -291,7 +295,7 @@ impl Filesystem for AyaFS {
parent_inode.uid,
parent_inode.gid,
parent_inode.mode,
- W_OK
+ W_OK,
) {
reply.error(EACCES);
return;
@@ -309,10 +313,7 @@ impl Filesystem for AyaFS {
let target = target.as_os_str();
let mut parent_inode = parent_inode.clone();
- if self
- .lookup_name(parent, &parent_inode, link_name)
- .is_ok()
- {
+ if self.lookup_name(parent, &parent_inode, link_name).is_ok() {
reply.error(EEXIST);
return;
}
@@ -337,21 +338,37 @@ impl Filesystem for AyaFS {
let block_index = write_ptr / BLOCK_SIZE;
let offset = write_ptr % BLOCK_SIZE;
- let write_length_within_block = if BLOCK_SIZE - offset < target.len() - write_ptr {
- BLOCK_SIZE - offset
- } else {
- target.len() - write_ptr
- };
-
- if let Some(block) = self.access_block_mut::<DataBlock>(&child_inode, block_index) {
- block.block.0[offset .. offset + write_length_within_block]
- .copy_from_slice(&target.as_bytes()[write_ptr .. write_ptr + write_length_within_block]);
+ let write_length_within_block =
+ if BLOCK_SIZE - offset < target.len() - write_ptr {
+ BLOCK_SIZE - offset
+ } else {
+ target.len() - write_ptr
+ };
+
+ if let Some(block) =
+ self.access_block_mut::<DataBlock>(&child_inode, block_index)
+ {
+ block.block.0[offset..offset + write_length_within_block]
+ .copy_from_slice(
+ &target.as_bytes()
+ [write_ptr..write_ptr + write_length_within_block],
+ );
write_ptr += write_length_within_block;
} else {
- if let Some((_block_index, block_index_within_inode)) = self.allocate_block_for(&mut child_inode) {
- let block = self.access_block_mut::<DataBlock>(&child_inode, block_index_within_inode).unwrap();
- block.block.0[offset .. offset + write_length_within_block]
- .copy_from_slice(&target.as_bytes()[write_ptr .. write_ptr + write_length_within_block]);
+ if let Some((_block_index, block_index_within_inode)) =
+ self.allocate_block_for(&mut child_inode)
+ {
+ let block = self
+ .access_block_mut::<DataBlock>(
+ &child_inode,
+ block_index_within_inode,
+ )
+ .unwrap();
+ block.block.0[offset..offset + write_length_within_block]
+ .copy_from_slice(
+ &target.as_bytes()
+ [write_ptr..write_ptr + write_length_within_block],
+ );
write_ptr += write_length_within_block;
} else {
reply.error(ENOSPC);
@@ -399,14 +416,20 @@ impl Filesystem for AyaFS {
let path_length = inode.size as usize;
let mut path = vec![0u8; path_length];
if path_length < 60 {
- debug!("symlink path length is {}, reading directly from inode.direct", path_length);
+ debug!(
+ "symlink path length is {}, reading directly from inode.direct",
+ path_length
+ );
let copy_src = unsafe {
let src = (&inode.direct) as *const u32 as *const u8;
slice::from_raw_parts(src, path_length)
};
path.as_mut_slice().copy_from_slice(copy_src);
} else {
- debug!("symlink path length is {}, using original read", path_length);
+ debug!(
+ "symlink path length is {}, using original read",
+ path_length
+ );
let inode = inode.clone();
let mut read_ptr = 0usize;
while read_ptr < path_length {
@@ -420,8 +443,9 @@ impl Filesystem for AyaFS {
};
if let Some(block) = self.access_block::<DataBlock>(&inode, block_index) {
- (&mut path[read_ptr .. read_ptr + read_length_within_block])
- .copy_from_slice(&block.block.0[offset .. offset + read_length_within_block]);
+ (&mut path[read_ptr..read_ptr + read_length_within_block]).copy_from_slice(
+ &block.block.0[offset..offset + read_length_within_block],
+ );
read_ptr += read_length_within_block;
} else {
reply.error(EIO);
@@ -429,13 +453,142 @@ impl Filesystem for AyaFS {
}
}
}
- debug!("readlink path read is {:?}", OsStr::from_bytes(path.as_slice()));
+ debug!(
+ "readlink path read is {:?}",
+ OsStr::from_bytes(path.as_slice())
+ );
reply.data(path.as_slice());
} else {
reply.error(ENOENT);
}
}
+ fn rename(
+ &mut self,
+ req: &Request<'_>,
+ parent: u64,
+ name: &OsStr,
+ new_parent: u64,
+ new_name: &OsStr,
+ flags: u32,
+ reply: ReplyEmpty,
+ ) {
+ debug!(
+ "rename(parent: {}, name: {:?}, new_parent: {}, new_name: {:?})",
+ parent, name, new_parent, new_name
+ );
+
+ let parent = parent as usize;
+ let new_parent = new_parent as usize;
+ if let Some(parent_inode) = self.get_inode(parent) {
+ if !check_access(
+ req.uid(),
+ req.gid(),
+ parent_inode.uid,
+ parent_inode.gid,
+ parent_inode.mode,
+ R_OK,
+ ) {
+ reply.error(EACCES);
+ return;
+ }
+
+ if name.len() > 255 {
+ reply.error(ENAMETOOLONG);
+ return;
+ }
+
+ let mut parent_inode = parent_inode.clone();
+ match self.lookup_name(parent, &parent_inode, name) {
+ Ok((inode_index, entry_index, inode)) => {
+ if let Some(new_parent_inode) = self.get_inode(new_parent) {
+ if !check_access(
+ req.uid(),
+ req.gid(),
+ new_parent_inode.uid,
+ new_parent_inode.gid,
+ new_parent_inode.mode,
+ W_OK,
+ ) {
+ reply.error(EACCES);
+ return;
+ }
+ if new_name.len() > 255 {
+ reply.error(ENAMETOOLONG);
+ return;
+ }
+
+ let mut new_parent_inode = new_parent_inode.clone();
+ match self.lookup_name(new_parent, &new_parent_inode, new_name) {
+ Ok((new_inode_index, new_entry_index, new_inode)) => {
+ // 新文件存在
+ if flags & RENAME_NOREPLACE != 0 { // 指定 noreplace 之后不允许覆盖文件
+ reply.error(EEXIST);
+ return;
+ }
+ if flags & RENAME_EXCHANGE != 0 { // 交换两个文件
+ if let Err(err_code) = self.exchange_direntry(
+ parent,
+ &mut parent_inode,
+ name,
+ new_parent,
+ &mut new_parent_inode,
+ new_name
+ ) {
+ reply.error(err_code);
+ return;
+ }
+ } else { // 用新文件替换旧文件
+ let dir_entry = self.get_direntry_by_name(parent, &parent_inode, name)
+ .unwrap();
+ if let Err(err_code) = self.remove_direntry(parent, &mut parent_inode, name, entry_index) {
+ reply.error(err_code);
+ return;
+ }
+ if let Err(err_code) = self.remove_direntry(new_parent, &mut new_parent_inode, new_name, new_entry_index) {
+ reply.error(err_code);
+ return;
+ }
+ if let Err(err_code) = self.add_direntry_2(new_parent, &mut new_parent_inode, new_name, dir_entry) {
+ reply.error(err_code);
+ return;
+ }
+ }
+ reply.ok();
+ },
+ Err(ENOENT) => { // 新文件不存在, 删除旧的创建新的
+ let dir_entry = self.get_direntry_by_name(parent, &parent_inode, name)
+ .unwrap();
+ if let Err(err_code) = self.remove_direntry(parent, &mut parent_inode, name, entry_index) {
+ reply.error(err_code);
+ return;
+ }
+ if let Err(err_code) = self.add_direntry_2(new_parent, &mut new_parent_inode, new_name, dir_entry) {
+ reply.error(err_code);
+ return;
+ }
+ reply.ok();
+ },
+ Err(err_code) => {
+ // 其他 Err code
+ reply.error(err_code);
+ return;
+ }
+ }
+ } else {
+ reply.error(ENOENT);
+ }
+ },
+ Err(err_code) => {
+ reply.error(err_code);
+ return;
+ }
+ }
+ } else {
+ reply.error(ENOENT);
+ }
+ }
+
fn mknod(
&mut self,
req: &Request<'_>,
@@ -479,10 +632,7 @@ impl Filesystem for AyaFS {
let mut parent_inode = parent_inode.clone();
// 如果已经存在, 返回 already exists
- if self
- .lookup_name(parent, &parent_inode, name)
- .is_ok()
- {
+ if self.lookup_name(parent, &parent_inode, name).is_ok() {
reply.error(EEXIST);
return;
}
@@ -622,7 +772,7 @@ impl Filesystem for AyaFS {
self.lookup_name(parent as usize, &parent_inode, name)
{
let inode_index = inode_index as usize;
-
+
match inode.file_type() {
FileType::RegularFile => {
inode.n_links -= 1;
@@ -639,20 +789,19 @@ impl Filesystem for AyaFS {
// n_links > 0 -> 只是移除了一个 hard link, 将改动写回
self.update_inode(inode_index, inode);
}
- },
- FileType::Symlink => {
-
- },
+ }
+ FileType::Symlink => {}
FileType::Directory => {
reply.error(EISDIR);
return;
- },
- _ => { // Not implemented!
+ }
+ _ => {
+ // Not implemented!
reply.error(EIO);
return;
}
}
-
+
// 删除 dir entry
if let Err(err_code) =
self.remove_direntry(parent as usize, &mut parent_inode, name, entry_index)
@@ -834,15 +983,19 @@ impl Filesystem for AyaFS {
let current_block_index = current_point / BLOCK_SIZE;
let current_offset = current_point % BLOCK_SIZE;
- let read_length_within_block = if BLOCK_SIZE - current_offset < read_length - read_ptr {
- BLOCK_SIZE - current_offset // 可以读到 block 最后
- } else {
- read_length - read_ptr // 读到中途会停下来
- };
+ let read_length_within_block =
+ if BLOCK_SIZE - current_offset < read_length - read_ptr {
+ BLOCK_SIZE - current_offset // 可以读到 block 最后
+ } else {
+ read_length - read_ptr // 读到中途会停下来
+ };
if let Some(block) = self.access_block::<DataBlock>(&inode, current_block_index) {
- (&mut read_buffer[read_ptr .. read_ptr + read_length_within_block])
- .copy_from_slice(&block.block.0[current_offset .. current_offset + read_length_within_block]);
+ (&mut read_buffer[read_ptr..read_ptr + read_length_within_block])
+ .copy_from_slice(
+ &block.block.0
+ [current_offset..current_offset + read_length_within_block],
+ );
read_ptr += read_length_within_block;
} else {
reply.error(EIO);
@@ -877,7 +1030,12 @@ impl Filesystem for AyaFS {
reply.error(EACCES);
return;
}
- debug!("writing inode {:#x} (offset {} size {})", ino, offset, data.len());
+ debug!(
+ "writing inode {:#x} (offset {} size {})",
+ ino,
+ offset,
+ data.len()
+ );
let write_length = data.len();
let mut write_ptr = 0usize;
@@ -888,25 +1046,37 @@ impl Filesystem for AyaFS {
let current_block_index = current_point / BLOCK_SIZE;
let current_offset = current_point % BLOCK_SIZE;
- let write_length_within_block = if BLOCK_SIZE - current_offset < write_length - write_ptr {
- BLOCK_SIZE - current_offset // 可以写满 block
- } else {
- write_length - write_ptr // 写完 buffer 就停下来
- };
+ let write_length_within_block =
+ if BLOCK_SIZE - current_offset < write_length - write_ptr {
+ BLOCK_SIZE - current_offset // 可以写满 block
+ } else {
+ write_length - write_ptr // 写完 buffer 就停下来
+ };
// 当前块已分配, 直接往里写
- if let Some(block) = self.access_block_mut::<DataBlock>(&inode, current_block_index) {
- debug!("writing {} bytes in block {} within inode", write_length_within_block, current_block_index);
- (block.block.0[current_offset .. current_offset + write_length_within_block])
- .copy_from_slice(&data[write_ptr .. write_ptr + write_length_within_block]);
+ if let Some(block) = self.access_block_mut::<DataBlock>(&inode, current_block_index)
+ {
+ debug!(
+ "writing {} bytes in block {} within inode",
+ write_length_within_block, current_block_index
+ );
+ (block.block.0[current_offset..current_offset + write_length_within_block])
+ .copy_from_slice(&data[write_ptr..write_ptr + write_length_within_block]);
write_ptr += write_length_within_block;
- } else { // 当前块未分配,尝试分配
- if let Some((block_index, block_index_within_inode)) = self.allocate_block_for(&mut inode) {
+ } else {
+ // 当前块未分配,尝试分配
+ if let Some((block_index, block_index_within_inode)) =
+ self.allocate_block_for(&mut inode)
+ {
debug!("writing {} bytes in allocated block {} within inode, block index is {}", write_length_within_block, block_index_within_inode, block_index);
// 能分配, 往里写
- let block = self.access_block_mut::<DataBlock>(&inode, block_index_within_inode).unwrap();
- (block.block.0[current_offset .. current_offset + write_length_within_block])
- .copy_from_slice(&data[write_ptr .. write_ptr + write_length_within_block]);
+ let block = self
+ .access_block_mut::<DataBlock>(&inode, block_index_within_inode)
+ .unwrap();
+ (block.block.0[current_offset..current_offset + write_length_within_block])
+ .copy_from_slice(
+ &data[write_ptr..write_ptr + write_length_within_block],
+ );
write_ptr += write_length_within_block;
} else {
// 分配不了, 没空间了
@@ -1004,7 +1174,10 @@ impl Filesystem for AyaFS {
return;
}
- debug!("reading dir entries from inode {:#x} with offset {}", ino, offset);
+ debug!(
+ "reading dir entries from inode {:#x} with offset {}",
+ ino, offset
+ );
let inode = inode.clone();
self.load_direntry_map(ino as usize, &inode).unwrap();
@@ -1016,12 +1189,15 @@ impl Filesystem for AyaFS {
.enumerate()
.skip(offset as usize)
{
- debug!(" entry {} from inode {:#x} with name {:?}", entry_index, dir_entry.inode, name);
+ debug!(
+ " entry {} from inode {:#x} with name {:?}",
+ entry_index, dir_entry.inode, name
+ );
if reply.add(
dir_entry.inode as u64,
entry_index as i64 + 1,
to_filetype(dir_entry.file_type).expect("not 0x0!"),
- name
+ name,
) {
break;
}
diff --git a/src/memory/cached_inode.rs b/src/memory/cached_inode.rs
index 441d0fb..16c40c2 100644
--- a/src/memory/cached_inode.rs
+++ b/src/memory/cached_inode.rs
@@ -1,7 +1,3 @@
-use std::ffi::OsStr;
-use std::os::unix::ffi::OsStrExt;
-use std::path::Path;
-use std::slice;
use crate::disk::block::InodeBlock;
use crate::disk::inode::{Inode, INODE_SIZE};
use crate::{utils, AyaFS};
@@ -9,6 +5,10 @@ use and_then_some::BoolExt;
use fuser::FileType;
use libc::{c_int, EIO, EISDIR, ENOENT, ENOTDIR, ENOTEMPTY};
use log::{debug, error};
+use std::ffi::OsStr;
+use std::os::unix::ffi::OsStrExt;
+use std::path::Path;
+use std::slice;
impl AyaFS {
pub(crate) fn create_file(
@@ -85,7 +85,7 @@ impl AyaFS {
if inode.size >= 60 {
self.deallocate_all_blocks_for(&inode).unwrap();
}
- },
+ }
FileType::Directory => return Err(EISDIR),
_ => return Err(EIO),
}
diff --git a/src/memory/dir_entry.rs b/src/memory/dir_entry.rs
index 5e030d3..c013e1e 100644
--- a/src/memory/dir_entry.rs
+++ b/src/memory/dir_entry.rs
@@ -6,6 +6,7 @@ use libc::{c_int, ENOENT, ENOSPC};
use log::debug;
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::OsStrExt;
+use indexmap::map::Entry::Occupied;
impl AyaFS {
pub(crate) fn init_direntry_map(&mut self, index: usize) {
@@ -99,18 +100,66 @@ impl AyaFS {
Ok(())
}
+ pub(crate) fn exchange_direntry<T: AsRef<OsStr>>(
+ &mut self,
+ parent_index: usize,
+ parent_inode: &mut Inode,
+ name: T,
+ new_parent_index: usize,
+ new_parent_inode: &mut Inode,
+ new_name: T,
+ ) -> Result<(), c_int> {
+ self.load_direntry_map(parent_index, parent_inode)?;
+ self.load_direntry_map(new_parent_index, new_parent_inode)?;
+
+ let dir_entry = self.dir_entry_map
+ .get(&parent_index)
+ .ok_or(ENOENT)?
+ .get(name.as_ref())
+ .cloned()
+ .ok_or(ENOENT)?;
+ let new_dir_entry = self.dir_entry_map
+ .get(&new_parent_index)
+ .ok_or(ENOENT)?
+ .get(new_name.as_ref())
+ .cloned()
+ .ok_or(ENOENT)?;
+
+ let name: &OsStr = name.as_ref();
+ let new_name: &OsStr = new_name.as_ref();
+
+ self.dir_entry_map
+ .get_mut(&parent_index)
+ .map(|dir_entry_map| {
+ if let Occupied(mut entry) = dir_entry_map.entry(name.to_os_string()) {
+ *entry.get_mut() = new_dir_entry.clone();
+ }
+ })
+ .ok_or(ENOENT)?;
+ self.dir_entry_map
+ .get_mut(&new_parent_index)
+ .map(|new_dir_entry_map| {
+ if let Occupied(mut entry) = new_dir_entry_map.entry(new_name.to_os_string()) {
+ *entry.get_mut() = dir_entry.clone();
+ }
+ })
+ .ok_or(ENOENT)?;
+
+ Ok(())
+ }
+
/// 删除第 entry_index 个 dir entry
- pub(crate) fn remove_direntry(
+ pub(crate) fn remove_direntry<T: AsRef<OsStr>>(
&mut self,
parent_index: usize,
parent_inode: &mut Inode,
- name: &OsStr,
+ name: T,
_entry_index: u32,
) -> Result<(), c_int> {
self.load_direntry_map(parent_index, parent_inode)?;
if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) {
debug!(" remove_direntry(ino: {}) using hashmap", parent_index);
- if dir_entry_map.shift_remove(name).is_some() {
+ if dir_entry_map.shift_remove(name.as_ref()).is_some() {
Ok(())
} else {
Err(ENOENT)
@@ -120,6 +169,29 @@ impl AyaFS {
}
}
+ pub(crate) fn add_direntry_2<T: AsRef<OsStr>>(
+ &mut self,
+ parent_index: usize,
+ parent_inode: &mut Inode,
+ child_inode_name: T,
+ dir_entry: DirectoryEntry,
+ ) -> Result<u32, c_int> {
+ let child_inode_name = child_inode_name.as_ref();
+ self.load_direntry_map(parent_index, parent_inode)?;
+ if let Some(dir_entry_map) = self.dir_entry_map.get_mut(&parent_index) {
+ let (entry_index, _) =
+ dir_entry_map.insert_full(child_inode_name.to_os_string(), dir_entry);
+ debug!(
+ " add_direntry(ino: {}) using hashmap, entry {}",
+ parent_index, entry_index
+ );
+ parent_inode.size += 1;
+ Ok(entry_index as u32)
+ } else {
+ Err(ENOENT)
+ }
+ }
+
pub(crate) fn add_direntry<T: AsRef<OsStr>>(
&mut self,
parent_index: usize,
@@ -155,6 +227,28 @@ impl AyaFS {
Err(ENOENT)
}
}
+
+ pub(crate) fn get_direntry_by_name<T: AsRef<OsStr>>(
+ &mut self,
+ parent_index: usize,
+ parent_inode: &Inode,
+ name: T,
+ ) -> Result<DirectoryEntry, c_int> {
+ self.load_direntry_map(parent_index, parent_inode)?;
+ if let Some(dir_entry_map) = self.dir_entry_map.get(&parent_index) {
+ debug!(
+ " get_direntry(ino: {}, name: {:?}) using hashmap",
+ parent_index, name.as_ref()
+ );
+ dir_entry_map
+ .get(name.as_ref())
+ .cloned()
+ .ok_or(ENOENT)
+ } else {
+ Err(ENOENT)
+ }
+ }
+
pub(crate) fn get_direntry(
&mut self,
parent_index: usize,