diff --git a/src/sfs.rs b/src/sfs.rs index e7eda15..9d9e471 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -271,6 +271,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); // Ensure the name is not exist assert!(self.get_file_inode_id(name).is_none(), "file name exist"); @@ -297,6 +298,8 @@ impl vfs::INode for INode { Ok(inode) } fn unlink(&mut self, name: &str) -> vfs::Result<()> { + assert!(name!="."); + assert!(name!=".."); let fs = self.fs.upgrade().unwrap(); let info = self.info().unwrap(); assert_eq!(info.type_, vfs::FileType::Dir); @@ -313,12 +316,20 @@ impl vfs::INode for INode { // only . and .. assert!(inode.borrow().disk_inode.blocks==2); } + inode.borrow_mut().nlinks_dec(); + if(type_==FileType::Dir){ + inode.borrow_mut().nlinks_dec();//for . + self.nlinks_dec();//for .. + } + let old_block_count=self.disk_inode.blocks as usize; + if(entry_id!=old_block_count - 1){//not last entry + let mut entry: DiskEntry = unsafe { uninitialized() }; + self._read_at((old_block_count - 1) * BLKSIZE, entry.as_buf_mut()).unwrap(); + self._write_at(entry_id * BLKSIZE, entry.as_buf()).unwrap(); + } + self._resize((old_block_count - 1) * BLKSIZE).unwrap(); - //todo: actually unlink: - //1. move the last entry to the original place - //2. free the disc space - - unimplemented!(); + Ok(()) } fn lookup(&self, path: &str) -> vfs::Result> { let fs = self.fs.upgrade().unwrap(); diff --git a/src/structs.rs b/src/structs.rs index 2b07667..f9596f5 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -29,6 +29,7 @@ pub struct DiskINode { /// one of SYS_TYPE_* above pub type_: FileType, /// number of hard links to this file + /// Note: "." and ".." is counted in this nlinks pub nlinks: u16, /// number of blocks pub blocks: u32, diff --git a/src/tests.rs b/src/tests.rs index 6abffb1..a33294b 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -168,6 +168,18 @@ fn kernel_image_file_create(){ sfs.sync().unwrap(); } +// #[test] +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"); + let files_count_after = root.borrow().list().unwrap().len(); + assert_eq!(files_count_before, files_count_after+1); + + sfs.sync().unwrap(); +} + #[test] fn nlinks(){ let sfs = _create_new_sfs(); @@ -179,6 +191,12 @@ fn nlinks(){ let dir1 = root.borrow_mut().create("dir1", FileType::Dir).unwrap(); assert_eq!(dir1.borrow().info().unwrap().nlinks,2); assert_eq!(root.borrow().info().unwrap().nlinks,3); + root.borrow_mut().unlink("file1").unwrap(); + assert_eq!(file1.borrow().info().unwrap().nlinks,0); + assert_eq!(root.borrow().info().unwrap().nlinks,3); + root.borrow_mut().unlink("dir1").unwrap(); + assert_eq!(dir1.borrow().info().unwrap().nlinks,0); + assert_eq!(root.borrow().info().unwrap().nlinks,2); sfs.sync().unwrap(); } \ No newline at end of file diff --git a/src/vfs.rs b/src/vfs.rs index e9b8375..1b5396c 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -37,6 +37,8 @@ pub struct FileInfo { pub mode: u32, pub type_: FileType, pub blocks: usize, + // Note: different from linux, "." and ".." count in nlinks + // this is same as original ucore. pub nlinks: usize, }