diff --git a/src/sfs.rs b/src/sfs.rs index e9ae51c..5e6db36 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -379,6 +379,8 @@ impl vfs::INode for INode { assert_eq!(info.type_, vfs::FileType::Dir); assert!(info.nlinks>0); + assert!(self.get_file_inode_id(new_name).is_none(), "file name exist"); + let inode_and_entry_id = self.get_file_inode_and_entry_id(old_name); if inode_and_entry_id.is_none() { return Err(()); @@ -401,9 +403,34 @@ impl vfs::INode for INode { 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().type_==vfs::FileType::Dir); assert!(dest.info().unwrap().nlinks>0); - unimplemented!() + + assert!(dest.get_file_inode_id(new_name).is_none(), "file name exist"); + + let inode_and_entry_id = self.get_file_inode_and_entry_id(old_name); + if inode_and_entry_id.is_none() { + return Err(()); + } + 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(); + 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){ + self.nlinks_dec(); + dest.nlinks_inc(); + } + + Ok(()) } fn find(&self, name: &str) -> vfs::Result> { let fs = self.fs.upgrade().unwrap(); @@ -613,7 +640,9 @@ impl SimpleFileSystem { } } } - inodes.remove(&id); + if(should_remove){ + inodes.remove(&id); + } } } } diff --git a/src/tests.rs b/src/tests.rs index d514e99..8a6b355 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -150,6 +150,7 @@ fn kernel_image_file_create(){ 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!(root.borrow().lookup("hello2").is_ok()); sfs.sync().unwrap(); } @@ -177,6 +178,26 @@ fn kernel_image_file_rename(){ let files_count_after = root.borrow().list().unwrap().len(); assert_eq!(files_count_before, files_count_after); assert!(root.borrow().lookup("hello").is_err()); + assert!(root.borrow().lookup("hello2").is_ok()); + + sfs.sync().unwrap(); +} + +// #[test] +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(); + let files_count_after = root.borrow().list().unwrap().len(); + 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()); + assert!(rust_dir.borrow().lookup("hello_world").is_ok()); sfs.sync().unwrap(); } @@ -197,33 +218,118 @@ fn hard_link(){ #[test] 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); + 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); + 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); + 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); - use core::ops::DerefMut; - dir1.borrow_mut().link("file2",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); + + let dir2 = root.borrow_mut().create("dir2", FileType::Dir).unwrap(); + // -root + // +-dir_1 + // | `-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); + + 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); + + 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); + + 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); - root.borrow_mut().unlink("file1").unwrap(); + + 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); - dir1.borrow_mut().unlink("file2").unwrap(); + + 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); + + 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); - root.borrow_mut().unlink("dir_1").unwrap(); + 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); sfs.sync().unwrap(); } \ No newline at end of file