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