wasmer_wasix/syscalls/wasi/fd_sync.rs
1use super::*;
2use crate::syscalls::*;
3
4/// ### `fd_sync()`
5/// Synchronize file and metadata to disk (TODO: expand upon what this means in our system)
6/// Inputs:
7/// - `Fd fd`
8/// The file descriptor to sync
9/// Errors:
10/// TODO: figure out which errors this should return
11/// - `Errno::Perm`
12/// - `Errno::Notcapable`
13#[instrument(level = "trace", skip_all, fields(%fd), ret)]
14pub fn fd_sync(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errno, WasiError> {
15 WasiEnv::do_pending_operations(&mut ctx)?;
16
17 let env = ctx.data();
18 let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
19 let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
20 if !fd_entry.inner.rights.contains(Rights::FD_SYNC) {
21 return Ok(Errno::Access);
22 }
23 let inode = fd_entry.inode;
24
25 // TODO: implement this for more than files
26 {
27 let mut guard = inode.write();
28 match guard.deref_mut() {
29 Kind::File { handle, .. } => {
30 if let Some(handle) = handle {
31 let handle = handle.clone();
32 drop(guard);
33
34 // TODO: remove allow once inodes are refactored (see comments on [`WasiState`])
35 #[allow(clippy::await_holding_lock)]
36 let size = {
37 wasi_try_ok!(__asyncify(&mut ctx, None, async move {
38 // TODO: remove allow once inodes are refactored (see comments on [`WasiState`])
39 #[allow(clippy::await_holding_lock)]
40 let mut handle = handle.write().unwrap();
41 handle.flush().await.map_err(map_io_err)?;
42 Ok(handle.size())
43 })?)
44 };
45
46 // Update FileStat to reflect the correct current size.
47 // TODO: don't lock twice - currently needed to not keep a lock on all inodes
48 {
49 let mut guard = inode.stat.write().unwrap();
50 guard.st_size = size;
51 }
52 } else {
53 return Ok(Errno::Inval);
54 }
55 }
56 Kind::Root { .. } | Kind::Dir { .. } => return Ok(Errno::Isdir),
57 // Linux fsync(2) returns EINVAL for fds "bound to a special file
58 // (e.g., a pipe, FIFO, or socket) which does not support
59 // synchronization.", mirror that behaviour
60 Kind::Buffer { .. }
61 | Kind::Symlink { .. }
62 | Kind::Socket { .. }
63 | Kind::PipeTx { .. }
64 | Kind::PipeRx { .. }
65 | Kind::DuplexPipe { .. }
66 | Kind::EventNotifications { .. }
67 | Kind::Epoll { .. } => return Ok(Errno::Inval),
68 }
69 }
70
71 Ok(Errno::Success)
72}