Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi-common/src/tokio/file.rs
1692 views
1
use crate::tokio::block_on_dummy_executor;
2
use crate::{
3
Error,
4
file::{Advice, FdFlags, FileType, Filestat, WasiFile},
5
};
6
#[cfg(windows)]
7
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
8
#[cfg(not(windows))]
9
use io_lifetimes::AsFd;
10
use std::any::Any;
11
use std::borrow::Borrow;
12
use std::io;
13
14
pub struct File(crate::sync::file::File);
15
16
impl File {
17
pub(crate) fn from_inner(file: crate::sync::file::File) -> Self {
18
File(file)
19
}
20
pub fn from_cap_std(file: cap_std::fs::File) -> Self {
21
Self::from_inner(crate::sync::file::File::from_cap_std(file))
22
}
23
}
24
25
pub struct TcpListener(crate::sync::net::TcpListener);
26
27
impl TcpListener {
28
pub(crate) fn from_inner(listener: crate::sync::net::TcpListener) -> Self {
29
TcpListener(listener)
30
}
31
pub fn from_cap_std(listener: cap_std::net::TcpListener) -> Self {
32
Self::from_inner(crate::sync::net::TcpListener::from_cap_std(listener))
33
}
34
}
35
36
pub struct TcpStream(crate::sync::net::TcpStream);
37
38
impl TcpStream {
39
pub(crate) fn from_inner(stream: crate::sync::net::TcpStream) -> Self {
40
TcpStream(stream)
41
}
42
pub fn from_cap_std(stream: cap_std::net::TcpStream) -> Self {
43
Self::from_inner(crate::sync::net::TcpStream::from_cap_std(stream))
44
}
45
}
46
47
#[cfg(unix)]
48
pub struct UnixListener(crate::sync::net::UnixListener);
49
50
#[cfg(unix)]
51
impl UnixListener {
52
pub(crate) fn from_inner(listener: crate::sync::net::UnixListener) -> Self {
53
UnixListener(listener)
54
}
55
pub fn from_cap_std(listener: cap_std::os::unix::net::UnixListener) -> Self {
56
Self::from_inner(crate::sync::net::UnixListener::from_cap_std(listener))
57
}
58
}
59
60
#[cfg(unix)]
61
pub struct UnixStream(crate::sync::net::UnixStream);
62
63
#[cfg(unix)]
64
impl UnixStream {
65
fn from_inner(stream: crate::sync::net::UnixStream) -> Self {
66
UnixStream(stream)
67
}
68
pub fn from_cap_std(stream: cap_std::os::unix::net::UnixStream) -> Self {
69
Self::from_inner(crate::sync::net::UnixStream::from_cap_std(stream))
70
}
71
}
72
73
pub struct Stdin(crate::sync::stdio::Stdin);
74
75
pub fn stdin() -> Stdin {
76
Stdin(crate::sync::stdio::stdin())
77
}
78
79
pub struct Stdout(crate::sync::stdio::Stdout);
80
81
pub fn stdout() -> Stdout {
82
Stdout(crate::sync::stdio::stdout())
83
}
84
85
pub struct Stderr(crate::sync::stdio::Stderr);
86
87
pub fn stderr() -> Stderr {
88
Stderr(crate::sync::stdio::stderr())
89
}
90
91
macro_rules! wasi_file_impl {
92
($ty:ty) => {
93
#[wiggle::async_trait]
94
impl WasiFile for $ty {
95
fn as_any(&self) -> &dyn Any {
96
self
97
}
98
#[cfg(unix)]
99
fn pollable(&self) -> Option<rustix::fd::BorrowedFd<'_>> {
100
Some(self.0.as_fd())
101
}
102
#[cfg(windows)]
103
fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {
104
Some(self.0.as_raw_handle_or_socket())
105
}
106
async fn datasync(&self) -> Result<(), Error> {
107
block_on_dummy_executor(|| self.0.datasync())
108
}
109
async fn sync(&self) -> Result<(), Error> {
110
block_on_dummy_executor(|| self.0.sync())
111
}
112
async fn get_filetype(&self) -> Result<FileType, Error> {
113
block_on_dummy_executor(|| self.0.get_filetype())
114
}
115
async fn get_fdflags(&self) -> Result<FdFlags, Error> {
116
block_on_dummy_executor(|| self.0.get_fdflags())
117
}
118
async fn set_fdflags(&mut self, fdflags: FdFlags) -> Result<(), Error> {
119
block_on_dummy_executor(|| self.0.set_fdflags(fdflags))
120
}
121
async fn get_filestat(&self) -> Result<Filestat, Error> {
122
block_on_dummy_executor(|| self.0.get_filestat())
123
}
124
async fn set_filestat_size(&self, size: u64) -> Result<(), Error> {
125
block_on_dummy_executor(move || self.0.set_filestat_size(size))
126
}
127
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
128
block_on_dummy_executor(move || self.0.advise(offset, len, advice))
129
}
130
async fn read_vectored<'a>(
131
&self,
132
bufs: &mut [io::IoSliceMut<'a>],
133
) -> Result<u64, Error> {
134
block_on_dummy_executor(move || self.0.read_vectored(bufs))
135
}
136
async fn read_vectored_at<'a>(
137
&self,
138
bufs: &mut [io::IoSliceMut<'a>],
139
offset: u64,
140
) -> Result<u64, Error> {
141
block_on_dummy_executor(move || self.0.read_vectored_at(bufs, offset))
142
}
143
async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
144
block_on_dummy_executor(move || self.0.write_vectored(bufs))
145
}
146
async fn write_vectored_at<'a>(
147
&self,
148
bufs: &[io::IoSlice<'a>],
149
offset: u64,
150
) -> Result<u64, Error> {
151
if bufs.iter().map(|i| i.len()).sum::<usize>() == 0 {
152
return Ok(0);
153
}
154
block_on_dummy_executor(move || self.0.write_vectored_at(bufs, offset))
155
}
156
async fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
157
block_on_dummy_executor(move || self.0.seek(pos))
158
}
159
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
160
block_on_dummy_executor(move || self.0.peek(buf))
161
}
162
async fn set_times(
163
&self,
164
atime: Option<crate::SystemTimeSpec>,
165
mtime: Option<crate::SystemTimeSpec>,
166
) -> Result<(), Error> {
167
block_on_dummy_executor(move || self.0.set_times(atime, mtime))
168
}
169
fn num_ready_bytes(&self) -> Result<u64, Error> {
170
self.0.num_ready_bytes()
171
}
172
fn isatty(&self) -> bool {
173
self.0.isatty()
174
}
175
176
#[cfg(not(windows))]
177
async fn readable(&self) -> Result<(), Error> {
178
// The Inner impls OwnsRaw, which asserts exclusive use of the handle by the owned object.
179
// AsyncFd needs to wrap an owned `impl std::os::unix::io::AsRawFd`. Rather than introduce
180
// mutability to let it own the `Inner`, we are depending on the `&mut self` bound on this
181
// async method to ensure this is the only Future which can access the RawFd during the
182
// lifetime of the AsyncFd.
183
use std::os::unix::io::AsRawFd;
184
use tokio::io::{Interest, unix::AsyncFd};
185
let rawfd = self.0.borrow().as_fd().as_raw_fd();
186
match AsyncFd::with_interest(rawfd, Interest::READABLE) {
187
Ok(asyncfd) => {
188
let _ = asyncfd.readable().await?;
189
Ok(())
190
}
191
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
192
// if e is EPERM, this file isn't supported by epoll because it is immediately
193
// available for reading:
194
Ok(())
195
}
196
Err(e) => Err(e.into()),
197
}
198
}
199
200
#[cfg(not(windows))]
201
async fn writable(&self) -> Result<(), Error> {
202
// The Inner impls OwnsRaw, which asserts exclusive use of the handle by the owned object.
203
// AsyncFd needs to wrap an owned `impl std::os::unix::io::AsRawFd`. Rather than introduce
204
// mutability to let it own the `Inner`, we are depending on the `&mut self` bound on this
205
// async method to ensure this is the only Future which can access the RawFd during the
206
// lifetime of the AsyncFd.
207
use std::os::unix::io::AsRawFd;
208
use tokio::io::{Interest, unix::AsyncFd};
209
let rawfd = self.0.borrow().as_fd().as_raw_fd();
210
match AsyncFd::with_interest(rawfd, Interest::WRITABLE) {
211
Ok(asyncfd) => {
212
let _ = asyncfd.writable().await?;
213
Ok(())
214
}
215
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
216
// if e is EPERM, this file isn't supported by epoll because it is immediately
217
// available for writing:
218
Ok(())
219
}
220
Err(e) => Err(e.into()),
221
}
222
}
223
224
async fn sock_accept(&self, fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
225
block_on_dummy_executor(|| self.0.sock_accept(fdflags))
226
}
227
}
228
#[cfg(windows)]
229
impl AsRawHandleOrSocket for $ty {
230
#[inline]
231
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
232
self.0.borrow().as_raw_handle_or_socket()
233
}
234
}
235
};
236
}
237
238
wasi_file_impl!(File);
239
wasi_file_impl!(TcpListener);
240
wasi_file_impl!(TcpStream);
241
#[cfg(unix)]
242
wasi_file_impl!(UnixListener);
243
#[cfg(unix)]
244
wasi_file_impl!(UnixStream);
245
wasi_file_impl!(Stdin);
246
wasi_file_impl!(Stdout);
247
wasi_file_impl!(Stderr);
248
249