use crate::disk::block::InodeBlock; use crate::disk::inode::{Inode, INODE_SIZE}; use crate::{utils, AyaFS}; 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( &mut self, permissions: u16, uid: u32, gid: u32, flags: u32, ) -> Option<(usize, &Inode)> { self.inode_bitmap.allocate().map(|inode_index| { self.get_inode_mut(inode_index).map(|inode| { *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0); }); (inode_index, self.get_inode(inode_index).unwrap()) }) } pub(crate) fn create_symlink( &mut self, permissions: u16, uid: u32, gid: u32, flags: u32, ) -> Option<(usize, &Inode)> { self.inode_bitmap.allocate().map(|inode_index| { self.get_inode_mut(inode_index).map(|inode| { *inode = Inode::symlink(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0); }); (inode_index, self.get_inode(inode_index).unwrap()) }) } /// 根目录的 parent_inode_number 传入 None, 会直接以自己作为 .. 的 inode number pub(crate) fn create_directory( &mut self, permissions: u16, uid: u32, gid: u32, flags: u32, parent_inode_number: Option, ) -> Option<(usize, &Inode)> { self.inode_bitmap.allocate().map(|inode_index| { // 创建 Inode let mut new_inode = Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0); self.init_direntry_map(inode_index); self.add_direntry(inode_index, &mut new_inode, inode_index, ".", 0x2) .unwrap(); self.add_direntry( inode_index, &mut new_inode, parent_inode_number.unwrap_or(inode_index), "..", 0x2, ) .unwrap(); // 把 inode 放到指定位置 self.get_inode_mut(inode_index).map(|inode| { *inode = new_inode; }); (inode_index, self.get_inode(inode_index).unwrap()) }) } pub(crate) fn remove_file(&mut self, inode_index: usize) -> Result { if self.inode_bitmap.query(inode_index) { let (block_index, offset) = self.locate_inode(inode_index); if let Some(cached_block) = self.cached_inodes.get_block::(block_index) { let inode = cached_block.block.inodes[offset / INODE_SIZE].clone(); match inode.file_type() { FileType::RegularFile => self.deallocate_all_blocks_for(&inode).unwrap(), FileType::Symlink => { if inode.size >= 60 { self.deallocate_all_blocks_for(&inode).unwrap(); } } FileType::Directory => return Err(EISDIR), _ => return Err(EIO), } } self.inode_bitmap.deallocate(inode_index); Ok(true) } else { Err(ENOENT) } } // 要删除的 inode 一定得是空的 pub(crate) fn remove_dir(&mut self, inode_index: usize) -> Result { if self.inode_bitmap.query(inode_index) { let (block_index, offset) = self.locate_inode(inode_index); if let Some(cached_block) = self.cached_inodes.get_block::(block_index) { let inode = &cached_block.block.inodes[offset / INODE_SIZE].clone(); if !inode.is_dir() { // 不是 dir -> ENOTDIR return Err(ENOTDIR); } if inode.size > 2 { // 有 . 和 .. 以外的 entry -> ENOTEMPTY return Err(ENOTEMPTY); } // 销毁 inode 里的所有 block self.deallocate_all_blocks_for(inode).unwrap(); } // 销毁 inode self.inode_bitmap.deallocate(inode_index); Ok(true) } else { Err(ENOENT) } } pub(crate) fn update_inode(&mut self, inode_index: usize, inode: Inode) -> bool { if self.inode_bitmap.query(inode_index) { let (block_index, offset) = self.locate_inode(inode_index); if let Some(cached_block) = self.cached_inodes.get_block_mut::(block_index) { cached_block.block.inodes[offset / INODE_SIZE] = inode; } true } else { false } } pub(crate) fn get_inode(&mut self, inode_index: usize) -> Option<&Inode> { self.inode_bitmap.query(inode_index).and_then(|| { let (block_index, offset) = self.locate_inode(inode_index); // debug!("get_inode(inode_index: {}) -> block_index: {}, offset: {}", inode_index, block_index, offset); self.cached_inodes .get_block::(block_index) .map(|cached_block| &cached_block.block.inodes[offset / INODE_SIZE]) }) } pub(crate) fn get_inode_mut(&mut self, inode_index: usize) -> Option<&mut Inode> { self.inode_bitmap.query(inode_index).and_then(|| { let (block_index, offset) = self.locate_inode(inode_index); // debug!("get_inode_mut(inode_index: {}) -> block_index: {}, offset: {}", inode_index, block_index, offset); self.cached_inodes .get_block_mut::(block_index) .map(|cached_block| { cached_block.dirty = true; // 保守一些, 只要返回了 &mut Inode 这个页一定标记为脏 &mut cached_block.block.inodes[offset / INODE_SIZE] }) }) } #[allow(unused)] pub(crate) fn peek_inode(&self, inode_index: usize) -> Option<&Inode> { self.inode_bitmap.query(inode_index).and_then(|| { let (block_index, offset) = self.locate_inode(inode_index); self.cached_inodes .peek_block::(block_index) .map(|cached_block| &cached_block.block.inodes[offset / INODE_SIZE]) }) } #[allow(unused)] pub(crate) fn peek_inode_mut(&mut self, inode_index: usize) -> Option<&mut Inode> { self.inode_bitmap.query(inode_index).and_then(|| { let (block_index, offset) = self.locate_inode(inode_index); self.cached_inodes .peek_block_mut::(block_index) .map(|cached_block| { cached_block.dirty = true; // 保守一些, 只要返回了 &mut Inode 这个页一定标记为脏 &mut cached_block.block.inodes[offset / INODE_SIZE] }) }) } }