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 env = ctx.data();
50                        let (_, mut state, inodes) =
51                            unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
52
53                        let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
54                        let inode = fd_entry.inode;
55                        let mut guard = inode.stat.write().unwrap();
56                        guard.st_size = size;
57                    }
58                } else {
59                    return Ok(Errno::Inval);
60                }
61            }
62            Kind::Root { .. } | Kind::Dir { .. } => return Ok(Errno::Isdir),
63            Kind::Buffer { .. }
64            | Kind::Symlink { .. }
65            | Kind::Socket { .. }
66            | Kind::PipeTx { .. }
67            | Kind::PipeRx { .. }
68            | Kind::DuplexPipe { .. }
69            | Kind::EventNotifications { .. }
70            | Kind::Epoll { .. } => return Ok(Errno::Inval),
71        }
72    }
73
74    Ok(Errno::Success)
75}