improve docs for vfs. add poll and ioctl.

master
WangRunji 6 years ago
parent acff8d5586
commit d7a2006cc3

@ -156,6 +156,13 @@ impl vfs::INode for INodeImpl {
let len = self.file.write_at(buf, offset)?;
Ok(len)
}
fn poll(&self) -> vfs::Result<vfs::PollStatus> {
Ok(vfs::PollStatus {
read: true,
write: true,
error: false
})
}
/// the size returned here is logical size(entry num for directory), not the disk space used.
fn metadata(&self) -> vfs::Result<vfs::Metadata> {
let disk_inode = self.disk_inode.read();
@ -404,6 +411,9 @@ impl vfs::INode for INodeImpl {
let entry = self.file.read_direntry(id)?;
Ok(String::from(entry.name.as_ref()))
}
fn io_control(&self, _cmd: u32, _data: u32) -> vfs::Result<()> {
Err(FsError::NotSupported)
}
fn fs(&self) -> Arc<vfs::FileSystem> {
self.fs.clone()
}

@ -398,6 +398,13 @@ impl vfs::INode for INodeImpl {
}
self._write_at(offset, buf)
}
fn poll(&self) -> vfs::Result<vfs::PollStatus> {
Ok(vfs::PollStatus {
read: true,
write: true,
error: false
})
}
/// the size returned here is logical size(entry num for directory), not the disk space used.
fn metadata(&self) -> vfs::Result<vfs::Metadata> {
let disk_inode = self.disk_inode.read();
@ -484,6 +491,36 @@ impl vfs::INode for INodeImpl {
Ok(inode)
}
fn link(&self, name: &str, other: &Arc<INode>) -> vfs::Result<()> {
let info = self.metadata()?;
if info.type_ != vfs::FileType::Dir {
return Err(FsError::NotDir);
}
if info.nlinks <= 0 {
return Err(FsError::DirRemoved);
}
if !self.get_file_inode_id(name).is_none() {
return Err(FsError::EntryExist);
}
let child = other
.downcast_ref::<INodeImpl>()
.ok_or(FsError::NotSameFs)?;
if !Arc::ptr_eq(&self.fs, &child.fs) {
return Err(FsError::NotSameFs);
}
if child.metadata()?.type_ == vfs::FileType::Dir {
return Err(FsError::IsDir);
}
let entry = DiskEntry {
id: child.id as u32,
name: Str256::from(name),
};
let old_size = self._size();
self._resize(old_size + BLKSIZE)?;
self._write_at(old_size, entry.as_buf()).unwrap();
child.nlinks_inc();
Ok(())
}
fn unlink(&self, name: &str) -> vfs::Result<()> {
let info = self.metadata()?;
if info.type_ != vfs::FileType::Dir {
@ -521,36 +558,6 @@ impl vfs::INode for INodeImpl {
Ok(())
}
fn link(&self, name: &str, other: &Arc<INode>) -> vfs::Result<()> {
let info = self.metadata()?;
if info.type_ != vfs::FileType::Dir {
return Err(FsError::NotDir);
}
if info.nlinks <= 0 {
return Err(FsError::DirRemoved);
}
if !self.get_file_inode_id(name).is_none() {
return Err(FsError::EntryExist);
}
let child = other
.downcast_ref::<INodeImpl>()
.ok_or(FsError::NotSameFs)?;
if !Arc::ptr_eq(&self.fs, &child.fs) {
return Err(FsError::NotSameFs);
}
if child.metadata()?.type_ == vfs::FileType::Dir {
return Err(FsError::IsDir);
}
let entry = DiskEntry {
id: child.id as u32,
name: Str256::from(name),
};
let old_size = self._size();
self._resize(old_size + BLKSIZE)?;
self._write_at(old_size, entry.as_buf()).unwrap();
child.nlinks_inc();
Ok(())
}
fn move_(&self, old_name: &str, target: &Arc<INode>, new_name: &str) -> vfs::Result<()> {
let info = self.metadata()?;
if info.type_ != vfs::FileType::Dir {
@ -635,6 +642,9 @@ impl vfs::INode for INodeImpl {
.unwrap();
Ok(String::from(entry.name.as_ref()))
}
fn io_control(&self, _cmd: u32, _data: u32) -> vfs::Result<()> {
Err(FsError::NotSupported)
}
fn fs(&self) -> Arc<vfs::FileSystem> {
self.fs.clone()
}

@ -4,40 +4,69 @@ use core::fmt;
use core::result;
use core::str;
/// Abstract operations on a inode.
/// Abstract file system object such as file or directory.
pub trait INode: Any + Sync + Send {
/// Read bytes at `offset` into `buf`, return the number of bytes read.
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize>;
/// Write bytes at `offset` from `buf`, return the number of bytes written.
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize>;
/// Poll the events, return a bitmap of events.
fn poll(&self) -> Result<PollStatus>;
/// Get metadata of the INode
fn metadata(&self) -> Result<Metadata>;
/// Set metadata of the INode
fn set_metadata(&self, metadata: &Metadata) -> Result<()>;
/// Sync all data and metadata
fn sync_all(&self) -> Result<()>;
/// Sync data (not include metadata)
fn sync_data(&self) -> Result<()>;
/// Resize the file
fn resize(&self, len: usize) -> Result<()>;
/// Create a new INode in the directory
fn create(&self, name: &str, type_: FileType, mode: u32) -> Result<Arc<INode>>;
fn unlink(&self, name: &str) -> Result<()>;
/// user of the vfs api should call borrow_mut by itself
/// Create a hard link `name` to `other`
fn link(&self, name: &str, other: &Arc<INode>) -> Result<()>;
/// Delete a hard link `name`
fn unlink(&self, name: &str) -> Result<()>;
/// Move INode `self/old_name` to `target/new_name`.
/// If `target` equals `self`, do rename.
fn move_(&self, old_name: &str, target: &Arc<INode>, new_name: &str) -> Result<()>;
/// lookup with only one layer
/// Find the INode `name` in the directory
fn find(&self, name: &str) -> Result<Arc<INode>>;
/// like list()[id]
/// only get one item in list, often faster than list
/// Get the name of directory entry
fn get_entry(&self, id: usize) -> Result<String>;
// fn io_ctrl(&mut self, op: u32, data: &[u8]) -> Result<()>;
/// Control device
fn io_control(&self, cmd: u32, data: u32) -> Result<()>;
/// Get the file system of the INode
fn fs(&self) -> Arc<FileSystem>;
/// this is used to implement dynamics cast
/// simply return self in the implement of the function
/// This is used to implement dynamics cast.
/// Simply return self in the implement of the function.
fn as_any_ref(&self) -> &Any;
}
impl INode {
/// Downcast the INode to specific struct
pub fn downcast_ref<T: INode>(&self) -> Option<&T> {
self.as_any_ref().downcast_ref::<T>()
}
/// Get all directory entries as a Vec
pub fn list(&self) -> Result<Vec<String>> {
let info = self.metadata()?;
if info.type_ != FileType::Dir {
@ -80,39 +109,40 @@ impl INode {
rest_path = String::from(&rest_path[pos + 1..]);
}
};
match result.find(&name) {
Err(error) => return Err(error),
Ok(inode) => {
// Handle symlink
if inode.metadata()?.type_ == FileType::SymLink && follow_times > 0 {
follow_times -= 1;
let mut content = [0u8; 256];
let len = inode.read_at(0, &mut content)?;
if let Ok(path) = str::from_utf8(&content[..len]) {
// result remains unchanged
rest_path = {
let mut new_path = String::from(path);
if let Some('/') = new_path.chars().last() {
new_path += &rest_path;
} else {
new_path += "/";
new_path += &rest_path;
}
new_path
};
} else {
return Err(FsError::NotDir);
}
let inode = result.find(&name)?;
// Handle symlink
if inode.metadata()?.type_ == FileType::SymLink && follow_times > 0 {
follow_times -= 1;
let mut content = [0u8; 256];
let len = inode.read_at(0, &mut content)?;
let path = str::from_utf8(&content[..len])
.map_err(|_| FsError::NotDir)?;
// result remains unchanged
rest_path = {
let mut new_path = String::from(path);
if let Some('/') = new_path.chars().last() {
new_path += &rest_path;
} else {
result = inode
new_path += "/";
new_path += &rest_path;
}
}
};
new_path
};
} else {
result = inode
}
}
Ok(result)
}
}
#[derive(Debug, Default)]
pub struct PollStatus {
pub read: bool,
pub write: bool,
pub error: bool,
}
/// Metadata of INode
///
/// Ref: [http://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/stat.h.html]
@ -223,9 +253,14 @@ impl std::error::Error for FsError {}
pub type Result<T> = result::Result<T, FsError>;
/// Abstract filesystem
/// Abstract file system
pub trait FileSystem: Sync {
/// Sync all data to the storage
fn sync(&self) -> Result<()>;
/// Get the root INode of the file system
fn root_inode(&self) -> Arc<INode>;
/// Get the file system information
fn info(&self) -> FsInfo;
}

Loading…
Cancel
Save