Skip to content
This repository has been archived by the owner on Oct 13, 2023. It is now read-only.

Implement sync and datasync on files and directories. #58

Merged
merged 1 commit into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions host/src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,24 @@ impl wasi_filesystem::WasiFilesystem for WasiCtx {
&mut self,
fd: wasi_filesystem::Descriptor,
) -> HostResult<(), wasi_filesystem::Errno> {
todo!()
let table = self.table();
if table.is::<Box<dyn WasiFile>>(fd) {
Ok(Ok(table
.get_file(fd)
.map_err(convert)?
.datasync()
.await
.map_err(convert)?))
} else if table.is::<Box<dyn WasiDir>>(fd) {
Ok(Ok(table
.get_dir(fd)
.map_err(convert)?
.datasync()
.await
.map_err(convert)?))
} else {
Err(wasi_filesystem::Errno::Badf.into())
}
}

async fn flags(
Expand Down Expand Up @@ -382,7 +399,24 @@ impl wasi_filesystem::WasiFilesystem for WasiCtx {
&mut self,
fd: wasi_filesystem::Descriptor,
) -> HostResult<(), wasi_filesystem::Errno> {
todo!()
let table = self.table();
if table.is::<Box<dyn WasiFile>>(fd) {
Ok(Ok(table
.get_file(fd)
.map_err(convert)?
.sync()
.await
.map_err(convert)?))
} else if table.is::<Box<dyn WasiDir>>(fd) {
Ok(Ok(table
.get_dir(fd)
.map_err(convert)?
.sync()
.await
.map_err(convert)?))
} else {
Err(wasi_filesystem::Errno::Badf.into())
}
}

async fn create_directory_at(
Expand Down
25 changes: 25 additions & 0 deletions host/tests/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,31 @@ async fn run_file_append(mut store: Store<WasiCtx>, wasi: Wasi) -> Result<()> {
Ok(())
}

async fn run_file_dir_sync(mut store: Store<WasiCtx>, wasi: Wasi) -> Result<()> {
let dir = tempfile::tempdir()?;

std::fs::File::create(dir.path().join("bar.txt"))?
.write_all(b"'Twas brillig, and the slithy toves.\n")?;

let descriptor =
store
.data_mut()
.push_dir(Box::new(wasi_cap_std_sync::dir::Dir::from_cap_std(
Dir::from_std_file(std::fs::File::open(dir.path())?),
)))?;

wasi.command(
&mut store,
0 as host::Descriptor,
1 as host::Descriptor,
&[],
&[],
&[(descriptor, "/")],
)
.await?
.map_err(|()| anyhow::anyhow!("command returned with failing exit status"))
}

async fn run_exit_success(mut store: Store<WasiCtx>, wasi: Wasi) -> Result<()> {
let r = wasi
.command(
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,14 +847,14 @@ pub unsafe extern "C" fn fd_readdir(
let dir = state.get_dir(fd)?;
iter = DirEntryIterator {
state,
cookie: 0,
cookie: wasi::DIRCOOKIE_START,
use_cache: false,
stream: DirEntryStream(wasi_filesystem::readdir(dir.fd)?),
};

// Skip to the entry that is requested by the `cookie`
// parameter.
for _ in 0..cookie {
for _ in wasi::DIRCOOKIE_START..cookie {
match iter.next() {
Some(Ok(_)) => {}
Some(Err(e)) => return Err(e),
Expand Down Expand Up @@ -2205,7 +2205,7 @@ impl State {
dirent_cache: DirentCache {
stream: Cell::new(None),
for_fd: Cell::new(0),
cookie: Cell::new(0),
cookie: Cell::new(wasi::DIRCOOKIE_START),
cached_dirent: Cell::new(wasi::Dirent {
d_next: 0,
d_ino: 0,
Expand Down
11 changes: 11 additions & 0 deletions test-programs/src/bin/file_dir_sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn main() -> std::io::Result<()> {
let file = std::fs::File::open("bar.txt")?;
file.sync_all()?;
file.sync_data()?;

let dir = std::fs::File::open(".")?;
dir.sync_all()?;
dir.sync_data()?;

Ok(())
}
41 changes: 36 additions & 5 deletions wasi-common/cap-std-sync/src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,6 @@ impl Dir {
Ok(File::from_cap_std(f))
}

pub fn get_fdflags(&self) -> Result<FdFlags, Error> {
let fdflags = get_fd_flags(&self.0)?;
Ok(fdflags)
}

pub fn open_dir_(&self, symlink_follow: bool, path: &str) -> Result<Self, Error> {
let d = if symlink_follow {
self.0.open_dir(Path::new(path))?
Expand Down Expand Up @@ -135,6 +130,42 @@ impl WasiDir for Dir {
Ok(Box::new(d))
}

async fn datasync(&self) -> Result<(), Error> {
#[cfg(unix)]
{
// We open directories with `O_PATH` which doesn't permit us to
// sync the handle we have, so we open `.` to get a new one.
Ok(self.0.open(std::path::Component::CurDir)?.sync_data()?)
}

#[cfg(windows)]
{
// Windows doesn't have any concept of ensuring that directory
// entries are sync'd. See
// https://github.com/WebAssembly/wasi-filesystem/issues/79
Ok(())
}
}

async fn sync(&self) -> Result<(), Error> {
#[cfg(unix)]
{
// As above, open `.` to get a new handle.
Ok(self.0.open(std::path::Component::CurDir)?.sync_all()?)
}

#[cfg(windows)]
{
// As above, see above.
Ok(())
}
}

async fn get_fdflags(&self) -> Result<FdFlags, Error> {
let fdflags = get_fd_flags(&self.0)?;
Ok(fdflags)
}

async fn create_dir(&self, path: &str) -> Result<(), Error> {
self.0.create_dir(Path::new(path))?;
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions wasi-common/cap-std-sync/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ impl WasiFile for File {
Ok(Box::new(Self(clone)))
}

async fn datasync(&mut self) -> Result<(), Error> {
async fn datasync(&self) -> Result<(), Error> {
self.0.sync_data()?;
Ok(())
}
async fn sync(&mut self) -> Result<(), Error> {
async fn sync(&self) -> Result<(), Error> {
self.0.sync_all()?;
Ok(())
}
Expand Down
4 changes: 4 additions & 0 deletions wasi-common/src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ pub trait WasiDir: Send + Sync {
Err(Error::not_supported())
}

async fn datasync(&self) -> Result<(), Error>;

async fn sync(&self) -> Result<(), Error>;

async fn get_fdflags(&self) -> Result<FdFlags, Error> {
Ok(FdFlags::empty())
}
Expand Down
8 changes: 2 additions & 6 deletions wasi-common/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ pub trait WasiFile: Send + Sync {
Err(Error::badf())
}

async fn datasync(&mut self) -> Result<(), Error> {
Ok(())
}
async fn datasync(&self) -> Result<(), Error>;

async fn sync(&mut self) -> Result<(), Error> {
Ok(())
}
async fn sync(&self) -> Result<(), Error>;

async fn get_fdflags(&self) -> Result<FdFlags, Error> {
Ok(FdFlags::empty())
Expand Down
4 changes: 2 additions & 2 deletions wasi-common/tokio/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ macro_rules! wasi_file_impl {
async fn try_clone(&mut self) -> Result<Box<dyn WasiFile>, Error> {
block_on_dummy_executor(|| self.0.try_clone())
}
async fn datasync(&mut self) -> Result<(), Error> {
async fn datasync(&self) -> Result<(), Error> {
block_on_dummy_executor(|| self.0.datasync())
}
async fn sync(&mut self) -> Result<(), Error> {
async fn sync(&self) -> Result<(), Error> {
block_on_dummy_executor(|| self.0.sync())
}
async fn get_filetype(&mut self) -> Result<FileType, Error> {
Expand Down