filestat ops

This commit is contained in:
Pat Hickey
2020-12-01 11:57:24 -08:00
parent 52035f51ee
commit beaad53dc0
3 changed files with 115 additions and 9 deletions

View File

@@ -104,6 +104,10 @@ pub enum Error {
/// Errno::Spipe: Invalid seek
#[error("Spipe: Invalid seek")]
Spipe,
/// Errno::NotCapable: Not capable
#[error("Not capable")]
NotCapable,
}
impl From<std::convert::Infallible> for Error {

View File

@@ -18,6 +18,19 @@ pub trait WasiFile: FileIoExt {
fn set_oflags(&self, _flags: OFlags) -> Result<(), Error> {
todo!("FileIoExt has no facilities for oflags");
}
fn filestat_get(&self) -> Result<Filestat, Error> {
todo!()
}
fn filestat_set_times(
&self,
_atim: Option<FilestatSetTime>,
_mtim: Option<FilestatSetTime>,
) -> Result<(), Error> {
todo!()
}
fn filestat_set_size(&self, _size: u64) -> Result<(), Error> {
todo!()
}
}
#[derive(Debug, Copy, Clone)]
@@ -53,6 +66,24 @@ impl OFlags {
// etc
}
#[derive(Debug, Clone)]
pub struct Filestat {
device_id: u64,
inode: u64,
filetype: Filetype,
nlink: u64,
size: usize,
atim: std::time::SystemTime,
mtim: std::time::SystemTime,
ctim: std::time::SystemTime,
}
#[derive(Debug, Copy, Clone)]
pub enum FilestatSetTime {
Now,
Absolute(std::time::SystemTime),
}
pub(crate) struct FileEntry {
pub(crate) base_caps: FileCaps,
pub(crate) inheriting_caps: FileCaps,
@@ -93,10 +124,13 @@ impl FileCaps {
pub const WRITE: Self = FileCaps { flags: 64 };
pub const ADVISE: Self = FileCaps { flags: 128 };
pub const ALLOCATE: Self = FileCaps { flags: 256 };
pub const FILESTAT_GET: Self = FileCaps { flags: 512 };
pub const FILESTAT_SET_SIZE: Self = FileCaps { flags: 1024 };
pub const FILESTAT_SET_TIMES: Self = FileCaps { flags: 2048 };
// This isnt in wasi-common, but lets use a cap to check
// if its valid to close a file, rather than depend on
// preopen logic
pub const CLOSE: Self = FileCaps { flags: 512 };
pub const CLOSE: Self = FileCaps { flags: 4096 };
}
impl std::fmt::Display for FileCaps {

View File

@@ -1,5 +1,5 @@
#![allow(unused_variables)]
use crate::file::{FileCaps, FileEntry, Filetype, OFlags};
use crate::file::{FileCaps, FileEntry, Filestat, FilestatSetTime, Filetype, OFlags};
use crate::{Error, WasiCtx};
use std::cell::RefMut;
use std::convert::TryFrom;
@@ -27,9 +27,9 @@ impl types::GuestErrorConversion for WasiCtx {
}
impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&self, e: Error) -> types::Errno {
fn errno_from_error(&self, e: Error) -> Result<types::Errno, String> {
debug!("Error: {:?}", e);
e.into()
Ok(e.into())
}
}
@@ -69,6 +69,7 @@ impl From<Error> for types::Errno {
Error::Perm => Errno::Perm,
Error::Spipe => Errno::Spipe,
Error::FileNotCapable { .. } => Errno::Notcapable,
Error::NotCapable => Errno::Notcapable,
}
}
}
@@ -185,7 +186,6 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FDSTAT_SET_FLAGS)?;
f.set_oflags(OFlags::try_from(flags)?)?;
Ok(())
}
@@ -196,15 +196,35 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fs_rights_base: types::Rights,
fs_rights_inheriting: types::Rights,
) -> Result<(), Error> {
unimplemented!()
let table = self.table();
let mut file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?;
let base_caps = FileCaps::try_from(&fs_rights_base)?;
let inheriting_caps = FileCaps::try_from(&fs_rights_inheriting)?;
if file_entry.base_caps.contains(&base_caps)
&& file_entry.inheriting_caps.contains(&inheriting_caps)
{
file_entry.base_caps = base_caps;
file_entry.inheriting_caps = inheriting_caps;
Ok(())
} else {
Err(Error::NotCapable)
}
}
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
unimplemented!()
let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FILESTAT_GET)?;
let filestat = f.filestat_get()?;
Ok(filestat.into())
}
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> {
unimplemented!()
let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_SIZE)?;
f.filestat_set_size(size)?;
Ok(())
}
fn fd_filestat_set_times(
@@ -214,7 +234,40 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
mtim: types::Timestamp,
fst_flags: types::Fstflags,
) -> Result<(), Error> {
unimplemented!()
use std::time::{Duration, UNIX_EPOCH};
let table = self.table();
let file_entry: RefMut<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_TIMES)?;
// Validate flags, transform into well-structured arguments
let set_atim = fst_flags.contains(&types::Fstflags::ATIM);
let set_atim_now = fst_flags.contains(&types::Fstflags::ATIM_NOW);
let set_mtim = fst_flags.contains(&types::Fstflags::MTIM);
let set_mtim_now = fst_flags.contains(&types::Fstflags::MTIM_NOW);
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::Inval);
}
let atim = if set_atim {
Some(FilestatSetTime::Absolute(
UNIX_EPOCH + Duration::from_nanos(atim),
))
} else if set_atim_now {
Some(FilestatSetTime::Now)
} else {
None
};
let mtim = if set_mtim {
Some(FilestatSetTime::Absolute(
UNIX_EPOCH + Duration::from_nanos(mtim),
))
} else if set_mtim_now {
Some(FilestatSetTime::Now)
} else {
None
};
f.filestat_set_times(atim, mtim)?;
Ok(())
}
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> {
@@ -457,12 +510,21 @@ impl From<&FileEntry> for types::Fdstat {
}
}
// FileCaps can always be represented as wasi Rights
impl From<&FileCaps> for types::Rights {
fn from(caps: &FileCaps) -> types::Rights {
todo!("translate FileCaps flags to Rights flags")
}
}
// FileCaps are a subset of wasi Rights - not all Rights have a valid representation as FileCaps
impl TryFrom<&types::Rights> for FileCaps {
type Error = Error;
fn try_from(rights: &types::Rights) -> Result<FileCaps, Self::Error> {
todo!("translate Rights flags to FileCaps flags")
}
}
impl From<&Filetype> for types::Filetype {
fn from(ft: &Filetype) -> types::Filetype {
match ft {
@@ -486,3 +548,9 @@ impl TryFrom<types::Fdflags> for OFlags {
todo!()
}
}
impl From<Filestat> for types::Filestat {
fn from(stat: Filestat) -> types::Filestat {
todo!()
}
}