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(&mut self, inode: &Inode, mut block_index_within_inode: usize) -> Option<&CachedBlock> { // direct block if block_index_within_inode < DIRECT_NUMBER { let block_index = inode.direct[block_index_within_inode] as usize; return self.get_block::(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::(inode.single_indirect as usize) { let block_index = indirect_block.block.entries[block_index_within_inode] as usize; self.get_block::(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::(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::(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::(block_index); } } return None; } else { block_index_within_inode -= double_indirect_number; } // triple indirect block if let Some(triple_indirect_block) = self.get_block::(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::(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::(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::(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 { 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 { let block_index_within_inode = (entry_index / 15) as usize; let entry_index_within_block = (entry_index % 15) as usize; self.access_block::(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 { // // 每个 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::(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::(inode.single_indirect as usize) // { // let block_index = indirect_block.block.entries[block_index_within_inode] as usize; // self.get_block::(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::(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::(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::(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::(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::(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::(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::(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) } }