2019-02-25 21:44:13 +04:00
|
|
|
//! File handle for process
|
2019-02-22 08:54:42 +04:00
|
|
|
|
|
|
|
use alloc::{string::String, sync::Arc};
|
2019-05-02 11:07:06 +04:00
|
|
|
use core::fmt;
|
2019-02-22 08:54:42 +04:00
|
|
|
|
2019-04-05 19:20:08 +04:00
|
|
|
use rcore_fs::vfs::{FsError, INode, Metadata, PollStatus, Result};
|
2019-02-22 08:54:42 +04:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
2019-02-25 21:44:13 +04:00
|
|
|
pub struct FileHandle {
|
2019-02-22 08:54:42 +04:00
|
|
|
inode: Arc<INode>,
|
2019-02-26 13:01:38 +04:00
|
|
|
offset: u64,
|
2019-02-25 21:44:13 +04:00
|
|
|
options: OpenOptions,
|
2019-05-02 11:07:06 +04:00
|
|
|
path: String,
|
2019-02-22 08:54:42 +04:00
|
|
|
}
|
|
|
|
|
2019-02-25 21:44:13 +04:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct OpenOptions {
|
|
|
|
pub read: bool,
|
|
|
|
pub write: bool,
|
|
|
|
/// Before each write, the file offset is positioned at the end of the file.
|
|
|
|
pub append: bool,
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:01:38 +04:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum SeekFrom {
|
|
|
|
Start(u64),
|
|
|
|
End(i64),
|
|
|
|
Current(i64),
|
|
|
|
}
|
|
|
|
|
2019-02-25 21:44:13 +04:00
|
|
|
impl FileHandle {
|
2019-05-02 11:47:10 +04:00
|
|
|
pub fn new(inode: Arc<INode>, options: OpenOptions, path: String) -> Self {
|
2019-05-02 11:07:06 +04:00
|
|
|
return FileHandle {
|
|
|
|
inode,
|
|
|
|
offset: 0,
|
|
|
|
options,
|
2019-05-02 11:47:10 +04:00
|
|
|
path,
|
2019-05-02 11:07:06 +04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:54:42 +04:00
|
|
|
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
2019-03-20 12:27:18 +04:00
|
|
|
let len = self.read_at(self.offset as usize, buf)?;
|
2019-02-26 13:01:38 +04:00
|
|
|
self.offset += len as u64;
|
2019-02-22 08:54:42 +04:00
|
|
|
Ok(len)
|
|
|
|
}
|
|
|
|
|
2019-03-08 10:22:00 +04:00
|
|
|
pub fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
|
|
|
if !self.options.read {
|
2019-03-27 14:35:08 +04:00
|
|
|
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
2019-03-08 10:22:00 +04:00
|
|
|
}
|
|
|
|
let len = self.inode.read_at(offset, buf)?;
|
|
|
|
Ok(len)
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:54:42 +04:00
|
|
|
pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
2019-03-20 12:27:18 +04:00
|
|
|
let offset = match self.options.append {
|
|
|
|
true => self.inode.metadata()?.size as u64,
|
|
|
|
false => self.offset,
|
|
|
|
} as usize;
|
|
|
|
let len = self.write_at(offset, buf)?;
|
|
|
|
self.offset = (offset + len) as u64;
|
2019-02-22 08:54:42 +04:00
|
|
|
Ok(len)
|
|
|
|
}
|
|
|
|
|
2019-03-08 14:03:46 +04:00
|
|
|
pub fn write_at(&mut self, offset: usize, buf: &[u8]) -> Result<usize> {
|
|
|
|
if !self.options.write {
|
2019-03-27 14:35:08 +04:00
|
|
|
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
2019-03-08 14:03:46 +04:00
|
|
|
}
|
|
|
|
let len = self.inode.write_at(offset, buf)?;
|
|
|
|
Ok(len)
|
|
|
|
}
|
|
|
|
|
2019-02-26 13:01:38 +04:00
|
|
|
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
|
|
|
|
self.offset = match pos {
|
|
|
|
SeekFrom::Start(offset) => offset,
|
|
|
|
SeekFrom::End(offset) => (self.inode.metadata()?.size as i64 + offset) as u64,
|
|
|
|
SeekFrom::Current(offset) => (self.offset as i64 + offset) as u64,
|
|
|
|
};
|
|
|
|
Ok(self.offset)
|
|
|
|
}
|
|
|
|
|
2019-03-02 19:16:11 +04:00
|
|
|
pub fn set_len(&mut self, len: u64) -> Result<()> {
|
|
|
|
if !self.options.write {
|
2019-03-27 14:35:08 +04:00
|
|
|
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
2019-03-02 19:16:11 +04:00
|
|
|
}
|
|
|
|
self.inode.resize(len as usize)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sync_all(&mut self) -> Result<()> {
|
2019-03-20 12:27:18 +04:00
|
|
|
self.inode.sync_all()
|
2019-03-02 19:16:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sync_data(&mut self) -> Result<()> {
|
2019-03-20 12:27:18 +04:00
|
|
|
self.inode.sync_data()
|
2019-03-02 19:16:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn metadata(&self) -> Result<Metadata> {
|
2019-02-22 13:10:07 +04:00
|
|
|
self.inode.metadata()
|
2019-02-22 08:54:42 +04:00
|
|
|
}
|
|
|
|
|
2019-03-23 20:36:13 +04:00
|
|
|
pub fn lookup_follow(&self, path: &str, max_follow: usize) -> Result<Arc<INode>> {
|
|
|
|
self.inode.lookup_follow(path, max_follow)
|
|
|
|
}
|
|
|
|
|
2019-03-02 13:17:57 +04:00
|
|
|
pub fn read_entry(&mut self) -> Result<String> {
|
|
|
|
if !self.options.read {
|
2019-03-27 14:35:08 +04:00
|
|
|
return Err(FsError::InvalidParam); // FIXME: => EBADF
|
2019-03-02 13:17:57 +04:00
|
|
|
}
|
|
|
|
let name = self.inode.get_entry(self.offset as usize)?;
|
|
|
|
self.offset += 1;
|
|
|
|
Ok(name)
|
2019-02-22 08:54:42 +04:00
|
|
|
}
|
2019-04-05 19:20:08 +04:00
|
|
|
|
|
|
|
pub fn poll(&self) -> Result<PollStatus> {
|
|
|
|
self.inode.poll()
|
|
|
|
}
|
|
|
|
|
2019-04-17 04:16:02 +04:00
|
|
|
pub fn io_control(&self, cmd: u32, arg: usize) -> Result<()> {
|
2019-04-05 19:20:08 +04:00
|
|
|
self.inode.io_control(cmd, arg)
|
|
|
|
}
|
2019-04-30 09:37:31 +04:00
|
|
|
|
|
|
|
pub fn inode(&self) -> Arc<INode> {
|
|
|
|
self.inode.clone()
|
|
|
|
}
|
2019-03-27 14:35:08 +04:00
|
|
|
}
|
2019-05-02 11:07:06 +04:00
|
|
|
|
|
|
|
impl fmt::Debug for FileHandle {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
return f
|
|
|
|
.debug_struct("FileHandle")
|
|
|
|
.field("offset", &self.offset)
|
|
|
|
.field("options", &self.options)
|
|
|
|
.field("path", &self.path)
|
|
|
|
.finish();
|
|
|
|
}
|
|
|
|
}
|