wasmer_wasix/syscalls/wasi/
fd_renumber.rs

1use super::*;
2use crate::fs::FlushPoller;
3use crate::syscalls::*;
4
5/// ### `fd_renumber()`
6/// Atomically copy file descriptor
7/// Inputs:
8/// - `Fd from`
9///     File descriptor to copy
10/// - `Fd to`
11///     Location to copy file descriptor to
12#[instrument(level = "trace", skip_all, fields(%from, %to), ret)]
13pub fn fd_renumber(
14    mut ctx: FunctionEnvMut<'_, WasiEnv>,
15    from: WasiFd,
16    to: WasiFd,
17) -> Result<Errno, WasiError> {
18    WasiEnv::do_pending_operations(&mut ctx)?;
19
20    let ret = fd_renumber_internal(&mut ctx, from, to)?;
21    let env = ctx.data();
22
23    if ret == Errno::Success {
24        #[cfg(feature = "journal")]
25        if env.enable_journal {
26            JournalEffector::save_fd_renumber(&mut ctx, from, to).map_err(|err| {
27                tracing::error!("failed to save file descriptor renumber event - {}", err);
28                WasiError::Exit(ExitCode::from(Errno::Fault))
29            })?;
30        }
31    }
32
33    Ok(ret)
34}
35
36pub(crate) fn fd_renumber_internal(
37    ctx: &mut FunctionEnvMut<'_, WasiEnv>,
38    from: WasiFd,
39    to: WasiFd,
40) -> Result<Errno, WasiError> {
41    let env = ctx.data();
42    let (_, state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
43
44    let flush_target = match state.fs.dup2_at(from, to) {
45        Err(errno) => return Ok(errno),
46        Ok(flush_target) => flush_target,
47    };
48
49    // Best-effort flush of the replaced entry; result depends only on map updates.
50    if let Some(file) = flush_target {
51        let _ = __asyncify_light(env, None, FlushPoller { file })?;
52    }
53
54    Ok(Errno::Success)
55}