implement hard link

master
Ben Pig Chu 6 years ago
parent 9d0b3d1891
commit 4a97d89b8f

@ -4,6 +4,7 @@ use core::cell::{RefCell, RefMut};
use core::mem::{uninitialized, size_of};
use core::slice;
use core::fmt::{Debug, Formatter, Error};
use core::any::Any;
use dirty::Dirty;
use structs::*;
use vfs::{self, Device};
@ -354,6 +355,25 @@ impl vfs::INode for INode {
Ok(())
}
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!(self.get_file_inode_id(name).is_none(), "file name exist");
let child = other.downcast_mut::<INode>().unwrap();
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();
self._resize(old_size + BLKSIZE).unwrap();
self._write_at(old_size, entry.as_buf()).unwrap();
child.nlinks_inc();
Ok(())
}
fn lookup(&self, path: &str) -> vfs::Result<Ptr<vfs::INode>> {
let fs = self.fs.upgrade().unwrap();
let info = self.info().unwrap();
@ -390,6 +410,12 @@ impl vfs::INode for INode {
fn fs(&self) -> Weak<vfs::FileSystem> {
self.fs.clone()
}
fn as_any_ref(&self) -> &Any {
self
}
fn as_any_mut(&mut self) -> &mut Any {
self
}
}
impl Drop for INode {

@ -181,6 +181,21 @@ fn kernel_image_file_unlink(){
sfs.sync().unwrap();
}
#[test]
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();
let file2 = root.borrow_mut().lookup("file2").unwrap();
file1.borrow_mut().resize(100);
assert_eq!(file2.borrow().info().unwrap().size,100);
sfs.sync().unwrap();
}
#[test]
fn nlinks(){
let sfs = _create_new_sfs();
@ -192,8 +207,17 @@ 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);
use core::ops::DerefMut;
dir1.borrow_mut().link("file2",file1.borrow_mut().deref_mut()).unwrap();
assert_eq!(dir1.borrow().info().unwrap().nlinks,2);
assert_eq!(root.borrow().info().unwrap().nlinks,3);
assert_eq!(file1.borrow().info().unwrap().nlinks,2);
root.borrow_mut().unlink("file1").unwrap();
assert_eq!(file1.borrow().info().unwrap().nlinks,1);
assert_eq!(root.borrow().info().unwrap().nlinks,3);
dir1.borrow_mut().unlink("file2").unwrap();
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();
assert_eq!(dir1.borrow().info().unwrap().nlinks,0);

@ -3,6 +3,7 @@ use core::cell::RefCell;
use core::mem::size_of;
use core;
use core::fmt::Debug;
use core::any::Any;
/// Interface for FS to read & write
/// TODO: use std::io::{Read, Write}
@ -12,7 +13,7 @@ pub trait Device {
}
/// Abstract operations on a inode.
pub trait INode: Debug {
pub trait INode: Debug + Any {
fn open(&mut self, flags: u32) -> Result<()>;
fn close(&mut self) -> Result<()>;
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
@ -23,12 +24,28 @@ pub trait INode: Debug {
// fn reclaim(&mut self) -> Result<()>;
fn resize(&mut self, len: usize) -> Result<()>;
fn create(&mut self, name: &str, type_: FileType) -> Result<INodePtr>;
// since we do not have link, unlink==remove
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<INodePtr>;
fn list(&self) -> Result<Vec<String>>;
// fn io_ctrl(&mut self, op: u32, data: &[u8]) -> Result<()>;
fn fs(&self) -> Weak<FileSystem>;
/// this is used to implement dynamics cast
/// simply return self in the implement of the function
fn as_any_ref(&self) -> &Any;
/// this is used to implement dynamics cast
/// simply return self in the implement of the function
fn as_any_mut(&mut self) -> &mut Any;
}
impl INode{
pub fn downcast_ref<T:INode>(&self) -> Option<&T> {
self.as_any_ref().downcast_ref::<T>()
}
pub fn downcast_mut<T:INode>(&mut self) -> Option<&mut T> {
self.as_any_mut().downcast_mut::<T>()
}
}
#[derive(Debug, Eq, PartialEq)]

Loading…
Cancel
Save