move the list and lookup implement to the vfs level

master
Ben Pig Chu 6 years ago
parent e640f78134
commit 9c0c3e0d83

@ -374,28 +374,6 @@ impl vfs::INode for INode {
child.nlinks_inc(); child.nlinks_inc();
Ok(()) Ok(())
} }
fn lookup(&self, path: &str) -> vfs::Result<Ptr<vfs::INode>> {
let fs = self.fs.upgrade().unwrap();
let info = self.info().unwrap();
assert_eq!(info.type_, vfs::FileType::Dir);
let (name, rest_path) = match path.find('/') {
None => (path, ""),
Some(pos) => (&path[0..pos], &path[pos + 1..]),
};
let inode_id = self.get_file_inode_id(name);
if inode_id.is_none() {
return Err(());
}
let inode = fs.get_inode(inode_id.unwrap());
let type_ = inode.borrow().disk_inode.type_;
match type_ {
FileType::File => if rest_path == "" { Ok(inode) } else { Err(()) },
FileType::Dir => if rest_path == "" { Ok(inode) } else { inode.borrow().lookup(rest_path) },
_ => unimplemented!(),
}
}
fn find(&self, name: &str) -> vfs::Result<Ptr<vfs::INode>> { fn find(&self, name: &str) -> vfs::Result<Ptr<vfs::INode>> {
let fs = self.fs.upgrade().unwrap(); let fs = self.fs.upgrade().unwrap();
let info = self.info().unwrap(); let info = self.info().unwrap();
@ -415,17 +393,6 @@ impl vfs::INode for INode {
self._read_at(id as usize * BLKSIZE, entry.as_buf_mut()).unwrap(); self._read_at(id as usize * BLKSIZE, entry.as_buf_mut()).unwrap();
Ok(String::from(entry.name.as_ref())) Ok(String::from(entry.name.as_ref()))
} }
fn list(&self) -> vfs::Result<Vec<String>> {
assert_eq!(self.disk_inode.type_, FileType::Dir);
Ok((0..self.disk_inode.blocks)
.map(|i| {
use vfs::INode;
let mut entry: DiskEntry = unsafe { uninitialized() };
self._read_at(i as usize * BLKSIZE, entry.as_buf_mut()).unwrap();
String::from(entry.name.as_ref())
}).collect())
}
fn fs(&self) -> Weak<vfs::FileSystem> { fn fs(&self) -> Weak<vfs::FileSystem> {
self.fs.clone() self.fs.clone()
} }

@ -128,6 +128,7 @@ fn resize() {
#[test] #[test]
fn create_then_lookup() { fn create_then_lookup() {
let sfs = _create_new_sfs(); let sfs = _create_new_sfs();
{
let root = sfs.root_inode(); let root = sfs.root_inode();
assert!(Rc::ptr_eq(&root.borrow().lookup(".").unwrap(), &root), "failed to find ."); assert!(Rc::ptr_eq(&root.borrow().lookup(".").unwrap(), &root), "failed to find .");
@ -144,7 +145,7 @@ fn create_then_lookup() {
.expect("failed to create /dir1/file2"); .expect("failed to create /dir1/file2");
assert!(Rc::ptr_eq(&root.borrow().lookup("dir1/file2").unwrap(), &file2), "failed to find dir1/file1"); assert!(Rc::ptr_eq(&root.borrow().lookup("dir1/file2").unwrap(), &file2), "failed to find dir1/file1");
assert!(Rc::ptr_eq(&dir1.borrow().lookup("..").unwrap(), &root), "failed to find .. from dir1"); assert!(Rc::ptr_eq(&dir1.borrow().lookup("..").unwrap(), &root), "failed to find .. from dir1");
}
sfs.sync().unwrap(); sfs.sync().unwrap();
} }
@ -192,7 +193,7 @@ fn hard_link(){
let file1 = root.borrow_mut().create("file1", FileType::File).unwrap(); let file1 = root.borrow_mut().create("file1", FileType::File).unwrap();
use core::ops::DerefMut; use core::ops::DerefMut;
root.borrow_mut().link("file2",file1.borrow_mut().deref_mut()).unwrap(); root.borrow_mut().link("file2",file1.borrow_mut().deref_mut()).unwrap();
let file2 = root.borrow_mut().lookup("file2").unwrap(); let file2 = root.borrow().lookup("file2").unwrap();
file1.borrow_mut().resize(100); file1.borrow_mut().resize(100);
assert_eq!(file2.borrow().info().unwrap().size,100); assert_eq!(file2.borrow().info().unwrap().size,100);

@ -27,10 +27,9 @@ pub trait INode: Debug + Any {
fn unlink(&mut self, name: &str) -> Result<()>; fn unlink(&mut self, name: &str) -> Result<()>;
/// user of the vfs api should call borrow_mut by itself /// user of the vfs api should call borrow_mut by itself
fn link(&mut self, name: &str, other:&mut INode) -> Result<()>; fn link(&mut self, name: &str, other:&mut INode) -> Result<()>;
fn lookup(&self, path: &str) -> Result<INodePtr>; // fn lookup(&self, path: &str) -> Result<INodePtr>;
/// lookup with only one layer /// lookup with only one layer
fn find(&self, name: &str) -> Result<INodePtr>; fn find(&self, name: &str) -> Result<INodePtr>;
fn list(&self) -> Result<Vec<String>>;
/// like list()[id] /// like list()[id]
/// only get one item in list, often faster than list /// only get one item in list, often faster than list
fn get_entry(&self,id: usize) -> Result<String>; fn get_entry(&self,id: usize) -> Result<String>;
@ -51,10 +50,42 @@ impl INode{
pub fn downcast_mut<T:INode>(&mut self) -> Option<&mut T> { pub fn downcast_mut<T:INode>(&mut self) -> Option<&mut T> {
self.as_any_mut().downcast_mut::<T>() self.as_any_mut().downcast_mut::<T>()
} }
pub fn list(&self) -> Result<Vec<String>> {
let info=self.info().unwrap();
assert_eq!(info.type_, FileType::Dir);
Ok((0..info.size).map(|i|{
self.get_entry(i).unwrap()
}).collect())
}
pub fn lookup(&self, path: &str) -> Result<INodePtr> {
if(self.info().unwrap().type_ != FileType::Dir){
return Err(())
}
let mut result=self.find(".").unwrap();
let mut rest_path=path;
while rest_path != "" {
if(result.borrow().info().unwrap().type_ != FileType::Dir){
return Err(())
}
let mut name;
match rest_path.find('/') {
None => {name=rest_path; rest_path=""},
Some(pos) => {name=&rest_path[0..pos]; rest_path=&rest_path[pos + 1..]},
};
let found=result.borrow().find(name);
match found {
Err(_) => return Err(()),
Ok(inode) => result=inode,
};
}
Ok(result)
}
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub struct FileInfo { pub struct FileInfo {
// Note: for normal file size is the actuate file size
// for directory this is count of dirent.
pub size: usize, pub size: usize,
pub mode: u32, pub mode: u32,
pub type_: FileType, pub type_: FileType,

Loading…
Cancel
Save