get a FileStat of a Dir
and fill out some remaining DirCaps from Rights
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::file::{FileCaps, FileType, OFlags, WasiFile};
|
use crate::file::{FileCaps, FileType, Filestat, OFlags, WasiFile};
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ pub trait WasiDir {
|
|||||||
fn remove_dir(&self, path: &str) -> Result<(), Error>;
|
fn remove_dir(&self, path: &str) -> Result<(), Error>;
|
||||||
fn unlink_file(&self, path: &str) -> Result<(), Error>;
|
fn unlink_file(&self, path: &str) -> Result<(), Error>;
|
||||||
fn read_link(&self, path: &str) -> Result<PathBuf, Error>;
|
fn read_link(&self, path: &str) -> Result<PathBuf, Error>;
|
||||||
|
fn get_filestat(&self) -> Result<Filestat, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct DirEntry {
|
pub(crate) struct DirEntry {
|
||||||
@@ -69,8 +71,8 @@ impl DirEntry {
|
|||||||
pub fn child_file_caps(&self, desired_caps: FileCaps) -> FileCaps {
|
pub fn child_file_caps(&self, desired_caps: FileCaps) -> FileCaps {
|
||||||
self.file_caps.intersection(&desired_caps)
|
self.file_caps.intersection(&desired_caps)
|
||||||
}
|
}
|
||||||
pub fn get_dirstat(&self) -> DirStat {
|
pub fn get_dir_fdstat(&self) -> DirFdStat {
|
||||||
DirStat {
|
DirFdStat {
|
||||||
dir_caps: self.caps,
|
dir_caps: self.caps,
|
||||||
file_caps: self.file_caps,
|
file_caps: self.file_caps,
|
||||||
}
|
}
|
||||||
@@ -113,16 +115,15 @@ impl DirCaps {
|
|||||||
pub const SYMLINK: Self = DirCaps { flags: 512 };
|
pub const SYMLINK: Self = DirCaps { flags: 512 };
|
||||||
pub const REMOVE_DIRECTORY: Self = DirCaps { flags: 1024 };
|
pub const REMOVE_DIRECTORY: Self = DirCaps { flags: 1024 };
|
||||||
pub const UNLINK_FILE: Self = DirCaps { flags: 2048 };
|
pub const UNLINK_FILE: Self = DirCaps { flags: 2048 };
|
||||||
|
pub const PATH_FILESTAT_GET: Self = DirCaps { flags: 4096 };
|
||||||
|
pub const PATH_FILESTAT_SET_TIMES: Self = DirCaps { flags: 8192 };
|
||||||
|
pub const FILESTAT_GET: Self = DirCaps { flags: 16384 };
|
||||||
|
pub const FILESTAT_SET_TIMES: Self = DirCaps { flags: 32768 };
|
||||||
|
|
||||||
// Missing that are in wasi-common directory_base:
|
// Missing that are in wasi-common directory_base:
|
||||||
// FD_FDSTAT_SET_FLAGS
|
// FD_FDSTAT_SET_FLAGS
|
||||||
// FD_SYNC
|
// FD_SYNC
|
||||||
// FD_ADVISE
|
// FD_ADVISE
|
||||||
// PATH_FILESTAT_GET
|
|
||||||
// PATH_FILESTAT_SET_SIZE
|
|
||||||
// PATH_FILESTAT_SET_TIMES
|
|
||||||
// FD_FILESTAT_GET
|
|
||||||
// FD_FILESTAT_SET_TIMES
|
|
||||||
|
|
||||||
pub fn all() -> DirCaps {
|
pub fn all() -> DirCaps {
|
||||||
Self::CREATE_DIRECTORY
|
Self::CREATE_DIRECTORY
|
||||||
@@ -137,6 +138,10 @@ impl DirCaps {
|
|||||||
| Self::SYMLINK
|
| Self::SYMLINK
|
||||||
| Self::REMOVE_DIRECTORY
|
| Self::REMOVE_DIRECTORY
|
||||||
| Self::UNLINK_FILE
|
| Self::UNLINK_FILE
|
||||||
|
| Self::PATH_FILESTAT_GET
|
||||||
|
| Self::PATH_FILESTAT_SET_TIMES
|
||||||
|
| Self::FILESTAT_GET
|
||||||
|
| Self::FILESTAT_SET_TIMES
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +154,7 @@ impl std::ops::BitOr for DirCaps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DirStat {
|
pub struct DirFdStat {
|
||||||
pub file_caps: FileCaps,
|
pub file_caps: FileCaps,
|
||||||
pub dir_caps: DirCaps,
|
pub dir_caps: DirCaps,
|
||||||
}
|
}
|
||||||
@@ -290,4 +295,18 @@ impl WasiDir for cap_std::fs::Dir {
|
|||||||
let link = self.read_link(Path::new(path))?;
|
let link = self.read_link(Path::new(path))?;
|
||||||
Ok(link)
|
Ok(link)
|
||||||
}
|
}
|
||||||
|
fn get_filestat(&self) -> Result<Filestat, Error> {
|
||||||
|
let meta = self.metadata(".")?;
|
||||||
|
use cap_fs_ext::MetadataExt;
|
||||||
|
Ok(Filestat {
|
||||||
|
device_id: meta.dev(),
|
||||||
|
inode: meta.ino(),
|
||||||
|
filetype: FileType::from(&meta.file_type()),
|
||||||
|
nlink: meta.nlink(),
|
||||||
|
size: meta.len(),
|
||||||
|
atim: meta.accessed().map(|t| Some(t.into_std())).unwrap_or(None),
|
||||||
|
mtim: meta.modified().map(|t| Some(t.into_std())).unwrap_or(None),
|
||||||
|
ctim: meta.created().map(|t| Some(t.into_std())).unwrap_or(None),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
use crate::dir::{DirCaps, DirEntry, DirStat, ReaddirCursor, TableDirExt};
|
use crate::dir::{DirCaps, DirEntry, DirFdStat, ReaddirCursor, ReaddirEntity, TableDirExt};
|
||||||
use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, FileType, Filestat, OFlags};
|
use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, FileType, Filestat, OFlags};
|
||||||
use crate::{Error, WasiCtx};
|
use crate::{Error, WasiCtx};
|
||||||
use fs_set_times::SystemTimeSpec;
|
use fs_set_times::SystemTimeSpec;
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
use std::convert::TryFrom;
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::io::{IoSlice, IoSliceMut};
|
use std::io::{IoSlice, IoSliceMut};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
@@ -228,8 +228,8 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
Ok(types::Fdstat::from(&fdstat))
|
Ok(types::Fdstat::from(&fdstat))
|
||||||
} else if table.is::<DirEntry>(fd) {
|
} else if table.is::<DirEntry>(fd) {
|
||||||
let dir_entry: Ref<DirEntry> = table.get(fd)?;
|
let dir_entry: Ref<DirEntry> = table.get(fd)?;
|
||||||
let dirstat = dir_entry.get_dirstat();
|
let dir_fdstat = dir_entry.get_dir_fdstat();
|
||||||
Ok(types::Fdstat::from(&dirstat))
|
Ok(types::Fdstat::from(&dir_fdstat))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::Badf)
|
Err(Error::Badf)
|
||||||
}
|
}
|
||||||
@@ -267,10 +267,20 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
|
|
||||||
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
|
fn fd_filestat_get(&self, fd: types::Fd) -> Result<types::Filestat, Error> {
|
||||||
let table = self.table();
|
let table = self.table();
|
||||||
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
|
let fd = u32::from(fd);
|
||||||
let f = file_entry.get_cap(FileCaps::FILESTAT_GET)?;
|
if table.is::<FileEntry>(fd) {
|
||||||
let filestat = f.get_filestat()?;
|
let file_entry: Ref<FileEntry> = table.get(fd)?;
|
||||||
Ok(filestat.into())
|
let f = file_entry.get_cap(FileCaps::FILESTAT_GET)?;
|
||||||
|
let filestat = f.get_filestat()?;
|
||||||
|
Ok(filestat.into())
|
||||||
|
} else if table.is::<DirEntry>(fd) {
|
||||||
|
let dir_entry: Ref<DirEntry> = table.get(fd)?;
|
||||||
|
let d = dir_entry.get_cap(DirCaps::FILESTAT_GET)?;
|
||||||
|
let filestat = d.get_filestat()?;
|
||||||
|
Ok(filestat.into())
|
||||||
|
} else {
|
||||||
|
Err(Error::Badf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> {
|
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> {
|
||||||
@@ -289,10 +299,6 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
fst_flags: types::Fstflags,
|
fst_flags: types::Fstflags,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
let table = self.table();
|
|
||||||
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
|
|
||||||
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_TIMES)?;
|
|
||||||
|
|
||||||
// Validate flags, transform into well-structured arguments
|
// Validate flags, transform into well-structured arguments
|
||||||
let set_atim = fst_flags.contains(&types::Fstflags::ATIM);
|
let set_atim = fst_flags.contains(&types::Fstflags::ATIM);
|
||||||
let set_atim_now = fst_flags.contains(&types::Fstflags::ATIM_NOW);
|
let set_atim_now = fst_flags.contains(&types::Fstflags::ATIM_NOW);
|
||||||
@@ -320,8 +326,20 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
f.set_times(atim, mtim)?;
|
let fd = u32::from(fd);
|
||||||
Ok(())
|
let table = self.table();
|
||||||
|
if table.is::<FileEntry>(fd) {
|
||||||
|
let file_entry: Ref<FileEntry> = table.get(fd).unwrap();
|
||||||
|
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_TIMES)?;
|
||||||
|
f.set_times(atim, mtim)?;
|
||||||
|
Ok(())
|
||||||
|
} else if table.is::<DirEntry>(fd) {
|
||||||
|
let dir_entry: Ref<DirEntry> = table.get(fd).unwrap();
|
||||||
|
let d = dir_entry.get_cap(DirCaps::FILESTAT_SET_TIMES)?;
|
||||||
|
todo!("d.set_times(atim, mtim)?;")
|
||||||
|
} else {
|
||||||
|
Err(Error::Badf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> {
|
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> {
|
||||||
@@ -560,7 +578,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
flags: types::Lookupflags,
|
flags: types::Lookupflags,
|
||||||
path: &GuestPtr<'_, str>,
|
path: &GuestPtr<'_, str>,
|
||||||
) -> Result<types::Filestat, Error> {
|
) -> Result<types::Filestat, Error> {
|
||||||
unimplemented!()
|
let table = self.table();
|
||||||
|
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
|
||||||
|
let dir = dir_entry.get_cap(DirCaps::PATH_FILESTAT_GET)?;
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_filestat_set_times(
|
fn path_filestat_set_times(
|
||||||
@@ -572,7 +593,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
|
|||||||
mtim: types::Timestamp,
|
mtim: types::Timestamp,
|
||||||
fst_flags: types::Fstflags,
|
fst_flags: types::Fstflags,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
unimplemented!()
|
let table = self.table();
|
||||||
|
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
|
||||||
|
let dir = dir_entry.get_cap(DirCaps::PATH_FILESTAT_SET_TIMES)?;
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_link(
|
fn path_link(
|
||||||
@@ -781,8 +805,8 @@ impl From<&FdStat> for types::Fdstat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&DirStat> for types::Fdstat {
|
impl From<&DirFdStat> for types::Fdstat {
|
||||||
fn from(dirstat: &DirStat) -> types::Fdstat {
|
fn from(dirstat: &DirFdStat) -> types::Fdstat {
|
||||||
let fs_rights_base = types::Rights::from(&dirstat.dir_caps);
|
let fs_rights_base = types::Rights::from(&dirstat.dir_caps);
|
||||||
let fs_rights_inheriting = types::Rights::from(&dirstat.file_caps);
|
let fs_rights_inheriting = types::Rights::from(&dirstat.file_caps);
|
||||||
types::Fdstat {
|
types::Fdstat {
|
||||||
@@ -922,6 +946,18 @@ impl From<&DirCaps> for types::Rights {
|
|||||||
if caps.contains(&DirCaps::UNLINK_FILE) {
|
if caps.contains(&DirCaps::UNLINK_FILE) {
|
||||||
rights = rights | types::Rights::PATH_UNLINK_FILE;
|
rights = rights | types::Rights::PATH_UNLINK_FILE;
|
||||||
}
|
}
|
||||||
|
if caps.contains(&DirCaps::PATH_FILESTAT_GET) {
|
||||||
|
rights = rights | types::Rights::PATH_FILESTAT_GET;
|
||||||
|
}
|
||||||
|
if caps.contains(&DirCaps::PATH_FILESTAT_SET_TIMES) {
|
||||||
|
rights = rights | types::Rights::PATH_FILESTAT_SET_TIMES;
|
||||||
|
}
|
||||||
|
if caps.contains(&DirCaps::FILESTAT_GET) {
|
||||||
|
rights = rights | types::Rights::FD_FILESTAT_GET;
|
||||||
|
}
|
||||||
|
if caps.contains(&DirCaps::FILESTAT_SET_TIMES) {
|
||||||
|
rights = rights | types::Rights::FD_FILESTAT_SET_TIMES;
|
||||||
|
}
|
||||||
rights
|
rights
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -966,6 +1002,18 @@ impl From<&types::Rights> for DirCaps {
|
|||||||
if rights.contains(&types::Rights::PATH_UNLINK_FILE) {
|
if rights.contains(&types::Rights::PATH_UNLINK_FILE) {
|
||||||
caps = caps | DirCaps::UNLINK_FILE;
|
caps = caps | DirCaps::UNLINK_FILE;
|
||||||
}
|
}
|
||||||
|
if rights.contains(&types::Rights::PATH_FILESTAT_GET) {
|
||||||
|
caps = caps | DirCaps::PATH_FILESTAT_GET;
|
||||||
|
}
|
||||||
|
if rights.contains(&types::Rights::PATH_FILESTAT_SET_TIMES) {
|
||||||
|
caps = caps | DirCaps::PATH_FILESTAT_SET_TIMES;
|
||||||
|
}
|
||||||
|
if rights.contains(&types::Rights::FD_FILESTAT_GET) {
|
||||||
|
caps = caps | DirCaps::FILESTAT_GET;
|
||||||
|
}
|
||||||
|
if rights.contains(&types::Rights::FD_FILESTAT_SET_TIMES) {
|
||||||
|
caps = caps | DirCaps::FILESTAT_SET_TIMES;
|
||||||
|
}
|
||||||
caps
|
caps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user