Add metadata in HNode
This commit is contained in:
parent
8085c2b797
commit
52b75e3e06
@ -3,7 +3,7 @@ use alloc::sync::{Arc, Weak};
|
|||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use rcore_fs::vfs::*;
|
use rcore_fs::vfs::*;
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
use std::os::unix::fs::{DirEntryExt, FileTypeExt, PermissionsExt};
|
use std::os::unix::fs::{DirEntryExt, FileExt, FileTypeExt, PermissionsExt};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{SgxMutex as Mutex, SgxMutexGuard as MutexGuard};
|
use std::sync::{SgxMutex as Mutex, SgxMutexGuard as MutexGuard};
|
||||||
use std::untrusted::fs;
|
use std::untrusted::fs;
|
||||||
@ -19,6 +19,7 @@ pub struct HostFS {
|
|||||||
pub struct HNode {
|
pub struct HNode {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
file: Mutex<Option<fs::File>>,
|
file: Mutex<Option<fs::File>>,
|
||||||
|
type_: FileType,
|
||||||
fs: Arc<HostFS>,
|
fs: Arc<HostFS>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ impl FileSystem for HostFS {
|
|||||||
Arc::new(HNode {
|
Arc::new(HNode {
|
||||||
path: self.path.clone(),
|
path: self.path.clone(),
|
||||||
file: Mutex::new(None),
|
file: Mutex::new(None),
|
||||||
|
type_: FileType::Dir,
|
||||||
fs: self.self_ref.upgrade().unwrap(),
|
fs: self.self_ref.upgrade().unwrap(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -76,32 +78,32 @@ macro_rules! try_std {
|
|||||||
|
|
||||||
impl INode for HNode {
|
impl INode for HNode {
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
if !self.path.is_file() {
|
if !self.is_file() {
|
||||||
return Err(FsError::NotFile);
|
return Err(FsError::NotFile);
|
||||||
}
|
}
|
||||||
let mut guard = self.open_file()?;
|
let mut guard = self.open_file()?;
|
||||||
let file = guard.as_mut().unwrap();
|
let file = guard.as_mut().unwrap();
|
||||||
try_std!(file.seek(SeekFrom::Start(offset as u64)));
|
let len = try_std!(file.read_at(buf, offset as u64));
|
||||||
let len = try_std!(file.read(buf));
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
if !self.path.is_file() {
|
if !self.is_file() {
|
||||||
return Err(FsError::NotFile);
|
return Err(FsError::NotFile);
|
||||||
}
|
}
|
||||||
let mut guard = self.open_file()?;
|
let mut guard = self.open_file()?;
|
||||||
let file = guard.as_mut().unwrap();
|
let file = guard.as_mut().unwrap();
|
||||||
try_std!(file.seek(SeekFrom::Start(offset as u64)));
|
let len = try_std!(file.write_at(buf, offset as u64));
|
||||||
let len = try_std!(file.write(buf));
|
|
||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&self) -> Result<PollStatus> {
|
fn poll(&self) -> Result<PollStatus> {
|
||||||
let metadata = try_std!(self.path.metadata());
|
if !self.is_file() {
|
||||||
if !metadata.is_file() {
|
|
||||||
return Err(FsError::NotFile);
|
return Err(FsError::NotFile);
|
||||||
}
|
}
|
||||||
|
let guard = self.open_file()?;
|
||||||
|
let file = guard.as_ref().unwrap();
|
||||||
|
let metadata = try_std!(file.metadata());
|
||||||
Ok(PollStatus {
|
Ok(PollStatus {
|
||||||
read: true,
|
read: true,
|
||||||
write: !metadata.permissions().readonly(),
|
write: !metadata.permissions().readonly(),
|
||||||
@ -110,7 +112,13 @@ impl INode for HNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Result<Metadata> {
|
fn metadata(&self) -> Result<Metadata> {
|
||||||
let metadata = try_std!(self.path.metadata());
|
let metadata = if self.is_file() {
|
||||||
|
let guard = self.open_file()?;
|
||||||
|
let file = guard.as_ref().unwrap();
|
||||||
|
try_std!(file.metadata())
|
||||||
|
} else {
|
||||||
|
try_std!(self.path.metadata())
|
||||||
|
};
|
||||||
Ok(metadata.into_fs_metadata())
|
Ok(metadata.into_fs_metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,9 +133,9 @@ impl INode for HNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sync_all(&self) -> Result<()> {
|
fn sync_all(&self) -> Result<()> {
|
||||||
if self.path.is_file() {
|
if self.is_file() {
|
||||||
let mut guard = self.open_file()?;
|
let guard = self.open_file()?;
|
||||||
let file = guard.as_mut().unwrap();
|
let file = guard.as_ref().unwrap();
|
||||||
try_std!(file.sync_all());
|
try_std!(file.sync_all());
|
||||||
} else {
|
} else {
|
||||||
warn!("no sync_all method about dir, do nothing");
|
warn!("no sync_all method about dir, do nothing");
|
||||||
@ -136,9 +144,9 @@ impl INode for HNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sync_data(&self) -> Result<()> {
|
fn sync_data(&self) -> Result<()> {
|
||||||
if self.path.is_file() {
|
if self.is_file() {
|
||||||
let mut guard = self.open_file()?;
|
let guard = self.open_file()?;
|
||||||
let file = guard.as_mut().unwrap();
|
let file = guard.as_ref().unwrap();
|
||||||
try_std!(file.sync_data());
|
try_std!(file.sync_data());
|
||||||
} else {
|
} else {
|
||||||
warn!("no sync_data method about dir, do nothing");
|
warn!("no sync_data method about dir, do nothing");
|
||||||
@ -147,11 +155,11 @@ impl INode for HNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, len: usize) -> Result<()> {
|
fn resize(&self, len: usize) -> Result<()> {
|
||||||
if !self.path.is_file() {
|
if !self.is_file() {
|
||||||
return Err(FsError::NotFile);
|
return Err(FsError::NotFile);
|
||||||
}
|
}
|
||||||
let mut guard = self.open_file()?;
|
let guard = self.open_file()?;
|
||||||
let file = guard.as_mut().unwrap();
|
let file = guard.as_ref().unwrap();
|
||||||
try_std!(file.set_len(len as u64));
|
try_std!(file.set_len(len as u64));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -162,23 +170,32 @@ impl INode for HNode {
|
|||||||
return Err(FsError::EntryExist);
|
return Err(FsError::EntryExist);
|
||||||
}
|
}
|
||||||
let perms = fs::Permissions::from_mode(mode as u32);
|
let perms = fs::Permissions::from_mode(mode as u32);
|
||||||
match type_ {
|
let file = match type_ {
|
||||||
FileType::File => {
|
FileType::File => {
|
||||||
let file = try_std!(fs::File::create(&new_path));
|
let file = try_std!(fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(&new_path));
|
||||||
try_std!(file.set_permissions(perms));
|
try_std!(file.set_permissions(perms));
|
||||||
|
Some(file)
|
||||||
}
|
}
|
||||||
FileType::Dir => {
|
FileType::Dir => {
|
||||||
try_std!(fs::create_dir(&new_path));
|
try_std!(fs::create_dir(&new_path));
|
||||||
try_std!(fs::set_permissions(&new_path, perms));
|
try_std!(fs::set_permissions(&new_path, perms));
|
||||||
|
None
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
warn!("only support creating regular file or directory in HostFS");
|
warn!("only support creating regular file or directory in HostFS");
|
||||||
return Err(FsError::PermError);
|
return Err(FsError::PermError);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Ok(Arc::new(HNode {
|
Ok(Arc::new(HNode {
|
||||||
path: new_path,
|
path: new_path,
|
||||||
file: Mutex::new(None),
|
file: Mutex::new(file),
|
||||||
|
type_,
|
||||||
fs: self.fs.clone(),
|
fs: self.fs.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -213,18 +230,27 @@ impl INode for HNode {
|
|||||||
|
|
||||||
fn find(&self, name: &str) -> Result<Arc<dyn INode>> {
|
fn find(&self, name: &str) -> Result<Arc<dyn INode>> {
|
||||||
let new_path = self.path.join(name);
|
let new_path = self.path.join(name);
|
||||||
if !new_path.exists() {
|
let metadata = fs::metadata(&new_path).map_err(|_| FsError::EntryNotFound)?;
|
||||||
return Err(FsError::EntryNotFound);
|
let file = if metadata.is_file() {
|
||||||
}
|
try_std!(fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(&new_path)
|
||||||
|
.map(Some))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Arc::new(HNode {
|
Ok(Arc::new(HNode {
|
||||||
path: new_path,
|
path: new_path,
|
||||||
file: Mutex::new(None),
|
file: Mutex::new(file),
|
||||||
|
type_: metadata.file_type().into_fs_filetype(),
|
||||||
fs: self.fs.clone(),
|
fs: self.fs.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entry(&self, id: usize) -> Result<String> {
|
fn get_entry(&self, id: usize) -> Result<String> {
|
||||||
if !self.path.is_dir() {
|
if !self.is_dir() {
|
||||||
return Err(FsError::NotDir);
|
return Err(FsError::NotDir);
|
||||||
}
|
}
|
||||||
if let Some(entry) = try_std!(self.path.read_dir()).nth(id) {
|
if let Some(entry) = try_std!(self.path.read_dir()).nth(id) {
|
||||||
@ -238,7 +264,7 @@ impl INode for HNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, ctx: &mut DirentWriterContext) -> Result<usize> {
|
fn iterate_entries(&self, ctx: &mut DirentWriterContext) -> Result<usize> {
|
||||||
if !self.path.is_dir() {
|
if !self.is_dir() {
|
||||||
return Err(FsError::NotDir);
|
return Err(FsError::NotDir);
|
||||||
}
|
}
|
||||||
let idx = ctx.pos();
|
let idx = ctx.pos();
|
||||||
@ -288,20 +314,26 @@ impl HNode {
|
|||||||
/// Ensure to open the file and store a `File` into `self.file`,
|
/// Ensure to open the file and store a `File` into `self.file`,
|
||||||
/// return the `MutexGuard`.
|
/// return the `MutexGuard`.
|
||||||
fn open_file(&self) -> Result<MutexGuard<Option<fs::File>>> {
|
fn open_file(&self) -> Result<MutexGuard<Option<fs::File>>> {
|
||||||
if !self.path.exists() {
|
|
||||||
return Err(FsError::EntryNotFound);
|
|
||||||
}
|
|
||||||
let mut maybe_file = self.file.lock().unwrap();
|
let mut maybe_file = self.file.lock().unwrap();
|
||||||
if maybe_file.is_none() {
|
if maybe_file.is_none() {
|
||||||
let file = try_std!(fs::OpenOptions::new()
|
let file = try_std!(fs::OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
|
||||||
.open(&self.path));
|
.open(&self.path));
|
||||||
*maybe_file = Some(file);
|
*maybe_file = Some(file);
|
||||||
}
|
}
|
||||||
Ok(maybe_file)
|
Ok(maybe_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if this HNode is for a regular file.
|
||||||
|
fn is_file(&self) -> bool {
|
||||||
|
self.type_ == FileType::File
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if this HNode is for a directory.
|
||||||
|
fn is_dir(&self) -> bool {
|
||||||
|
self.type_ == FileType::Dir
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IntoFsError {
|
trait IntoFsError {
|
||||||
|
@ -114,12 +114,21 @@ pub fn mount_nonroot_fs_according_to(
|
|||||||
mount_fs_at(sefs, root, &mc.target, follow_symlink)?;
|
mount_fs_at(sefs, root, &mc.target, follow_symlink)?;
|
||||||
}
|
}
|
||||||
TYPE_HOSTFS => {
|
TYPE_HOSTFS => {
|
||||||
if mc.source.is_none() {
|
let source_path =
|
||||||
|
mc.source.as_ref().and_then(
|
||||||
|
|source| {
|
||||||
|
if source.is_dir() {
|
||||||
|
Some(source)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if source_path.is_none() {
|
||||||
return_errno!(EINVAL, "Source is expected for HostFS");
|
return_errno!(EINVAL, "Source is expected for HostFS");
|
||||||
}
|
}
|
||||||
let source_path = mc.source.as_ref().unwrap();
|
|
||||||
|
|
||||||
let hostfs = HostFS::new(source_path);
|
let hostfs = HostFS::new(source_path.unwrap());
|
||||||
mount_fs_at(hostfs, root, &mc.target, follow_symlink)?;
|
mount_fs_at(hostfs, root, &mc.target, follow_symlink)?;
|
||||||
}
|
}
|
||||||
TYPE_RAMFS => {
|
TYPE_RAMFS => {
|
||||||
|
Loading…
Reference in New Issue
Block a user