You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.9 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

use alloc::{vec::Vec, string::String, rc::{Rc, Weak}};
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}
pub trait Device {
fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option<usize>;
fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option<usize>;
}
/// Abstract operations on a inode.
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>;
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize>;
fn info(&self) -> Result<FileInfo>;
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<INodePtr>;
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>;
/// lookup with only one layer
fn find(&self, name: &str) -> Result<INodePtr>;
/// like list()[id]
/// only get one item in list, often faster than list
fn get_entry(&self,id: usize) -> Result<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>()
}
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)]
pub struct FileInfo {
// Note: for normal file size is the actuate file size
// for directory this is count of dirent.
pub size: usize,
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,
}
#[derive(Debug, Eq, PartialEq)]
pub enum FileType {
File, Dir,
}
#[derive(Debug)]
pub struct FsInfo {
pub max_file_size: usize,
}
pub type Result<T> = core::result::Result<T, ()>;
/// Abstract filesystem
pub trait FileSystem {
fn sync(&self) -> Result<()>;
fn root_inode(&self) -> INodePtr;
fn info(&self) -> &'static FsInfo;
// fn unmount(&self) -> Result<()>;
// fn cleanup(&self);
}
pub type INodePtr = Rc<RefCell<INode>>;