1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-27 10:13:28 +04:00
rCore/kernel/src/fs/file.rs

166 lines
4.3 KiB
Rust
Raw Normal View History

//! File handle for process
2019-02-22 08:54:42 +04:00
use alloc::{string::String, sync::Arc};
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)]
pub struct FileHandle {
2019-02-22 08:54:42 +04:00
inode: Arc<INode>,
2019-02-26 13:01:38 +04:00
offset: u64,
options: OpenOptions,
// for debugging
#[cfg(debug_assertions)]
path: String,
2019-02-22 08:54:42 +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),
}
impl FileHandle {
pub fn new(inode: Arc<INode>, options: OpenOptions) -> Self {
#[cfg(debug_assertions)]
return FileHandle {
inode,
offset: 0,
options,
path: String::from("unknown"),
};
#[cfg(not(debug_assertions))]
return FileHandle {
inode,
offset: 0,
options,
};
}
#[cfg(debug_assertions)]
pub fn set_path(&mut self, path: &str) {
self.path = String::from(path);
}
#[cfg(not(debug_assertions))]
pub fn set_path(&mut self, _path: &str) {
unreachable!()
2019-02-22 08:54:42 +04:00
}
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
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)
}
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
}
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> {
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)
}
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
}
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)
}
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
}
self.inode.resize(len as usize)?;
Ok(())
}
pub fn sync_all(&mut self) -> Result<()> {
self.inode.sync_all()
}
pub fn sync_data(&mut self) -> Result<()> {
self.inode.sync_data()
}
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)
}
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
}
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()
}
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
}
impl fmt::Debug for FileHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// for debugging
#[cfg(debug_assertions)]
return f
.debug_struct("FileHandle")
.field("offset", &self.offset)
.field("options", &self.options)
.field("path", &self.path)
.finish();
#[cfg(not(debug_assertions))]
return f
.debug_struct("FileHandle")
.field("offset", &self.offset)
.field("options", &self.options)
.finish();
}
}