wasmer_wasix/syscalls/wasi/
fd_filestat_set_size.rs

1use super::*;
2use crate::syscalls::*;
3
4/// ### `fd_filestat_set_size()`
5/// Change the size of an open file, zeroing out any new bytes
6/// Inputs:
7/// - `Fd fd`
8///     File descriptor to adjust
9/// - `Filesize st_size`
10///     New size that `fd` will be set to
11#[instrument(level = "trace", skip_all, fields(%fd, %st_size), ret)]
12pub fn fd_filestat_set_size(
13    mut ctx: FunctionEnvMut<'_, WasiEnv>,
14    fd: WasiFd,
15    st_size: Filesize,
16) -> Result<Errno, WasiError> {
17    WasiEnv::do_pending_operations(&mut ctx)?;
18
19    wasi_try_ok!(fd_filestat_set_size_internal(&mut ctx, fd, st_size));
20    let env = ctx.data();
21
22    #[cfg(feature = "journal")]
23    if env.enable_journal {
24        JournalEffector::save_fd_set_size(&mut ctx, fd, st_size).map_err(|err| {
25            tracing::error!("failed to save file set size event - {}", err);
26            WasiError::Exit(ExitCode::from(Errno::Fault))
27        })?;
28    }
29
30    Ok(Errno::Success)
31}
32
33pub(crate) fn fd_filestat_set_size_internal(
34    ctx: &mut FunctionEnvMut<'_, WasiEnv>,
35    fd: WasiFd,
36    st_size: Filesize,
37) -> Result<(), Errno> {
38    let env = ctx.data();
39    let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
40    let fd_entry = state.fs.get_fd(fd)?;
41    let inode = fd_entry.inode;
42
43    if !fd_entry.inner.rights.contains(Rights::FD_FILESTAT_SET_SIZE) {
44        return Err(Errno::Access);
45    }
46
47    {
48        let mut guard = inode.write();
49        match guard.deref_mut() {
50            Kind::File { handle, .. } => {
51                if let Some(handle) = handle {
52                    let mut handle = handle.write().unwrap();
53                    handle.set_len(st_size).map_err(fs_error_into_wasi_err)?;
54                } else {
55                    return Err(Errno::Badf);
56                }
57            }
58            Kind::Buffer { buffer } => {
59                buffer.resize(st_size as usize, 0);
60            }
61            Kind::Socket { .. }
62            | Kind::PipeRx { .. }
63            | Kind::PipeTx { .. }
64            | Kind::DuplexPipe { .. }
65            | Kind::Symlink { .. }
66            | Kind::EventNotifications { .. }
67            | Kind::Epoll { .. } => return Err(Errno::Badf),
68            Kind::Dir { .. } | Kind::Root { .. } => return Err(Errno::Isdir),
69        }
70    }
71    inode.stat.write().unwrap().st_size = st_size;
72
73    Ok(())
74}