From b3db8a5a710aa0890c80241ffb3fd9792bf1cbe7 Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Wed, 29 Nov 2023 13:29:03 -0800 Subject: Add rename --- src/disk/allocation.rs | 10 +- src/disk/inode.rs | 10 +- src/filesystem/trait_impl.rs | 332 +++++++++++++++++++++++++++++++++---------- src/memory/cached_inode.rs | 10 +- src/memory/dir_entry.rs | 100 ++++++++++++- 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 { - 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> { 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::(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 { 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, mtime: Option, _ctime: Option, - fh: Option, // 当 setattr 被 ftruncate invoke 时会提供 fh - _crtime: Option, // 忽略 - _chgtime: Option, // 忽略 + fh: Option, // 当 setattr 被 ftruncate invoke 时会提供 fh + _crtime: Option, // 忽略 + _chgtime: Option, // 忽略 _bkuptime: Option, // 忽略 - _flags: Option, // 忽略 + _flags: Option, // 忽略 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::(&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::(&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::(&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::( + &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::(&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::(&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::(&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::(&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::(&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::(&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>( + &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>( &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>( + &mut self, + parent_index: usize, + parent_inode: &mut Inode, + child_inode_name: T, + dir_entry: DirectoryEntry, + ) -> Result { + 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>( &mut self, parent_index: usize, @@ -155,6 +227,28 @@ impl AyaFS { Err(ENOENT) } } + + pub(crate) fn get_direntry_by_name>( + &mut self, + parent_index: usize, + parent_inode: &Inode, + name: T, + ) -> Result { + 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, -- cgit v1.2.3-70-g09d2