diff --git a/src/bin/mksfs.rs b/src/bin/mksfs.rs index 98d2cc6..de694d7 100644 --- a/src/bin/mksfs.rs +++ b/src/bin/mksfs.rs @@ -18,7 +18,7 @@ fn main() -> Result<()> { _ => { println!("USAGE: "); panic!("Invalid command: {}", cmd); - }, + } } } diff --git a/src/sfs.rs b/src/sfs.rs index 5e6db36..a3adbf7 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -32,6 +32,7 @@ trait DeviceExt: Device { s } } + impl DeviceExt for Device {} type Ptr = Rc>; @@ -97,19 +98,19 @@ impl INode { } } /// Only for Dir - fn get_file_inode_and_entry_id(&self, name: &str) -> Option<(INodeId,usize)> { + fn get_file_inode_and_entry_id(&self, name: &str) -> Option<(INodeId, usize)> { (0..self.disk_inode.blocks) .map(|i| { use vfs::INode; let mut entry: DiskEntry = unsafe { uninitialized() }; self._read_at(i as usize * BLKSIZE, entry.as_buf_mut()).unwrap(); - (entry,i) + (entry, i) }) - .find(|(entry,id)| entry.name.as_ref() == name) - .map(|(entry,id)| (entry.id as INodeId,id as usize)) + .find(|(entry, id)| entry.name.as_ref() == name) + .map(|(entry, id)| (entry.id as INodeId, id as usize)) } fn get_file_inode_id(&self, name: &str) -> Option { - self.get_file_inode_and_entry_id(name).map(|(inode_id,entry_id)|{inode_id}) + self.get_file_inode_and_entry_id(name).map(|(inode_id, entry_id)| { inode_id }) } /// Init dir content. Insert 2 init entries. /// This do not init nlinks, please modify the nlinks in the invoker. @@ -133,11 +134,11 @@ impl INode { fn remove_dirent_page(&mut self, id: usize) -> vfs::Result<()> { assert!(id < self.disk_inode.blocks as usize); let fs = self.fs.upgrade().unwrap(); - let to_remove=self.get_disk_block_id(id).unwrap(); - let current_last=self.get_disk_block_id(self.disk_inode.blocks as usize -1).unwrap(); - self.set_disk_block_id(id,current_last).unwrap(); + let to_remove = self.get_disk_block_id(id).unwrap(); + let current_last = self.get_disk_block_id(self.disk_inode.blocks as usize - 1).unwrap(); + self.set_disk_block_id(id, current_last).unwrap(); self.disk_inode.blocks -= 1; - let new_size=self.disk_inode.blocks as usize * BLKSIZE; + let new_size = self.disk_inode.blocks as usize * BLKSIZE; self._set_size(new_size); fs.free_block(to_remove); Ok(()) @@ -196,8 +197,8 @@ impl INode { } /// Set the ucore compat size of this inode, /// Size in inode for dir is size of entries - fn _set_size(&mut self,len: usize) { - self.disk_inode.size=match self.disk_inode.type_ { + fn _set_size(&mut self, len: usize) { + self.disk_inode.size = match self.disk_inode.type_ { FileType::Dir => self.disk_inode.blocks as usize * DIRENT_SIZE, FileType::File => len, _ => unimplemented!(), @@ -246,11 +247,11 @@ impl INode { Ok(()) } fn nlinks_inc(&mut self) { - self.disk_inode.nlinks+=1; + self.disk_inode.nlinks += 1; } fn nlinks_dec(&mut self) { - assert!(self.disk_inode.nlinks>0); - self.disk_inode.nlinks-=1; + assert!(self.disk_inode.nlinks > 0); + self.disk_inode.nlinks -= 1; } } @@ -300,7 +301,7 @@ impl vfs::INode for INode { let fs = self.fs.upgrade().unwrap(); let info = self.info().unwrap(); assert_eq!(info.type_, vfs::FileType::Dir); - assert!(info.nlinks>0); + assert!(info.nlinks > 0); // Ensure the name is not exist assert!(self.get_file_inode_id(name).is_none(), "file name exist"); @@ -316,11 +317,11 @@ impl vfs::INode for INode { id: inode.borrow().id as u32, name: Str256::from(name), }; - let old_size=self._size(); + let old_size = self._size(); self._resize(old_size + BLKSIZE).unwrap(); self._write_at(old_size, entry.as_buf()).unwrap(); inode.borrow_mut().nlinks_inc(); - if(type_==vfs::FileType::Dir){ + if (type_ == vfs::FileType::Dir) { inode.borrow_mut().nlinks_inc();//for . self.nlinks_inc();//for .. } @@ -328,8 +329,8 @@ impl vfs::INode for INode { Ok(inode) } fn unlink(&mut self, name: &str) -> vfs::Result<()> { - assert!(name!="."); - assert!(name!=".."); + assert!(name != "."); + assert!(name != ".."); let fs = self.fs.upgrade().unwrap(); let info = self.info().unwrap(); assert_eq!(info.type_, vfs::FileType::Dir); @@ -338,16 +339,16 @@ impl vfs::INode for INode { if inode_and_entry_id.is_none() { return Err(()); } - let (inode_id,entry_id)=inode_and_entry_id.unwrap(); + let (inode_id, entry_id) = inode_and_entry_id.unwrap(); let inode = fs.get_inode(inode_id); let type_ = inode.borrow().disk_inode.type_; - if(type_==FileType::Dir){ + if (type_ == FileType::Dir) { // only . and .. - assert!(inode.borrow().disk_inode.blocks==2); + assert!(inode.borrow().disk_inode.blocks == 2); } inode.borrow_mut().nlinks_dec(); - if(type_==FileType::Dir){ + if (type_ == FileType::Dir) { inode.borrow_mut().nlinks_dec();//for . self.nlinks_dec();//for .. } @@ -355,29 +356,29 @@ impl vfs::INode for INode { Ok(()) } - fn link(&mut self, name: &str, other:&mut vfs::INode) -> vfs::Result<()> { + fn link(&mut self, name: &str, other: &mut vfs::INode) -> vfs::Result<()> { let fs = self.fs.upgrade().unwrap(); let info = self.info().unwrap(); assert_eq!(info.type_, vfs::FileType::Dir); - assert!(info.nlinks>0); + assert!(info.nlinks > 0); assert!(self.get_file_inode_id(name).is_none(), "file name exist"); let child = other.downcast_mut::().unwrap(); - assert!(Rc::ptr_eq(&fs,&child.fs.upgrade().unwrap())); - assert!(child.info().unwrap().type_!=vfs::FileType::Dir); + assert!(Rc::ptr_eq(&fs, &child.fs.upgrade().unwrap())); + assert!(child.info().unwrap().type_ != vfs::FileType::Dir); let entry = DiskEntry { id: child.id as u32, name: Str256::from(name), }; - let old_size=self._size(); + let old_size = self._size(); self._resize(old_size + BLKSIZE).unwrap(); self._write_at(old_size, entry.as_buf()).unwrap(); child.nlinks_inc(); Ok(()) } - fn rename(&mut self, old_name: &str, new_name: &str) -> vfs::Result<()>{ + fn rename(&mut self, old_name: &str, new_name: &str) -> vfs::Result<()> { let info = self.info().unwrap(); assert_eq!(info.type_, vfs::FileType::Dir); - assert!(info.nlinks>0); + assert!(info.nlinks > 0); assert!(self.get_file_inode_id(new_name).is_none(), "file name exist"); @@ -385,26 +386,26 @@ impl vfs::INode for INode { if inode_and_entry_id.is_none() { return Err(()); } - let (_,entry_id)=inode_and_entry_id.unwrap(); + let (_, entry_id) = inode_and_entry_id.unwrap(); // in place modify name let mut entry: DiskEntry = unsafe { uninitialized() }; - let entry_pos=entry_id as usize * BLKSIZE; + let entry_pos = entry_id as usize * BLKSIZE; self._read_at(entry_pos, entry.as_buf_mut()).unwrap(); - entry.name=Str256::from(new_name); + entry.name = Str256::from(new_name); self._write_at(entry_pos, entry.as_buf()).unwrap(); Ok(()) } - fn move_(&mut self, old_name: &str,target:&mut vfs::INode, new_name: &str) -> vfs::Result<()>{ + fn move_(&mut self, old_name: &str, target: &mut vfs::INode, new_name: &str) -> vfs::Result<()> { let fs = self.fs.upgrade().unwrap(); let info = self.info().unwrap(); assert_eq!(info.type_, vfs::FileType::Dir); - assert!(info.nlinks>0); + assert!(info.nlinks > 0); let dest = target.downcast_mut::().unwrap(); - assert!(Rc::ptr_eq(&fs,&dest.fs.upgrade().unwrap())); - assert!(dest.info().unwrap().type_==vfs::FileType::Dir); - assert!(dest.info().unwrap().nlinks>0); + assert!(Rc::ptr_eq(&fs, &dest.fs.upgrade().unwrap())); + assert!(dest.info().unwrap().type_ == vfs::FileType::Dir); + assert!(dest.info().unwrap().nlinks > 0); assert!(dest.get_file_inode_id(new_name).is_none(), "file name exist"); @@ -412,20 +413,20 @@ impl vfs::INode for INode { if inode_and_entry_id.is_none() { return Err(()); } - let (inode_id,entry_id)=inode_and_entry_id.unwrap(); + let (inode_id, entry_id) = inode_and_entry_id.unwrap(); let inode = fs.get_inode(inode_id); let entry = DiskEntry { id: inode_id as u32, name: Str256::from(new_name), }; - let old_size=dest._size(); + let old_size = dest._size(); dest._resize(old_size + BLKSIZE).unwrap(); dest._write_at(old_size, entry.as_buf()).unwrap(); self.remove_dirent_page(entry_id); - if(inode.borrow().info().unwrap().type_==vfs::FileType::Dir){ + if (inode.borrow().info().unwrap().type_ == vfs::FileType::Dir) { self.nlinks_dec(); dest.nlinks_inc(); } @@ -443,9 +444,9 @@ impl vfs::INode for INode { let inode = fs.get_inode(inode_id.unwrap()); Ok(inode) } - fn get_entry(&self,id: usize) -> vfs::Result { + fn get_entry(&self, id: usize) -> vfs::Result { assert_eq!(self.disk_inode.type_, FileType::Dir); - assert!(id = inodes.keys().cloned().collect(); for id in ids.iter() { - let mut should_remove=false; + let mut should_remove = false; // Since non-lexical-lifetime is not stable... { - let inodeRc=inodes.get(&id).unwrap(); - if Rc::strong_count(inodeRc)<=1 { + let inodeRc = inodes.get(&id).unwrap(); + if Rc::strong_count(inodeRc) <= 1 { use vfs::INode; - if inodeRc.borrow().info().unwrap().nlinks==0 { - should_remove=true; + if inodeRc.borrow().info().unwrap().nlinks == 0 { + should_remove = true; } } } - if(should_remove){ + if (should_remove) { inodes.remove(&id); } } diff --git a/src/structs.rs b/src/structs.rs index 9001498..ff7bb55 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -58,6 +58,7 @@ pub struct DiskEntry { #[repr(C)] pub struct Str256(pub [u8; 256]); + #[repr(C)] pub struct Str32(pub [u8; 32]); @@ -67,22 +68,26 @@ impl AsRef for Str256 { str::from_utf8(&self.0[0..len]).unwrap() } } + impl AsRef for Str32 { fn as_ref(&self) -> &str { let len = self.0.iter().enumerate().find(|(_, &b)| b == 0).unwrap().0; str::from_utf8(&self.0[0..len]).unwrap() } } + impl Debug for Str256 { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "{}", self.as_ref()) } } + impl Debug for Str32 { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "{}", self.as_ref()) } } + impl<'a> From<&'a str> for Str256 { fn from(s: &'a str) -> Self { let mut ret = [0u8; 256]; @@ -90,6 +95,7 @@ impl<'a> From<&'a str> for Str256 { Str256(ret) } } + impl<'a> From<&'a str> for Str32 { fn from(s: &'a str) -> Self { let mut ret = [0u8; 32]; @@ -132,16 +138,19 @@ impl DiskINode { /// Convert structs to [u8] slice pub trait AsBuf { fn as_buf(&self) -> &[u8] { - unsafe{ slice::from_raw_parts(self as *const _ as *const u8, size_of_val(self)) } + unsafe { slice::from_raw_parts(self as *const _ as *const u8, size_of_val(self)) } } fn as_buf_mut(&mut self) -> &mut [u8] { - unsafe{ slice::from_raw_parts_mut(self as *mut _ as *mut u8, size_of_val(self)) } + unsafe { slice::from_raw_parts_mut(self as *mut _ as *mut u8, size_of_val(self)) } } } impl AsBuf for SuperBlock {} + impl AsBuf for DiskINode {} + impl AsBuf for DiskEntry {} + impl AsBuf for u32 {} /* @@ -184,7 +193,10 @@ pub const DIRENT_SIZE: usize = MAX_FNAME_LEN + 1; #[repr(u16)] #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum FileType { - Invalid = 0, File = 1, Dir = 2, Link = 3, + Invalid = 0, + File = 1, + Dir = 2, + Link = 3, } const_assert!(o1; size_of::() <= BLKSIZE); diff --git a/src/tests.rs b/src/tests.rs index 8a6b355..a127a01 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -10,7 +10,7 @@ use std::mem::uninitialized; use super::structs::{DiskEntry, AsBuf}; fn _open_sample_file() -> Rc { - fs::copy("sfs.img","test.img").expect("failed to open sfs.img"); + fs::copy("sfs.img", "test.img").expect("failed to open sfs.img"); let file = OpenOptions::new() .read(true).write(true).open("test.img") .expect("failed to open test.img"); @@ -44,7 +44,7 @@ fn print_root() { let files = root.borrow().list().unwrap(); println!("{:?}", files); - assert_eq!(files[3],root.borrow().get_entry(3).unwrap()); + assert_eq!(files[3], root.borrow().get_entry(3).unwrap()); sfs.sync().unwrap(); } @@ -77,7 +77,7 @@ fn resize() { const SIZE2: usize = 0x1250; file1.borrow_mut().resize(SIZE1).unwrap(); assert_eq!(file1.borrow().info().unwrap().size, SIZE1, "wrong size after resize"); - let mut data1: [u8; SIZE2] = unsafe{uninitialized()}; + let mut data1: [u8; SIZE2] = unsafe { uninitialized() }; impl AsBuf for [u8; SIZE2] {} let len = file1.borrow().read_at(0, data1.as_buf_mut()).unwrap(); assert_eq!(len, SIZE1, "wrong size returned by read_at()"); @@ -137,32 +137,32 @@ fn rc_layout() { // ^ start ^ Rc::into_raw let p = Rc::new([2u8; 5]); let ptr = Rc::into_raw(p); - let start = unsafe{ (ptr as *const usize).offset(-2) }; - let ns = unsafe{ &*(start as *const [usize; 2]) }; + let start = unsafe { (ptr as *const usize).offset(-2) }; + let ns = unsafe { &*(start as *const [usize; 2]) }; assert_eq!(ns, &[1usize, 1]); } // #[test] -fn kernel_image_file_create(){ +fn kernel_image_file_create() { let sfs = _open_sample_file(); let root = sfs.root_inode(); let files_count_before = root.borrow().list().unwrap().len(); - root.borrow_mut().create("hello2",FileType::File).unwrap(); + root.borrow_mut().create("hello2", FileType::File).unwrap(); let files_count_after = root.borrow().list().unwrap().len(); - assert_eq!(files_count_before+1, files_count_after); + assert_eq!(files_count_before + 1, files_count_after); assert!(root.borrow().lookup("hello2").is_ok()); sfs.sync().unwrap(); } // #[test] -fn kernel_image_file_unlink(){ +fn kernel_image_file_unlink() { let sfs = _open_sample_file(); let root = sfs.root_inode(); let files_count_before = root.borrow().list().unwrap().len(); root.borrow_mut().unlink("hello").unwrap(); let files_count_after = root.borrow().list().unwrap().len(); - assert_eq!(files_count_before, files_count_after+1); + assert_eq!(files_count_before, files_count_after + 1); assert!(root.borrow().lookup("hello").is_err()); sfs.sync().unwrap(); @@ -170,11 +170,11 @@ fn kernel_image_file_unlink(){ // #[test] -fn kernel_image_file_rename(){ +fn kernel_image_file_rename() { let sfs = _open_sample_file(); let root = sfs.root_inode(); let files_count_before = root.borrow().list().unwrap().len(); - root.borrow_mut().rename("hello","hello2").unwrap(); + root.borrow_mut().rename("hello", "hello2").unwrap(); let files_count_after = root.borrow().list().unwrap().len(); assert_eq!(files_count_before, files_count_after); assert!(root.borrow().lookup("hello").is_err()); @@ -184,16 +184,16 @@ fn kernel_image_file_rename(){ } // #[test] -fn kernel_image_file_move(){ +fn kernel_image_file_move() { use core::ops::DerefMut; let sfs = _open_sample_file(); let root = sfs.root_inode(); let files_count_before = root.borrow().list().unwrap().len(); root.borrow_mut().unlink("divzero").unwrap(); let rust_dir = root.borrow_mut().create("rust", FileType::Dir).unwrap(); - root.borrow_mut().move_("hello",rust_dir.borrow_mut().deref_mut(),"hello_world").unwrap(); + root.borrow_mut().move_("hello", rust_dir.borrow_mut().deref_mut(), "hello_world").unwrap(); let files_count_after = root.borrow().list().unwrap().len(); - assert_eq!(files_count_before, files_count_after+1); + assert_eq!(files_count_before, files_count_after + 1); assert!(root.borrow().lookup("hello").is_err()); assert!(root.borrow().lookup("divzero").is_err()); assert!(root.borrow().lookup("rust").is_ok()); @@ -203,55 +203,55 @@ fn kernel_image_file_move(){ } #[test] -fn hard_link(){ +fn hard_link() { let sfs = _create_new_sfs(); let root = sfs.root_inode(); let file1 = root.borrow_mut().create("file1", FileType::File).unwrap(); use core::ops::DerefMut; - root.borrow_mut().link("file2",file1.borrow_mut().deref_mut()).unwrap(); + root.borrow_mut().link("file2", file1.borrow_mut().deref_mut()).unwrap(); let file2 = root.borrow().lookup("file2").unwrap(); file1.borrow_mut().resize(100); - assert_eq!(file2.borrow().info().unwrap().size,100); + assert_eq!(file2.borrow().info().unwrap().size, 100); sfs.sync().unwrap(); } #[test] -fn nlinks(){ +fn nlinks() { use core::ops::DerefMut; let sfs = _create_new_sfs(); let root = sfs.root_inode(); // -root - assert_eq!(root.borrow().info().unwrap().nlinks,2); + assert_eq!(root.borrow().info().unwrap().nlinks, 2); let file1 = root.borrow_mut().create("file1", FileType::File).unwrap(); // -root // `-file1 - assert_eq!(file1.borrow().info().unwrap().nlinks,1); - assert_eq!(root.borrow().info().unwrap().nlinks,2); + assert_eq!(file1.borrow().info().unwrap().nlinks, 1); + assert_eq!(root.borrow().info().unwrap().nlinks, 2); let dir1 = root.borrow_mut().create("dir1", FileType::Dir).unwrap(); // -root // +-dir1 // `-file1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(root.borrow().info().unwrap().nlinks,3); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); root.borrow_mut().rename("dir1", "dir_1").unwrap(); // -root // +-dir_1 // `-file1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(root.borrow().info().unwrap().nlinks,3); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); - dir1.borrow_mut().link("file1_",file1.borrow_mut().deref_mut()).unwrap(); + dir1.borrow_mut().link("file1_", file1.borrow_mut().deref_mut()).unwrap(); // -root // +-dir_1 // | `-file1_ // `-file1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(root.borrow().info().unwrap().nlinks,3); - assert_eq!(file1.borrow().info().unwrap().nlinks,2); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); + assert_eq!(file1.borrow().info().unwrap().nlinks, 2); let dir2 = root.borrow_mut().create("dir2", FileType::Dir).unwrap(); // -root @@ -259,77 +259,77 @@ fn nlinks(){ // | `-file1_ // +-dir2 // `-file1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,2); - assert_eq!(root.borrow().info().unwrap().nlinks,4); - assert_eq!(file1.borrow().info().unwrap().nlinks,2); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 2); + assert_eq!(root.borrow().info().unwrap().nlinks, 4); + assert_eq!(file1.borrow().info().unwrap().nlinks, 2); - root.borrow_mut().rename("file1","file_1").unwrap(); + root.borrow_mut().rename("file1", "file_1").unwrap(); // -root // +-dir_1 // | `-file1_ // +-dir2 // `-file_1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,2); - assert_eq!(root.borrow().info().unwrap().nlinks,4); - assert_eq!(file1.borrow().info().unwrap().nlinks,2); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 2); + assert_eq!(root.borrow().info().unwrap().nlinks, 4); + assert_eq!(file1.borrow().info().unwrap().nlinks, 2); - root.borrow_mut().move_("file_1",dir2.borrow_mut().deref_mut(),"file__1").unwrap(); + root.borrow_mut().move_("file_1", dir2.borrow_mut().deref_mut(), "file__1").unwrap(); // -root // +-dir_1 // | `-file1_ // `-dir2 // `-file__1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,2); - assert_eq!(root.borrow().info().unwrap().nlinks,4); - assert_eq!(file1.borrow().info().unwrap().nlinks,2); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 2); + assert_eq!(root.borrow().info().unwrap().nlinks, 4); + assert_eq!(file1.borrow().info().unwrap().nlinks, 2); - root.borrow_mut().move_("dir_1",dir2.borrow_mut().deref_mut(),"dir__1").unwrap(); + root.borrow_mut().move_("dir_1", dir2.borrow_mut().deref_mut(), "dir__1").unwrap(); // -root // `-dir2 // +-dir__1 // | `-file1_ // `-file__1 - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,3); - assert_eq!(root.borrow().info().unwrap().nlinks,3); - assert_eq!(file1.borrow().info().unwrap().nlinks,2); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 3); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); + assert_eq!(file1.borrow().info().unwrap().nlinks, 2); dir2.borrow_mut().unlink("file__1").unwrap(); // -root // `-dir2 // `-dir__1 // `-file1_ - assert_eq!(file1.borrow().info().unwrap().nlinks,1); - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,3); - assert_eq!(root.borrow().info().unwrap().nlinks,3); + assert_eq!(file1.borrow().info().unwrap().nlinks, 1); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 3); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); dir1.borrow_mut().unlink("file1_").unwrap(); // -root // `-dir2 // `-dir__1 - assert_eq!(file1.borrow().info().unwrap().nlinks,0); - assert_eq!(dir1.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,3); - assert_eq!(root.borrow().info().unwrap().nlinks,3); + assert_eq!(file1.borrow().info().unwrap().nlinks, 0); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 3); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); dir2.borrow_mut().unlink("dir__1").unwrap(); // -root // `-dir2 - assert_eq!(file1.borrow().info().unwrap().nlinks,0); - assert_eq!(dir1.borrow().info().unwrap().nlinks,0); - assert_eq!(root.borrow().info().unwrap().nlinks,3); - assert_eq!(dir2.borrow().info().unwrap().nlinks,2); + assert_eq!(file1.borrow().info().unwrap().nlinks, 0); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 0); + assert_eq!(root.borrow().info().unwrap().nlinks, 3); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 2); root.borrow_mut().unlink("dir2").unwrap(); // -root - assert_eq!(file1.borrow().info().unwrap().nlinks,0); - assert_eq!(dir1.borrow().info().unwrap().nlinks,0); - assert_eq!(root.borrow().info().unwrap().nlinks,2); - assert_eq!(dir2.borrow().info().unwrap().nlinks,0); + assert_eq!(file1.borrow().info().unwrap().nlinks, 0); + assert_eq!(dir1.borrow().info().unwrap().nlinks, 0); + assert_eq!(root.borrow().info().unwrap().nlinks, 2); + assert_eq!(dir2.borrow().info().unwrap().nlinks, 0); sfs.sync().unwrap(); } \ No newline at end of file diff --git a/src/vfs.rs b/src/vfs.rs index f04fb54..945524b 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -24,16 +24,16 @@ pub trait INode: Debug + Any { fn create(&mut self, name: &str, type_: FileType) -> Result; fn unlink(&mut self, name: &str) -> Result<()>; /// user of the vfs api should call borrow_mut by itself - fn link(&mut self, name: &str, other:&mut INode) -> Result<()>; + fn link(&mut self, name: &str, other: &mut INode) -> Result<()>; fn rename(&mut self, old_name: &str, new_name: &str) -> Result<()>; // when self==target use rename instead since it's not possible to have two mut_ref at the same time. - fn move_(&mut self, old_name: &str,target:&mut INode, new_name: &str) -> Result<()>; + fn move_(&mut self, old_name: &str, target: &mut INode, new_name: &str) -> Result<()>; /// lookup with only one layer fn find(&self, name: &str) -> Result; /// like list()[id] /// only get one item in list, often faster than list - fn get_entry(&self,id: usize) -> Result; -// fn io_ctrl(&mut self, op: u32, data: &[u8]) -> Result<()>; + fn get_entry(&self, id: usize) -> Result; + // fn io_ctrl(&mut self, op: u32, data: &[u8]) -> Result<()>; fn fs(&self) -> Weak; /// this is used to implement dynamics cast /// simply return self in the implement of the function @@ -43,39 +43,45 @@ pub trait INode: Debug + Any { fn as_any_mut(&mut self) -> &mut Any; } -impl INode{ - pub fn downcast_ref(&self) -> Option<&T> { +impl INode { + pub fn downcast_ref(&self) -> Option<&T> { self.as_any_ref().downcast_ref::() } - pub fn downcast_mut(&mut self) -> Option<&mut T> { + pub fn downcast_mut(&mut self) -> Option<&mut T> { self.as_any_mut().downcast_mut::() } pub fn list(&self) -> Result> { - let info=self.info().unwrap(); + let info = self.info().unwrap(); assert_eq!(info.type_, FileType::Dir); - Ok((0..info.size).map(|i|{ + Ok((0..info.size).map(|i| { self.get_entry(i).unwrap() }).collect()) } pub fn lookup(&self, path: &str) -> Result { - if(self.info().unwrap().type_ != FileType::Dir){ - return Err(()) + if self.info().unwrap().type_ != FileType::Dir { + return Err(()); } - let mut result=self.find(".").unwrap(); - let mut rest_path=path; + let mut result = self.find(".").unwrap(); + let mut rest_path = path; while rest_path != "" { - if(result.borrow().info().unwrap().type_ != FileType::Dir){ - return Err(()) + if result.borrow().info().unwrap().type_ != FileType::Dir { + return Err(()); } let mut name; match rest_path.find('/') { - None => {name=rest_path; rest_path=""}, - Some(pos) => {name=&rest_path[0..pos]; rest_path=&rest_path[pos + 1..]}, + None => { + name = rest_path; + rest_path = "" + } + Some(pos) => { + name = &rest_path[0..pos]; + rest_path = &rest_path[pos + 1..] + } }; - let found=result.borrow().find(name); + let found = result.borrow().find(name); match found { Err(_) => return Err(()), - Ok(inode) => result=inode, + Ok(inode) => result = inode, }; } Ok(result) @@ -97,7 +103,8 @@ pub struct FileInfo { #[derive(Debug, Eq, PartialEq)] pub enum FileType { - File, Dir, + File, + Dir, } #[derive(Debug)]