summaryrefslogtreecommitdiff
path: root/src/memory/inode_iter.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/memory/inode_iter.rs')
-rw-r--r--src/memory/inode_iter.rs233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/memory/inode_iter.rs b/src/memory/inode_iter.rs
new file mode 100644
index 0000000..d5909bc
--- /dev/null
+++ b/src/memory/inode_iter.rs
@@ -0,0 +1,233 @@
+use std::ffi::OsStr;
+use std::os::unix::ffi::OsStrExt;
+use libc::{c_int, ENOENT, ENOSPC};
+use crate::disk::block::{Block, DirectoryBlock, DirectoryEntry, DoubleIndirectBlock, IndirectBlock, TripleIndirectBlock};
+use crate::disk::inode::{Inode, DIRECT_NUMBER};
+use crate::{AyaFS, INODE_PER_BLOCK};
+use crate::memory::cached_block::CachedBlock;
+
+impl AyaFS {
+ pub(crate) fn access_block<T: Block>(&mut self, inode: &Inode, mut block_index_within_inode: usize) -> Option<&CachedBlock<T>> {
+ // direct block
+ if block_index_within_inode < DIRECT_NUMBER {
+ let block_index = inode.direct[block_index_within_inode] as usize;
+ return self.get_block::<T>(block_index);
+ } else {
+ block_index_within_inode -= DIRECT_NUMBER;
+ }
+
+ // indirect block
+ let indirect_number = INODE_PER_BLOCK;
+ if block_index_within_inode < indirect_number {
+ return if let Some(indirect_block) =
+ self.get_block::<IndirectBlock>(inode.single_indirect as usize)
+ {
+ let block_index = indirect_block.block.entries[block_index_within_inode] as usize;
+ self.get_block::<T>(block_index)
+ } else {
+ None
+ };
+ } else {
+ block_index_within_inode -= indirect_number;
+ }
+
+ // double indirect block
+ let double_indirect_number = INODE_PER_BLOCK * INODE_PER_BLOCK;
+ if block_index_within_inode < double_indirect_number {
+ if let Some(double_indirect_block) =
+ self.get_block::<DoubleIndirectBlock>(inode.double_indirect as usize)
+ {
+ // 取出 double indirect block
+ let indirect_block_index = double_indirect_block.block.indirect
+ [block_index_within_inode / INODE_PER_BLOCK]
+ as usize;
+ // 要找的 entry 在 double indirect block 中的第几个 indirect block
+ if let Some(indirect_block) = self.get_block::<IndirectBlock>(indirect_block_index)
+ {
+ let block_index = indirect_block.block.entries
+ [block_index_within_inode % INODE_PER_BLOCK]
+ as usize;
+ // 拿到 DirectoryBlock 的 index
+ return self.get_block::<T>(block_index);
+ }
+ }
+ return None;
+ } else {
+ block_index_within_inode -= double_indirect_number;
+ }
+
+ // triple indirect block
+ if let Some(triple_indirect_block) =
+ self.get_block::<TripleIndirectBlock>(inode.triple_indirect as usize)
+ {
+ // 取出 triple indirect block
+ let double_indirect_block_index = triple_indirect_block.block.double_indirect
+ [block_index_within_inode / (INODE_PER_BLOCK * INODE_PER_BLOCK)]
+ as usize;
+ // 要找的 entry 在 triple indirect block 中的第几个 double indirect block
+ if let Some(double_indirect_block) =
+ self.get_block::<DoubleIndirectBlock>(double_indirect_block_index)
+ {
+ // 取出 double indirect block
+ let indirect_block_index = double_indirect_block.block.indirect
+ [block_index_within_inode % (INODE_PER_BLOCK * INODE_PER_BLOCK)
+ / INODE_PER_BLOCK] as usize;
+ // 要找的 entry 在 double indirect block 中的第几个 indirect block
+ if let Some(indirect_block) = self.get_block::<IndirectBlock>(indirect_block_index)
+ {
+ let block_index = indirect_block.block.entries
+ [block_index_within_inode % INODE_PER_BLOCK]
+ as usize;
+ // DirectoryBlock 的 index
+ return self.get_block::<T>(block_index);
+ }
+ }
+ }
+
+ None
+ }
+
+ pub(crate) fn add_direntry(
+ &mut self,
+ parent_inode: &mut Inode,
+ child_inode_index: u32,
+ child_inode_name: &OsStr,
+ child_inode: &Inode,
+ ) -> Result<u32, c_int> {
+ let entry_index = parent_inode.size;
+ let block_index_within_inode = (entry_index / 15) as usize;
+ let entry_index_within_block = (entry_index % 15) as usize;
+
+ // TODO 如果 block 内 offset 是 0 (或者访问到 block_index_within_inode 无效?)则为 Inode 分配新的 block
+
+ // TODO 把新的 entry 写到对应位置
+
+ Err(ENOSPC)
+ }
+ pub(crate) fn get_direntry(
+ &mut self,
+ inode: &Inode,
+ entry_index: u32
+ ) -> Option<DirectoryEntry> {
+ let block_index_within_inode = (entry_index / 15) as usize;
+ let entry_index_within_block = (entry_index % 15) as usize;
+
+ self.access_block::<DirectoryBlock>(inode, block_index_within_inode)
+ .map(|directory_block| {
+ directory_block.block.entries[entry_index_within_block].clone()
+ })
+ }
+
+ // pub(crate) fn get_direntry(
+ // &mut self,
+ // inode: &Inode,
+ // entry_index: u32,
+ // ) -> Option<DirectoryEntry> {
+ // // 每个 DirectoryBlock 里有 15 个 entry, 先确定 block 再确定 offset
+ // let mut block_index_within_inode = (entry_index / 15) as usize;
+ // let entry_index_within_block = (entry_index % 15) as usize;
+ //
+ // // direct block
+ // if block_index_within_inode < DIRECT_NUMBER {
+ // let block_index = inode.direct[block_index_within_inode] as usize;
+ // return self
+ // .get_block::<DirectoryBlock>(block_index)
+ // .map(|inode_block| inode_block.block.entries[entry_index_within_block].clone());
+ // } else {
+ // block_index_within_inode -= DIRECT_NUMBER;
+ // }
+ //
+ // // indirect block
+ // let indirect_number = INODE_PER_BLOCK;
+ // if block_index_within_inode < indirect_number {
+ // return if let Some(indirect_block) =
+ // self.get_block::<IndirectBlock>(inode.single_indirect as usize)
+ // {
+ // let block_index = indirect_block.block.entries[block_index_within_inode] as usize;
+ // self.get_block::<DirectoryBlock>(block_index)
+ // .map(|inode_block| inode_block.block.entries[entry_index_within_block].clone())
+ // } else {
+ // None
+ // };
+ // } else {
+ // block_index_within_inode -= indirect_number;
+ // }
+ //
+ // // double indirect block
+ // let double_indirect_number = INODE_PER_BLOCK * INODE_PER_BLOCK;
+ // if block_index_within_inode < double_indirect_number {
+ // if let Some(double_indirect_block) =
+ // self.get_block::<DoubleIndirectBlock>(inode.double_indirect as usize)
+ // {
+ // // 取出 double indirect block
+ // let indirect_block_index = double_indirect_block.block.indirect
+ // [block_index_within_inode / INODE_PER_BLOCK]
+ // as usize;
+ // // 要找的 entry 在 double indirect block 中的第几个 indirect block
+ // if let Some(indirect_block) = self.get_block::<IndirectBlock>(indirect_block_index)
+ // {
+ // let block_index = indirect_block.block.entries
+ // [block_index_within_inode % INODE_PER_BLOCK]
+ // as usize;
+ // // 拿到 DirectoryBlock 的 index
+ // return self
+ // .get_block::<DirectoryBlock>(block_index)
+ // .map(|inode_block| {
+ // inode_block.block.entries[entry_index_within_block].clone()
+ // });
+ // }
+ // }
+ // return None;
+ // } else {
+ // block_index_within_inode -= double_indirect_number;
+ // }
+ //
+ // // triple indirect block
+ // if let Some(triple_indirect_block) =
+ // self.get_block::<TripleIndirectBlock>(inode.triple_indirect as usize)
+ // {
+ // // 取出 triple indirect block
+ // let double_indirect_block_index = triple_indirect_block.block.double_indirect
+ // [block_index_within_inode / (INODE_PER_BLOCK * INODE_PER_BLOCK)]
+ // as usize;
+ // // 要找的 entry 在 triple indirect block 中的第几个 double indirect block
+ // if let Some(double_indirect_block) =
+ // self.get_block::<DoubleIndirectBlock>(double_indirect_block_index)
+ // {
+ // // 取出 double indirect block
+ // let indirect_block_index = double_indirect_block.block.indirect
+ // [block_index_within_inode % (INODE_PER_BLOCK * INODE_PER_BLOCK)
+ // / INODE_PER_BLOCK] as usize;
+ // // 要找的 entry 在 double indirect block 中的第几个 indirect block
+ // if let Some(indirect_block) = self.get_block::<IndirectBlock>(indirect_block_index)
+ // {
+ // let block_index = indirect_block.block.entries
+ // [block_index_within_inode % INODE_PER_BLOCK]
+ // as usize;
+ // // DirectoryBlock 的 index
+ // return self
+ // .get_block::<DirectoryBlock>(block_index)
+ // .map(|inode_block| {
+ // inode_block.block.entries[entry_index_within_block].clone()
+ // });
+ // }
+ // }
+ // }
+ // None
+ // }
+
+ // TODO 实现一个带 cache 的版本
+ pub fn lookup_name(&mut self, parent_inode: &Inode, name: &OsStr) -> Result<(u32, Inode), c_int> {
+ let mut entry_index = 0;
+ while entry_index < parent_inode.size {
+ if let Some(entry) = self.get_direntry(parent_inode, entry_index) {
+ if entry.name() == name {
+ let inode = self.get_inode(entry.inode as usize).unwrap().clone();
+ return Ok((entry.inode, inode))
+ }
+ }
+ entry_index += 1;
+ }
+ Err(ENOENT)
+ }
+}