From 85c3b73b4ea75a5c1fc91ac58423758fb9aea16f Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 21 Jan 2021 13:51:18 -0800 Subject: [PATCH] stdio compiles on windows! --- Cargo.lock | 80 +++++++--- crates/wasi-c2/Cargo.toml | 7 +- crates/wasi-c2/cap-std-sync/Cargo.toml | 11 +- crates/wasi-c2/cap-std-sync/src/stdio.rs | 184 ++++++++++++++++------- 4 files changed, 194 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4d5ae3b3a..9f0d008bda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,12 +201,13 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "cap-fs-ext" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685f3e4cc7b497dcf02be09a40ecc82fd8f8be36e80d611aa0d92d839dcb6eb3" +checksum = "ce7f38ec6d0dd8a67d9553f95a61ee41fce23c9947bceac7bfe5b3711f9ab2fe" dependencies = [ - "cap-primitives", - "cap-std", + "cap-primitives 0.11.0", + "cap-std 0.11.0", + "unsafe-io", ] [[package]] @@ -225,11 +226,30 @@ dependencies = [ "winx 0.21.0", ] +[[package]] +name = "cap-primitives" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0363d39135d2cd4694e669f858246839648e11de632c5107ad3ee8ae9d12249c" +dependencies = [ + "errno", + "fs-set-times", + "ipnet", + "libc", + "maybe-owned", + "once_cell", + "posish", + "unsafe-io", + "winapi", + "winapi-util", + "winx 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cap-rand" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1107a56cbc947984568f38bc42cf2652cdd6c8a8ba8db6cdc9fd64a41623dd" +checksum = "3ff901c15baead18c2abaae7345dbb2e2a84229c56310cefd303b0b6f2f82bd2" dependencies = [ "rand 0.8.1", ] @@ -240,19 +260,29 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdd2d37dc52e2a73735c6056a336f877c5cfb7a20f5301b40d3d04d8c469ca9b" dependencies = [ - "cap-primitives", + "cap-primitives 0.9.0", +] + +[[package]] +name = "cap-std" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e03b5ca2d4181980f2546074ad15a069f0f5860519e0d83e492c78b411d7c39f" +dependencies = [ + "cap-primitives 0.11.0", + "unsafe-io", ] [[package]] name = "cap-time-ext" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083c07fd4c2754536834432d941c9470f0a430359d9c25ac1dd1f2dda45528ff" +checksum = "5f51194e7bd1b6e77f10c367b1c7b21856a49142e70b4cd3d4da17b51c25ca76" dependencies = [ - "cap-primitives", + "cap-primitives 0.11.0", "once_cell", "posish", - "winx 0.21.0", + "winx 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1187,9 +1217,9 @@ checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" [[package]] name = "libc" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "libfuzzer-sys" @@ -1275,6 +1305,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "memchr" version = "2.3.4" @@ -1575,9 +1611,9 @@ checksum = "6b063f57ec186e6140e2b8b6921e5f1bd89c7356dda5b33acc5401203ca6131c" [[package]] name = "posish" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e066cc5d9abbd9dd56fb7864347ffbc4389b44e145d9232de08a5916d00df894" +checksum = "077963e9645b0b35e26719e32ad4f77419be1e90a4ef6039008dd5497c02312f" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2189,12 +2225,12 @@ dependencies = [ [[package]] name = "system-interface" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4491d080ba27a6e906f264ad9b3d3db925b53160e71df56e65973441a186ab" +checksum = "5f553b2d73f8d21a632ffdd399f8f50cb1f7bc642c1c9f3764bf05ba7f2999c5" dependencies = [ "atty", - "cap-std", + "cap-std 0.11.0", "posish", "rustc_version 0.3.3", "unsafe-io", @@ -2256,7 +2292,7 @@ name = "test-programs" version = "0.19.0" dependencies = [ "anyhow", - "cap-std", + "cap-std 0.9.0", "cfg-if 1.0.0", "os_pipe", "pretty_env_logger", @@ -2517,8 +2553,7 @@ dependencies = [ "anyhow", "bitflags", "cap-rand", - "cap-std", - "cfg-if 1.0.0", + "cap-std 0.11.0", "libc", "system-interface", "thiserror", @@ -2532,12 +2567,13 @@ version = "0.22.0" dependencies = [ "cap-fs-ext", "cap-rand", - "cap-std", + "cap-std 0.11.0", "cap-time-ext", "fs-set-times", "libc", "system-interface", "tracing", + "unsafe-io", "wasi-c2", "yanix 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/crates/wasi-c2/Cargo.toml b/crates/wasi-c2/Cargo.toml index de412a5954..22de654ae3 100644 --- a/crates/wasi-c2/Cargo.toml +++ b/crates/wasi-c2/Cargo.toml @@ -24,10 +24,9 @@ thiserror = "1.0" libc = "0.2" wiggle = { path = "../wiggle", default-features = false, version = "0.22.0" } tracing = "0.1.19" -system-interface = { version = "0.5", features = ["cap_std_impls"] } -cap-std = "0.9" -cap-rand = "0.9" -cfg-if = "1" +system-interface = { version = "0.5.2", features = ["cap_std_impls"] } +cap-std = "0.11" +cap-rand = "0.11" bitflags = "1.2" [badges] diff --git a/crates/wasi-c2/cap-std-sync/Cargo.toml b/crates/wasi-c2/cap-std-sync/Cargo.toml index 3aaaf65314..53b43889d1 100644 --- a/crates/wasi-c2/cap-std-sync/Cargo.toml +++ b/crates/wasi-c2/cap-std-sync/Cargo.toml @@ -14,12 +14,13 @@ publish = false [dependencies] wasi-c2 = { path = "../" } -cap-std = "0.9" -cap-fs-ext = "0.9" -cap-time-ext = "0.9" -cap-rand = "0.9" +cap-std = "0.11" +cap-fs-ext = "0.11" +cap-time-ext = "0.11" +cap-rand = "0.11" fs-set-times = "0.2.2" +unsafe-io = "0.2" yanix = "0.22" -system-interface = { version = "0.5", features = ["cap_std_impls"] } +system-interface = { version = "0.5.2", features = ["cap_std_impls"] } tracing = "0.1.19" libc = "0.2" diff --git a/crates/wasi-c2/cap-std-sync/src/stdio.rs b/crates/wasi-c2/cap-std-sync/src/stdio.rs index 40c9616003..e3dd0d2b5e 100644 --- a/crates/wasi-c2/cap-std-sync/src/stdio.rs +++ b/crates/wasi-c2/cap-std-sync/src/stdio.rs @@ -3,22 +3,117 @@ use fs_set_times::SetTimes; use std::any::Any; use std::convert::TryInto; use std::io; -use system_interface::{ - fs::{Advice, FileIoExt}, - io::ReadReady, -}; +use std::io::{Read, Write}; +use system_interface::{fs::Advice, io::ReadReady}; + +#[cfg(unix)] +use std::os::unix::io::{AsRawFd, RawFd}; +#[cfg(windows)] +use std::os::windows::io::{AsRawHandle, RawHandle}; +use unsafe_io::AsUnsafeFile; use wasi_c2::{ file::{FdFlags, FileType, Filestat, WasiFile}, Error, }; -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, RawFd}; +pub struct Stdin(std::io::Stdin); + +pub fn stdin() -> Stdin { + Stdin(std::io::stdin()) +} + +impl WasiFile for Stdin { + fn as_any(&self) -> &dyn Any { + self + } + fn datasync(&self) -> Result<(), Error> { + Ok(()) + } + fn sync(&self) -> Result<(), Error> { + Ok(()) + } + fn get_filetype(&self) -> Result { + Ok(FileType::Unknown) + } + fn get_fdflags(&self) -> Result { + // XXX get_fdflags is not implemented but lets lie rather than panic: + Ok(FdFlags::empty()) + } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + // XXX + Err(Error::Perm) + } + fn get_filestat(&self) -> Result { + let meta = self.0.as_file_view().metadata()?; + // XXX can unsafe-io give a way to get metadata? + Ok(Filestat { + device_id: 0, + inode: 0, + filetype: self.get_filetype()?, + nlink: 0, + size: meta.len(), + atim: meta.accessed().ok(), + mtim: meta.modified().ok(), + ctim: meta.created().ok(), + }) + } + fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { + // XXX is this the right error? + Err(Error::Perm) + } + fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> { + Err(Error::Badf) + } + fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> { + Err(Error::Badf) + } + fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result { + let n = self.0.as_file_view().read_vectored(bufs)?; + Ok(n.try_into().map_err(|_| Error::Overflow)?) + } + fn read_vectored_at(&self, _bufs: &mut [io::IoSliceMut], _offset: u64) -> Result { + Err(Error::Spipe) + } + fn write_vectored(&self, _bufs: &[io::IoSlice]) -> Result { + Err(Error::Badf) + } + fn write_vectored_at(&self, _bufs: &[io::IoSlice], _offset: u64) -> Result { + Err(Error::Badf) + } + fn seek(&self, _pos: std::io::SeekFrom) -> Result { + Err(Error::Spipe) + } + fn peek(&self, _buf: &mut [u8]) -> Result { + Err(Error::Spipe) + } + fn set_times( + &self, + atime: Option, + mtime: Option, + ) -> Result<(), Error> { + self.0 + .set_times(convert_systimespec(atime), convert_systimespec(mtime))?; + Ok(()) + } + fn num_ready_bytes(&self) -> Result { + Ok(self.0.num_ready_bytes()?) + } +} #[cfg(windows)] -use std::os::windows::io::{AsRawHandle, RawHandle}; +impl AsRawHandle for Stdin { + fn as_raw_handle(&self) -> RawHandle { + self.0.as_raw_handle() + } +} +#[cfg(unix)] +impl AsRawFd for Stdin { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} -macro_rules! wasi_file_impl { - ($ty:ty, $additional:item) => { +macro_rules! wasi_file_write_impl { + ($ty:ty) => { impl WasiFile for $ty { fn as_any(&self) -> &dyn Any { self @@ -57,50 +152,47 @@ macro_rules! wasi_file_impl { // XXX is this the right error? Err(Error::Perm) } - fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { - self.0.advise(offset, len, advice)?; - Ok(()) + fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> { + Err(Error::Badf) } - fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> { - self.0.allocate(offset, len)?; - Ok(()) + fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> { + Err(Error::Badf) } - fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result { - let n = self.0.read_vectored(bufs)?; - Ok(n.try_into().map_err(|_| Error::Overflow)?) + fn read_vectored(&self, _bufs: &mut [io::IoSliceMut]) -> Result { + Err(Error::Badf) } fn read_vectored_at( &self, - bufs: &mut [io::IoSliceMut], - offset: u64, + _bufs: &mut [io::IoSliceMut], + _offset: u64, ) -> Result { - let n = self.0.read_vectored_at(bufs, offset)?; - Ok(n.try_into().map_err(|_| Error::Overflow)?) + Err(Error::Badf) } fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result { - let n = self.0.write_vectored(bufs)?; + let n = self.0.as_file_view().write_vectored(bufs)?; Ok(n.try_into().map_err(|_| Error::Overflow)?) } - fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result { - let n = self.0.write_vectored_at(bufs, offset)?; - Ok(n.try_into().map_err(|_| Error::Overflow)?) + fn write_vectored_at(&self, _bufs: &[io::IoSlice], _offset: u64) -> Result { + Err(Error::Spipe) } - fn seek(&self, pos: std::io::SeekFrom) -> Result { - Ok(self.0.seek(pos)?) + fn seek(&self, _pos: std::io::SeekFrom) -> Result { + Err(Error::Spipe) } - fn peek(&self, buf: &mut [u8]) -> Result { - let n = self.0.peek(buf)?; - Ok(n.try_into().map_err(|_| Error::Overflow)?) + fn peek(&self, _buf: &mut [u8]) -> Result { + Err(Error::Badf) } fn set_times( &self, atime: Option, mtime: Option, ) -> Result<(), Error> { - self.0.set_times(convert_systimespec(atime), convert_systimespec(mtime))?; + self.0 + .set_times(convert_systimespec(atime), convert_systimespec(mtime))?; Ok(()) } - $additional + fn num_ready_bytes(&self) -> Result { + Ok(0) + } } #[cfg(windows)] impl AsRawHandle for $ty { @@ -117,38 +209,16 @@ macro_rules! wasi_file_impl { }; } -pub struct Stdin(std::io::Stdin); - -pub fn stdin() -> Stdin { - Stdin(std::io::stdin()) -} -wasi_file_impl!( - Stdin, - fn num_ready_bytes(&self) -> Result { - Ok(self.0.num_ready_bytes()?) - } -); - pub struct Stdout(std::io::Stdout); pub fn stdout() -> Stdout { Stdout(std::io::stdout()) } -wasi_file_impl!( - Stdout, - fn num_ready_bytes(&self) -> Result { - Ok(0) - } -); +wasi_file_write_impl!(Stdout); pub struct Stderr(std::io::Stderr); pub fn stderr() -> Stderr { Stderr(std::io::stderr()) } -wasi_file_impl!( - Stderr, - fn num_ready_bytes(&self) -> Result { - Ok(0) - } -); +wasi_file_write_impl!(Stderr);