diff --git a/src/sfs.rs b/src/sfs.rs index d9dcabb..e9ae51c 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -374,6 +374,37 @@ impl vfs::INode for INode { child.nlinks_inc(); Ok(()) } + 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); + + let inode_and_entry_id = self.get_file_inode_and_entry_id(old_name); + if inode_and_entry_id.is_none() { + return Err(()); + } + 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; + self._read_at(entry_pos, entry.as_buf_mut()).unwrap(); + 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<()>{ + let fs = self.fs.upgrade().unwrap(); + let info = self.info().unwrap(); + assert_eq!(info.type_, vfs::FileType::Dir); + 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); + unimplemented!() + } fn find(&self, name: &str) -> vfs::Result> { let fs = self.fs.upgrade().unwrap(); let info = self.info().unwrap(); diff --git a/src/tests.rs b/src/tests.rs index 00d45d5..d514e99 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -168,6 +168,19 @@ fn kernel_image_file_unlink(){ } +// #[test] +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(); + let files_count_after = root.borrow().list().unwrap().len(); + assert_eq!(files_count_before, files_count_after); + assert!(root.borrow().lookup("hello").is_err()); + + sfs.sync().unwrap(); +} + #[test] fn hard_link(){ let sfs = _create_new_sfs(); @@ -193,6 +206,9 @@ 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().rename("dir1", "dir_1").unwrap(); + 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(); assert_eq!(dir1.borrow().info().unwrap().nlinks,2); @@ -205,7 +221,7 @@ fn nlinks(){ assert_eq!(file1.borrow().info().unwrap().nlinks,0); assert_eq!(dir1.borrow().info().unwrap().nlinks,2); assert_eq!(root.borrow().info().unwrap().nlinks,3); - root.borrow_mut().unlink("dir1").unwrap(); + root.borrow_mut().unlink("dir_1").unwrap(); assert_eq!(dir1.borrow().info().unwrap().nlinks,0); assert_eq!(root.borrow().info().unwrap().nlinks,2); diff --git a/src/vfs.rs b/src/vfs.rs index 15c4968..f04fb54 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -20,14 +20,14 @@ pub trait INode: Debug + Any { fn write_at(&self, offset: usize, buf: &[u8]) -> Result; fn info(&self) -> Result; fn sync(&mut self) -> Result<()>; -// fn name_file(&mut self) -> Result<()>; -// fn reclaim(&mut self) -> Result<()>; fn resize(&mut self, len: usize) -> Result<()>; 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 lookup(&self, path: &str) -> 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<()>; /// lookup with only one layer fn find(&self, name: &str) -> Result; /// like list()[id]