wasmer_wasix/syscalls/wasi/
fd_allocate.rs1use super::*;
2use crate::syscalls::*;
3
4#[instrument(level = "trace", skip_all, fields(%fd, %offset, %len), ret)]
14pub fn fd_allocate(
15 mut ctx: FunctionEnvMut<'_, WasiEnv>,
16 fd: WasiFd,
17 offset: Filesize,
18 len: Filesize,
19) -> Result<Errno, WasiError> {
20 WasiEnv::do_pending_operations(&mut ctx)?;
21
22 wasi_try_ok!(fd_allocate_internal(&mut ctx, fd, offset, len));
23 let env = ctx.data();
24
25 #[cfg(feature = "journal")]
26 if env.enable_journal {
27 JournalEffector::save_fd_allocate(&mut ctx, fd, offset, len).map_err(|err| {
28 tracing::error!("failed to save file descriptor allocate event - {}", err);
29 WasiError::Exit(ExitCode::from(Errno::Fault))
30 })?;
31 }
32
33 Ok(Errno::Success)
34}
35
36pub(crate) fn fd_allocate_internal(
37 ctx: &mut FunctionEnvMut<'_, WasiEnv>,
38 fd: WasiFd,
39 offset: Filesize,
40 len: Filesize,
41) -> Result<(), Errno> {
42 let env = ctx.data();
43 let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
44 let fd_entry = state.fs.get_fd(fd)?;
45 let inode = fd_entry.inode;
46
47 if !fd_entry.inner.rights.contains(Rights::FD_ALLOCATE) {
48 return Err(Errno::Access);
49 }
50 let new_size = offset.checked_add(len).ok_or(Errno::Inval)?;
51 {
52 let mut guard = inode.write();
53 match guard.deref_mut() {
54 Kind::File { handle, .. } => {
55 if let Some(handle) = handle {
56 let mut handle = handle.write().unwrap();
57 handle.set_len(new_size).map_err(fs_error_into_wasi_err)?;
58 } else {
59 return Err(Errno::Badf);
60 }
61 }
62 Kind::Buffer { buffer } => {
63 buffer.resize(new_size as usize, 0);
64 }
65 Kind::Socket { .. }
66 | Kind::PipeRx { .. }
67 | Kind::PipeTx { .. }
68 | Kind::DuplexPipe { .. }
69 | Kind::Symlink { .. }
70 | Kind::EventNotifications { .. }
71 | Kind::Epoll { .. } => return Err(Errno::Badf),
72 Kind::Dir { .. } | Kind::Root { .. } => return Err(Errno::Isdir),
73 }
74 }
75 inode.stat.write().unwrap().st_size = new_size;
76 debug!(%new_size);
77
78 Ok(())
79}