use virtual_fs::Pipe;
use super::*;
use crate::syscalls::*;
#[instrument(level = "trace", skip_all, fields(fd1 = field::Empty, fd2 = field::Empty), ret)]
pub fn fd_pipe<M: MemorySize>(
mut ctx: FunctionEnvMut<'_, WasiEnv>,
ro_fd1: WasmPtr<WasiFd, M>,
ro_fd2: WasmPtr<WasiFd, M>,
) -> Result<Errno, WasiError> {
let (fd1, fd2) = wasi_try_ok!(fd_pipe_internal(&mut ctx, None, None));
let env = ctx.data();
#[cfg(feature = "journal")]
if env.enable_journal {
JournalEffector::save_fd_pipe(&mut ctx, fd1, fd2).map_err(|err| {
tracing::error!("failed to save create pipe event - {}", err);
WasiError::Exit(ExitCode::from(Errno::Fault))
})?;
}
let env = ctx.data();
let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
Span::current().record("fd1", fd1).record("fd2", fd2);
wasi_try_mem_ok!(ro_fd1.write(&memory, fd1));
wasi_try_mem_ok!(ro_fd2.write(&memory, fd2));
Ok(Errno::Success)
}
pub fn fd_pipe_internal(
ctx: &mut FunctionEnvMut<'_, WasiEnv>,
with_fd1: Option<WasiFd>,
with_fd2: Option<WasiFd>,
) -> Result<(WasiFd, WasiFd), Errno> {
let env = ctx.data();
let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
let (pipe1, pipe2) = Pipe::channel();
let inode1 = state.fs.create_inode_with_default_stat(
inodes,
Kind::Pipe { pipe: pipe1 },
false,
"pipe".to_string().into(),
);
let inode2 = state.fs.create_inode_with_default_stat(
inodes,
Kind::Pipe { pipe: pipe2 },
false,
"pipe".to_string().into(),
);
let rights = Rights::FD_READ
| Rights::FD_WRITE
| Rights::FD_SYNC
| Rights::FD_DATASYNC
| Rights::POLL_FD_READWRITE
| Rights::SOCK_SEND
| Rights::FD_FDSTAT_SET_FLAGS
| Rights::FD_FILESTAT_GET;
let fd1 = if let Some(fd) = with_fd1 {
state
.fs
.with_fd(rights, rights, Fdflags::empty(), 0, inode1, fd)
.map(|_| fd)?
} else {
state
.fs
.create_fd(rights, rights, Fdflags::empty(), 0, inode1)?
};
let fd2 = if let Some(fd) = with_fd2 {
state
.fs
.with_fd(rights, rights, Fdflags::empty(), 0, inode2, fd)
.map(|_| fd)?
} else {
state
.fs
.create_fd(rights, rights, Fdflags::empty(), 0, inode2)?
};
Ok((fd1, fd2))
}