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