wasmer_wasix/syscalls/wasix/
fd_pipe.rs1use std::sync::atomic::AtomicUsize;
2
3use virtual_fs::Pipe;
4
5use super::*;
6use crate::syscalls::*;
7
8static PIPE_NUMBER: AtomicUsize = AtomicUsize::new(0);
12
13#[instrument(level = "trace", skip_all, fields(read_fd = field::Empty, write_fd = field::Empty), ret)]
21pub fn fd_pipe<M: MemorySize>(
22 mut ctx: FunctionEnvMut<'_, WasiEnv>,
23 ro_read_fd: WasmPtr<WasiFd, M>,
24 ro_write_fd: WasmPtr<WasiFd, M>,
25) -> Result<Errno, WasiError> {
26 WasiEnv::do_pending_operations(&mut ctx)?;
27
28 let (read_fd, write_fd) = wasi_try_ok!(fd_pipe_internal(&mut ctx, None, None));
29 let env = ctx.data();
30
31 #[cfg(feature = "journal")]
32 if env.enable_journal {
33 JournalEffector::save_fd_pipe(&mut ctx, read_fd, write_fd).map_err(|err| {
34 tracing::error!("failed to save create pipe event - {}", err);
35 WasiError::Exit(ExitCode::from(Errno::Fault))
36 })?;
37 }
38
39 let env = ctx.data();
40 let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
41
42 Span::current()
43 .record("read_fd", read_fd)
44 .record("write_fd", write_fd);
45
46 wasi_try_mem_ok!(ro_read_fd.write(&memory, read_fd));
47 wasi_try_mem_ok!(ro_write_fd.write(&memory, write_fd));
48
49 Ok(Errno::Success)
50}
51
52pub fn fd_pipe_internal(
53 ctx: &mut FunctionEnvMut<'_, WasiEnv>,
54 with_read_fd: Option<WasiFd>,
55 with_write_fd: Option<WasiFd>,
56) -> Result<(WasiFd, WasiFd), Errno> {
57 let env = ctx.data();
58 let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
59 let (tx, rx) = Pipe::new().split();
60
61 let pipe_no = PIPE_NUMBER.fetch_add(1, Ordering::SeqCst);
64
65 let rx_inode = state.fs.create_inode_with_default_stat(
66 inodes,
67 Kind::PipeRx { rx },
68 false,
69 format!("pipe{pipe_no}-rx").into(),
70 );
71 let tx_inode = state.fs.create_inode_with_default_stat(
72 inodes,
73 Kind::PipeTx { tx },
74 false,
75 format!("pipe{pipe_no}-tx").into(),
76 );
77
78 let rights = Rights::FD_SYNC
79 | Rights::FD_DATASYNC
80 | Rights::POLL_FD_READWRITE
81 | Rights::SOCK_SEND
82 | Rights::FD_FDSTAT_SET_FLAGS
83 | Rights::FD_FILESTAT_GET;
84
85 let read_rights = rights | Rights::FD_READ;
86 let write_rights = rights | Rights::FD_WRITE;
87
88 let read_fd = if let Some(fd) = with_read_fd {
89 state
90 .fs
91 .with_fd(
92 read_rights,
93 read_rights,
94 Fdflags::empty(),
95 Fdflagsext::empty(),
96 0,
97 rx_inode,
98 fd,
99 )
100 .map(|()| fd)?
101 } else {
102 state.fs.create_fd(
103 read_rights,
104 read_rights,
105 Fdflags::empty(),
106 Fdflagsext::empty(),
107 0,
108 rx_inode,
109 )?
110 };
111
112 let write_fd = if let Some(fd) = with_write_fd {
113 state
114 .fs
115 .with_fd(
116 write_rights,
117 write_rights,
118 Fdflags::empty(),
119 Fdflagsext::empty(),
120 0,
121 tx_inode,
122 fd,
123 )
124 .map(|()| fd)?
125 } else {
126 state.fs.create_fd(
127 write_rights,
128 write_rights,
129 Fdflags::empty(),
130 Fdflagsext::empty(),
131 0,
132 tx_inode,
133 )?
134 };
135
136 Ok((read_fd, write_fd))
137}