basic unlink implement

master
Ben Pig Chu 6 years ago
parent 77cea66f7e
commit 36277c5769

@ -271,6 +271,7 @@ impl vfs::INode for INode {
let fs = self.fs.upgrade().unwrap(); let fs = self.fs.upgrade().unwrap();
let info = self.info().unwrap(); let info = self.info().unwrap();
assert_eq!(info.type_, vfs::FileType::Dir); assert_eq!(info.type_, vfs::FileType::Dir);
assert!(info.nlinks>0);
// Ensure the name is not exist // Ensure the name is not exist
assert!(self.get_file_inode_id(name).is_none(), "file name exist"); assert!(self.get_file_inode_id(name).is_none(), "file name exist");
@ -297,6 +298,8 @@ impl vfs::INode for INode {
Ok(inode) Ok(inode)
} }
fn unlink(&mut self, name: &str) -> vfs::Result<()> { fn unlink(&mut self, name: &str) -> vfs::Result<()> {
assert!(name!=".");
assert!(name!="..");
let fs = self.fs.upgrade().unwrap(); let fs = self.fs.upgrade().unwrap();
let info = self.info().unwrap(); let info = self.info().unwrap();
assert_eq!(info.type_, vfs::FileType::Dir); assert_eq!(info.type_, vfs::FileType::Dir);
@ -313,12 +316,20 @@ impl vfs::INode for INode {
// only . and .. // 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){
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: Ok(())
//1. move the last entry to the original place
//2. free the disc space
unimplemented!();
} }
fn lookup(&self, path: &str) -> vfs::Result<Ptr<vfs::INode>> { fn lookup(&self, path: &str) -> vfs::Result<Ptr<vfs::INode>> {
let fs = self.fs.upgrade().unwrap(); let fs = self.fs.upgrade().unwrap();

@ -29,6 +29,7 @@ pub struct DiskINode {
/// one of SYS_TYPE_* above /// one of SYS_TYPE_* above
pub type_: FileType, pub type_: FileType,
/// number of hard links to this file /// number of hard links to this file
/// Note: "." and ".." is counted in this nlinks
pub nlinks: u16, pub nlinks: u16,
/// number of blocks /// number of blocks
pub blocks: u32, pub blocks: u32,

@ -168,6 +168,18 @@ fn kernel_image_file_create(){
sfs.sync().unwrap(); 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] #[test]
fn nlinks(){ fn nlinks(){
let sfs = _create_new_sfs(); let sfs = _create_new_sfs();
@ -179,6 +191,12 @@ fn nlinks(){
let dir1 = root.borrow_mut().create("dir1", FileType::Dir).unwrap(); let dir1 = root.borrow_mut().create("dir1", FileType::Dir).unwrap();
assert_eq!(dir1.borrow().info().unwrap().nlinks,2); assert_eq!(dir1.borrow().info().unwrap().nlinks,2);
assert_eq!(root.borrow().info().unwrap().nlinks,3); 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(); sfs.sync().unwrap();
} }

@ -37,6 +37,8 @@ pub struct FileInfo {
pub mode: u32, pub mode: u32,
pub type_: FileType, pub type_: FileType,
pub blocks: usize, pub blocks: usize,
// Note: different from linux, "." and ".." count in nlinks
// this is same as original ucore.
pub nlinks: usize, pub nlinks: usize,
} }

Loading…
Cancel
Save