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 let mut current_size;
52 {
53 let mut guard = inode.write();
54 match guard.deref_mut() {
55 Kind::File { handle, .. } => {
56 if let Some(handle) = handle {
57 let mut handle = handle.write().unwrap();
58 current_size = handle.size();
59 if new_size > current_size {
60 handle.set_len(new_size).map_err(fs_error_into_wasi_err)?;
61 current_size = new_size;
62 }
63 } else {
64 return Err(Errno::Badf);
65 }
66 }
67 Kind::Buffer { buffer } => {
68 current_size = buffer.len() as u64;
69 if new_size > current_size {
70 buffer.resize(new_size as usize, 0);
71 current_size = new_size;
72 }
73 }
74 Kind::Socket { .. }
75 | Kind::PipeRx { .. }
76 | Kind::PipeTx { .. }
77 | Kind::DuplexPipe { .. }
78 | Kind::Symlink { .. }
79 | Kind::EventNotifications { .. }
80 | Kind::Epoll { .. } => return Err(Errno::Badf),
81 Kind::Dir { .. } | Kind::Root { .. } => return Err(Errno::Isdir),
82 }
83 }
84 inode.stat.write().unwrap().st_size = current_size;
85 debug!(%new_size);
86
87 Ok(())
88}