diff --git a/Cargo.lock b/Cargo.lock index 653f89cc9..d55f9631b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,20 +39,26 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30275ad0ad84ec1c06dde3b3f7d23c6006b7d76d61a85e7060b426b747eff70d" + [[package]] name = "ansi_term" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "libc", + "winapi", ] [[package]] @@ -63,9 +69,9 @@ checksum = "70033777eb8b5124a81a1889416543dddef2de240019b674c81285a2635a7e1e" [[package]] name = "anyhow" -version = "1.0.62" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "arbitrary" @@ -110,9 +116,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", @@ -223,10 +229,16 @@ dependencies = [ ] [[package]] -name = "bumpalo" -version = "3.11.0" +name = "build_const" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytecheck" @@ -279,8 +291,8 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" dependencies = [ - "clap 3.2.17", - "heck", + "clap 3.2.23", + "heck 0.4.0", "indexmap", "log", "proc-macro2", @@ -340,9 +352,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.17" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", "bitflags", @@ -357,9 +369,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.17" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -523,9 +535,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -982,6 +994,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -1137,6 +1155,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures" version = "0.3.25" @@ -1385,9 +1409,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -1464,7 +1488,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.3", + "itoa 1.0.4", ] [[package]] @@ -1502,18 +1526,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - [[package]] name = "hyper" version = "0.14.22" @@ -1551,6 +1563,19 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "iana-time-zone" version = "0.1.53" @@ -1581,56 +1606,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" -[[package]] -name = "hyper" -version = "0.14.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.3", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "js-sys", - "wasm-bindgen", - "winapi", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -1740,12 +1715,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" - [[package]] name = "itertools" version = "0.10.5" @@ -1808,9 +1777,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.135" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libfuzzer-sys" @@ -1833,6 +1802,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1848,21 +1826,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "llvm-sys" -version = "120.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" -dependencies = [ - "cc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "llvm-sys" version = "120.2.5" @@ -1878,9 +1841,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -1972,12 +1935,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "minifb" -version = "0.19.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - [[package]] name = "mime_guess" version = "2.0.4" @@ -2031,14 +1988,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -2058,9 +2015,9 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -2174,9 +2131,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "oorandom" @@ -2218,9 +2175,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.76" +version = "0.9.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" +checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" dependencies = [ "autocfg", "cc", @@ -2247,9 +2204,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.3.0" +version = "6.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9" [[package]] name = "output_vt100" @@ -2297,18 +2254,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - [[package]] name = "percent-encoding" version = "2.2.0" @@ -2317,9 +2262,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" +checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a" dependencies = [ "thiserror", "ucd-trie", @@ -2337,12 +2282,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.26" @@ -2351,9 +2290,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716b4eeb6c4a1d3ecc956f75b43ec2e8e8ba80026413e70a3f41fd3313d3492b" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -2761,25 +2700,31 @@ dependencies = [ "http", "http-body", "hyper", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", "log", "mime", + "mime_guess", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls 0.20.7", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 0.22.5", "winreg", ] @@ -3005,9 +2950,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "security-framework" -version = "2.3.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -3070,9 +3015,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] @@ -3109,9 +3054,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", @@ -3120,9 +3065,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" dependencies = [ "itoa 1.0.4", "ryu", @@ -3136,7 +3081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.3", + "itoa 1.0.4", "ryu", "serde", ] @@ -3192,9 +3137,9 @@ checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -3216,15 +3161,9 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" dependencies = [ - "dirs", + "dirs 4.0.0", ] -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -3265,16 +3204,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "socket2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "spin" version = "0.5.2" @@ -3287,7 +3216,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e3a7cd01625b7e43e62815677d692cb59b221c2fdc2853d1eb86a260ee0c272" dependencies = [ - "ansi_term", + "ansi_term 0.7.5", "term 0.6.1", ] @@ -3659,6 +3588,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.7", + "tokio", + "webpki 0.22.0", +] + [[package]] name = "tokio-util" version = "0.7.4" @@ -3688,12 +3628,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" -[[package]] -name = "tracing" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - [[package]] name = "tracing" version = "0.1.37" @@ -3755,7 +3689,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ - "ansi_term", + "ansi_term 0.12.1", "chrono", "lazy_static", "matchers 0.0.1", @@ -3793,7 +3727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" dependencies = [ "tracing", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.16", "wasm-bindgen", ] @@ -3803,12 +3737,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" -[[package]] -name = "trybuild" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - [[package]] name = "trybuild" version = "1.0.71" @@ -3875,12 +3803,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" -[[package]] -name = "unicode-ident" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" - [[package]] name = "unicode-ident" version = "1.0.5" @@ -3902,15 +3824,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-width" version = "0.1.10" @@ -3974,18 +3887,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - [[package]] name = "version-compare" version = "0.1.0" @@ -4040,6 +3941,23 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wapm-toml" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d60213ef08e950dfda77b5497ffc32a63d70dbb4ba075ba6d1787de9d98fc431" +dependencies = [ + "anyhow", + "semver 1.0.14", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "serde_yaml", + "thiserror", + "toml", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4159,9 +4077,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.16.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d443c5a7daae71697d97ec12ad70b4fe8766d3a0f4db16158ac8b781365892f7" +checksum = "c5816e88e8ea7335016aa62eb0485747f786136d505a9b3890f8c400211d9b5f" dependencies = [ "leb128", ] @@ -4250,9 +4168,9 @@ dependencies = [ "wasmer-inline-c", "wasmer-middlewares", "wasmer-types", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", "wasmer-wasi", - "webc", + "webc 3.0.1", ] [[package]] @@ -4297,7 +4215,8 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.17", + "chrono", + "clap 3.2.23", "colored 2.0.0", "dirs 4.0.0", "distance", @@ -4330,12 +4249,12 @@ dependencies = [ "wasmer-object", "wasmer-registry", "wasmer-types", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", "wasmer-vm", "wasmer-wasi", "wasmer-wasi-experimental-io-devices", "wasmer-wast", - "webc", + "webc 3.0.1", ] [[package]] @@ -4372,7 +4291,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.17", + "clap 3.2.23", "colored 2.0.0", "distance", "fern", @@ -4574,17 +4493,20 @@ dependencies = [ name = "wasmer-vbus" version = "3.0.0-rc.2" dependencies = [ + "libc", + "slab", "thiserror", "tracing", "typetag", "wasmer", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", ] [[package]] name = "wasmer-vfs" version = "3.0.0-rc.2" dependencies = [ + "anyhow", "async-trait", "lazy_static", "libc", @@ -4593,7 +4515,21 @@ dependencies = [ "thiserror", "tracing", "typetag", - "webc", + "webc 3.0.1", +] + +[[package]] +name = "wasmer-vfs" +version = "3.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034ee8bfde757ab08b1285059b5943a9a7f12a296f5a63e9ed08cc0be04e4f16" +dependencies = [ + "anyhow", + "libc", + "slab", + "thiserror", + "tracing", + "webc 3.0.1", ] [[package]] @@ -4628,13 +4564,14 @@ dependencies = [ "async-trait", "bytes", "thiserror", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", ] [[package]] name = "wasmer-wasi" version = "3.0.0-rc.2" dependencies = [ + "anyhow", "async-trait", "bincode", "bytes", @@ -4649,9 +4586,10 @@ dependencies = [ "lazy_static", "libc", "linked_hash_set", - "rand", + "rand 0.8.5", "reqwest", "serde", + "serde_cbor", "serde_derive", "serde_json", "serde_yaml", @@ -4674,13 +4612,14 @@ dependencies = [ "wasmer-compiler-cranelift", "wasmer-compiler-llvm", "wasmer-compiler-singlepass", + "wasmer-emscripten", "wasmer-types", "wasmer-vbus", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", "wasmer-vnet", "wasmer-wasi-local-networking", "wasmer-wasi-types", - "webc", + "webc 3.0.1", "webc-vfs", "weezl", "winapi", @@ -4707,7 +4646,7 @@ dependencies = [ "bytes", "tokio", "tracing", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", "wasmer-vnet", ] @@ -4737,7 +4676,7 @@ dependencies = [ "tempfile", "thiserror", "wasmer", - "wasmer-vfs", + "wasmer-vfs 3.0.0-rc.2", "wasmer-wasi", "wast 38.0.1", ] @@ -4826,7 +4765,7 @@ dependencies = [ "test-generator", "test-log", "tracing", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.16", "wasi-test-generator", "wasmer", "wasmer-cache", @@ -4849,21 +4788,21 @@ checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" [[package]] name = "wasmparser" -version = "0.89.1" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5d3e08b13876f96dd55608d03cd4883a0545884932d5adf11925876c96daef" +checksum = "c5a4460aa3e271fa180b6a5d003e728f3963fb30e3ba0fa7c9634caa06049328" dependencies = [ "indexmap", ] [[package]] name = "wasmprinter" -version = "0.2.39" +version = "0.2.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9e5ee2f56cc8a5da489558114e8c118e5a8416d96aefe63dcf1b5b05b858c6" +checksum = "6c9f096ba095329c6aa55b7e9cafa26c5b50e9ab7fc2415fd0b26cb80dca8f05" dependencies = [ "anyhow", - "wasmparser 0.89.1", + "wasmparser 0.93.0", ] [[package]] @@ -4886,23 +4825,23 @@ dependencies = [ [[package]] name = "wast" -version = "46.0.0" +version = "48.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0ab19660e3ea6891bba69167b9be40fad00fb1fe3dd39c5eebcee15607131b" +checksum = "84825b5ac7164df8260c9e2b2e814075334edbe7ac426f2469b93a5eeac23cce" dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder 0.16.0", + "wasm-encoder 0.19.0", ] [[package]] name = "wat" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f775282def4d5bffd94d60d6ecd57bfe6faa46171cdbf8d32bd5458842b1e3e" +checksum = "129da4a03ec6d2a815f42c88f641824e789d5be0d86d2f90aa8a218c7068e0be" dependencies = [ - "wast 46.0.0", + "wast 48.0.0", ] [[package]] @@ -4991,6 +4930,28 @@ dependencies = [ [[package]] name = "webc" version = "0.1.0" +dependencies = [ + "anyhow", + "base64", + "indexmap", + "leb128", + "lexical-sort", + "memchr", + "path-clean", + "rand 0.8.5", + "serde", + "serde_cbor", + "serde_json", + "sha2", + "url", + "walkdir", +] + +[[package]] +name = "webc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef87e7b955d5d1feaa8697ae129f1a9ce8859e151574ad3baceae9413b48d2f0" dependencies = [ "anyhow", "base64", @@ -5000,7 +4961,7 @@ dependencies = [ "memchr", "memmap2", "path-clean", - "rand", + "rand 0.8.5", "serde", "serde_cbor", "serde_json", @@ -5014,8 +4975,8 @@ name = "webc-vfs" version = "0.1.0" dependencies = [ "anyhow", - "wasmer-vfs", - "webc", + "wasmer-vfs 3.0.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webc 0.1.0", ] [[package]] @@ -5048,20 +5009,20 @@ dependencies = [ ] [[package]] -name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - -[[package]] -name = "which" -version = "3.1.1" +name = "webpki-roots" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + [[package]] name = "whoami" version = "1.2.3" @@ -5117,6 +5078,19 @@ dependencies = [ "windows_x86_64_msvc 0.33.0", ] +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + [[package]] name = "windows-sys" version = "0.42.0" @@ -5144,6 +5118,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + [[package]] name = "windows_aarch64_msvc" version = "0.42.0" @@ -5156,6 +5136,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + [[package]] name = "windows_i686_gnu" version = "0.42.0" @@ -5168,6 +5154,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + [[package]] name = "windows_i686_msvc" version = "0.42.0" @@ -5180,6 +5172,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + [[package]] name = "windows_x86_64_gnu" version = "0.42.0" @@ -5198,6 +5196,12 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "windows_x86_64_msvc" version = "0.42.0" @@ -5213,15 +5217,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - [[package]] name = "x11-dl" version = "2.20.0" @@ -5265,3 +5260,9 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/docs/migration_to_3.0.0.md b/docs/migration_to_3.0.0.md index 46ef126db..dc8d2b45e 100644 --- a/docs/migration_to_3.0.0.md +++ b/docs/migration_to_3.0.0.md @@ -196,7 +196,7 @@ import_object.define("env", "host_function", host_function); let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); ``` -For WASI, don't forget to initialize it +For WASI, don't forget to initialize the `WasiEnv` (it will import the memory) ```rust let mut wasi_env = WasiState::new("hello").finalize()?; diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 6123eebde..5ab3af33d 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -26,8 +26,8 @@ indexmap = { version = "1.6" } cfg-if = "1.0" thiserror = "1.0" more-asserts = "0.2" -bytes = "1" derivative = { version = "^2" } +bytes = "1" # - Optional shared dependencies. wat = { version = "1.0", optional = true } tracing = { version = "0.1", optional = true } diff --git a/lib/api/src/js/export.rs b/lib/api/src/js/export.rs index 685bb3f2d..1cf18286a 100644 --- a/lib/api/src/js/export.rs +++ b/lib/api/src/js/export.rs @@ -10,12 +10,10 @@ use std::fmt; use tracing::trace; use wasm_bindgen::{JsCast, JsValue}; use wasmer_types::{ - ExternType, FunctionType, GlobalType, MemoryType, Pages, StoreSnapshot, TableType, + ExternType, FunctionType, GlobalType, MemoryError, MemoryType, Pages, StoreSnapshot, TableType, WASM_PAGE_SIZE, }; -pub use wasmer_types::MemoryError; - /// Represents linear memory that is managed by the javascript runtime #[derive(Clone, Debug, PartialEq)] pub struct VMMemory { @@ -38,6 +36,18 @@ impl VMMemory { Self { memory, ty } } + /// Returns the size of the memory buffer in pages + pub fn get_runtime_size(&self) -> u32 { + let dummy: DummyBuffer = match serde_wasm_bindgen::from_value(self.memory.buffer()) { + Ok(o) => o, + Err(_) => return 0, + }; + if dummy.byte_length == 0 { + return 0; + } + dummy.byte_length / WASM_PAGE_SIZE as u32 + } + /// Attempts to clone this memory (if its clonable) pub(crate) fn try_clone(&self) -> Option { Some(self.clone()) diff --git a/lib/api/src/js/externals/memory.rs b/lib/api/src/js/externals/memory.rs index 0dba4bcbe..c4273879b 100644 --- a/lib/api/src/js/externals/memory.rs +++ b/lib/api/src/js/externals/memory.rs @@ -86,11 +86,6 @@ impl Memory { /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); /// ``` pub fn new(store: &mut impl AsStoreMut, ty: MemoryType) -> Result { - let vm_memory = VMMemory::new(Self::new_internal(ty.clone())?, ty); - Ok(Self::from_vm_export(store, vm_memory)) - } - - pub(crate) fn new_internal(ty: MemoryType) -> Result { let descriptor = js_sys::Object::new(); js_sys::Reflect::set(&descriptor, &"initial".into(), &ty.minimum.0.into()).unwrap(); if let Some(max) = ty.maximum { @@ -103,6 +98,11 @@ impl Memory { Ok(js_memory) } + // FIXME: resolve! + // pub fn new(store: &mut impl AsStoreMut, ty: MemoryType) -> Result { + // let vm_memory = VMMemory::new(Self::new_internal(ty.clone())?, ty); + // Ok(Self::from_vm_export(store, vm_memory)) + // } /// Creates a new host `Memory` from provided JavaScript memory. pub fn new_raw( @@ -111,12 +111,19 @@ impl Memory { ty: MemoryType, ) -> Result { let vm_memory = VMMemory::new(js_memory, ty); - Ok(Self::from_vm_export(store, vm_memory)) + let handle = StoreHandle::new(store.objects_mut(), vm_memory); + Ok(Self::from_vm_extern(store, handle.internal_handle())) } /// Create a memory object from an existing memory and attaches it to the store pub fn new_from_existing(new_store: &mut impl AsStoreMut, memory: VMMemory) -> Self { - Self::from_vm_export(new_store, memory) + let handle = StoreHandle::new(new_store.objects_mut(), memory); + Self::from_vm_extern(new_store, handle.internal_handle()) + } + + /// To `VMExtern`. + pub(crate) fn to_vm_extern(&self) -> VMExtern { + VMExtern::Memory(self.handle.internal_handle()) } /// Returns the [`MemoryType`] of the `Memory`. @@ -248,16 +255,16 @@ impl Memory { mem.try_clone() } + /// Checks whether this `Global` can be used with the given context. + pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool { + self.handle.store_id() == store.as_store_ref().objects().id() + } + /// Copies this memory to a new memory pub fn fork(&mut self, store: &impl AsStoreRef) -> Result { let mem = self.handle.get(store.as_store_ref().objects()); mem.fork() } - - /// Checks whether this `Global` can be used with the given context. - pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool { - self.handle.store_id() == store.as_store_ref().objects().id() - } } impl std::cmp::PartialEq for Memory { diff --git a/lib/api/src/js/imports.rs b/lib/api/src/js/imports.rs index 4ac8dd47a..a668b96d5 100644 --- a/lib/api/src/js/imports.rs +++ b/lib/api/src/js/imports.rs @@ -181,6 +181,81 @@ impl Imports { pub fn iter<'a>(&'a self) -> ImportsIterator<'a> { ImportsIterator::new(self) } + + /// Create a new `Imports` from a JS Object, it receives a reference to a `Module` to + /// map and assign the types of each import and the JS Object + /// that contains the values of imports. + /// + /// # Usage + /// ```ignore + /// let import_object = Imports::new_from_js_object(&mut store, &module, js_object); + /// ``` + pub fn new_from_js_object( + store: &mut impl AsStoreMut, + module: &Module, + object: js_sys::Object, + ) -> Result { + use crate::js::externals::VMExtern; + let module_imports: HashMap<(String, String), ExternType> = module + .imports() + .map(|import| { + ( + (import.module().to_string(), import.name().to_string()), + import.ty().clone(), + ) + }) + .collect::>(); + + let mut map: HashMap<(String, String), Extern> = HashMap::new(); + + for module_entry in js_sys::Object::entries(&object).iter() { + let module_entry: js_sys::Array = module_entry.into(); + let module_name = module_entry.get(0).as_string().unwrap().to_string(); + let module_import_object: js_sys::Object = module_entry.get(1).into(); + for import_entry in js_sys::Object::entries(&module_import_object).iter() { + let import_entry: js_sys::Array = import_entry.into(); + let import_name = import_entry.get(0).as_string().unwrap().to_string(); + let import_js: wasm_bindgen::JsValue = import_entry.get(1); + let key = (module_name.clone(), import_name); + let extern_type = module_imports.get(&key).unwrap(); + let export = VMExtern::from_js_value(import_js, store, extern_type.clone())?; + let extern_ = Extern::from_vm_extern(store, export); + map.insert(key, extern_); + } + } + + Ok(Self { map }) + } +} + +impl AsJs for Imports { + fn as_jsvalue(&self, store: &impl AsStoreRef) -> wasm_bindgen::JsValue { + let imports_object = js_sys::Object::new(); + for (namespace, name, extern_) in self.iter() { + let val = js_sys::Reflect::get(&imports_object, &namespace.into()).unwrap(); + if !val.is_undefined() { + // If the namespace is already set + js_sys::Reflect::set( + &val, + &name.into(), + &extern_.as_jsvalue(&store.as_store_ref()), + ) + .unwrap(); + } else { + // If the namespace doesn't exist + let import_namespace = js_sys::Object::new(); + js_sys::Reflect::set( + &import_namespace, + &name.into(), + &extern_.as_jsvalue(&store.as_store_ref()), + ) + .unwrap(); + js_sys::Reflect::set(&imports_object, &namespace.into(), &import_namespace.into()) + .unwrap(); + } + } + imports_object.into() + } } pub struct ImportsIterator<'a> { diff --git a/lib/api/src/js/instance.rs b/lib/api/src/js/instance.rs index a10196e3c..fe0df29f5 100644 --- a/lib/api/src/js/instance.rs +++ b/lib/api/src/js/instance.rs @@ -63,11 +63,11 @@ impl Instance { module: &Module, imports: &Imports, ) -> Result { - let (instance, externs): (StoreHandle, Vec) = module + let instance: WebAssembly::Instance = module .instantiate(&mut store, imports) .map_err(|e| InstantiationError::Start(e))?; - let self_instance = Self::from_module_and_instance(store, module, externs, instance)?; + let self_instance = Self::from_module_and_instance(store, module, instance)?; //self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::>())?; Ok(self_instance) } @@ -106,10 +106,10 @@ impl Instance { pub fn from_module_and_instance( mut store: &mut impl AsStoreMut, module: &Module, - externs: Vec, - instance: StoreHandle, + instance: WebAssembly::Instance, ) -> Result { - let instance_exports = instance.get(store.as_store_ref().objects()).exports(); + use crate::js::externals::VMExtern; + let instance_exports = instance.exports(); let mut exports = module .exports() .map(|export_type| { @@ -123,6 +123,7 @@ impl Instance { Ok((name.to_string(), extern_)) }) .collect::>()?; + let handle = StoreHandle::new(store.as_store_mut().objects_mut(), instance); // If the memory is imported then also export it for backwards compatibility reasons // (many will assume the memory is always exported) - later we can remove this diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 6f04a5960..80631734c 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -3,6 +3,7 @@ use crate::js::error::WasmError; use crate::js::error::{CompileError, InstantiationError}; #[cfg(feature = "js-serializable-module")] use crate::js::error::{DeserializeError, SerializeError}; +use crate::js::externals::Extern; use crate::js::imports::Imports; use crate::js::store::AsStoreMut; use crate::js::types::{AsJs, ExportType, ImportType}; @@ -110,28 +111,6 @@ pub struct Module { raw_bytes: Option, } -pub trait IntoBytes { - fn into_bytes(self) -> Bytes; -} - -impl IntoBytes for Bytes { - fn into_bytes(self) -> Bytes { - self - } -} - -impl IntoBytes for Vec { - fn into_bytes(self) -> Bytes { - Bytes::from(self) - } -} - -impl IntoBytes for &[u8] { - fn into_bytes(self) -> Bytes { - Bytes::from(self.to_vec()) - } -} - impl Module { /// Creates a new WebAssembly Module given the configuration /// in the store. @@ -286,7 +265,7 @@ impl Module { type_hints, name, #[cfg(feature = "js-serializable-module")] - raw_bytes: Some(binary), + raw_bytes: Some(binary.into_bytes()), }) } @@ -296,15 +275,15 @@ impl Module { /// This validation is normally pretty fast and checks the enabled /// WebAssembly features in the Store Engine to assure deterministic /// validation of the Module. - pub fn validate(_store: &impl AsStoreRef, binary: impl IntoBytes) -> Result<(), CompileError> { - let binary = binary.into_bytes(); - let js_bytes = unsafe { Uint8Array::view(&binary[..]) }; + pub fn validate(_store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> { + let js_bytes = unsafe { Uint8Array::view(binary) }; match WebAssembly::validate(&js_bytes.into()) { Ok(true) => Ok(()), _ => Err(CompileError::Validate("Invalid Wasm file".to_owned())), } } + // FIXME: resolve! pub(crate) fn instantiate( &self, store: &mut impl AsStoreMut, @@ -319,70 +298,90 @@ impl Module { InstantiationError::DifferentStores, ))); } - let imports_object = js_sys::Object::new(); - let mut import_externs: Vec = vec![]; - for import_type in self.imports() { - let resolved_import = imports.get_export(import_type.module(), import_type.name()); - #[allow(unused_variables)] - if let wasmer_types::ExternType::Memory(mem_ty) = import_type.ty() { - if resolved_import.is_some() { - #[cfg(feature = "tracing")] - debug!("imported shared memory {:?}", &mem_ty); - } else { - #[cfg(feature = "tracing")] - warn!( - "Error while importing {0:?}.{1:?}: memory. Expected {2:?}", - import_type.module(), - import_type.name(), - import_type.ty(), - ); - } - } - if let Some(import) = resolved_import { - let val = js_sys::Reflect::get(&imports_object, &import_type.module().into())?; - if !val.is_undefined() { - // If the namespace is already set - js_sys::Reflect::set( - &val, - &import_type.name().into(), - &import.as_jsvalue(&store.as_store_ref()), - )?; - } else { - // If the namespace doesn't exist - let import_namespace = js_sys::Object::new(); - js_sys::Reflect::set( - &import_namespace, - &import_type.name().into(), - &import.as_jsvalue(&store.as_store_ref()), - )?; - js_sys::Reflect::set( - &imports_object, - &import_type.module().into(), - &import_namespace.into(), - )?; - } - import_externs.push(import); - } else { - #[cfg(feature = "tracing")] - warn!( - "import not found {}:{}", - import_type.module(), - import_type.name() - ); - } - // in case the import is not found, the JS Wasm VM will handle - // the error for us, so we don't need to handle it - } - Ok(( - StoreHandle::new( - store.as_store_mut().objects_mut(), - WebAssembly::Instance::new(&self.module, &imports_object) - .map_err(|e: JsValue| -> RuntimeError { e.into() })?, - ), - import_externs, - )) + + let imports_js_obj = imports.as_jsvalue(store).into(); + Ok(WebAssembly::Instance::new(&self.module, &imports_js_obj) + .map_err(|e: JsValue| -> RuntimeError { e.into() })?) } + // pub(crate) fn instantiate( + // &self, + // store: &mut impl AsStoreMut, + // imports: &Imports, + // ) -> Result<(StoreHandle, Vec), RuntimeError> { + // // Ensure all imports come from the same store. + // if imports + // .into_iter() + // .any(|(_, import)| !import.is_from_store(store)) + // { + // return Err(RuntimeError::user(Box::new( + // InstantiationError::DifferentStores, + // ))); + // } + // let imports_object = js_sys::Object::new(); + // let mut import_externs: Vec = vec![]; + // for import_type in self.imports() { + // let resolved_import = imports.get_export(import_type.module(), import_type.name()); + // #[allow(unused_variables)] + // if let wasmer_types::ExternType::Memory(mem_ty) = import_type.ty() { + // if resolved_import.is_some() { + // #[cfg(feature = "tracing")] + // debug!("imported shared memory {:?}", &mem_ty); + // } else { + // #[cfg(feature = "tracing")] + // warn!( + // "Error while importing {0:?}.{1:?}: memory. Expected {2:?}", + // import_type.module(), + // import_type.name(), + // import_type.ty(), + // ); + // } + // } + // if let Some(import) = resolved_import { + // let val = js_sys::Reflect::get(&imports_object, &import_type.module().into())?; + // if !val.is_undefined() { + // // If the namespace is already set + // js_sys::Reflect::set( + // &val, + // &import_type.name().into(), + // &import.as_jsvalue(&store.as_store_ref()), + // )?; + // } else { + // // If the namespace doesn't exist + // let import_namespace = js_sys::Object::new(); + // js_sys::Reflect::set( + // &import_namespace, + // &import_type.name().into(), + // &import.as_jsvalue(&store.as_store_ref()), + // )?; + // js_sys::Reflect::set( + // &imports_object, + // &import_type.module().into(), + // &import_namespace.into(), + // )?; + // } + // import_externs.push(import); + // } else { + // #[cfg(feature = "tracing")] + // warn!( + // "import not found {}:{}", + // import_type.module(), + // import_type.name() + // ); + // } + // // in case the import is not found, the JS Wasm VM will handle + // // the error for us, so we don't need to handle it + // } + // Ok(( + // StoreHandle::new( + // store.as_store_mut().objects_mut(), + // WebAssembly::Instance::new(&self.module, &imports_object) + // .map_err(|e: JsValue| -> RuntimeError { e.into() })?, + // ), + // import_externs, + // )) + // } + /// Returns the name of the current module. /// /// This name is normally set in the WebAssembly bytecode by some @@ -691,6 +690,26 @@ impl Module { // pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator> + 'a { // unimplemented!(); // } + /// Get the custom sections of the module given a `name`. + /// + /// # Important + /// + /// Following the WebAssembly spec, one name can have multiple + /// custom sections. That's why an iterator (rather than one element) + /// is returned. + pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator> + 'a { + // TODO: implement on JavaScript + DefaultCustomSectionsIterator {} + } +} + +pub struct DefaultCustomSectionsIterator {} + +impl Iterator for DefaultCustomSectionsIterator { + type Item = Box<[u8]>; + fn next(&mut self) -> Option { + None + } } impl fmt::Debug for Module { diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 3ebb790cd..3d3a8c7fc 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -10,8 +10,8 @@ use std::mem::MaybeUninit; use std::slice; #[cfg(feature = "tracing")] use tracing::warn; -use wasmer_types::{LinearMemory, Pages, WASM_PAGE_SIZE}; -use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, VMExtern, VMMemory}; +use wasmer_types::{Pages, WASM_PAGE_SIZE}; +use wasmer_vm::{InternalStoreHandle, LinearMemory, MemoryError, StoreHandle, VMExtern, VMMemory}; use super::MemoryView; @@ -62,9 +62,8 @@ impl Memory { /// Create a memory object from an existing memory and attaches it to the store pub fn new_from_existing(new_store: &mut impl AsStoreMut, memory: VMMemory) -> Self { - Self { - handle: StoreHandle::new(new_store.objects_mut(), memory), - } + let handle = StoreHandle::new(new_store.objects_mut(), memory); + Self::from_vm_extern(new_store, handle.internal_handle()) } /// Returns the [`MemoryType`] of the `Memory`. @@ -184,6 +183,7 @@ impl Memory { mem.try_clone().map(|mem| mem.into()) } + /// To `VMExtern`. pub(crate) fn to_vm_extern(&self) -> VMExtern { VMExtern::Memory(self.handle.internal_handle()) } diff --git a/lib/api/src/sys/externals/memory_view.rs b/lib/api/src/sys/externals/memory_view.rs index f55aad1dd..ee1cbaea1 100644 --- a/lib/api/src/sys/externals/memory_view.rs +++ b/lib/api/src/sys/externals/memory_view.rs @@ -4,7 +4,8 @@ use std::convert::TryInto; use std::marker::PhantomData; use std::mem::MaybeUninit; use std::slice; -use wasmer_types::{LinearMemory, Pages}; +use wasmer_types::Pages; +use wasmer_vm::LinearMemory; use super::memory::MemoryBuffer; use super::Memory; diff --git a/lib/api/src/sys/module.rs b/lib/api/src/sys/module.rs index d7badd46a..fc22139da 100644 --- a/lib/api/src/sys/module.rs +++ b/lib/api/src/sys/module.rs @@ -2,6 +2,7 @@ use crate::sys::InstantiationError; use crate::AsStoreMut; use crate::AsStoreRef; use bytes::Bytes; +use std::borrow::Cow; use std::fmt; use std::io; use std::path::Path; @@ -71,12 +72,6 @@ impl IntoBytes for Vec { } } -impl IntoBytes for &Vec { - fn into_bytes(self) -> Bytes { - Bytes::from(self.clone()) - } -} - impl IntoBytes for &[u8] { fn into_bytes(self) -> Bytes { Bytes::from(self.to_vec()) @@ -95,6 +90,12 @@ impl IntoBytes for &str { } } +impl IntoBytes for Cow<'_, [u8]> { + fn into_bytes(self) -> Bytes { + Bytes::from(self.to_vec()) + } +} + impl Module { #[cfg(feature = "compiler")] /// Creates a new WebAssembly Module given the configuration @@ -161,15 +162,14 @@ impl Module { let mut bytes = bytes.into_bytes(); #[cfg(feature = "wat")] if bytes.starts_with(b"\0asm") == false { - let parsed_bytes = wat::parse_bytes(&bytes[..]).map_err(|e| { + bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { CompileError::Wasm(WasmError::Generic(format!( "Error when converting wat: {}", e ))) })?; - bytes = Bytes::from(parsed_bytes.to_vec()); } - Self::from_binary(store, bytes) + Self::from_binary(store, bytes.as_ref()) } #[cfg(feature = "compiler")] @@ -181,7 +181,7 @@ impl Module { let file_ref = file.as_ref(); let canonical = file_ref.canonicalize()?; let wasm_bytes = std::fs::read(file_ref)?; - let mut module = Self::new(store, wasm_bytes)?; + let mut module = Self::new(store, &wasm_bytes)?; // Set the module name to the absolute path of the filename. // This is useful for debugging the stack traces. let filename = canonical.as_path().to_str().unwrap(); @@ -195,12 +195,8 @@ impl Module { /// Opposed to [`Module::new`], this function is not compatible with /// the WebAssembly text format (if the "wat" feature is enabled for /// this crate). - pub fn from_binary( - store: &impl AsStoreRef, - binary: impl IntoBytes, - ) -> Result { - let binary = binary.into_bytes(); - Self::validate(store, binary.clone())?; + pub fn from_binary(store: &impl AsStoreRef, binary: &[u8]) -> Result { + Self::validate(store, binary)?; unsafe { Self::from_binary_unchecked(store, binary) } } @@ -309,9 +305,10 @@ impl Module { /// ``` pub unsafe fn deserialize( store: &impl AsStoreRef, - bytes: impl AsRef<[u8]>, + bytes: impl IntoBytes, ) -> Result { - let artifact = store.as_store_ref().engine().deserialize(bytes.as_ref())?; + let bytes = bytes.into_bytes(); + let artifact = store.as_store_ref().engine().deserialize(&bytes)?; Ok(Self::from_artifact(artifact)) } diff --git a/lib/api/src/sys/native.rs b/lib/api/src/sys/native.rs index 4a7d3a30c..ededff8a4 100644 --- a/lib/api/src/sys/native.rs +++ b/lib/api/src/sys/native.rs @@ -73,17 +73,72 @@ macro_rules! impl_native_traits { #[allow(unused_mut)] #[allow(clippy::too_many_arguments)] pub fn call(&self, store: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result { + let anyfunc = unsafe { + *self.func + .handle + .get(store.as_store_ref().objects()) + .anyfunc + .as_ptr() + .as_ref() + }; // Ensure all parameters come from the same context. if $(!FromToNativeWasmType::is_from_store(&$x, store) ||)* false { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); } - - let params_list = vec![ $( $x.to_native().into_raw(store) ),* ]; - self.call_raw(store, params_list) + // TODO: when `const fn` related features mature more, we can declare a single array + // of the correct size here. + let mut params_list = [ $( $x.to_native().into_raw(store) ),* ]; + let mut rets_list_array = Rets::empty_array(); + let rets_list: &mut [RawValue] = rets_list_array.as_mut(); + let using_rets_array; + let args_rets: &mut [RawValue] = if params_list.len() > rets_list.len() { + using_rets_array = false; + params_list.as_mut() + } else { + using_rets_array = true; + for (i, &arg) in params_list.iter().enumerate() { + rets_list[i] = arg; + } + rets_list.as_mut() + }; + unsafe { + wasmer_vm::wasmer_call_trampoline( + store.as_store_ref().signal_handler(), + anyfunc.vmctx, + anyfunc.call_trampoline, + anyfunc.func_ptr, + args_rets.as_mut_ptr() as *mut u8, + ) + }?; + let num_rets = rets_list.len(); + if !using_rets_array && num_rets > 0 { + let src_pointer = params_list.as_ptr(); + let rets_list = &mut rets_list_array.as_mut()[0] as *mut RawValue; + unsafe { + // TODO: we can probably remove this copy by doing some clever `transmute`s. + // we know it's not overlapping because `using_rets_array` is false + std::ptr::copy_nonoverlapping(src_pointer, + rets_list, + num_rets); + } + } + Ok(unsafe { Rets::from_array(store, rets_list_array) }) + // TODO: When the Host ABI and Wasm ABI are the same, we could do this instead: + // but we can't currently detect whether that's safe. + // + // let results = unsafe { + // wasmer_vm::catch_traps_with_result(self.vmctx, || { + // let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Rets::CStruct>(self.address()); + // // We always pass the vmctx + // f( self.vmctx, $( $x, )* ) + // }).map_err(RuntimeError::from_trap)? + // }; + // Ok(Rets::from_c_struct(results)) } + // FIXME: evaluate what's going on here, and compare with the significintaly expanded Self::call impl #[doc(hidden)] #[allow(missing_docs)] #[allow(unused_mut)] diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index 97dfc2774..aacfef3c3 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -25,20 +25,21 @@ doc = false required-features = ["headless"] [dependencies] -wasmer = { version = "=3.0.0-beta", path = "../api", default-features = false } -wasmer-compiler = { version = "=3.0.0-beta", path = "../compiler", features = ["compiler", ] } -wasmer-compiler-cranelift = { version = "=3.0.0-beta", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "=3.0.0-beta", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "=3.0.0-beta", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "=3.0.0-beta", path = "../emscripten", optional = true } -wasmer-vm = { version = "=3.0.0-beta", path = "../vm", features = [ "tracing" ] } -wasmer-wasi = { version = "=3.0.0-beta", path = "../wasi", features = [], optional = true } -wasmer-wasi-experimental-io-devices = { version = "=3.0.0-beta", path = "../wasi-experimental-io-devices", optional = true, features = ["link_external_libs"] } -wasmer-wast = { version = "=3.0.0-beta", path = "../../tests/lib/wast", optional = true } -wasmer-cache = { version = "=3.0.0-beta", path = "../cache", optional = true } -wasmer-types = { version = "=3.0.0-beta", path = "../types" } -wasmer-object = { version = "=3.0.0-beta", path = "../object", optional = true } -wasmer-vfs = { version = "=3.0.0-beta", path = "../vfs", default-features = false, features = ["host-fs"] } +wasmer = { version = "=3.0.0-rc.2", path = "../api", default-features = false } +wasmer-compiler = { version = "=3.0.0-rc.2", path = "../compiler", features = ["compiler", ] } +wasmer-compiler-cranelift = { version = "=3.0.0-rc.2", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "=3.0.0-rc.2", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "=3.0.0-rc.2", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "=3.0.0-rc.2", path = "../emscripten", optional = true } +wasmer-vm = { version = "=3.0.0-rc.2", path = "../vm", features = ["tracing"] } +wasmer-wasi = { version = "=3.0.0-rc.2", path = "../wasi", optional = true } +wasmer-wasi-experimental-io-devices = { version = "=3.0.0-rc.2", path = "../wasi-experimental-io-devices", optional = true, features = ["link_external_libs"] } +wasmer-wast = { version = "=3.0.0-rc.2", path = "../../tests/lib/wast", optional = true } +wasmer-cache = { version = "=3.0.0-rc.2", path = "../cache", optional = true } +wasmer-types = { version = "=3.0.0-rc.2", path = "../types" } +wasmer-registry = { version = "=3.0.0-rc.2", path = "../registry" } +wasmer-object = { version = "=3.0.0-rc.2", path = "../object", optional = true } +wasmer-vfs = { version = "=3.0.0-rc.2", path = "../vfs", default-features = false, features = ["host-fs"] } atty = "0.2" colored = "2.0" anyhow = "1.0" diff --git a/lib/vbus/Cargo.toml b/lib/vbus/Cargo.toml index 414fbad17..75b00420d 100644 --- a/lib/vbus/Cargo.toml +++ b/lib/vbus/Cargo.toml @@ -7,12 +7,14 @@ license = "MIT" edition = "2018" [dependencies] +# FIXME: evaluate if still needed +libc = { version = "^0.2", default-features = false, optional = true } thiserror = "1" tracing = { version = "0.1" } typetag = { version = "0.1", optional = true } slab = { version = "0.4", optional = true } -wasmer = { path = "../api", version = "=3.0.0-beta", default-features = false } -wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false } +wasmer = { path = "../api", version = "=3.0.0-rc.2", default-features = false } +wasmer-vfs = { path = "../vfs", version = "=3.0.0-rc.2", default-features = false } [features] default = ["mem_fs"] diff --git a/lib/vfs/Cargo.toml b/lib/vfs/Cargo.toml index f2ee209c7..63302d54e 100644 --- a/lib/vfs/Cargo.toml +++ b/lib/vfs/Cargo.toml @@ -13,6 +13,8 @@ tracing = { version = "0.1" } typetag = { version = "0.1", optional = true } serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } slab = { version = "0.4", optional = true } +webc = { version = "3.0.1", optional = true } +anyhow = { version = "1.0.66", optional = true } async-trait = { version = "^0.1" } lazy_static = "1.4" diff --git a/lib/vm/src/instance/mod.rs b/lib/vm/src/instance/mod.rs index 121480480..d6b6e2341 100644 --- a/lib/vm/src/instance/mod.rs +++ b/lib/vm/src/instance/mod.rs @@ -36,9 +36,8 @@ use std::sync::Arc; use wasmer_types::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, PrimaryMap}; use wasmer_types::{ DataIndex, DataInitializer, ElemIndex, ExportIndex, FunctionIndex, GlobalIndex, GlobalInit, - LinearMemory, LocalFunctionIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, - MemoryError, MemoryIndex, ModuleInfo, Pages, SignatureIndex, TableIndex, TableInitializer, - VMMemoryDefinition, VMOffsets, + LocalFunctionIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryError, + MemoryIndex, ModuleInfo, Pages, SignatureIndex, TableIndex, TableInitializer, VMOffsets, }; /// A WebAssembly instance. diff --git a/lib/vm/src/lib.rs b/lib/vm/src/lib.rs index 91a3aee9f..d36c6ef86 100644 --- a/lib/vm/src/lib.rs +++ b/lib/vm/src/lib.rs @@ -45,7 +45,7 @@ pub use crate::function_env::VMFunctionEnvironment; pub use crate::global::*; pub use crate::imports::Imports; pub use crate::instance::{InstanceAllocator, InstanceHandle}; -pub use crate::memory::{VMMemory, VMOwnedMemory, VMSharedMemory}; +pub use crate::memory::{initialize_memory_with_data, LinearMemory, VMMemory, VMOwnedMemory, VMSharedMemory}; pub use crate::mmap::Mmap; pub use crate::probestack::PROBESTACK; pub use crate::sig_registry::SignatureRegistry; @@ -56,11 +56,12 @@ pub use crate::table::{TableElement, VMTable}; pub use crate::trap::*; pub use crate::vmcontext::{ VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionContext, - VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryImport, - VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline, + VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, + VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline, }; pub use wasmer_types::LibCall; pub use wasmer_types::MemoryError; +pub use wasmer_types::MemoryStyle; use wasmer_types::RawValue; pub use wasmer_types::TableStyle; pub use wasmer_types::{MemoryStyle, VMMemoryDefinition}; diff --git a/lib/vm/src/memory.rs b/lib/vm/src/memory.rs index d66221e6b..33d15d1cd 100644 --- a/lib/vm/src/memory.rs +++ b/lib/vm/src/memory.rs @@ -5,16 +5,14 @@ //! //! `Memory` is to WebAssembly linear memories what `Table` is to WebAssembly tables. -use crate::{mmap::Mmap, store::MaybeInstanceOwned}; +use crate::trap::Trap; +use crate::{mmap::Mmap, store::MaybeInstanceOwned, vmcontext::VMMemoryDefinition}; use more_asserts::assert_ge; use std::cell::UnsafeCell; use std::convert::TryInto; use std::ptr::NonNull; -use std::sync::{Arc, RwLock}; -use wasmer_types::{ - Bytes, LinearMemory, MemoryError, MemoryRole, MemoryStyle, MemoryType, Pages, - VMMemoryDefinition, -}; +use std::slice; +use wasmer_types::{Bytes, MemoryError, MemoryStyle, MemoryType, Pages, MemoryRole, LinearMemory,}; // Represents a region of memory that plays a particular role #[derive(Debug, Clone)] @@ -36,7 +34,7 @@ struct WasmMmap { size: Pages, // List of the regions that have been marked regions: Vec, - // The owned memory definition used by the generated code + /// The owned memory definition used by the generated code vm_memory_definition: MaybeInstanceOwned, } @@ -130,43 +128,6 @@ impl WasmMmap { Ok(prev_pages) } - - /// Marks a region of the memory for a particular role - pub fn mark_region(&mut self, start: u64, end: u64, role: MemoryRole) { - self.regions.push(VMMemoryRegion { start, end, role }); - } - - /// Returns the role of a part of the memory - pub fn region(&self, pointer: u64) -> MemoryRole { - for region in self.regions.iter() { - if pointer >= region.start && pointer < region.end { - return region.role; - } - } - MemoryRole::default() - } - - /// Copies the memory - /// (in this case it performs a copy-on-write to save memory) - pub fn fork(&mut self) -> Result { - let mem_length = self.size.bytes().0; - let mut alloc = self - .alloc - .fork(Some(mem_length)) - .map_err(|err| MemoryError::Generic(err))?; - let base_ptr = alloc.as_mut_ptr(); - Ok(Self { - vm_memory_definition: MaybeInstanceOwned::Host(Box::new(UnsafeCell::new( - VMMemoryDefinition { - base: base_ptr, - current_length: mem_length, - }, - ))), - alloc, - size: self.size, - regions: self.regions.clone(), - }) - } } /// A linear memory instance. @@ -208,18 +169,6 @@ pub struct VMOwnedMemory { unsafe impl Send for VMOwnedMemory {} unsafe impl Sync for VMOwnedMemory {} -/// A shared linear memory instance. -#[derive(Debug, Clone)] -pub struct VMSharedMemory { - /// The underlying allocation. - mmap: Arc>, - /// Configuration of this memory - config: VMMemoryConfig, -} - -unsafe impl Send for VMSharedMemory {} -unsafe impl Sync for VMSharedMemory {} - impl VMOwnedMemory { /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. /// @@ -313,12 +262,12 @@ impl VMOwnedMemory { }; Ok(Self { - mmap: mmap, + mmap, config: VMMemoryConfig { maximum: memory.maximum, offset_guard_size: offset_guard_bytes, memory: *memory, - style: style.clone(), + style: *style, }, }) } @@ -388,12 +337,180 @@ impl LinearMemory for VMOwnedMemory { } } -impl Into for VMOwnedMemory { - fn into(self) -> VMMemory { - VMMemory(Box::new(self)) +impl From for VMMemory { + fn from(mem: VMOwnedMemory) -> Self { + Self(Box::new(mem)) } } +/// Represents linear memory that can be either owned or shared +#[derive(Debug)] +pub struct VMMemory(pub Box); + +impl From> for VMMemory { + fn from(mem: Box) -> Self { + Self(mem) + } +} + +impl LinearMemory for VMMemory { + /// Returns the type for this memory. + fn ty(&self) -> MemoryType { + self.0.ty() + } + + /// Returns the size of hte memory in pages + fn size(&self) -> Pages { + self.0.size() + } + + /// Grow memory by the specified amount of wasm pages. + /// + /// Returns `None` if memory can't be grown by the specified amount + /// of wasm pages. + fn grow(&mut self, delta: Pages) -> Result { + self.0.grow(delta) + } + + /// Returns the memory style for this memory. + fn style(&self) -> MemoryStyle { + self.0.style() + } + + /// Return a `VMMemoryDefinition` for exposing the memory to compiled wasm code. + fn vmmemory(&self) -> NonNull { + self.0.vmmemory() + } + + /// Attempts to clone this memory (if its clonable) + fn try_clone(&self) -> Option> { + self.0.try_clone() + } + + /// Initialize memory with data + unsafe fn initialize_with_data(&self, start: usize, data: &[u8]) -> Result<(), Trap> { + self.0.initialize_with_data(start, data) + } +} + +impl VMMemory { + /// Creates a new linear memory instance of the correct type with specified + /// minimum and maximum number of wasm pages. + /// + /// This creates a `Memory` with owned metadata: this can be used to create a memory + /// that will be imported into Wasm modules. + pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result { + Ok(Self(Box::new(VMOwnedMemory::new(memory, style)?))) + } + + /// Returns the number of pages in the allocated memory block + pub fn get_runtime_size(&self) -> u32 { + self.0.size().0 + } + + /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. + /// + /// This creates a `Memory` with metadata owned by a VM, pointed to by + /// `vm_memory_location`: this can be used to create a local memory. + /// + /// # Safety + /// - `vm_memory_location` must point to a valid location in VM memory. + pub unsafe fn from_definition( + memory: &MemoryType, + style: &MemoryStyle, + vm_memory_location: NonNull, + ) -> Result { + Ok(if memory.shared { + Self(Box::new(VMSharedMemory::from_definition( + memory, + style, + vm_memory_location, + )?)) + } else { + Self(Box::new(VMOwnedMemory::from_definition( + memory, + style, + vm_memory_location, + )?)) + }) + } + + /// Creates VMMemory from a custom implementation - the following into implementations + /// are natively supported + /// - VMOwnedMemory -> VMMemory + /// - Box -> VMMemory + pub fn from_custom(memory: IntoVMMemory) -> Self + where + IntoVMMemory: Into, + { + memory.into() + } +} + +#[doc(hidden)] +/// Default implementation to initialize memory with data +pub unsafe fn initialize_memory_with_data( + memory: &VMMemoryDefinition, + start: usize, + data: &[u8], +) -> Result<(), Trap> { + let mem_slice = slice::from_raw_parts_mut(memory.base, memory.current_length); + let end = start + data.len(); + let to_init = &mut mem_slice[start..end]; + to_init.copy_from_slice(data); + + Ok(()) +} + +/// Represents memory that is used by the WebAsssembly module +pub trait LinearMemory +where + Self: std::fmt::Debug + Send, +{ + /// Returns the type for this memory. + fn ty(&self) -> MemoryType; + + /// Returns the size of hte memory in pages + fn size(&self) -> Pages; + + /// Returns the memory style for this memory. + fn style(&self) -> MemoryStyle; + + /// Grow memory by the specified amount of wasm pages. + /// + /// Returns `None` if memory can't be grown by the specified amount + /// of wasm pages. + fn grow(&mut self, delta: Pages) -> Result; + + /// Return a `VMMemoryDefinition` for exposing the memory to compiled wasm code. + fn vmmemory(&self) -> NonNull; + + /// Attempts to clone this memory (if its clonable) + fn try_clone(&self) -> Option>; + + #[doc(hidden)] + /// # Safety + /// This function is unsafe because WebAssembly specification requires that data is always set at initialization time. + /// It should be the implementors responsibility to make sure this respects the spec + unsafe fn initialize_with_data(&self, start: usize, data: &[u8]) -> Result<(), Trap> { + let memory = self.vmmemory().as_ref(); + + initialize_memory_with_data(memory, start, data) + } +} + +/// A shared linear memory instance. +#[derive(Debug, Clone)] +pub struct VMSharedMemory { + /// The underlying allocation. + mmap: Arc>, + /// Configuration of this memory + config: VMMemoryConfig, +} + +unsafe impl Send for VMSharedMemory {} +unsafe impl Sync for VMSharedMemory {} + impl VMSharedMemory { /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. /// @@ -487,117 +604,3 @@ impl Into for VMSharedMemory { VMMemory(Box::new(self)) } } - -/// Represents linear memory that can be either owned or shared -#[derive(Debug)] -pub struct VMMemory(pub Box); - -impl Into for Box { - fn into(self) -> VMMemory { - VMMemory(self) - } -} - -impl LinearMemory for VMMemory { - /// Returns the type for this memory. - fn ty(&self) -> MemoryType { - self.0.ty() - } - - /// Returns the size of hte memory in pages - fn size(&self) -> Pages { - self.0.size() - } - - /// Grow memory by the specified amount of wasm pages. - /// - /// Returns `None` if memory can't be grown by the specified amount - /// of wasm pages. - fn grow(&mut self, delta: Pages) -> Result { - self.0.grow(delta) - } - - /// Returns the memory style for this memory. - fn style(&self) -> MemoryStyle { - self.0.style() - } - - /// Return a `VMMemoryDefinition` for exposing the memory to compiled wasm code. - fn vmmemory(&self) -> NonNull { - self.0.vmmemory() - } - - /// Attempts to clone this memory (if its clonable) - fn try_clone(&self) -> Option> { - self.0.try_clone() - } - - /// Copies this memory to a new memory - fn fork(&mut self) -> Result, MemoryError> { - self.0.fork() - } - - /// Marks a region of the memory for a particular role - fn mark_region(&mut self, start: u64, end: u64, role: MemoryRole) { - self.0.mark_region(start, end, role) - } - - /// Returns the role of a part of the memory - fn region(&self, pointer: u64) -> MemoryRole { - self.0.region(pointer) - } -} - -impl VMMemory { - /// Creates a new linear memory instance of the correct type with specified - /// minimum and maximum number of wasm pages. - /// - /// This creates a `Memory` with owned metadata: this can be used to create a memory - /// that will be imported into Wasm modules. - pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result { - Ok(if memory.shared { - Self(Box::new(VMSharedMemory::new(memory, style)?)) - } else { - Self(Box::new(VMOwnedMemory::new(memory, style)?)) - }) - } - - /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. - /// - /// This creates a `Memory` with metadata owned by a VM, pointed to by - /// `vm_memory_location`: this can be used to create a local memory. - /// - /// # Safety - /// - `vm_memory_location` must point to a valid location in VM memory. - pub unsafe fn from_definition( - memory: &MemoryType, - style: &MemoryStyle, - vm_memory_location: NonNull, - ) -> Result { - Ok(if memory.shared { - Self(Box::new(VMSharedMemory::from_definition( - memory, - style, - vm_memory_location, - )?)) - } else { - Self(Box::new(VMOwnedMemory::from_definition( - memory, - style, - vm_memory_location, - )?)) - }) - } - - /// Creates VMMemory from a custom implementation - the following into implementations - /// are natively supported - /// - VMOwnedMemory -> VMMemory - /// - VMSharedMemory -> VMMemory - /// - Box -> VMMemory - pub fn from_custom(memory: IntoVMMemory) -> VMMemory - where - IntoVMMemory: Into, - { - memory.into() - } -} diff --git a/lib/wasi-types/regenerate.sh b/lib/wasi-types/regenerate.sh index b7b976bd7..c7c767fa4 100755 --- a/lib/wasi-types/regenerate.sh +++ b/lib/wasi-types/regenerate.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash BASEDIR=$(dirname "$0") @@ -30,4 +30,4 @@ pwd `pwd`/target/debug/wasi-types-generator-extra cd .. -cargo fmt --all \ No newline at end of file +cargo fmt --all diff --git a/lib/wasi-types/src/bus.rs b/lib/wasi-types/src/bus.rs deleted file mode 100644 index 3cd543e5e..000000000 --- a/lib/wasi-types/src/bus.rs +++ /dev/null @@ -1,127 +0,0 @@ -use super::*; -use wasmer_derive::ValueType; - -pub type __wasi_small_hash_t = u64; - -pub type __wasi_hash_t = u128; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_option_hash_t { - pub tag: __wasi_option_t, - pub u: __wasi_hash_t, -} - -pub type __wasi_busdataformat_t = u8; -pub const __WASI_BUS_DATA_FORMAT_RAW: __wasi_busdataformat_t = 0; -pub const __WASI_BUS_DATA_FORMAT_BINCODE: __wasi_busdataformat_t = 1; -pub const __WASI_BUS_DATA_FORMAT_MESSAGE_PACK: __wasi_busdataformat_t = 2; -pub const __WASI_BUS_DATA_FORMAT_JSON: __wasi_busdataformat_t = 3; -pub const __WASI_BUS_DATA_FORMAT_YAML: __wasi_busdataformat_t = 4; -pub const __WASI_BUS_DATA_FORMAT_XML: __wasi_busdataformat_t = 5; -pub const __WASI_BUS_DATA_FORMAT_RKYV: __wasi_busdataformat_t = 6; - -pub type __wasi_buseventtype_t = u8; -pub const __WASI_BUS_EVENT_TYPE_NOOP: __wasi_buseventtype_t = 0; -pub const __WASI_BUS_EVENT_TYPE_EXIT: __wasi_buseventtype_t = 1; -pub const __WASI_BUS_EVENT_TYPE_CALL: __wasi_buseventtype_t = 2; -pub const __WASI_BUS_EVENT_TYPE_RESULT: __wasi_buseventtype_t = 3; -pub const __WASI_BUS_EVENT_TYPE_FAULT: __wasi_buseventtype_t = 4; -pub const __WASI_BUS_EVENT_TYPE_CLOSE: __wasi_buseventtype_t = 5; - -pub type __wasi_bid_t = u32; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_option_bid_t { - pub tag: __wasi_option_t, - pub bid: __wasi_bid_t, -} - -pub type __wasi_cid_t = u64; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_option_fd_t { - pub tag: __wasi_option_t, - pub fd: __wasi_fd_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_option_cid_t { - pub tag: __wasi_option_t, - pub cid: __wasi_cid_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_bus_handles_t { - pub bid: __wasi_bid_t, - pub stdin: __wasi_option_fd_t, - pub stdout: __wasi_option_fd_t, - pub stderr: __wasi_option_fd_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_busevent_exit_t { - pub bid: __wasi_bid_t, - pub rval: __wasi_exitcode_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_busevent_call_t { - pub parent: __wasi_option_cid_t, - pub cid: __wasi_cid_t, - pub format: __wasi_busdataformat_t, - pub topic_hash: __wasi_hash_t, - pub fd: __wasi_fd_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_busevent_result_t { - pub format: __wasi_busdataformat_t, - pub cid: __wasi_cid_t, - pub fd: __wasi_fd_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_busevent_fault_t { - pub cid: __wasi_cid_t, - pub err: __bus_errno_t, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_busevent_close_t { - pub cid: __wasi_cid_t, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union __wasi_busevent_u { - pub noop: u8, - pub exit: __wasi_busevent_exit_t, - pub call: __wasi_busevent_call_t, - pub result: __wasi_busevent_result_t, - pub fault: __wasi_busevent_fault_t, - pub close: __wasi_busevent_close_t, -} - -#[derive(Copy, Clone, ValueType)] -#[repr(C)] -pub struct __wasi_busevent_t { - pub tag: __wasi_buseventtype_t, - pub padding: [u8; 63], -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub struct __wasi_busevent_t2 { - pub tag: __wasi_buseventtype_t, - pub u: __wasi_busevent_u, -} diff --git a/lib/wasi-types/src/file.rs b/lib/wasi-types/src/file.rs deleted file mode 100644 index 92f0e74a6..000000000 --- a/lib/wasi-types/src/file.rs +++ /dev/null @@ -1,340 +0,0 @@ -use crate::*; -#[cfg(feature = "enable-serde")] -use serde::{Deserialize, Serialize}; -use std::{ - fmt, - mem::{self, MaybeUninit}, -}; -use wasmer_derive::ValueType; -use wasmer_types::ValueType; - -pub type __wasi_device_t = u64; - -pub type __wasi_fd_t = u32; -pub const __WASI_STDIN_FILENO: __wasi_fd_t = 0; -pub const __WASI_STDOUT_FILENO: __wasi_fd_t = 1; -pub const __WASI_STDERR_FILENO: __wasi_fd_t = 2; - -pub type __wasi_pid_t = u32; -pub type __wasi_tid_t = u32; - -pub type __wasi_tl_key_t = u32; -pub type __wasi_tl_val_t = u64; - -pub type __wasi_fdflags_t = u16; -pub const __WASI_FDFLAG_APPEND: __wasi_fdflags_t = 1 << 0; -pub const __WASI_FDFLAG_DSYNC: __wasi_fdflags_t = 1 << 1; -pub const __WASI_FDFLAG_NONBLOCK: __wasi_fdflags_t = 1 << 2; -pub const __WASI_FDFLAG_RSYNC: __wasi_fdflags_t = 1 << 3; -pub const __WASI_FDFLAG_SYNC: __wasi_fdflags_t = 1 << 4; - -pub type __wasi_eventfdflags = u16; -pub const __WASI_EVENTFDFLAGS_SEMAPHORE: __wasi_eventfdflags = 1 << 0; - -pub type __wasi_preopentype_t = u8; -pub const __WASI_PREOPENTYPE_DIR: __wasi_preopentype_t = 0; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_prestat_u_dir_t { - pub pr_name_len: u32, -} - -#[derive(Copy, Clone)] -#[repr(C)] -pub union __wasi_prestat_u { - dir: __wasi_prestat_u_dir_t, -} - -impl fmt::Debug for __wasi_prestat_u { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "__wasi_prestat_u") - } -} - -#[derive(Debug, Copy, Clone)] -#[repr(C)] -pub struct __wasi_prestat_t { - pub pr_type: __wasi_preopentype_t, - pub u: __wasi_prestat_u, -} - -#[derive(Copy, Clone)] -pub enum PrestatEnum { - Dir { pr_name_len: u32 }, -} - -impl PrestatEnum { - pub fn untagged(self) -> __wasi_prestat_u { - match self { - PrestatEnum::Dir { pr_name_len } => __wasi_prestat_u { - dir: __wasi_prestat_u_dir_t { pr_name_len }, - }, - } - } -} - -impl __wasi_prestat_t { - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn tagged(&self) -> Option { - match self.pr_type { - __WASI_PREOPENTYPE_DIR => Some(PrestatEnum::Dir { - pr_name_len: unsafe { self.u.dir.pr_name_len }, - }), - _ => None, - } - } -} - -unsafe impl ValueType for __wasi_prestat_t { - fn zero_padding_bytes(&self, bytes: &mut [MaybeUninit]) { - macro_rules! field { - ($($f:tt)*) => { - &self.$($f)* as *const _ as usize - self as *const _ as usize - }; - } - macro_rules! field_end { - ($($f:tt)*) => { - field!($($f)*) + mem::size_of_val(&self.$($f)*) - }; - } - macro_rules! zero { - ($start:expr, $end:expr) => { - for i in $start..$end { - bytes[i] = MaybeUninit::new(0); - } - }; - } - self.pr_type - .zero_padding_bytes(&mut bytes[field!(pr_type)..field_end!(pr_type)]); - zero!(field_end!(pr_type), field!(u)); - match self.pr_type { - __WASI_PREOPENTYPE_DIR => unsafe { - self.u - .dir - .zero_padding_bytes(&mut bytes[field!(u.dir)..field_end!(u.dir)]); - zero!(field_end!(u.dir), field_end!(u)); - }, - _ => zero!(field!(u), field_end!(u)), - } - zero!(field_end!(u), mem::size_of_val(self)); - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, ValueType)] -#[repr(C)] -pub struct __wasi_fdstat_t { - pub fs_filetype: __wasi_filetype_t, - pub fs_flags: __wasi_fdflags_t, - pub fs_rights_base: __wasi_rights_t, - pub fs_rights_inheriting: __wasi_rights_t, -} - -pub type __wasi_filedelta_t = i64; - -pub type __wasi_filesize_t = u64; - -#[derive(Copy, Clone, PartialEq, Eq, ValueType)] -#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] -#[repr(C)] -pub struct __wasi_filestat_t { - pub st_dev: __wasi_device_t, - pub st_ino: __wasi_inode_t, - pub st_filetype: __wasi_filetype_t, - pub st_nlink: __wasi_linkcount_t, - pub st_size: __wasi_filesize_t, - pub st_atim: __wasi_timestamp_t, - pub st_mtim: __wasi_timestamp_t, - pub st_ctim: __wasi_timestamp_t, -} - -impl Default for __wasi_filestat_t { - fn default() -> Self { - __wasi_filestat_t { - st_dev: Default::default(), - st_ino: Default::default(), - st_filetype: __WASI_FILETYPE_UNKNOWN, - st_nlink: 1, - st_size: Default::default(), - st_atim: Default::default(), - st_mtim: Default::default(), - st_ctim: Default::default(), - } - } -} - -impl fmt::Debug for __wasi_filestat_t { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let convert_ts_into_time_string = |ts| { - let tspec = ::time::OffsetDateTime::from_unix_timestamp_nanos(ts); - format!("{} ({})", tspec.format("%a, %d %b %Y %T %z"), ts) - }; - f.debug_struct("__wasi_filestat_t") - .field("st_dev", &self.st_dev) - .field("st_ino", &self.st_ino) - .field( - "st_filetype", - &format!( - "{} ({})", - wasi_filetype_to_name(self.st_filetype), - self.st_filetype, - ), - ) - .field("st_nlink", &self.st_nlink) - .field("st_size", &self.st_size) - .field( - "st_atim", - &convert_ts_into_time_string(self.st_atim as i128), - ) - .field( - "st_mtim", - &convert_ts_into_time_string(self.st_mtim as i128), - ) - .field( - "st_ctim", - &convert_ts_into_time_string(self.st_ctim as i128), - ) - .finish() - } -} - -pub fn wasi_filetype_to_name(ft: __wasi_filetype_t) -> &'static str { - match ft { - __WASI_FILETYPE_UNKNOWN => "Unknown", - __WASI_FILETYPE_BLOCK_DEVICE => "Block device", - __WASI_FILETYPE_CHARACTER_DEVICE => "Character device", - __WASI_FILETYPE_DIRECTORY => "Directory", - __WASI_FILETYPE_REGULAR_FILE => "Regular file", - __WASI_FILETYPE_SOCKET_DGRAM => "Socket dgram", - __WASI_FILETYPE_SOCKET_STREAM => "Socket stream", - __WASI_FILETYPE_SYMBOLIC_LINK => "Symbolic link", - _ => "Invalid", - } -} - -pub type __wasi_filetype_t = u8; -pub const __WASI_FILETYPE_UNKNOWN: __wasi_filetype_t = 0; -pub const __WASI_FILETYPE_BLOCK_DEVICE: __wasi_filetype_t = 1; -pub const __WASI_FILETYPE_CHARACTER_DEVICE: __wasi_filetype_t = 2; -pub const __WASI_FILETYPE_DIRECTORY: __wasi_filetype_t = 3; -pub const __WASI_FILETYPE_REGULAR_FILE: __wasi_filetype_t = 4; -pub const __WASI_FILETYPE_SOCKET_DGRAM: __wasi_filetype_t = 5; -pub const __WASI_FILETYPE_SOCKET_STREAM: __wasi_filetype_t = 6; -pub const __WASI_FILETYPE_SYMBOLIC_LINK: __wasi_filetype_t = 7; -pub const __WASI_FILETYPE_SOCKET_RAW: __wasi_filetype_t = 8; -pub const __WASI_FILETYPE_SOCKET_SEQPACKET: __wasi_filetype_t = 9; - -pub type __wasi_fstflags_t = u16; -pub const __WASI_FILESTAT_SET_ATIM: __wasi_fstflags_t = 1 << 0; -pub const __WASI_FILESTAT_SET_ATIM_NOW: __wasi_fstflags_t = 1 << 1; -pub const __WASI_FILESTAT_SET_MTIM: __wasi_fstflags_t = 1 << 2; -pub const __WASI_FILESTAT_SET_MTIM_NOW: __wasi_fstflags_t = 1 << 3; - -pub type __wasi_inode_t = u64; - -pub type __wasi_linkcount_t = u64; - -pub type __wasi_lookupflags_t = u32; -pub const __WASI_LOOKUP_SYMLINK_FOLLOW: __wasi_lookupflags_t = 1 << 0; - -pub type __wasi_oflags_t = u16; -pub const __WASI_O_CREAT: __wasi_oflags_t = 1 << 0; -pub const __WASI_O_DIRECTORY: __wasi_oflags_t = 1 << 1; -pub const __WASI_O_EXCL: __wasi_oflags_t = 1 << 2; -pub const __WASI_O_TRUNC: __wasi_oflags_t = 1 << 3; - -pub type __wasi_rights_t = u64; -pub const __WASI_RIGHT_FD_DATASYNC: __wasi_rights_t = 1 << 0; -pub const __WASI_RIGHT_FD_READ: __wasi_rights_t = 1 << 1; -pub const __WASI_RIGHT_FD_SEEK: __wasi_rights_t = 1 << 2; -pub const __WASI_RIGHT_FD_FDSTAT_SET_FLAGS: __wasi_rights_t = 1 << 3; -pub const __WASI_RIGHT_FD_SYNC: __wasi_rights_t = 1 << 4; -pub const __WASI_RIGHT_FD_TELL: __wasi_rights_t = 1 << 5; -pub const __WASI_RIGHT_FD_WRITE: __wasi_rights_t = 1 << 6; -pub const __WASI_RIGHT_FD_ADVISE: __wasi_rights_t = 1 << 7; -pub const __WASI_RIGHT_FD_ALLOCATE: __wasi_rights_t = 1 << 8; -pub const __WASI_RIGHT_PATH_CREATE_DIRECTORY: __wasi_rights_t = 1 << 9; -pub const __WASI_RIGHT_PATH_CREATE_FILE: __wasi_rights_t = 1 << 10; -pub const __WASI_RIGHT_PATH_LINK_SOURCE: __wasi_rights_t = 1 << 11; -pub const __WASI_RIGHT_PATH_LINK_TARGET: __wasi_rights_t = 1 << 12; -pub const __WASI_RIGHT_PATH_OPEN: __wasi_rights_t = 1 << 13; -pub const __WASI_RIGHT_FD_READDIR: __wasi_rights_t = 1 << 14; -pub const __WASI_RIGHT_PATH_READLINK: __wasi_rights_t = 1 << 15; -pub const __WASI_RIGHT_PATH_RENAME_SOURCE: __wasi_rights_t = 1 << 16; -pub const __WASI_RIGHT_PATH_RENAME_TARGET: __wasi_rights_t = 1 << 17; -pub const __WASI_RIGHT_PATH_FILESTAT_GET: __wasi_rights_t = 1 << 18; -pub const __WASI_RIGHT_PATH_FILESTAT_SET_SIZE: __wasi_rights_t = 1 << 19; -pub const __WASI_RIGHT_PATH_FILESTAT_SET_TIMES: __wasi_rights_t = 1 << 20; -pub const __WASI_RIGHT_FD_FILESTAT_GET: __wasi_rights_t = 1 << 21; -pub const __WASI_RIGHT_FD_FILESTAT_SET_SIZE: __wasi_rights_t = 1 << 22; -pub const __WASI_RIGHT_FD_FILESTAT_SET_TIMES: __wasi_rights_t = 1 << 23; -pub const __WASI_RIGHT_PATH_SYMLINK: __wasi_rights_t = 1 << 24; -pub const __WASI_RIGHT_PATH_REMOVE_DIRECTORY: __wasi_rights_t = 1 << 25; -pub const __WASI_RIGHT_PATH_UNLINK_FILE: __wasi_rights_t = 1 << 26; -pub const __WASI_RIGHT_POLL_FD_READWRITE: __wasi_rights_t = 1 << 27; -pub const __WASI_RIGHT_SOCK_SHUTDOWN: __wasi_rights_t = 1 << 28; -pub const __WASI_RIGHT_SOCK_ACCEPT: __wasi_rights_t = 1 << 29; -pub const __WASI_RIGHT_SOCK_CONNECT: __wasi_rights_t = 1 << 30; -pub const __WASI_RIGHT_SOCK_LISTEN: __wasi_rights_t = 1 << 31; -pub const __WASI_RIGHT_SOCK_BIND: __wasi_rights_t = 1 << 32; -pub const __WASI_RIGHT_SOCK_RECV: __wasi_rights_t = 1 << 33; -pub const __WASI_RIGHT_SOCK_SEND: __wasi_rights_t = 1 << 34; -pub const __WASI_RIGHT_SOCK_ADDR_LOCAL: __wasi_rights_t = 1 << 35; -pub const __WASI_RIGHT_SOCK_ADDR_REMOTE: __wasi_rights_t = 1 << 36; -pub const __WASI_RIGHT_SOCK_RECV_FROM: __wasi_rights_t = 1 << 37; -pub const __WASI_RIGHT_SOCK_SEND_TO: __wasi_rights_t = 1 << 38; - -/// function for debugging rights issues -#[allow(dead_code)] -pub fn print_right_set(rights: __wasi_rights_t) { - // BTreeSet for consistent order - let mut right_set = std::collections::BTreeSet::new(); - for i in 0..28 { - let cur_right = rights & (1 << i); - if cur_right != 0 { - right_set.insert(right_to_string(cur_right).unwrap_or("INVALID RIGHT")); - } - } - println!("{:#?}", right_set); -} - -/// expects a single right, returns None if out of bounds or > 1 bit set -pub fn right_to_string(right: __wasi_rights_t) -> Option<&'static str> { - Some(match right { - __WASI_RIGHT_FD_DATASYNC => "__WASI_RIGHT_FD_DATASYNC", - __WASI_RIGHT_FD_READ => "__WASI_RIGHT_FD_READ", - __WASI_RIGHT_FD_SEEK => "__WASI_RIGHT_FD_SEEK", - __WASI_RIGHT_FD_FDSTAT_SET_FLAGS => "__WASI_RIGHT_FD_FDSTAT_SET_FLAGS", - __WASI_RIGHT_FD_SYNC => "__WASI_RIGHT_FD_SYNC", - __WASI_RIGHT_FD_TELL => "__WASI_RIGHT_FD_TELL", - __WASI_RIGHT_FD_WRITE => "__WASI_RIGHT_FD_WRITE", - __WASI_RIGHT_FD_ADVISE => "__WASI_RIGHT_FD_ADVISE", - __WASI_RIGHT_FD_ALLOCATE => "__WASI_RIGHT_FD_ALLOCATE", - __WASI_RIGHT_PATH_CREATE_DIRECTORY => "__WASI_RIGHT_PATH_CREATE_DIRECTORY", - __WASI_RIGHT_PATH_CREATE_FILE => "__WASI_RIGHT_PATH_CREATE_FILE", - __WASI_RIGHT_PATH_LINK_SOURCE => "__WASI_RIGHT_PATH_LINK_SOURCE", - __WASI_RIGHT_PATH_LINK_TARGET => "__WASI_RIGHT_PATH_LINK_TARGET", - __WASI_RIGHT_PATH_OPEN => "__WASI_RIGHT_PATH_OPEN", - __WASI_RIGHT_FD_READDIR => "__WASI_RIGHT_FD_READDIR", - __WASI_RIGHT_PATH_READLINK => "__WASI_RIGHT_PATH_READLINK", - __WASI_RIGHT_PATH_RENAME_SOURCE => "__WASI_RIGHT_PATH_RENAME_SOURCE", - __WASI_RIGHT_PATH_RENAME_TARGET => "__WASI_RIGHT_PATH_RENAME_TARGET", - __WASI_RIGHT_PATH_FILESTAT_GET => "__WASI_RIGHT_PATH_FILESTAT_GET", - __WASI_RIGHT_PATH_FILESTAT_SET_SIZE => "__WASI_RIGHT_PATH_FILESTAT_SET_SIZE", - __WASI_RIGHT_PATH_FILESTAT_SET_TIMES => "__WASI_RIGHT_PATH_FILESTAT_SET_TIMES", - __WASI_RIGHT_FD_FILESTAT_GET => "__WASI_RIGHT_FD_FILESTAT_GET", - __WASI_RIGHT_FD_FILESTAT_SET_SIZE => "__WASI_RIGHT_FD_FILESTAT_SET_SIZE", - __WASI_RIGHT_FD_FILESTAT_SET_TIMES => "__WASI_RIGHT_FD_FILESTAT_SET_TIMES", - __WASI_RIGHT_PATH_SYMLINK => "__WASI_RIGHT_PATH_SYMLINK", - __WASI_RIGHT_PATH_UNLINK_FILE => "__WASI_RIGHT_PATH_UNLINK_FILE", - __WASI_RIGHT_PATH_REMOVE_DIRECTORY => "__WASI_RIGHT_PATH_REMOVE_DIRECTORY", - __WASI_RIGHT_POLL_FD_READWRITE => "__WASI_RIGHT_POLL_FD_READWRITE", - __WASI_RIGHT_SOCK_SHUTDOWN => "__WASI_RIGHT_SOCK_SHUTDOWN", - _ => return None, - }) -} - -pub type __wasi_whence_t = u8; -pub const __WASI_WHENCE_SET: __wasi_whence_t = 0; -pub const __WASI_WHENCE_CUR: __wasi_whence_t = 1; -pub const __WASI_WHENCE_END: __wasi_whence_t = 2; diff --git a/lib/wasi-types/src/lib.rs b/lib/wasi-types/src/lib.rs index e95d9eb1f..2e54b95e5 100644 --- a/lib/wasi-types/src/lib.rs +++ b/lib/wasi-types/src/lib.rs @@ -8,37 +8,36 @@ pub mod wasi; fn fail_if_wit_files_arent_up_to_date() { use wit_bindgen_core::Generator; -// Needed for #[derive(ValueType)] -extern crate wasmer_types as wasmer; - -mod advice; -mod asyncify; -mod bus; -mod directory; -mod error; -mod event; -mod file; -mod io; -mod net; -mod signal; -mod subscription; -mod time; -mod versions; - -pub use crate::time::*; -pub use advice::*; -pub use asyncify::*; -pub use bus::*; -pub use directory::*; -pub use error::*; -pub use event::*; -pub use file::*; -pub use io::*; -pub use net::*; -pub use signal::*; -pub use subscription::*; -pub use versions::*; - -pub type __wasi_exitcode_t = u32; - -pub type __wasi_userdata_t = u64; + let output_wit = concat!(env!("CARGO_MANIFEST_DIR"), "/wit-clean/output.wit"); + let bindings_target = + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/wasi/bindings.rs")); + let mut generator = wit_bindgen_rust_wasm::Opts { + ..wit_bindgen_rust_wasm::Opts::default() + } + .build(); + let output_wit_parsed = wit_parser::Interface::parse_file(output_wit).unwrap(); + let imports = vec![output_wit_parsed]; + let exports = vec![]; + let mut files = Default::default(); + generator.generate_all( + &imports, &exports, &mut files, /* generate_structs */ true, + ); + let generated = files + .iter() + .filter_map(|(k, v)| if k == "bindings.rs" { Some(v) } else { None }) + .next() + .unwrap(); + let generated_str = String::from_utf8_lossy(generated); + let generated_str = generated_str + .lines() + .map(|s| s.to_string()) + .collect::>() + .join("\r\n"); + let generated_str = generated_str.replace("mod output {", "pub mod output {"); + let bindings_target = bindings_target + .lines() + .map(|s| s.to_string()) + .collect::>() + .join("\r\n"); + pretty_assertions::assert_eq!(generated_str, bindings_target); // output.wit out of date? regenerate bindings.rs +} diff --git a/lib/wasi-types/src/signal.rs b/lib/wasi-types/src/signal.rs deleted file mode 100644 index 7b23f05c4..000000000 --- a/lib/wasi-types/src/signal.rs +++ /dev/null @@ -1,42 +0,0 @@ -use wasmer_derive::ValueType; - -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, ValueType)] -#[repr(C)] -pub struct __wasi_stack_snaphost_t { - pub user: u64, - pub hash: u128, -} - -pub type __wasi_longsize_t = u64; - -pub type __wasi_signal_t = u8; -pub const __WASI_SIGHUP: u8 = 1; -pub const __WASI_SIGINT: u8 = 2; -pub const __WASI_SIGQUIT: u8 = 3; -pub const __WASI_SIGILL: u8 = 4; -pub const __WASI_SIGTRAP: u8 = 5; -pub const __WASI_SIGABRT: u8 = 6; -pub const __WASI_SIGBUS: u8 = 7; -pub const __WASI_SIGFPE: u8 = 8; -pub const __WASI_SIGKILL: u8 = 9; -pub const __WASI_SIGUSR1: u8 = 10; -pub const __WASI_SIGSEGV: u8 = 11; -pub const __WASI_SIGUSR2: u8 = 12; -pub const __WASI_SIGPIPE: u8 = 13; -pub const __WASI_SIGALRM: u8 = 14; -pub const __WASI_SIGTERM: u8 = 15; -pub const __WASI_SIGCHLD: u8 = 16; -pub const __WASI_SIGCONT: u8 = 17; -pub const __WASI_SIGSTOP: u8 = 18; -pub const __WASI_SIGTSTP: u8 = 19; -pub const __WASI_SIGTTIN: u8 = 20; -pub const __WASI_SIGTTOU: u8 = 21; -pub const __WASI_SIGURG: u8 = 22; -pub const __WASI_SIGXCPU: u8 = 23; -pub const __WASI_SIGXFSZ: u8 = 24; -pub const __WASI_SIGVTALRM: u8 = 25; -pub const __WASI_SIGPROF: u8 = 26; -pub const __WASI_SIGWINCH: u8 = 27; -pub const __WASI_SIGPOLL: u8 = 28; -pub const __WASI_SIGPWR: u8 = 29; -pub const __WASI_SIGSYS: u8 = 30; diff --git a/lib/wasi-types/wit-clean/typenames.wit b/lib/wasi-types/wit-clean/typenames.wit index a4bf2927b..3d770aefc 100644 --- a/lib/wasi-types/wit-clean/typenames.wit +++ b/lib/wasi-types/wit-clean/typenames.wit @@ -1236,4 +1236,37 @@ enum timeout { write, connect, accept, -} \ No newline at end of file +} + +// FIXME: move to wasix file and re-work naming? +type longsize = u64; +type thread-local-key = u32; +type thread-local-value = u64; +type small-hash = u64; +type hash = tuple; + +// FIXME: should be optional? +record option-hash { + tag: option-tag, + hash: hash, +} + +record stack-snapshot { + user: u64, + hash: hash, +} + +record bus-event { + tag: bus-event-type, + // [u8; 63] == 504 bytes == + // FIXME: why is this padding here? + padding: tuple, +} + +// FIXME: what's going on here? +record bus-event2 { + tag: bus-event-type, + event: bus-event, +} + +// FIXME: port other stuff from deleted diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index ba3570b30..9c57051d6 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -16,29 +16,34 @@ thiserror = "1" generational-arena = { version = "0.2" } tracing = "0.1" getrandom = "0.2" -wasmer-wasi-types = { path = "../wasi-types", version = "=3.0.0-beta" } -wasmer = { path = "../api", version = "=3.0.0-beta", default-features = false } -wasmer-types = { path = "../types", version = "=3.0.0-beta" } -wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false, features = ["mem-fs"] } -wasmer-vbus = { path = "../vbus", version = "=3.0.0-beta", default-features = false } -wasmer-vnet = { path = "../vnet", version = "=3.0.0-beta", default-features = false } -wasmer-wasi-local-networking = { path = "../wasi-local-networking", version = "=3.0.0-beta", default-features = false, optional = true } +wasmer-wasi-types = { path = "../wasi-types", version = "=3.0.0-rc.2" } +# FIXME: evaluate if needed +wasmer-types = { path = "../types", version = "=3.0.0-rc.2" } +wasmer = { path = "../api", version = "=3.0.0-rc.2", default-features = false } +wasmer-vfs = { path = "../vfs", version = "=3.0.0-rc.2", default-features = false, features = ["mem-fs"] } +wasmer-vbus = { path = "../vbus", version = "=3.0.0-rc.2", default-features = false } +wasmer-vnet = { path = "../vnet", version = "=3.0.0-rc.2", default-features = false } +wasmer-wasi-local-networking = { path = "../wasi-local-networking", version = "=3.0.0-rc.2", default-features = false, optional = true } typetag = { version = "0.1", optional = true } serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } bincode = { version = "1.3", optional = true } chrono = { version = "^0.4", default-features = false, features = [ "wasmbind", "std", "clock" ], optional = true } derivative = { version = "^2" } bytes = "1" +webc = { version = "3.0.1", optional = true, default-features = false, features = ["std", "mmap"] } +serde_cbor = { version = "0.11.2", optional = true } +anyhow = { version = "1.0.66", optional = true } +wasmer-emscripten = { path = "../emscripten", version = "=3.0.0-rc.2", optional = true } lazy_static = "1.4" sha2 = { version = "0.10" } waker-fn = { version = "1.1" } cooked-waker = "^5" rand = "0.8" -webc = { version = "0.1", path = "../../../pirita/crates/webc" } # used by feature='os' tokio = { version = "1", features = [ "sync", "macros" ], default_features = false, optional = true } async-trait = { version = "^0.1", optional = true } urlencoding = { version = "^2", optional = true } +# FIXME: proper dependency! webc-vfs = { version = "0.1", path = "../../../pirita/crates/webc-vfs", optional = true } serde_derive = { version = "^1", optional = true } serde_json = { version = "^1", optional = true } @@ -79,7 +84,11 @@ tracing-subscriber = { version = "^0.2" } default = ["sys-default"] wasix = [] -sys = ["wasmer/sys", "webc/mmap"] +webc_runner = ["webc", "serde_cbor", "anyhow", "serde", "wasmer/compiler", "wasmer/cranelift"] +webc_runner_rt_emscripten = ["wasmer-emscripten"] +webc_runner_rt_wasi = [] + +sys = ["wasmer/sys", "wasmer-wasi-types/sys", "wasix", "webc/mmap"] sys-default = ["wasmer/wat", "wasmer/compiler", "sys", "os", "logging", "host-fs", "sys-poll", "sys-thread", "host-vnet", "host-threads", "host-reqwest" ] sys-poll = [] sys-thread = ["tokio/rt", "tokio/rt-multi-thread"] diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 92a05f066..83ddbaf11 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -1,3 +1,5 @@ +// FIXME: merge with ./lib.rs_upstream + #![deny(unused_mut)] #![doc(html_favicon_url = "https://wasmer.io/images/icons/favicon-32x32.png")] #![doc(html_logo_url = "https://github.com/wasmerio.png?size=200")] @@ -103,13 +105,11 @@ use std::cell::RefCell; use std::ops::Deref; use std::sync::atomic::{AtomicU32, Ordering}; use thiserror::Error; -use tracing::trace; use wasmer::{ imports, namespace, AsStoreMut, AsStoreRef, ExportError, Exports, Function, FunctionEnv, Global, Imports, Instance, Memory, Memory32, Memory64, MemoryAccessError, MemorySize, MemoryView, Module, Store, TypedFunction, Value, }; -use wasmer_wasi_types::wasi::{BusErrno, Errno, Snapshot0Clockid}; pub use runtime::{ PluggableRuntimeImplementation, SpawnedMemory, VirtualTaskManager, WasiRuntimeImplementation, @@ -982,33 +982,6 @@ impl WasiFunctionEnv { Ok(()) } - /// Initializes the WasiEnv using the instance exports - /// (this must be executed before attempting to use it) - /// (as the stores can not by themselves be passed between threads we can store the module - /// in a thread-local variables and use it later - for multithreading) - pub fn initialize( - &mut self, - store: &mut impl AsStoreMut, - instance: &Instance, - ) -> Result<(), ExportError> { - // List all the exports and imports - for ns in instance.module().exports() { - //trace!("module::export - {} ({:?})", ns.name(), ns.ty()); - trace!("module::export - {}", ns.name()); - } - for ns in instance.module().imports() { - trace!("module::import - {}::{}", ns.module(), ns.name()); - } - - // First we get the malloc function which if it exists will be used to - // create the pthread_self structure - let memory = instance.exports.get_memory("memory")?.clone(); - let env = self.data_mut(store); - env.set_memory(memory); - - Ok(()) - } - /// Like `import_object` but containing all the WASI versions detected in /// the module. pub fn import_object_for_all_wasi_versions( @@ -1523,7 +1496,6 @@ fn generate_import_object_snapshot1( } /// Combines a state generating function with the import list for snapshot 1 -#[cfg(feature = "wasix")] fn generate_import_object_wasix32_v1( store: &mut impl AsStoreMut, env: &FunctionEnv, @@ -1534,7 +1506,6 @@ fn generate_import_object_wasix32_v1( } } -#[cfg(feature = "wasix")] fn generate_import_object_wasix64_v1( store: &mut impl AsStoreMut, env: &FunctionEnv, @@ -1545,20 +1516,20 @@ fn generate_import_object_wasix64_v1( } } -fn mem_error_to_wasi(err: MemoryAccessError) -> Errno { +fn mem_error_to_wasi(err: MemoryAccessError) -> types::__wasi_errno_t { match err { - MemoryAccessError::HeapOutOfBounds => Errno::Fault, - MemoryAccessError::Overflow => Errno::Overflow, - MemoryAccessError::NonUtf8String => Errno::Inval, - _ => Errno::Inval, + MemoryAccessError::HeapOutOfBounds => types::__WASI_EFAULT, + MemoryAccessError::Overflow => types::__WASI_EOVERFLOW, + MemoryAccessError::NonUtf8String => types::__WASI_EINVAL, + _ => types::__WASI_EINVAL, } } -fn mem_error_to_bus(err: MemoryAccessError) -> BusErrno { +fn mem_error_to_bus(err: MemoryAccessError) -> types::__bus_errno_t { match err { - MemoryAccessError::HeapOutOfBounds => BusErrno::Memviolation, - MemoryAccessError::Overflow => BusErrno::Memviolation, - MemoryAccessError::NonUtf8String => BusErrno::Badrequest, - _ => BusErrno::Unknown, + MemoryAccessError::HeapOutOfBounds => types::__BUS_EMEMVIOLATION, + MemoryAccessError::Overflow => types::__BUS_EMEMVIOLATION, + MemoryAccessError::NonUtf8String => types::__BUS_EBADREQUEST, + _ => types::__BUS_EUNKNOWN, } } diff --git a/lib/wasi/src/lib.rs_upstream b/lib/wasi/src/lib.rs_upstream new file mode 100644 index 000000000..81a77fc7f --- /dev/null +++ b/lib/wasi/src/lib.rs_upstream @@ -0,0 +1,835 @@ +#![deny(unused_mut)] +#![doc(html_favicon_url = "https://wasmer.io/images/icons/favicon-32x32.png")] +#![doc(html_logo_url = "https://github.com/wasmerio.png?size=200")] + +//! Wasmer's WASI implementation +//! +//! Use `generate_import_object` to create an [`Imports`]. This [`Imports`] +//! can be combined with a module to create an `Instance` which can execute WASI +//! Wasm functions. +//! +//! See `state` for the experimental WASI FS API. Also see the +//! [WASI plugin example](https://github.com/wasmerio/wasmer/blob/master/examples/plugin.rs) +//! for an example of how to extend WASI using the WASI FS API. + +#[cfg(all(not(feature = "sys"), not(feature = "js")))] +compile_error!("At least the `sys` or the `js` feature must be enabled. Please, pick one."); + +#[cfg(all(feature = "sys", feature = "js"))] +compile_error!( + "Cannot have both `sys` and `js` features enabled at the same time. Please, pick one." +); + +#[cfg(all(feature = "sys", target_arch = "wasm32"))] +compile_error!("The `sys` feature must be enabled only for non-`wasm32` target."); + +#[cfg(all(feature = "js", not(target_arch = "wasm32")))] +compile_error!( + "The `js` feature must be enabled only for the `wasm32` target (either `wasm32-unknown-unknown` or `wasm32-wasi`)." +); + +#[cfg(all(feature = "host-fs", feature = "mem-fs"))] +compile_error!( + "Cannot have both `host-fs` and `mem-fs` features enabled at the same time. Please, pick one." +); + +#[macro_use] +mod macros; +mod runtime; +mod state; +mod syscalls; +mod utils; + +/// Runners for WASI / Emscripten +#[cfg(feature = "webc_runner")] +pub mod runners; + +use crate::syscalls::*; + +pub use crate::state::{ + Fd, Pipe, Stderr, Stdin, Stdout, WasiBidirectionalPipePair, WasiBidirectionalSharedPipePair, + WasiFs, WasiInodes, WasiPipe, WasiState, WasiStateBuilder, WasiStateCreationError, ALL_RIGHTS, + VIRTUAL_ROOT_FD, +}; +pub use crate::syscalls::types; +#[cfg(feature = "wasix")] +pub use crate::utils::is_wasix_module; +pub use crate::utils::{get_wasi_version, get_wasi_versions, is_wasi_module, WasiVersion}; +pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; +#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")] +pub use wasmer_vfs::FsError as WasiFsError; +#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::VirtualFile`")] +pub use wasmer_vfs::VirtualFile as WasiFile; +pub use wasmer_vfs::{FsError, VirtualFile}; +pub use wasmer_vnet::{UnsupportedVirtualNetworking, VirtualNetworking}; + +use derivative::*; +use std::ops::Deref; +use thiserror::Error; +use tracing::trace; +use wasmer::{ + imports, namespace, AsStoreMut, AsStoreRef, ExportError, Exports, Function, FunctionEnv, + Imports, Instance, Memory, Memory32, MemoryAccessError, MemorySize, MemoryView, Module, + TypedFunction, +}; +use wasmer_wasi_types::wasi::{BusErrno, Errno, Snapshot0Clockid}; + +pub use runtime::{ + PluggableRuntimeImplementation, WasiRuntimeImplementation, WasiThreadError, WasiTtyState, +}; +use std::sync::{mpsc, Arc, Mutex, RwLockReadGuard, RwLockWriteGuard}; +use std::time::Duration; + +/// This is returned in `RuntimeError`. +/// Use `downcast` or `downcast_ref` to retrieve the `ExitCode`. +#[derive(Error, Debug)] +pub enum WasiError { + #[error("WASI exited with code: {0}")] + Exit(syscalls::types::__wasi_exitcode_t), + #[error("The WASI version could not be determined")] + UnknownWasiVersion, +} + +/// Represents the ID of a WASI thread +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WasiThreadId(u32); + +impl From for WasiThreadId { + fn from(id: u32) -> Self { + Self(id) + } +} +impl From for u32 { + fn from(t: WasiThreadId) -> u32 { + t.0 as u32 + } +} + +/// Represents the ID of a sub-process +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WasiBusProcessId(u32); + +impl From for WasiBusProcessId { + fn from(id: u32) -> Self { + Self(id) + } +} +impl From for u32 { + fn from(id: WasiBusProcessId) -> u32 { + id.0 as u32 + } +} + +#[derive(Debug, Clone)] +pub struct WasiThread { + /// ID of this thread + #[allow(dead_code)] + id: WasiThreadId, + /// Signalers used to tell joiners that the thread has exited + exit: Arc>>>, + /// Event to wait on for the thread to join + join: Arc>>, +} + +impl WasiThread { + /// Waits for the thread to exit (false = timeout) + pub fn join(&self, timeout: Duration) -> bool { + let guard = self.join.lock().unwrap(); + let timeout = guard.recv_timeout(timeout); + match timeout { + Ok(_) => true, + Err(mpsc::RecvTimeoutError::Disconnected) => true, + Err(mpsc::RecvTimeoutError::Timeout) => false, + } + } +} + +pub struct WasiFunctionEnv { + pub env: FunctionEnv, +} + +impl WasiFunctionEnv { + pub fn new(store: &mut impl AsStoreMut, env: WasiEnv) -> Self { + Self { + env: FunctionEnv::new(store, env), + } + } + + /// Get an `Imports` for a specific version of WASI detected in the module. + pub fn import_object( + &self, + store: &mut impl AsStoreMut, + module: &Module, + ) -> Result { + let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; + Ok(generate_import_object_from_env( + store, + &self.env, + wasi_version, + )) + } + + pub fn data_mut<'a>(&'a self, store: &'a mut impl AsStoreMut) -> &'a mut WasiEnv { + self.env.as_mut(store) + } + + /// Initializes the WasiEnv using the instance exports + /// (this must be executed before attempting to use it) + /// (as the stores can not by themselves be passed between threads we can store the module + /// in a thread-local variables and use it later - for multithreading) + pub fn initialize( + &mut self, + store: &mut impl AsStoreMut, + instance: &Instance, + ) -> Result<(), ExportError> { + // List all the exports and imports + for ns in instance.module().exports() { + //trace!("module::export - {} ({:?})", ns.name(), ns.ty()); + trace!("module::export - {}", ns.name()); + } + for ns in instance.module().imports() { + trace!("module::import - {}::{}", ns.module(), ns.name()); + } + + // First we get the malloc function which if it exists will be used to + // create the pthread_self structure + let memory = instance.exports.get_memory("memory")?.clone(); + let env = self.data_mut(store); + env.set_memory(memory); + + Ok(()) + } + + /// Like `import_object` but containing all the WASI versions detected in + /// the module. + pub fn import_object_for_all_wasi_versions( + &self, + store: &mut impl AsStoreMut, + module: &Module, + ) -> Result { + let wasi_versions = + get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; + + let mut resolver = Imports::new(); + for version in wasi_versions.iter() { + let new_import_object = generate_import_object_from_env(store, &self.env, *version); + for ((n, m), e) in new_import_object.into_iter() { + resolver.define(&n, &m, e); + } + } + + #[cfg(feature = "wasix")] + if is_wasix_module(module) { + self.data_mut(store) + .state + .fs + .is_wasix + .store(true, std::sync::atomic::Ordering::Release); + } + + Ok(resolver) + } +} + +/// The environment provided to the WASI imports. +#[derive(Derivative, Clone)] +#[derivative(Debug)] +#[allow(dead_code)] +pub struct WasiEnv { + /// ID of this thread (zero is the main thread) + id: WasiThreadId, + /// Represents a reference to the memory + memory: Option, + /// If the module has it then map the thread start + #[derivative(Debug = "ignore")] + thread_start: Option>, + #[derivative(Debug = "ignore")] + reactor_work: Option>, + #[derivative(Debug = "ignore")] + reactor_finish: Option>, + #[derivative(Debug = "ignore")] + malloc: Option>, + #[derivative(Debug = "ignore")] + free: Option>, + /// Shared state of the WASI system. Manages all the data that the + /// executing WASI program can see. + pub state: Arc, + /// Implementation of the WASI runtime. + pub(crate) runtime: Arc, +} + +impl WasiEnv { + /// Create a new WasiEnv from a WasiState (memory will be set to None) + pub fn new(state: WasiState) -> Self { + Self { + id: 0u32.into(), + state: Arc::new(state), + memory: None, + thread_start: None, + reactor_work: None, + reactor_finish: None, + malloc: None, + free: None, + runtime: Arc::new(PluggableRuntimeImplementation::default()), + } + } + + /// Returns a copy of the current runtime implementation for this environment + pub fn runtime(&self) -> &(dyn WasiRuntimeImplementation) { + self.runtime.deref() + } + + /// Overrides the runtime implementation for this environment + pub fn set_runtime(&mut self, runtime: R) + where + R: WasiRuntimeImplementation + Send + Sync + 'static, + { + self.runtime = Arc::new(runtime); + } + + /// Returns the current thread ID + pub fn current_thread_id(&self) -> WasiThreadId { + self.id + } + + /// Creates a new thread only this wasi environment + pub fn new_thread(&self) -> WasiThread { + let (tx, rx) = mpsc::channel(); + + let mut guard = self.state.threading.lock().unwrap(); + + guard.thread_seed += 1; + let next_id: WasiThreadId = guard.thread_seed.into(); + + let thread = WasiThread { + id: next_id, + exit: Arc::new(Mutex::new(Some(tx))), + join: Arc::new(Mutex::new(rx)), + }; + + guard.threads.insert(thread.id, thread.clone()); + thread + } + + /// Copy the lazy reference so that when it's initialized during the + /// export phase, all the other references get a copy of it + pub fn memory_clone(&self) -> Option { + self.memory.clone() + } + + // Yields execution + pub fn yield_now(&self) -> Result<(), WasiError> { + self.runtime.yield_now(self.id)?; + Ok(()) + } + + // Sleeps for a period of time + pub fn sleep(&self, duration: Duration) -> Result<(), WasiError> { + let duration = duration.as_nanos(); + let start = + platform_clock_time_get(Snapshot0Clockid::Monotonic, 1_000_000).unwrap() as u128; + self.yield_now()?; + loop { + let now = + platform_clock_time_get(Snapshot0Clockid::Monotonic, 1_000_000).unwrap() as u128; + let delta = match now.checked_sub(start) { + Some(a) => a, + None => { + break; + } + }; + if delta >= duration { + break; + } + let remaining = match duration.checked_sub(delta) { + Some(a) => Duration::from_nanos(a as u64), + None => { + break; + } + }; + std::thread::sleep(remaining.min(Duration::from_millis(10))); + self.yield_now()?; + } + Ok(()) + } + + /// Accesses the virtual networking implementation + pub fn net(&self) -> &(dyn VirtualNetworking) { + self.runtime.networking() + } + + /// Accesses the virtual bus implementation + pub fn bus(&self) -> &(dyn VirtualBus) { + self.runtime.bus() + } + + /// Set the memory of the WasiEnv (can only be done once) + pub fn set_memory(&mut self, memory: Memory) { + if self.memory.is_some() { + panic!("Memory of a WasiEnv can only be set once!"); + } + self.memory = Some(memory); + } + + /// Providers safe access to the memory + /// (it must be initialized before it can be used) + pub fn memory_view<'a>(&'a self, store: &'a impl AsStoreRef) -> MemoryView<'a> { + self.memory().view(store) + } + + /// Get memory, that needs to have been set fist + pub fn memory(&self) -> &Memory { + self.memory.as_ref().unwrap() + } + + /// Get the WASI state + pub fn state(&self) -> &WasiState { + &self.state + } + + pub(crate) fn get_memory_and_wasi_state<'a>( + &'a self, + store: &'a impl AsStoreRef, + _mem_index: u32, + ) -> (MemoryView<'a>, &WasiState) { + let memory = self.memory_view(store); + let state = self.state.deref(); + (memory, state) + } + + pub(crate) fn get_memory_and_wasi_state_and_inodes<'a>( + &'a self, + store: &'a impl AsStoreRef, + _mem_index: u32, + ) -> (MemoryView<'a>, &WasiState, RwLockReadGuard) { + let memory = self.memory_view(store); + let state = self.state.deref(); + let inodes = state.inodes.read().unwrap(); + (memory, state, inodes) + } + + pub(crate) fn get_memory_and_wasi_state_and_inodes_mut<'a>( + &'a self, + store: &'a impl AsStoreRef, + _mem_index: u32, + ) -> (MemoryView<'a>, &WasiState, RwLockWriteGuard) { + let memory = self.memory_view(store); + let state = self.state.deref(); + let inodes = state.inodes.write().unwrap(); + (memory, state, inodes) + } +} + +/// Create an [`Imports`] from a [`Context`] +pub fn generate_import_object_from_env( + store: &mut impl AsStoreMut, + env: &FunctionEnv, + version: WasiVersion, +) -> Imports { + match version { + WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, env), + WasiVersion::Snapshot1 | WasiVersion::Latest => { + generate_import_object_snapshot1(store, env) + } + #[cfg(feature = "wasix")] + WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env), + #[cfg(feature = "wasix")] + WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env), + #[cfg(not(feature = "wasix"))] + _ => unimplemented!(), + } +} + +fn wasi_unstable_exports(mut store: &mut impl AsStoreMut, env: &FunctionEnv) -> Exports { + let namespace = namespace! { + "args_get" => Function::new_typed_with_env(&mut store, env, args_get::), + "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::), + "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::), + "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::), + "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::), + "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::), + "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), + "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), + "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), + "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), + "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::fd_filestat_get), + "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), + "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::), + "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::), + "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::), + "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::), + "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), + "fd_seek" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::fd_seek), + "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), + "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::), + "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::), + "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::), + "path_filestat_get" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::path_filestat_get), + "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::), + "path_link" => Function::new_typed_with_env(&mut store, env, path_link::), + "path_open" => Function::new_typed_with_env(&mut store, env, path_open::), + "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::), + "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::), + "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::), + "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::), + "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::), + "poll_oneoff" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::poll_oneoff), + "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), + "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), + "random_get" => Function::new_typed_with_env(&mut store, env, random_get::), + "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), + "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::), + "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::), + "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), + }; + namespace +} + +fn wasi_snapshot_preview1_exports( + mut store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Exports { + let namespace = namespace! { + "args_get" => Function::new_typed_with_env(&mut store, env, args_get::), + "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::), + "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::), + "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::), + "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::), + "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::), + "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), + "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), + "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), + "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), + "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::), + "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), + "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::), + "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::), + "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::), + "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::), + "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), + "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::), + "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), + "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::), + "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::), + "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::), + "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::), + "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::), + "path_link" => Function::new_typed_with_env(&mut store, env, path_link::), + "path_open" => Function::new_typed_with_env(&mut store, env, path_open::), + "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::), + "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::), + "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::), + "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::), + "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::), + "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::), + "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), + "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), + "random_get" => Function::new_typed_with_env(&mut store, env, random_get::), + "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), + "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::), + "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::), + "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), + }; + namespace +} +pub fn import_object_for_all_wasi_versions( + store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Imports { + let wasi_unstable_exports = wasi_unstable_exports(store, env); + let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(store, env); + imports! { + "wasi_unstable" => wasi_unstable_exports, + "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports, + } +} + +/// Combines a state generating function with the import list for legacy WASI +fn generate_import_object_snapshot0( + store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Imports { + let wasi_unstable_exports = wasi_unstable_exports(store, env); + imports! { + "wasi_unstable" => wasi_unstable_exports + } +} + +fn generate_import_object_snapshot1( + store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Imports { + let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(store, env); + imports! { + "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports + } +} + +/// Combines a state generating function with the import list for snapshot 1 +#[cfg(feature = "wasix")] +fn generate_import_object_wasix32_v1( + mut store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Imports { + use self::wasix32::*; + imports! { + "wasix_32v1" => { + "args_get" => Function::new_typed_with_env(&mut store, env, args_get), + "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get), + "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get), + "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get), + "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get), + "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get), + "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), + "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), + "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), + "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), + "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get), + "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get), + "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), + "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread), + "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get), + "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name), + "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite), + "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read), + "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir), + "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), + "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup), + "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event), + "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek), + "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), + "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell), + "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write), + "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe), + "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory), + "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get), + "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times), + "path_link" => Function::new_typed_with_env(&mut store, env, path_link), + "path_open" => Function::new_typed_with_env(&mut store, env, path_open), + "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink), + "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory), + "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename), + "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink), + "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file), + "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff), + "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), + "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), + "random_get" => Function::new_typed_with_env(&mut store, env, random_get), + "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get), + "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set), + "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd), + "chdir" => Function::new_typed_with_env(&mut store, env, chdir), + "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn), + "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep), + "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id), + "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join), + "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism), + "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit), + "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), + "getpid" => Function::new_typed_with_env(&mut store, env, getpid), + "process_spawn" => Function::new_typed_with_env(&mut store, env, process_spawn), + "bus_open_local" => Function::new_typed_with_env(&mut store, env, bus_open_local), + "bus_open_remote" => Function::new_typed_with_env(&mut store, env, bus_open_remote), + "bus_close" => Function::new_typed_with_env(&mut store, env, bus_close), + "bus_call" => Function::new_typed_with_env(&mut store, env, bus_call), + "bus_subcall" => Function::new_typed_with_env(&mut store, env, bus_subcall), + "bus_poll" => Function::new_typed_with_env(&mut store, env, bus_poll), + "call_reply" => Function::new_typed_with_env(&mut store, env, call_reply), + "call_fault" => Function::new_typed_with_env(&mut store, env, call_fault), + "call_close" => Function::new_typed_with_env(&mut store, env, call_close), + "ws_connect" => Function::new_typed_with_env(&mut store, env, ws_connect), + "http_request" => Function::new_typed_with_env(&mut store, env, http_request), + "http_status" => Function::new_typed_with_env(&mut store, env, http_status), + "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge), + "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge), + "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire), + "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add), + "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove), + "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear), + "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list), + "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac), + "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set), + "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add), + "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove), + "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear), + "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list), + "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status), + "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local), + "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer), + "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open), + "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag), + "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time), + "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time), + "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size), + "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size), + "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4), + "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4), + "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6), + "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6), + "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind), + "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen), + "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept), + "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect), + "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv), + "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from), + "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send), + "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to), + "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file), + "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), + "resolve" => Function::new_typed_with_env(&mut store, env, resolve), + } + } +} + +#[cfg(feature = "wasix")] +fn generate_import_object_wasix64_v1( + mut store: &mut impl AsStoreMut, + env: &FunctionEnv, +) -> Imports { + use self::wasix64::*; + imports! { + "wasix_64v1" => { + "args_get" => Function::new_typed_with_env(&mut store, env, args_get), + "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get), + "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get), + "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get), + "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get), + "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get), + "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise), + "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate), + "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close), + "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync), + "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get), + "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get), + "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times), + "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread), + "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get), + "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name), + "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite), + "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read), + "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir), + "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber), + "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup), + "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event), + "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek), + "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync), + "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell), + "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write), + "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe), + "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory), + "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get), + "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times), + "path_link" => Function::new_typed_with_env(&mut store, env, path_link), + "path_open" => Function::new_typed_with_env(&mut store, env, path_open), + "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink), + "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory), + "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename), + "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink), + "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file), + "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff), + "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit), + "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise), + "random_get" => Function::new_typed_with_env(&mut store, env, random_get), + "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get), + "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set), + "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd), + "chdir" => Function::new_typed_with_env(&mut store, env, chdir), + "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn), + "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep), + "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id), + "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join), + "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism), + "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit), + "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield), + "getpid" => Function::new_typed_with_env(&mut store, env, getpid), + "process_spawn" => Function::new_typed_with_env(&mut store, env, process_spawn), + "bus_open_local" => Function::new_typed_with_env(&mut store, env, bus_open_local), + "bus_open_remote" => Function::new_typed_with_env(&mut store, env, bus_open_remote), + "bus_close" => Function::new_typed_with_env(&mut store, env, bus_close), + "bus_call" => Function::new_typed_with_env(&mut store, env, bus_call), + "bus_subcall" => Function::new_typed_with_env(&mut store, env, bus_subcall), + "bus_poll" => Function::new_typed_with_env(&mut store, env, bus_poll), + "call_reply" => Function::new_typed_with_env(&mut store, env, call_reply), + "call_fault" => Function::new_typed_with_env(&mut store, env, call_fault), + "call_close" => Function::new_typed_with_env(&mut store, env, call_close), + "ws_connect" => Function::new_typed_with_env(&mut store, env, ws_connect), + "http_request" => Function::new_typed_with_env(&mut store, env, http_request), + "http_status" => Function::new_typed_with_env(&mut store, env, http_status), + "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge), + "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge), + "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire), + "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add), + "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove), + "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear), + "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list), + "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac), + "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set), + "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add), + "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove), + "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear), + "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list), + "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status), + "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local), + "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer), + "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open), + "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag), + "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time), + "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time), + "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size), + "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size), + "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4), + "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4), + "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6), + "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6), + "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind), + "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen), + "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept), + "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect), + "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv), + "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from), + "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send), + "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to), + "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file), + "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown), + "resolve" => Function::new_typed_with_env(&mut store, env, resolve), + } + } +} + +fn mem_error_to_wasi(err: MemoryAccessError) -> Errno { + match err { + MemoryAccessError::HeapOutOfBounds => Errno::Fault, + MemoryAccessError::Overflow => Errno::Overflow, + MemoryAccessError::NonUtf8String => Errno::Inval, + _ => Errno::Inval, + } +} + +fn mem_error_to_bus(err: MemoryAccessError) -> BusErrno { + match err { + MemoryAccessError::HeapOutOfBounds => BusErrno::Memviolation, + MemoryAccessError::Overflow => BusErrno::Memviolation, + MemoryAccessError::NonUtf8String => BusErrno::Badrequest, + _ => BusErrno::Unknown, + } +} diff --git a/lib/wasi/src/macros.rs b/lib/wasi/src/macros.rs index 9018a2626..36699a954 100644 --- a/lib/wasi/src/macros.rs +++ b/lib/wasi/src/macros.rs @@ -6,7 +6,10 @@ macro_rules! wasi_try { ($expr:expr) => {{ let res: Result<_, crate::syscalls::types::wasi::Errno> = $expr; match res { - Ok(val) => val, + Ok(val) => { + tracing::trace!("wasi::wasi_try::val: {:?}", val); + val + } Err(err) => { tracing::debug!("wasi::wasi_try::err: {:?}", err); return err; @@ -21,7 +24,10 @@ macro_rules! wasi_try_ok { ($expr:expr) => {{ let res: Result<_, crate::syscalls::types::wasi::Errno> = $expr; match res { - Ok(val) => val, + Ok(val) => { + tracing::trace!("wasi::wasi_try_ok::val: {:?}", val); + val + } Err(err) => { tracing::debug!("wasi::wasi_try_ok::err: {:?}", err); return Ok(err); @@ -32,7 +38,10 @@ macro_rules! wasi_try_ok { ($expr:expr, $thread:expr) => {{ let res: Result<_, crate::syscalls::types::wasi::Errno> = $expr; match res { - Ok(val) => val, + Ok(val) => { + tracing::trace!("wasi::wasi_try_ok::val: {:?}", val); + val + } Err(err) => { if err == crate::syscalls::types::wasi::Errno::Intr { $thread.yield_now()?; @@ -50,7 +59,10 @@ macro_rules! wasi_try_bus { ($expr:expr) => {{ let res: Result<_, crate::syscalls::types::wasi::BusErrno> = $expr; match res { - Ok(val) => val, + Ok(val) => { + tracing::trace!("wasi::wasi_try_bus::val: {:?}", val); + val + } Err(err) => { tracing::debug!("wasi::wasi_try_bus::err: {:?}", err); return err; @@ -63,7 +75,7 @@ macro_rules! wasi_try_bus { /// succeeded or returns the error value. macro_rules! wasi_try_bus_ok { ($expr:expr) => {{ - let res: Result<_, crate::syscalls::types::__bus_errno_t> = $expr; + let res: Result<_, crate::syscalls::types::BusErrno> = $expr; match res { Ok(val) => { //tracing::trace!("wasi::wasi_try_bus::val: {:?}", val); @@ -77,7 +89,7 @@ macro_rules! wasi_try_bus_ok { }}; } -/// Like `wasi_try` but converts a `MemoryAccessError` to a __wasi_errno_t`. +/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`. macro_rules! wasi_try_mem { ($expr:expr) => {{ wasi_try!($expr.map_err($crate::mem_error_to_wasi)) @@ -91,14 +103,7 @@ macro_rules! wasi_try_mem_bus { }}; } -/// Like `wasi_try` but converts a `MemoryAccessError` to a __bus_errno_t`. -macro_rules! wasi_try_mem_bus_ok { - ($expr:expr) => {{ - wasi_try_bus_ok!($expr.map_err($crate::mem_error_to_bus)) - }}; -} - -/// Like `wasi_try` but converts a `MemoryAccessError` to a __wasi_errno_t`. +/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`. macro_rules! wasi_try_mem_ok { ($expr:expr) => {{ wasi_try_ok!($expr.map_err($crate::mem_error_to_wasi)) diff --git a/lib/wasi/src/runtime.rs b/lib/wasi/src/runtime.rs new file mode 100644 index 000000000..1394e010b --- /dev/null +++ b/lib/wasi/src/runtime.rs @@ -0,0 +1,151 @@ +use std::fmt; +use std::ops::Deref; +use std::sync::atomic::{AtomicU32, Ordering}; +use thiserror::Error; +use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; +use wasmer_vnet::VirtualNetworking; +use wasmer_wasi_types::wasi::Errno; + +use super::WasiError; +use super::WasiThreadId; + +#[derive(Error, Debug)] +pub enum WasiThreadError { + #[error("Multithreading is not supported")] + Unsupported, + #[error("The method named is not an exported function")] + MethodNotFound, +} + +impl From for Errno { + fn from(a: WasiThreadError) -> Errno { + match a { + WasiThreadError::Unsupported => Errno::Notsup, + WasiThreadError::MethodNotFound => Errno::Inval, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct WasiTtyState { + pub cols: u32, + pub rows: u32, + pub width: u32, + pub height: u32, + pub stdin_tty: bool, + pub stdout_tty: bool, + pub stderr_tty: bool, + pub echo: bool, + pub line_buffered: bool, +} + +/// Represents an implementation of the WASI runtime - by default everything is +/// unimplemented. +pub trait WasiRuntimeImplementation: fmt::Debug + Sync { + /// For WASI runtimes that support it they can implement a message BUS implementation + /// which allows runtimes to pass serialized messages between each other similar to + /// RPC's. BUS implementation can be implemented that communicate across runtimes + /// thus creating a distributed computing architecture. + fn bus(&self) -> &(dyn VirtualBus); + + /// Provides access to all the networking related functions such as sockets. + /// By default networking is not implemented. + fn networking(&self) -> &(dyn VirtualNetworking); + + /// Generates a new thread ID + fn thread_generate_id(&self) -> WasiThreadId; + + /// Gets the TTY state + fn tty_get(&self) -> WasiTtyState { + WasiTtyState { + rows: 25, + cols: 80, + width: 800, + height: 600, + stdin_tty: false, + stdout_tty: false, + stderr_tty: false, + echo: true, + line_buffered: true, + } + } + + /// Sets the TTY state + fn tty_set(&self, _tty_state: WasiTtyState) {} + + /// Spawns a new thread by invoking the + fn thread_spawn( + &self, + _callback: Box, + ) -> Result<(), WasiThreadError> { + Err(WasiThreadError::Unsupported) + } + + /// Returns the amount of parallelism that is possible on this platform + fn thread_parallelism(&self) -> Result { + Err(WasiThreadError::Unsupported) + } + + /// Invokes whenever a WASM thread goes idle. In some runtimes (like singlethreaded + /// execution environments) they will need to do asynchronous work whenever the main + /// thread goes idle and this is the place to hook for that. + fn yield_now(&self, _id: WasiThreadId) -> Result<(), WasiError> { + std::thread::yield_now(); + Ok(()) + } + + /// Gets the current process ID + fn getpid(&self) -> Option { + None + } +} + +#[derive(Debug)] +pub struct PluggableRuntimeImplementation { + pub bus: Box, + pub networking: Box, + pub thread_id_seed: AtomicU32, +} + +impl PluggableRuntimeImplementation { + pub fn set_bus_implementation(&mut self, bus: I) + where + I: VirtualBus + Sync, + { + self.bus = Box::new(bus) + } + + pub fn set_networking_implementation(&mut self, net: I) + where + I: VirtualNetworking + Sync, + { + self.networking = Box::new(net) + } +} + +impl Default for PluggableRuntimeImplementation { + fn default() -> Self { + Self { + #[cfg(not(feature = "host-vnet"))] + networking: Box::new(wasmer_vnet::UnsupportedVirtualNetworking::default()), + #[cfg(feature = "host-vnet")] + networking: Box::new(wasmer_wasi_local_networking::LocalNetworking::default()), + bus: Box::new(UnsupportedVirtualBus::default()), + thread_id_seed: Default::default(), + } + } +} + +impl WasiRuntimeImplementation for PluggableRuntimeImplementation { + fn bus(&self) -> &(dyn VirtualBus) { + self.bus.deref() + } + + fn networking(&self) -> &(dyn VirtualNetworking) { + self.networking.deref() + } + + fn thread_generate_id(&self) -> WasiThreadId { + self.thread_id_seed.fetch_add(1, Ordering::Relaxed).into() + } +} diff --git a/lib/wasi/src/state/mod.rs b/lib/wasi/src/state/mod.rs index dc06e12da..4efa1142d 100644 --- a/lib/wasi/src/state/mod.rs +++ b/lib/wasi/src/state/mod.rs @@ -67,6 +67,11 @@ use std::{ }, }; use tracing::{debug, trace}; +use wasmer_vbus::BusSpawnedProcess; +use wasmer_wasi_types::wasi::{ + Errno, Fd as WasiFd, Fdflags, Fdstat, Filesize, Filestat, Filetype, Preopentype, Rights, +}; +use wasmer_wasi_types::wasi::{Prestat, PrestatEnum}; use wasmer::Store; use wasmer_vbus::VirtualBusCalled; use wasmer_vbus::VirtualBusInvocation; @@ -209,10 +214,10 @@ pub struct Fd { /// The reference count is only increased when the FD is /// duplicates - fd_close will not kill the inode until this reaches zero pub ref_cnt: Arc, - pub rights: __wasi_rights_t, - pub rights_inheriting: __wasi_rights_t, - pub flags: __wasi_fdflags_t, - pub offset: Arc, + pub rights: Rights, + pub rights_inheriting: Rights, + pub flags: Fdflags, + pub offset: u64, /// Flags that determine how the [`Fd`] can be used. /// /// Used when reopening a [`VirtualFile`] during [`WasiState`] deserialization. @@ -319,8 +324,8 @@ impl WasiInodes { fn std_dev_get<'a>( &'a self, fd_map: &RwLock>, - fd: __wasi_fd_t, - ) -> Result { + fd: WasiFd, + ) -> Result, FsError> { if let Some(fd) = fd_map.read().unwrap().get(&fd) { let guard = self.arena[fd.inode].read(); if let Kind::File { handle, .. } = guard.deref() { @@ -343,8 +348,8 @@ impl WasiInodes { fn std_dev_get_mut<'a>( &'a self, fd_map: &RwLock>, - fd: __wasi_fd_t, - ) -> Result { + fd: WasiFd, + ) -> Result, FsError> { if let Some(fd) = fd_map.read().unwrap().get(&fd) { let guard = self.arena[fd.inode].read(); if let Kind::File { handle, .. } = guard.deref() { @@ -934,7 +939,7 @@ impl WasiFs { pub fn swap_file( &self, inodes: &WasiInodes, - fd: __wasi_fd_t, + fd: WasiFd, mut file: Box, ) -> Result>, FsError> { match fd { @@ -1002,9 +1007,10 @@ impl WasiFs { drop(guard); inodes.arena[inode].stat.write().unwrap().st_size = new_size; - return Ok(new_size as __wasi_filesize_t); + Ok(new_size as Filesize) + } else { + Err(Errno::Badf) } - Err(__WASI_EBADF) } Kind::Dir { .. } | Kind::Root { .. } => Err(Errno::Isdir), _ => Err(Errno::Inval), @@ -1187,8 +1193,8 @@ impl WasiFs { inodes, kind, false, - file.to_string_lossy().to_string().into(), - __wasi_filestat_t { + file.to_string_lossy().to_string(), + Filestat { st_filetype: file_type, ..Filestat::default() }, @@ -1518,12 +1524,13 @@ impl WasiFs { debug!("fdstat: {:?}", fd); let guard = inodes.arena[fd.inode].read(); - Ok(__wasi_fdstat_t { - fs_filetype: match guard.deref() { - Kind::File { .. } => __WASI_FILETYPE_REGULAR_FILE, - Kind::Dir { .. } => __WASI_FILETYPE_DIRECTORY, - Kind::Symlink { .. } => __WASI_FILETYPE_SYMBOLIC_LINK, - _ => __WASI_FILETYPE_UNKNOWN, + let deref = guard.deref(); + Ok(Fdstat { + fs_filetype: match deref { + Kind::File { .. } => Filetype::RegularFile, + Kind::Dir { .. } => Filetype::Directory, + Kind::Symlink { .. } => Filetype::SymbolicLink, + _ => Filetype::Unknown, }, fs_flags: fd.flags, fs_rights_base: fd.rights, @@ -1561,11 +1568,17 @@ impl WasiFs { __WASI_STDOUT_FILENO => inodes .stdout_mut(&self.fd_map) .map_err(fs_error_into_wasi_err)? + .as_mut() + .map(|f| f.flush().map_err(map_io_err)) + .unwrap_or_else(|| Err(Errno::Io))?, .flush() .map_err(map_io_err)?, __WASI_STDERR_FILENO => inodes .stderr_mut(&self.fd_map) .map_err(fs_error_into_wasi_err)? + .as_mut() + .and_then(|f| f.flush().ok()) + .ok_or(Errno::Io)?, .flush() .map_err(map_io_err)?, _ => { @@ -1580,7 +1593,7 @@ impl WasiFs { handle: Some(file), .. } => { let mut file = file.write().unwrap(); - file.flush().map_err(|_| __WASI_EIO)? + file.flush().map_err(|_| Errno::Io)? } // TODO: verify this behavior Kind::Dir { .. } => return Err(Errno::Isdir), @@ -1624,7 +1637,7 @@ impl WasiFs { kind: Kind, is_preopened: bool, name: Cow<'static, str>, - mut stat: __wasi_filestat_t, + mut stat: Filestat, ) -> Inode { stat.st_ino = self.get_next_inode_index(); @@ -1643,7 +1656,7 @@ impl WasiFs { flags: Fdflags, open_flags: u16, inode: Inode, - ) -> Result<__wasi_fd_t, __wasi_errno_t> { + ) -> Result { let idx = self.next_fd.fetch_add(1, Ordering::AcqRel); self.create_fd_ext(rights, rights_inheriting, flags, open_flags, inode, idx)?; Ok(idx) @@ -1670,7 +1683,7 @@ impl WasiFs { inode, }, ); - Ok(()) + Ok(idx) } pub fn clone_fd(&self, fd: WasiFd) -> Result { @@ -1717,7 +1730,7 @@ impl WasiFs { inodes.arena.insert(InodeVal { stat: RwLock::new(stat), is_preopened: true, - name: "/".into(), + name: "/".to_string(), kind: RwLock::new(root_kind), }) } @@ -1776,7 +1789,7 @@ impl WasiFs { inodes.arena.insert(InodeVal { stat: RwLock::new(stat), is_preopened: true, - name: name.to_string().into(), + name: name.to_string(), kind: RwLock::new(kind), }) }; @@ -1800,15 +1813,15 @@ impl WasiFs { Kind::File { handle, path, .. } => match handle { Some(wf) => { let wf = wf.read().unwrap(); - return Ok(__wasi_filestat_t { - st_filetype: __WASI_FILETYPE_REGULAR_FILE, + return Ok(Filestat { + st_filetype: Filetype::RegularFile, st_size: wf.size(), st_atim: wf.last_accessed(), st_mtim: wf.last_modified(), st_ctim: wf.created_time(), - ..__wasi_filestat_t::default() - }); + ..Filestat::default() + }) } None => self .root_fs @@ -1858,6 +1871,76 @@ impl WasiFs { }) } + // FIXME: resolve + // /// Closes an open FD, handling all details such as FD being preopen + // pub(crate) fn close_fd(&self, inodes: &WasiInodes, fd: WasiFd) -> Result<(), Errno> { + // let inode = self.get_fd_inode(fd)?; + // let inodeval = inodes.get_inodeval(inode)?; + // let is_preopened = inodeval.is_preopened; + // + // let mut guard = inodeval.write(); + // match guard.deref_mut() { + // Kind::File { ref mut handle, .. } => { + // let mut empty_handle = None; + // std::mem::swap(handle, &mut empty_handle); + // } + // Kind::Socket { ref mut socket, .. } => { + // let mut closed_socket = InodeSocket::new(InodeSocketKind::Closed); + // std::mem::swap(socket, &mut closed_socket); + // } + // Kind::Pipe { ref mut pipe } => { + // pipe.close(); + // } + // Kind::Dir { parent, path, .. } => { + // debug!("Closing dir {:?}", &path); + // let key = path + // .file_name() + // .ok_or(Errno::Inval)? + // .to_string_lossy() + // .to_string(); + // if let Some(p) = *parent { + // drop(guard); + // let mut guard = inodes.arena[p].write(); + // match guard.deref_mut() { + // Kind::Dir { entries, .. } | Kind::Root { entries } => { + // fd_map.remove(&fd).unwrap(); + // if is_preopened { + // let mut idx = None; + // { + // let preopen_fds = self.preopen_fds.read().unwrap(); + // for (i, po_fd) in preopen_fds.iter().enumerate() { + // if *po_fd == fd { + // idx = Some(i); + // break; + // } + // } + // } + // if let Some(i) = idx { + // // only remove entry properly if this is the original preopen FD + // // calling `path_open` can give you an fd to the same inode as a preopen fd + // entries.remove(&key); + // self.preopen_fds.write().unwrap().remove(i); + // // Maybe recursively closes fds if original preopen? + // } + // } + // } + // _ => unreachable!( + // "Fatal internal logic error, directory's parent is not a directory" + // ), + // } + // } else { + // // this shouldn't be possible anymore due to Root + // debug!("HIT UNREACHABLE CODE! Non-root directory does not have a parent"); + // return Err(Errno::Inval); + // } + // } + // Kind::EventNotifications { .. } => {} + // Kind::Root { .. } => return Err(Errno::Access), + // Kind::Symlink { .. } | Kind::Buffer { .. } => return Err(Errno::Inval), + // } + // + // Ok(()) + // } /// Closes an open FD, handling all details such as FD being preopen pub(crate) fn close_fd( &self, @@ -1904,7 +1987,7 @@ impl WasiFs { debug!("Closing dir {:?}", &path); let key = path .file_name() - .ok_or(Errno::Inval)? + .ok_or(__WASI_EINVAL)? .to_string_lossy() .to_string(); if let Some(p) = *parent { @@ -1940,12 +2023,12 @@ impl WasiFs { } else { // this shouldn't be possible anymore due to Root debug!("HIT UNREACHABLE CODE! Non-root directory does not have a parent"); - return Err(Errno::Inval); + return Err(__WASI_EINVAL); } } Kind::EventNotifications { .. } => {} - Kind::Root { .. } => return Err(Errno::Access), - Kind::Symlink { .. } | Kind::Buffer { .. } => return Err(Errno::Inval), + Kind::Root { .. } => return Err(__WASI_EACCES), + Kind::Symlink { .. } | Kind::Buffer { .. } => return Err(__WASI_EINVAL), } Ok(()) @@ -1957,21 +2040,21 @@ impl WasiState { pub(crate) fn fs_read_dir>( &self, path: P, - ) -> Result { + ) -> Result { self.fs .root_fs .read_dir(path.as_ref()) .map_err(fs_error_into_wasi_err) } - pub(crate) fn fs_create_dir>(&self, path: P) -> Result<(), __wasi_errno_t> { + pub(crate) fn fs_create_dir>(&self, path: P) -> Result<(), Errno> { self.fs .root_fs .create_dir(path.as_ref()) .map_err(fs_error_into_wasi_err) } - pub(crate) fn fs_remove_dir>(&self, path: P) -> Result<(), __wasi_errno_t> { + pub(crate) fn fs_remove_dir>(&self, path: P) -> Result<(), Errno> { self.fs .root_fs .remove_dir(path.as_ref()) @@ -1982,14 +2065,14 @@ impl WasiState { &self, from: P, to: Q, - ) -> Result<(), __wasi_errno_t> { + ) -> Result<(), Errno> { self.fs .root_fs .rename(from.as_ref(), to.as_ref()) .map_err(fs_error_into_wasi_err) } - pub(crate) fn fs_remove_file>(&self, path: P) -> Result<(), __wasi_errno_t> { + pub(crate) fn fs_remove_file>(&self, path: P) -> Result<(), Errno> { self.fs .root_fs .remove_file(path.as_ref()) diff --git a/lib/wasi/src/state/pipe.rs b/lib/wasi/src/state/pipe.rs index 98590db73..0dce1d017 100644 --- a/lib/wasi/src/state/pipe.rs +++ b/lib/wasi/src/state/pipe.rs @@ -2,13 +2,18 @@ use crate::syscalls::types::*; use crate::syscalls::{read_bytes, write_bytes}; use bytes::{Buf, Bytes}; use std::convert::TryInto; +use std::io::{self, Read, Seek, SeekFrom, Write}; use std::io::{Read, Seek, Write}; use std::ops::DerefMut; +use std::sync::mpsc; +use std::sync::Arc; use std::sync::mpsc::{self, TryRecvError}; use std::sync::Mutex; use std::time::Duration; use wasmer::WasmSlice; use wasmer::{MemorySize, MemoryView}; +use wasmer_vfs::{FsError, VirtualFile}; +use wasmer_wasi_types::wasi::Errno; use wasmer_vfs::VirtualFile; #[derive(Debug)] @@ -19,6 +24,8 @@ pub struct WasiPipe { rx: Mutex>>, /// Buffers the last read message from the pipe while its being consumed read_buffer: Mutex>, + /// Whether the pipe should block or not block to wait for stdin reads + block: bool, } /// Pipe pair of (a, b) WasiPipes that are connected together @@ -88,12 +95,14 @@ impl WasiBidirectionalPipePair { tx: Mutex::new(tx1), rx: Mutex::new(rx2), read_buffer: Mutex::new(None), + block: true, }; let pipe2 = WasiPipe { tx: Mutex::new(tx2), rx: Mutex::new(rx1), read_buffer: Mutex::new(None), + block: true, }; WasiBidirectionalPipePair { @@ -229,7 +238,7 @@ impl WasiPipe { memory: &MemoryView, iov: WasmSlice<__wasi_iovec_t>, timeout: Duration, - ) -> Result { + ) -> Result { let mut elapsed = Duration::ZERO; let mut tick_wait = 0u64; loop { @@ -250,7 +259,7 @@ impl WasiPipe { Ok(a) => a, Err(TryRecvError::Empty) => { if elapsed > timeout { - return Err(__WASI_ETIMEDOUT); + return Err(Errno::Timedout); } // Linearly increasing wait time tick_wait += 1; @@ -266,6 +275,7 @@ impl WasiPipe { }; drop(rx); + // FIXME: this looks like a race condition! let mut read_buffer = self.read_buffer.lock().unwrap(); read_buffer.replace(Bytes::from(data)); } @@ -329,11 +339,16 @@ impl Seek for WasiPipe { impl Read for WasiPipe { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { loop { - { - let mut read_buffer = self.read_buffer.lock().unwrap(); - if let Some(inner_buf) = read_buffer.as_mut() { - let buf_len = inner_buf.len(); - if buf_len > 0 { + let mut read_buffer = self.read_buffer.lock().unwrap(); + if let Some(inner_buf) = read_buffer.as_mut() { + let buf_len = inner_buf.len(); + if buf_len > 0 { + if inner_buf.len() > buf.len() { + let mut reader = inner_buf.as_ref(); + let read = reader.read_exact(buf).map(|_| buf.len())?; + inner_buf.advance(read); + return Ok(read); + } else { let mut reader = inner_buf.as_ref(); let read = reader.read(buf).map(|_| buf_len as usize)?; inner_buf.advance(read); @@ -342,19 +357,49 @@ impl Read for WasiPipe { } } let rx = self.rx.lock().unwrap(); - if let Ok(data) = rx.recv() { - drop(rx); + + // We need to figure out whether we need to block here. + // The problem is that in cases of multiple buffered reads like: + // + // println!("abc"); + // println!("def"); + // + // get_stdout() // would only return "abc\n" instead of "abc\ndef\n" + + let data = match rx.try_recv() { + Ok(mut s) => { + s.append(&mut rx.try_iter().flat_map(|f| f.into_iter()).collect()); + s + } + Err(_) => { + if !self.block { + // If self.block is explicitly set to false, never block + Vec::new() + } else { + // could not immediately receive bytes, so we need to block + match rx.recv() { + Ok(o) => o, + // Errors can happen if the sender has been dropped already + // In this case, just return 0 to indicate that we can't read any + // bytes anymore + Err(_) => { + return Ok(0); + } + } + } + } + }; let mut read_buffer = self.read_buffer.lock().unwrap(); + if data.is_empty() && read_buffer.lock().unwrap().as_ref().map(|s| s.len()).unwrap_or(0) == 0 { + return Ok(0); + } read_buffer.replace(Bytes::from(data)); - } else { - return Ok(0); - } } } } -impl Write for WasiPipe { +impl std::io::Write for WasiPipe { fn write(&mut self, buf: &[u8]) -> std::io::Result { let tx = self.tx.lock().unwrap(); tx.send(buf.to_vec()) @@ -367,9 +412,35 @@ impl Write for WasiPipe { } } -impl Seek for WasiPipe { - fn seek(&mut self, _pos: std::io::SeekFrom) -> std::io::Result { - Ok(0) +impl VirtualFile for WasiPipe { + fn last_accessed(&self) -> u64 { + 0 + } + fn last_modified(&self) -> u64 { + 0 + } + fn created_time(&self) -> u64 { + 0 + } + fn size(&self) -> u64 { + self.read_buffer + .as_ref() + .map(|s| s.len() as u64) + .unwrap_or_default() + } + fn set_len(&mut self, _: u64) -> Result<(), FsError> { + Ok(()) + } + fn unlink(&mut self) -> Result<(), FsError> { + Ok(()) + } + fn bytes_available_read(&self) -> Result, FsError> { + Ok(Some( + self.read_buffer + .as_ref() + .map(|s| s.len()) + .unwrap_or_default(), + )) } } @@ -396,31 +467,31 @@ impl VirtualFile for WasiPipe { /// Change the size of the file, if the `new_size` is greater than the current size /// the extra bytes will be allocated and zeroed - fn set_len(&mut self, _new_size: u64) -> wasmer_vfs::Result<()> { + fn set_len(&mut self, _new_size: u64) -> Result<(), FsError> { Ok(()) } /// Request deletion of the file - fn unlink(&mut self) -> wasmer_vfs::Result<()> { + fn unlink(&mut self) -> Result<(), FsError> { Ok(()) } /// Store file contents and metadata to disk /// Default implementation returns `Ok(())`. You should implement this method if you care /// about flushing your cache to permanent storage - fn sync_to_disk(&self) -> wasmer_vfs::Result<()> { + fn sync_to_disk(&self) -> Result<(), FsError> { Ok(()) } /// Returns the number of bytes available. This function must not block - fn bytes_available(&self) -> wasmer_vfs::Result { + fn bytes_available(&self) -> Result { Ok(self.bytes_available_read()?.unwrap_or(0usize) + self.bytes_available_write()?.unwrap_or(0usize)) } /// Returns the number of bytes available. This function must not block /// Defaults to `None` which means the number of bytes is unknown - fn bytes_available_read(&self) -> wasmer_vfs::Result> { + fn bytes_available_read(&self) -> Result, FsError> { loop { { let read_buffer = self.read_buffer.lock().unwrap(); @@ -432,6 +503,7 @@ impl VirtualFile for WasiPipe { } } let rx = self.rx.lock().unwrap(); + // FIXME: why is a bytes available check consuming data? - this shouldn't be necessary if let Ok(data) = rx.try_recv() { drop(rx); @@ -445,7 +517,7 @@ impl VirtualFile for WasiPipe { /// Returns the number of bytes available. This function must not block /// Defaults to `None` which means the number of bytes is unknown - fn bytes_available_write(&self) -> wasmer_vfs::Result> { + fn bytes_available_write(&self) -> Result, FsError> { Ok(None) } diff --git a/lib/wasi/src/state/socket.rs b/lib/wasi/src/state/socket.rs index a5b0ebb1c..a935723ca 100644 --- a/lib/wasi/src/state/socket.rs +++ b/lib/wasi/src/state/socket.rs @@ -1,5 +1,6 @@ use super::types::net_error_into_wasi_err; use crate::syscalls::types::*; +use crate::syscalls::{read_bytes, write_bytes}; use bytes::{Buf, Bytes}; use std::future::Future; use std::mem::transmute; @@ -172,7 +173,7 @@ impl InodeSocket { &self, net: Arc, set_addr: SocketAddr, - ) -> Result, __wasi_errno_t> { + ) -> Result, Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::PreSocket { @@ -209,8 +210,8 @@ impl InodeSocket { // more to do at this time None } - __WASI_SOCK_TYPE_DGRAM => { - let mut socket = net + Socktype::Dgram => { + let socket = net .bind_udp(addr, *reuse_port, *reuse_addr) .await .map_err(net_error_into_wasi_err)?; @@ -230,7 +231,7 @@ impl InodeSocket { &self, net: Arc, _backlog: usize, - ) -> Result, __wasi_errno_t> { + ) -> Result, Errno> { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::PreSocket { @@ -246,7 +247,7 @@ impl InodeSocket { Socktype::Stream => { if addr.is_none() { tracing::warn!("wasi[?]::sock_listen - failed - address not set"); - return Err(__WASI_EINVAL); + return Err(Errno::Inval); } let addr = *addr.as_ref().unwrap(); let mut socket = net @@ -268,42 +269,59 @@ impl InodeSocket { } _ => { tracing::warn!("wasi[?]::sock_listen - failed - not supported(1)"); - return Err(__WASI_ENOTSUP); + return Err(Errno::Notsup); } }), InodeSocketKind::Closed => { tracing::warn!("wasi[?]::sock_listen - failed - socket closed"); - Err(__WASI_EIO) + Err(Errno::io) } _ => { tracing::warn!("wasi[?]::sock_listen - failed - not supported(2)"); - Err(__WASI_ENOTSUP) + Err(Errno::Notsup) } } } pub async fn accept( &self, - _fd_flags: __wasi_fdflags_t, - ) -> Result<(Box, SocketAddr), __wasi_errno_t> { + _fd_flags: Fdflags, + ) -> Result<(Box, SocketAddr), Errno> { let mut inner = self.inner.write().unwrap(); let (sock, addr) = match &mut inner.kind { InodeSocketKind::TcpListener(sock) => { let (child, addr) = sock.accept().await.map_err(net_error_into_wasi_err)?; Ok((child, addr)) } - InodeSocketKind::PreSocket { .. } => Err(__WASI_ENOTCONN), - InodeSocketKind::Closed => Err(__WASI_EIO), - _ => Err(__WASI_ENOTSUP), + InodeSocketKind::PreSocket { .. } => Err(Errno::Notconn), + InodeSocketKind::Closed => Err(Errno::Io), + _ => Err(Errno::Notsup), + }?; + Ok((sock, addr)) + } + + // FIXME: make async like Self::accept + pub fn accept_timeout( + &self, + _fd_flags: Fdflags, + timeout: Duration, + ) -> Result<(Box, SocketAddr), Errno> { + let (sock, addr) = match &self.kind { + InodeSocketKind::TcpListener(sock) => sock + .accept_timeout(timeout) + .map_err(net_error_into_wasi_err), + InodeSocketKind::PreSocket { .. } => Err(Errno::Notconn), + InodeSocketKind::Closed => Err(Errno::Io), + _ => Err(Errno::Notsup), }?; Ok((sock, addr)) } pub async fn connect( - &self, + &mut self, net: Arc, peer: SocketAddr, - ) -> Result, __wasi_errno_t> { + ) -> Result, Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::PreSocket { @@ -353,7 +371,7 @@ impl InodeSocket { } } - pub fn status(&self) -> Result { + pub fn status(&self) -> Result { let inner = self.inner.read().unwrap(); Ok(match &inner.kind { InodeSocketKind::PreSocket { .. } => WasiSocketStatus::Opening, @@ -367,7 +385,7 @@ impl InodeSocket { }) } - pub fn http_status(&self) -> Result { + pub fn http_status(&self) -> Result { let inner = self.inner.read().unwrap(); Ok(match &inner.kind { InodeSocketKind::HttpRequest(http, ..) => { @@ -389,7 +407,7 @@ impl InodeSocket { }) } - pub fn addr_local(&self) -> Result { + pub fn addr_local(&self) -> Result { let inner = self.inner.read().unwrap(); Ok(match &inner.kind { InodeSocketKind::PreSocket { family, addr, .. } => { @@ -421,7 +439,7 @@ impl InodeSocket { }) } - pub fn addr_peer(&self) -> Result { + pub fn addr_peer(&self) -> Result { let inner = self.inner.read().unwrap(); Ok(match &inner.kind { InodeSocketKind::PreSocket { family, .. } => SocketAddr::new( @@ -457,7 +475,7 @@ impl InodeSocket { }) } - pub fn set_opt_flag(&self, option: WasiSocketOption, val: bool) -> Result<(), __wasi_errno_t> { + pub fn set_opt_flag(&mut self, option: WasiSocketOption, val: bool) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::PreSocket { @@ -503,9 +521,9 @@ impl InodeSocket { Ok(()) } - pub fn get_opt_flag(&self, option: WasiSocketOption) -> Result { - let inner = self.inner.read().unwrap(); - Ok(match &inner.kind { + pub fn get_opt_flag(&self, option: WasiSocketOption) -> Result { + let mut inner = self.inner.write().unwrap(); + match &mut inner.kind { InodeSocketKind::PreSocket { only_v6, reuse_port, @@ -539,10 +557,10 @@ impl InodeSocket { }, InodeSocketKind::Closed => return Err(Errno::Io), _ => return Err(Errno::Notsup), - }) + } } - pub fn set_send_buf_size(&self, size: usize) -> Result<(), __wasi_errno_t> { + pub fn set_send_buf_size(&mut self, size: usize) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::PreSocket { send_buf_size, .. } => { @@ -558,7 +576,7 @@ impl InodeSocket { Ok(()) } - pub fn send_buf_size(&self) -> Result { + pub fn send_buf_size(&self) -> Result { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::PreSocket { send_buf_size, .. } => { @@ -572,7 +590,7 @@ impl InodeSocket { } } - pub fn set_recv_buf_size(&self, size: usize) -> Result<(), __wasi_errno_t> { + pub fn set_recv_buf_size(&mut self, size: usize) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::PreSocket { recv_buf_size, .. } => { @@ -588,7 +606,7 @@ impl InodeSocket { Ok(()) } - pub fn recv_buf_size(&self) -> Result { + pub fn recv_buf_size(&self) -> Result { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::PreSocket { recv_buf_size, .. } => { @@ -602,7 +620,7 @@ impl InodeSocket { } } - pub fn set_linger(&self, linger: Option) -> Result<(), __wasi_errno_t> { + pub fn set_linger(&mut self, linger: Option) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::TcpStream(sock) => { @@ -614,7 +632,7 @@ impl InodeSocket { } } - pub fn nonblocking(&self) -> Result { + pub fn nonblocking(&self) -> Result { let inner = self.inner.read().unwrap(); Ok(match &inner.kind { InodeSocketKind::TcpStream(sock) => { @@ -634,12 +652,12 @@ impl InodeSocket { } InodeSocketKind::PreSocket { nonblocking, .. } => *nonblocking, _ => { - return Err(__WASI_ENOTSUP); + return Err(Errno::Notsup); } }) } - pub fn set_nonblocking(&self, val: bool) -> Result<(), __wasi_errno_t> { + pub fn set_nonblocking(&self, val: bool) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); Ok(match &mut inner.kind { InodeSocketKind::TcpStream(sock) => { @@ -661,12 +679,12 @@ impl InodeSocket { (*nonblocking) = val; } _ => { - return Err(__WASI_ENOTSUP); + return Err(Errno::Notsup); } }) } - pub fn linger(&self) -> Result, __wasi_errno_t> { + pub fn linger(&self) -> Result, Errno> { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::TcpStream(sock) => sock.linger().map_err(net_error_into_wasi_err), @@ -676,11 +694,12 @@ impl InodeSocket { } } + pub fn set_opt_time( &self, ty: TimeType, timeout: Option, - ) -> Result<(), __wasi_errno_t> { + ) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::TcpStream(sock) => sock @@ -722,7 +741,7 @@ impl InodeSocket { } } - pub fn opt_time(&self, ty: TimeType) -> Result, __wasi_errno_t> { + pub fn opt_time(&self, ty: TimeType) -> Result, Errno> { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::TcpStream(sock) => sock.opt_time(ty).map_err(net_error_into_wasi_err), @@ -748,9 +767,9 @@ impl InodeSocket { } } - pub fn set_ttl(&self, ttl: u32) -> Result<(), __wasi_errno_t> { - let mut inner = self.inner.write().unwrap(); - match &mut inner.kind { + pub fn set_ttl(&self, ttl: u32) -> Result<(), Errno> { + let inner = self.inner.read().unwrap(); + match &inner.kind { InodeSocketKind::TcpStream(sock) => sock.set_ttl(ttl).map_err(net_error_into_wasi_err), InodeSocketKind::UdpSocket(sock) => sock.set_ttl(ttl).map_err(net_error_into_wasi_err), InodeSocketKind::PreSocket { .. } => Err(Errno::Io), @@ -759,7 +778,7 @@ impl InodeSocket { } } - pub fn ttl(&self) -> Result { + pub fn ttl(&self) -> Result { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::TcpStream(sock) => sock.ttl().map_err(net_error_into_wasi_err), @@ -770,7 +789,7 @@ impl InodeSocket { } } - pub fn set_multicast_ttl_v4(&self, ttl: u32) -> Result<(), __wasi_errno_t> { + pub fn set_multicast_ttl_v4(&self, ttl: u32) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::UdpSocket(sock) => sock @@ -782,7 +801,7 @@ impl InodeSocket { } } - pub fn multicast_ttl_v4(&self) -> Result { + pub fn multicast_ttl_v4(&self) -> Result { let inner = self.inner.read().unwrap(); match &inner.kind { InodeSocketKind::UdpSocket(sock) => { @@ -794,11 +813,7 @@ impl InodeSocket { } } - pub async fn join_multicast_v4( - &self, - multiaddr: Ipv4Addr, - iface: Ipv4Addr, - ) -> Result<(), __wasi_errno_t> { + pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::UdpSocket(sock) => sock @@ -814,7 +829,7 @@ impl InodeSocket { &self, multiaddr: Ipv4Addr, iface: Ipv4Addr, - ) -> Result<(), __wasi_errno_t> { + ) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::UdpSocket(sock) => sock @@ -826,11 +841,7 @@ impl InodeSocket { } } - pub async fn join_multicast_v6( - &self, - multiaddr: Ipv6Addr, - iface: u32, - ) -> Result<(), __wasi_errno_t> { + pub async fn join_multicast_v6(&self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::UdpSocket(sock) => sock @@ -842,11 +853,7 @@ impl InodeSocket { } } - pub async fn leave_multicast_v6( - &self, - multiaddr: Ipv6Addr, - iface: u32, - ) -> Result<(), __wasi_errno_t> { + pub async fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> { let mut inner = self.inner.write().unwrap(); match &mut inner.kind { InodeSocketKind::UdpSocket(sock) => sock @@ -858,10 +865,20 @@ impl InodeSocket { } } - pub async fn send(&self, buf: Vec) -> Result { - let buf_len = buf.len(); + pub async fn send( + &self, + memory: &MemoryView, + iov: WasmSlice<__wasi_ciovec_t>, + ) -> Result { + let buf_len: M::Offset = iov + .iter() + .filter_map(|a| a.read().ok()) + .map(|a| a.buf_len) + .sum(); + let buf_len: usize = buf_len.try_into().map_err(|_| Errno::Inval)?; + let mut buf = Vec::with_capacity(buf_len); + write_bytes(&mut buf, memory, iov)?; let mut inner = self.inner.write().unwrap(); - let ret = match &mut inner.kind { InodeSocketKind::HttpRequest(sock, ty) => { let sock = sock.get_mut().unwrap(); @@ -883,38 +900,79 @@ impl InodeSocket { .await .map(|_| buf_len) .map_err(net_error_into_wasi_err), - InodeSocketKind::Raw(sock) => sock - .send(Bytes::from(buf)) - .await - .map_err(net_error_into_wasi_err), - InodeSocketKind::TcpStream(sock) => sock - .send(Bytes::from(buf)) - .await - .map_err(net_error_into_wasi_err), - InodeSocketKind::UdpSocket(sock) => sock - .send(Bytes::from(buf)) - .await - .map_err(net_error_into_wasi_err), - InodeSocketKind::PreSocket { .. } => Err(__WASI_ENOTCONN), - InodeSocketKind::Closed => Err(__WASI_EIO), - _ => Err(__WASI_ENOTSUP), + InodeSocketKind::Raw(sock) => { + sock.send(Bytes::from(buf)).await.map_err(net_error_into_wasi_err) + } + InodeSocketKind::TcpStream(sock) => { + sock.send(Bytes::from(buf)).await.map_err(net_error_into_wasi_err) + } + InodeSocketKind::UdpSocket(sock) => { + sock.send(Bytes::from(buf)).await.map_err(net_error_into_wasi_err) + } + InodeSocketKind::PreSocket { .. } => Err(Errno::Notconn), + InodeSocketKind::Closed => Err(Errno::Io), + _ => Err(Errno::Notsup), } .map(|_| buf_len)?; if ret > 0 { - inner.silence_write_ready = false; + inner.silence_write_ready = false; } Ok(ret) } - pub async fn send_to( - &self, - buf: Vec, - addr: SocketAddr, - ) -> Result { + pub fn send_bytes(&mut self, buf: Bytes) -> Result { let buf_len = buf.len(); - let mut inner = self.inner.write().unwrap(); + match &mut self.kind { + InodeSocketKind::HttpRequest(sock, ty) => { + let sock = sock.get_mut().unwrap(); + match ty { + InodeHttpSocketType::Request => { + if sock.request.is_none() { + return Err(Errno::Io); + } + let request = sock.request.as_ref().unwrap(); + request + .send(buf.to_vec()) + .map(|_| buf_len) + .map_err(|_| Errno::Io) + } + _ => { + return Err(Errno::Io); + } + } + } + InodeSocketKind::WebSocket(sock) => sock + .send(buf) + .map(|_| buf_len) + .map_err(net_error_into_wasi_err), + InodeSocketKind::Raw(sock) => sock.send(buf).map_err(net_error_into_wasi_err), + InodeSocketKind::TcpStream(sock) => sock.send(buf).map_err(net_error_into_wasi_err), + InodeSocketKind::UdpSocket(sock) => sock.send(buf).map_err(net_error_into_wasi_err), + InodeSocketKind::PreSocket { .. } => Err(Errno::Notconn), + InodeSocketKind::Closed => Err(Errno::Io), + _ => Err(Errno::Notsup), + } + .map(|_| buf_len) + } + pub async fn send_to( + &mut self, + memory: &MemoryView, + iov: WasmSlice<__wasi_ciovec_t>, + addr: WasmPtr<__wasi_addr_port_t, M>, + ) -> Result { + let (addr_ip, addr_port) = read_ip_port(memory, addr)?; + let addr = SocketAddr::new(addr_ip, addr_port); + let buf_len: M::Offset = iov + .iter() + .filter_map(|a| a.read().ok()) + .map(|a| a.buf_len) + .sum(); + let buf_len: usize = buf_len.try_into().map_err(|_| Errno::Inval)?; + let mut buf = Vec::with_capacity(buf_len); + write_bytes(&mut buf, memory, iov)?; + let mut inner = self.inner.write().unwrap(); let ret = match &mut inner.kind { InodeSocketKind::Icmp(sock) => sock .send_to(Bytes::from(buf), addr) @@ -924,11 +982,11 @@ impl InodeSocket { .send_to(Bytes::from(buf), addr) .await .map_err(net_error_into_wasi_err), - InodeSocketKind::PreSocket { .. } => Err(__WASI_ENOTCONN), - InodeSocketKind::Closed => Err(__WASI_EIO), - _ => Err(__WASI_ENOTSUP), + InodeSocketKind::PreSocket { .. } => Err(Errno::Notconn), + InodeSocketKind::Closed => Err(Errno::Io), + _ => Err(Errno::Notsup), } - .map(|_| buf_len)?; + .map(|_| buf_len); if ret > 0 { inner.silence_write_ready = false; @@ -936,7 +994,7 @@ impl InodeSocket { Ok(ret) } - pub fn peek(&self) -> Result { + pub fn peek(&self) -> Result { let mut inner = self.inner.write().unwrap(); if let Some(buf) = inner.read_buffer.as_ref() { if buf.len() > 0 { @@ -949,7 +1007,7 @@ impl InodeSocket { match ty { InodeHttpSocketType::Response => { if sock.response.is_none() { - return Err(__WASI_EIO); + return Err(Errno::Io); } let response = sock.response.as_ref().unwrap(); @@ -957,7 +1015,7 @@ impl InodeSocket { match response.try_recv() { Ok(a) => Bytes::from(a), Err(TryRecvError::Disconnected) => { - return Err(__WASI_EIO); + return Err(Errno::Io); } Err(TryRecvError::Empty) => { return Ok(0); @@ -966,7 +1024,7 @@ impl InodeSocket { } InodeHttpSocketType::Headers => { if sock.headers.is_none() { - return Err(__WASI_EIO); + return Err(Errno::Io); } let headers = sock.headers.as_ref().unwrap(); @@ -974,7 +1032,7 @@ impl InodeSocket { let headers = match headers.try_recv() { Ok(a) => a, Err(TryRecvError::Disconnected) => { - return Err(__WASI_EIO); + return Err(Errno::Io); } Err(TryRecvError::Empty) => { return Ok(0); @@ -1028,8 +1086,8 @@ impl InodeSocket { InodeSocketKind::TcpListener(sock) => { return sock.peek().map_err(net_error_into_wasi_err); } - InodeSocketKind::PreSocket { .. } => return Err(__WASI_ENOTCONN), - InodeSocketKind::Closed => return Err(__WASI_EIO), + InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn), + InodeSocketKind::Closed => return Err(Errno::Io), _ => return Err(__WASI_ENOTSUP), }; inner.read_buffer.replace(data); @@ -1041,7 +1099,11 @@ impl InodeSocket { } } - pub async fn recv(&self, max_size: usize) -> Result { + pub async fn recv( + &mut self, + memory: &MemoryView, + iov: WasmSlice<__wasi_iovec_t>, + ) -> Result { let mut inner = self.inner.write().unwrap(); loop { let is_tcp = if let InodeSocketKind::TcpStream(..) = &inner.kind { @@ -1052,14 +1114,14 @@ impl InodeSocket { if let Some(buf) = inner.read_buffer.as_mut() { let buf_len = buf.len(); if buf_len > 0 { - let read = buf_len.min(max_size); - let ret = buf.slice(..read); + let reader = buf.as_ref(); + let read = read_bytes(reader, memory, iov).map(|_| buf_len)?; if is_tcp { buf.advance(read); } else { buf.clear(); } - return Ok(ret); + return Ok(read); } } let data = match &mut inner.kind { @@ -1115,7 +1177,7 @@ impl InodeSocket { } } - pub async fn peek_from(&self) -> Result { + pub async fn peek_from(&self) -> Result { let mut inner = self.inner.write().unwrap(); if let Some(buf) = inner.read_buffer.as_ref() { if buf.len() > 0 { @@ -1139,9 +1201,9 @@ impl InodeSocket { } } } - InodeSocketKind::PreSocket { .. } => return Err(__WASI_ENOTCONN), - InodeSocketKind::Closed => return Err(__WASI_EIO), - _ => return Err(__WASI_ENOTSUP), + InodeSocketKind::PreSocket { .. } => return Err(Errno::NotConn), + InodeSocketKind::Closed => return Err(Errno::Io), + _ => return Err(Errno::Notsup), }; inner.read_buffer.replace(rcv.data); inner.read_addr.replace(rcv.addr); @@ -1152,8 +1214,12 @@ impl InodeSocket { } } - pub async fn recv_from(&self, max_size: usize) -> Result<(Bytes, SocketAddr), __wasi_errno_t> { - let mut inner = self.inner.write().unwrap(); + pub async fn recv_from( + &mut self, + memory: &MemoryView, + iov: WasmSlice<__wasi_iovec_t>, + addr: WasmPtr<__wasi_addr_port_t, M>, + ) -> Result<(Bytes, SocketAddr), Errno> { loop { let is_tcp = if let InodeSocketKind::TcpStream(..) = &inner.kind { true @@ -1162,14 +1228,13 @@ impl InodeSocket { }; if let Some(buf) = inner.read_buffer.as_mut() { if !buf.is_empty() { - let buf_len = buf.len(); - let read = buf_len.min(max_size); - let ret = buf.slice(..read); - if is_tcp { - buf.advance(read); - } else { - buf.clear(); - } + let reader = buf.as_ref(); + let ret = read_bytes(reader, memory, iov)?; + let peer = self + .read_addr + .unwrap_or_else(|| SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)); + write_ip_port(memory, addr, peer.ip(), peer.port())?; + let peer = inner .read_addr .unwrap_or_else(|| SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)); @@ -1177,22 +1242,20 @@ impl InodeSocket { } } let rcv = match &mut inner.kind { - InodeSocketKind::Icmp(sock) => { - sock.recv_from().await.map_err(net_error_into_wasi_err)? - } + InodeSocketKind::Icmp(sock) => sock.recv_from().await.map_err(net_error_into_wasi_err)?, InodeSocketKind::UdpSocket(sock) => { sock.recv_from().await.map_err(net_error_into_wasi_err)? } - InodeSocketKind::PreSocket { .. } => return Err(__WASI_ENOTCONN), - InodeSocketKind::Closed => return Err(__WASI_EIO), - _ => return Err(__WASI_ENOTSUP), + InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn), + InodeSocketKind::Closed => return Err(Errno::Io), + _ => return Err(Errno::Notsup), }; inner.read_buffer.replace(rcv.data); inner.read_addr.replace(rcv.addr); } } - pub async fn shutdown(&self, how: std::net::Shutdown) -> Result<(), __wasi_errno_t> { + pub async fn shutdown(&mut self, how: std::net::Shutdown) -> Result<(), Errno> { use std::net::Shutdown; let mut inner = self.inner.write().unwrap(); inner.silence_write_ready = false; diff --git a/lib/wasi/src/state/types.rs b/lib/wasi/src/state/types.rs index dfcefd4a2..16b5f3be1 100644 --- a/lib/wasi/src/state/types.rs +++ b/lib/wasi/src/state/types.rs @@ -3,6 +3,9 @@ use serde::{Deserialize, Serialize}; #[cfg(all(unix, feature = "sys-poll", not(feature = "os")))] use std::convert::TryInto; +use std::time::Duration; +use wasmer_vbus::BusError; +use wasmer_wasi_types::wasi::{BusErrno, Errno}; use std::{ collections::VecDeque, io::{self, Read, Seek, Write}, @@ -23,56 +26,56 @@ use wasmer_vnet::NetworkError; pub fn fs_error_from_wasi_err(err: Errno) -> FsError { match err { - __WASI_EBADF => FsError::InvalidFd, - __WASI_EEXIST => FsError::AlreadyExists, - __WASI_EIO => FsError::IOError, - __WASI_EADDRINUSE => FsError::AddressInUse, - __WASI_EADDRNOTAVAIL => FsError::AddressNotAvailable, - __WASI_EPIPE => FsError::BrokenPipe, - __WASI_ECONNABORTED => FsError::ConnectionAborted, - __WASI_ECONNREFUSED => FsError::ConnectionRefused, - __WASI_ECONNRESET => FsError::ConnectionReset, - __WASI_EINTR => FsError::Interrupted, - __WASI_EINVAL => FsError::InvalidInput, - __WASI_ENOTCONN => FsError::NotConnected, - __WASI_ENODEV => FsError::NoDevice, - __WASI_ENOENT => FsError::EntryNotFound, - __WASI_EPERM => FsError::PermissionDenied, - __WASI_ETIMEDOUT => FsError::TimedOut, - __WASI_EPROTO => FsError::UnexpectedEof, - __WASI_EAGAIN => FsError::WouldBlock, - __WASI_ENOSPC => FsError::WriteZero, - __WASI_ENOTEMPTY => FsError::DirectoryNotEmpty, + Errno::Badf => FsError::InvalidFd, + Errno::Exist => FsError::AlreadyExists, + Errno::Io => FsError::IOError, + Errno::Addrinuse => FsError::AddressInUse, + Errno::Addrnotavail => FsError::AddressNotAvailable, + Errno::Pipe => FsError::BrokenPipe, + Errno::Connaborted => FsError::ConnectionAborted, + Errno::Connrefused => FsError::ConnectionRefused, + Errno::Connreset => FsError::ConnectionReset, + Errno::Intr => FsError::Interrupted, + Errno::Inval => FsError::InvalidInput, + Errno::Notconn => FsError::NotConnected, + Errno::Nodev => FsError::NoDevice, + Errno::Noent => FsError::EntityNotFound, + Errno::Perm => FsError::PermissionDenied, + Errno::Timedout => FsError::TimedOut, + Errno::Proto => FsError::UnexpectedEof, + Errno::Again => FsError::WouldBlock, + Errno::Nospc => FsError::WriteZero, + Errno::Notempty => FsError::DirectoryNotEmpty, _ => FsError::UnknownError, } } pub fn fs_error_into_wasi_err(fs_error: FsError) -> Errno { match fs_error { - FsError::AlreadyExists => __WASI_EEXIST, - FsError::AddressInUse => __WASI_EADDRINUSE, - FsError::AddressNotAvailable => __WASI_EADDRNOTAVAIL, - FsError::BaseNotDirectory => __WASI_ENOTDIR, - FsError::BrokenPipe => __WASI_EPIPE, - FsError::ConnectionAborted => __WASI_ECONNABORTED, - FsError::ConnectionRefused => __WASI_ECONNREFUSED, - FsError::ConnectionReset => __WASI_ECONNRESET, - FsError::Interrupted => __WASI_EINTR, - FsError::InvalidData => __WASI_EIO, - FsError::InvalidFd => __WASI_EBADF, - FsError::InvalidInput => __WASI_EINVAL, - FsError::IOError => __WASI_EIO, - FsError::NoDevice => __WASI_ENODEV, - FsError::NotAFile => __WASI_EINVAL, - FsError::NotConnected => __WASI_ENOTCONN, - FsError::EntryNotFound => __WASI_ENOENT, - FsError::PermissionDenied => __WASI_EPERM, - FsError::TimedOut => __WASI_ETIMEDOUT, - FsError::UnexpectedEof => __WASI_EPROTO, - FsError::WouldBlock => __WASI_EAGAIN, - FsError::WriteZero => __WASI_ENOSPC, - FsError::DirectoryNotEmpty => __WASI_ENOTEMPTY, - FsError::Lock | FsError::UnknownError => __WASI_EIO, + FsError::AlreadyExists => Errno::Exist, + FsError::AddressInUse => Errno::Addrinuse, + FsError::AddressNotAvailable => Errno::Addrnotavail, + FsError::BaseNotDirectory => Errno::Notdir, + FsError::BrokenPipe => Errno::Pipe, + FsError::ConnectionAborted => Errno::Connaborted, + FsError::ConnectionRefused => Errno::Connrefused, + FsError::ConnectionReset => Errno::Connreset, + FsError::Interrupted => Errno::Intr, + FsError::InvalidData => Errno::Io, + FsError::InvalidFd => Errno::Badf, + FsError::InvalidInput => Errno::Inval, + FsError::IOError => Errno::Io, + FsError::NoDevice => Errno::Nodev, + FsError::NotAFile => Errno::Inval, + FsError::NotConnected => Errno::Notconn, + FsError::EntityNotFound => Errno::Noent, + FsError::PermissionDenied => Errno::Perm, + FsError::TimedOut => Errno::Timedout, + FsError::UnexpectedEof => Errno::Proto, + FsError::WouldBlock => Errno::Again, + FsError::WriteZero => Errno::Nospc, + FsError::DirectoryNotEmpty => Errno::Notempty, + FsError::Lock | FsError::UnknownError => Errno::Io, } } @@ -103,54 +106,55 @@ pub fn net_error_into_wasi_err(net_error: NetworkError) -> Errno { } } -pub fn bus_error_into_wasi_err(bus_error: VirtualBusError) -> __bus_errno_t { - use VirtualBusError::*; +pub fn bus_error_into_wasi_err(bus_error: BusError) -> BusErrno { + use BusError::*; match bus_error { - Serialization => __BUS_ESER, - Deserialization => __BUS_EDES, - NotFound => __BUS_EWAPM, - InvalidWapm => __BUS_EWAPM, - FetchFailed => __BUS_EFETCH, - CompileError => __BUS_ECOMPILE, - InvalidABI => __BUS_EABI, - Aborted => __BUS_EABORTED, - BadHandle => __BUS_EBADHANDLE, - InvalidTopic => __BUS_ETOPIC, - BadCallback => __BUS_EBADCB, - Unsupported => __BUS_EUNSUPPORTED, - BadRequest => __BUS_EBADREQUEST, - AccessDenied => __BUS_EDENIED, - InternalError => __BUS_EINTERNAL, - MemoryAllocationFailed => __BUS_EALLOC, - InvokeFailed => __BUS_EINVOKE, - AlreadyConsumed => __BUS_ECONSUMED, - MemoryAccessViolation => __BUS_EMEMVIOLATION, - UnknownError => __BUS_EUNKNOWN, + Serialization => BusErrno::Ser, + Deserialization => BusErrno::Des, + InvalidWapm => BusErrno::Wapm, + FetchFailed => BusErrno::Fetch, + CompileError => BusErrno::Compile, + InvalidABI => BusErrno::Abi, + Aborted => BusErrno::Aborted, + BadHandle => BusErrno::Badhandle, + InvalidTopic => BusErrno::Topic, + BadCallback => BusErrno::Badcb, + Unsupported => BusErrno::Unsupported, + BadRequest => BusErrno::Badrequest, + AccessDenied => BusErrno::Denied, + InternalError => BusErrno::Internal, + MemoryAllocationFailed => BusErrno::Alloc, + InvokeFailed => BusErrno::Invoke, + AlreadyConsumed => BusErrno::Consumed, + MemoryAccessViolation => BusErrno::Memviolation, + UnknownError => BusErrno::Unknown, } } -pub fn wasi_error_into_bus_err(bus_error: __bus_errno_t) -> VirtualBusError { - use VirtualBusError::*; +pub fn wasi_error_into_bus_err(bus_error: BusErrno) -> BusError { + use BusError::*; match bus_error { - __BUS_ESER => Serialization, - __BUS_EDES => Deserialization, - __BUS_EWAPM => InvalidWapm, - __BUS_EFETCH => FetchFailed, - __BUS_ECOMPILE => CompileError, - __BUS_EABI => InvalidABI, - __BUS_EABORTED => Aborted, - __BUS_EBADHANDLE => BadHandle, - __BUS_ETOPIC => InvalidTopic, - __BUS_EBADCB => BadCallback, - __BUS_EUNSUPPORTED => Unsupported, - __BUS_EBADREQUEST => BadRequest, - __BUS_EDENIED => AccessDenied, - __BUS_EINTERNAL => InternalError, - __BUS_EALLOC => MemoryAllocationFailed, - __BUS_EINVOKE => InvokeFailed, - __BUS_ECONSUMED => AlreadyConsumed, - __BUS_EMEMVIOLATION => MemoryAccessViolation, - __BUS_EUNKNOWN | _ => UnknownError, + // TODO: success == unknownerror? what's that about? + BusErrno::Success => UnknownError, + BusErrno::Ser => Serialization, + BusErrno::Des => Deserialization, + BusErrno::Wapm => InvalidWapm, + BusErrno::Fetch => FetchFailed, + BusErrno::Compile => CompileError, + BusErrno::Abi => InvalidABI, + BusErrno::Aborted => Aborted, + BusErrno::Badhandle => BadHandle, + BusErrno::Topic => InvalidTopic, + BusErrno::Badcb => BadCallback, + BusErrno::Unsupported => Unsupported, + BusErrno::Badrequest => BadRequest, + BusErrno::Denied => AccessDenied, + BusErrno::Internal => InternalError, + BusErrno::Alloc => MemoryAllocationFailed, + BusErrno::Invoke => InvokeFailed, + BusErrno::Consumed => AlreadyConsumed, + BusErrno::Memviolation => MemoryAccessViolation, + BusErrno::Unknown => UnknownError, } } @@ -328,7 +332,9 @@ pub(crate) fn poll( #[cfg(any(not(unix), not(feature = "sys-poll"), feature = "os"))] pub(crate) fn poll( - files: &[super::InodeValFilePollGuard], + files: &[&(dyn VirtualFile + Send + Sync + 'static)], + // FIXME: evaluate changd signature + // files: &[super::InodeValFilePollGuard], events: &[PollEventSet], seen_events: &mut [PollEventSet], timeout: Duration, @@ -342,53 +348,39 @@ pub(crate) fn poll( for (n, file) in files.iter().enumerate() { let mut builder = PollEventBuilder::new(); - let mut can_read = None; - let mut can_write = None; - let mut is_closed = None; + let file = files[n]; + let can_read = file.bytes_available_read()?.map(|_| true).unwrap_or(false); + let can_write = file + .bytes_available_write()? + .map(|s| s > 0) + .unwrap_or(false); + let is_closed = file.is_open() == false; - /* tracing::debug!( "poll_evt can_read={} can_write={} is_closed={}", can_read, can_write, is_closed ); - */ for event in iterate_poll_events(events[n]) { match event { - PollEvent::PollIn => { - if can_read.is_none() { - can_read = - Some(file.bytes_available_read()?.map(|s| s > 0).unwrap_or(false)); - } - if can_read.unwrap_or_default() { - tracing::debug!("poll_evt can_read=true file={:?}", file); - builder = builder.add(PollEvent::PollIn); - } + PollEvent::PollIn if can_read => { + builder = builder.add(PollEvent::PollIn); } - PollEvent::PollOut => { - if can_write.is_none() { - can_write = Some( - file.bytes_available_write()? - .map(|s| s > 0) - .unwrap_or(false), - ); - } - if can_write.unwrap_or_default() { - tracing::debug!("poll_evt can_write=true file={:?}", file); - builder = builder.add(PollEvent::PollOut); - } + PollEvent::PollOut if can_write => { + builder = builder.add(PollEvent::PollOut); } - PollEvent::PollHangUp | PollEvent::PollInvalid | PollEvent::PollError => { - if is_closed.is_none() { - is_closed = Some(file.is_open() == false); - } - if is_closed.unwrap_or_default() { - tracing::debug!("poll_evt is_closed=true file={:?}", file); - builder = builder.add(event); - } + PollEvent::PollHangUp if is_closed => { + builder = builder.add(PollEvent::PollHangUp); } + PollEvent::PollInvalid if is_closed => { + builder = builder.add(PollEvent::PollInvalid); + } + PollEvent::PollError if is_closed => { + builder = builder.add(PollEvent::PollError); + } + _ => {} } } let revents = builder.build(); diff --git a/lib/wasi/src/syscalls/legacy/snapshot0.rs b/lib/wasi/src/syscalls/legacy/snapshot0.rs index 322e61897..38dd7ae82 100644 --- a/lib/wasi/src/syscalls/legacy/snapshot0.rs +++ b/lib/wasi/src/syscalls/legacy/snapshot0.rs @@ -1,6 +1,6 @@ use crate::syscalls; -use crate::syscalls::types::{self, snapshot0}; -use crate::{mem_error_to_wasi, Memory32, MemorySize, WasiEnv, WasiError}; +use crate::syscalls::types; +use crate::{mem_error_to_wasi, Memory32, MemorySize, WasiEnv, WasiError, WasiThread}; use wasmer::{AsStoreMut, FunctionEnvMut, WasmPtr}; use wasmer_wasi_types::wasi::{ Errno, Event, Fd, Filesize, Filestat, Filetype, Snapshot0Filestat, Snapshot0Subscription, @@ -32,7 +32,7 @@ pub fn fd_filestat_get( // Set up complete, make the call with the pointer that will write to the // struct and some unrelated memory after the struct. - let result = syscalls::fd_filestat_get_internal::(&mut ctx, fd, new_buf); + let result = syscalls::fd_filestat_get::(ctx.as_mut(), fd, new_buf); // reborrow memory let env = ctx.data(); @@ -145,31 +145,14 @@ pub fn poll_oneoff( let in_origs = wasi_try_mem_ok!(in_origs.read_to_vec()); // get a pointer to the smaller new type - let in_new_type_ptr: WasmPtr = in_.cast(); + let in_new_type_ptr: WasmPtr = in_.cast(); for (in_sub_new, orig) in wasi_try_mem_ok!(in_new_type_ptr.slice(&memory, nsubscriptions_offset)) .iter() .zip(in_origs.iter()) { - wasi_try_mem_ok!(in_sub_new.write(types::__wasi_subscription_t { - userdata: orig.userdata, - type_: orig.type_, - u: if orig.type_ == types::__WASI_EVENTTYPE_CLOCK { - types::__wasi_subscription_u { - clock: types::__wasi_subscription_clock_t { - clock_id: unsafe { orig.u.clock.clock_id }, - timeout: unsafe { orig.u.clock.timeout }, - precision: unsafe { orig.u.clock.precision }, - flags: unsafe { orig.u.clock.flags }, - }, - } - } else { - types::__wasi_subscription_u { - fd_readwrite: unsafe { orig.u.fd_readwrite }, - } - }, - })); + wasi_try_mem_ok!(in_sub_new.write(Subscription::from(*orig))); } in_new_type_ptr }; diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 2afc0faeb..8486bef1a 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -18,8 +18,24 @@ pub mod wasm; pub mod windows; pub mod legacy; +//pub mod wasi; +#[cfg(feature = "wasix")] +pub mod wasix32; +#[cfg(feature = "wasix")] +pub mod wasix64; -use self::types::*; +use self::types::{ + wasi::{ + Addressfamily, Advice, Bid, BusDataFormat, BusErrno, BusHandles, Cid, Clockid, Dircookie, + Dirent, Errno, Event, EventEnum, EventFdReadwrite, Eventrwflags, Eventtype, Fd as WasiFd, + Fdflags, Fdstat, Filesize, Filestat, Filetype, Fstflags, Linkcount, OptionFd, Pid, Prestat, + Rights, Snapshot0Clockid, Sockoption, Sockstatus, Socktype, StdioMode as WasiStdioMode, + Streamsecurity, Subscription, SubscriptionEnum, SubscriptionFsReadwrite, Tid, Timestamp, + Tty, Whence, + }, + *, +}; +use crate::state::{bus_error_into_wasi_err, wasi_error_into_bus_err, InodeHttpSocketType}; #[cfg(feature = "os")] use crate::bin_factory::spawn_exec_module; use crate::runtime::SpawnType; @@ -30,6 +46,7 @@ use crate::state::{ use crate::state::{read_ip_port, write_ip_port, WasiProcessWait}; use crate::utils::map_io_err; use crate::{ + WasiBusProcessId, current_caller_id, import_object_for_all_wasi_versions, VirtualTaskManager, WasiEnvInner, WasiFunctionEnv, WasiRuntimeImplementation, WasiThread, WasiVFork, DEFAULT_STACK_SIZE, }; @@ -40,7 +57,8 @@ use crate::{ virtual_file_type_to_wasi_file_type, Inode, InodeSocket, InodeSocketKind, InodeVal, Kind, PollEvent, PollEventBuilder, WasiBidirectionalPipePair, WasiState, MAX_SYMLINKS, }, - WasiEnv, WasiError, + Fd, WasiEnv, WasiError, WasiThread, WasiThreadId, + WasiEnv, }; use bytes::{Bytes, BytesMut}; use cooked_waker::IntoWaker; @@ -162,11 +180,6 @@ pub(crate) fn read_bytes( Ok(bytes_read) } -/// checks that `rights_check_set` is a subset of `rights_set` -fn has_rights(rights_set: __wasi_rights_t, rights_check_set: __wasi_rights_t) -> bool { - rights_set | rights_check_set == rights_set -} - /// Writes data to the stderr pub fn stderr_write(ctx: &FunctionEnvMut<'_, WasiEnv>, buf: &[u8]) -> Result<(), __wasi_errno_t> { let env = ctx.data(); @@ -188,7 +201,7 @@ fn __sock_actor( where T: 'static, F: FnOnce(crate::state::InodeSocket) -> Fut + 'static, - Fut: std::future::Future>, + Fut: std::future::Future>, { let env = ctx.data(); let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); @@ -296,15 +309,16 @@ fn __sock_actor_mut( where T: 'static, F: FnOnce(crate::state::InodeSocket) -> Fut + 'static, - Fut: std::future::Future>, + Fut: std::future::Future>, { let env = ctx.data(); let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = state.fs.get_fd(sock)?; - if !rights.is_empty() && !fd_entry.rights.contains(rights) { - return Err(Errno::Access); - } + let ret = { + if !rights.is_empty() && !fd_entry.rights.contains(rights) { + return Err(Errno::Access); + } let inode_idx = fd_entry.inode; let inode = &inodes.arena[inode_idx]; @@ -320,26 +334,26 @@ where __asyncify(tasks, &env.thread, None, async move { actor(socket).await }) } _ => { - return Err(__WASI_ENOTSOCK); + return Err(Errno::Notsock); } } } fn __sock_upgrade( ctx: &FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - rights: __wasi_rights_t, + sock: WasiFd, + rights: Rights, actor: F, -) -> Result<(), __wasi_errno_t> +) -> Result<(), Errno> where F: FnOnce(crate::state::InodeSocket) -> Fut + 'static, - Fut: std::future::Future, __wasi_errno_t>>, + Fut: std::future::Future, Errno>>, { let env = ctx.data(); let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = state.fs.get_fd(sock)?; - if rights != 0 && !has_rights(fd_entry.rights, rights) { + if !rights.is_empty() && !fd_entry.rights.contains(rights) { tracing::warn!( "wasi[{}:{}]::sock_upgrade(fd={}, rights={}) - failed - no access rights to upgrade", ctx.data().pid(), @@ -347,7 +361,7 @@ where sock, rights ); - return Err(__WASI_EACCES); + return Err(Errno::Access); } let inode_idx = fd_entry.inode; @@ -379,7 +393,7 @@ where sock, rights ); - return Err(__WASI_ENOTSOCK); + return Err(Errno::Notsock); } } } @@ -392,7 +406,7 @@ where sock, rights ); - return Err(__WASI_ENOTSOCK); + return Err(Errno::Notsock); } } @@ -430,9 +444,9 @@ fn write_buffer_array( Errno::Success } -fn get_current_time_in_nanos() -> Result<__wasi_timestamp_t, __wasi_errno_t> { +fn get_current_time_in_nanos() -> Result<__wasi_timestamp_t, Errno> { let now = platform_clock_time_get(__WASI_CLOCK_MONOTONIC, 1_000_000).unwrap() as u128; - Ok(now as __wasi_timestamp_t) + Ok(now as Timestamp) } /// ### `args_get()` @@ -448,13 +462,12 @@ pub fn args_get( mut ctx: FunctionEnvMut<'_, WasiEnv>, argv: WasmPtr, M>, argv_buf: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!("wasi[{}:{}]::args_get", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); - let state_args: Vec> = state.args.iter().map(|a| a.as_bytes().to_vec()).collect(); - let result = write_buffer_array(&memory, &*state_args, argv, argv_buf); + let result = write_buffer_array(&memory, &state.args, argv, argv_buf); debug!( "=> args:\n{}", @@ -462,7 +475,7 @@ pub fn args_get( .args .iter() .enumerate() - .map(|(i, v)| format!("{:>20}: {}", i, v)) + .map(|(i, v)| format!("{:>20}: {}", i, ::std::str::from_utf8(v).unwrap())) .collect::>() .join("\n") ); @@ -481,7 +494,7 @@ pub fn args_sizes_get( mut ctx: FunctionEnvMut<'_, WasiEnv>, argc: WasmPtr, argv_buf_size: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::args_sizes_get", ctx.data().pid(), @@ -515,9 +528,9 @@ pub fn args_sizes_get( /// The resolution of the clock in nanoseconds pub fn clock_res_get( mut ctx: FunctionEnvMut<'_, WasiEnv>, - clock_id: __wasi_clockid_t, - resolution: WasmPtr<__wasi_timestamp_t, M>, -) -> __wasi_errno_t { + clock_id: Clockid, + resolution: WasmPtr, +) -> Errno { trace!( "wasi[{}:{}]::clock_res_get", ctx.data().pid(), @@ -547,38 +560,35 @@ pub fn clock_res_get( /// The value of the clock in nanoseconds pub fn clock_time_get( ctx: FunctionEnvMut<'_, WasiEnv>, - clock_id: __wasi_clockid_t, - precision: __wasi_timestamp_t, - time: WasmPtr<__wasi_timestamp_t, M>, -) -> __wasi_errno_t { - /* - trace!( - "wasi[{}:{}]::clock_time_get clock_id: {}, precision: {}", - ctx.data().pid(), clock_id, precision + clock_id: Clockid, + precision: Timestamp, + time: WasmPtr, +) -> Errno { + debug!( + "wasi::clock_time_get clock_id: {}, precision: {}", + clock_id as u8, precision ); - */ let env = ctx.data(); let memory = env.memory_view(&ctx); - let mut t_out = wasi_try!(platform_clock_time_get(clock_id, precision)); - + let mut t_out = wasi_try!(platform_clock_time_get( + Snapshot0Clockid::from(clock_id), + precision + )); { let guard = env.state.clock_offset.lock().unwrap(); if let Some(offset) = guard.get(&clock_id) { t_out += *offset; } }; - wasi_try_mem!(time.write(&memory, t_out as __wasi_timestamp_t)); - let result = __WASI_ESUCCESS; - /* + let result = Errno::Success; trace!( "time: {} => {}", - t_out as __wasi_timestamp_t, + wasi_try_mem!(time.deref(&memory).read()), result ); - */ result } @@ -591,9 +601,9 @@ pub fn clock_time_get( /// The value of the clock in nanoseconds pub fn clock_time_set( ctx: FunctionEnvMut<'_, WasiEnv>, - clock_id: __wasi_clockid_t, - time: __wasi_timestamp_t, -) -> __wasi_errno_t { + clock_id: Clockid, + time: Timestamp, +) -> Errno { trace!( "wasi::clock_time_set clock_id: {}, time: {}", clock_id, @@ -627,17 +637,16 @@ pub fn environ_get( ctx: FunctionEnvMut<'_, WasiEnv>, environ: WasmPtr, M>, environ_buf: WasmPtr, -) -> __wasi_errno_t { - trace!( +) -> Errno { + debug!( "wasi::environ_get. Environ: {:?}, environ_buf: {:?}", - environ, - environ_buf + environ, environ_buf ); let env = ctx.data(); let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); trace!(" -> State envs: {:?}", state.envs); - write_buffer_array(&memory, &state.envs, environ, environ_buf) + write_buffer_array(&memory, &*state.envs, environ, environ_buf) } /// ### `environ_sizes_get()` @@ -651,7 +660,7 @@ pub fn environ_sizes_get( ctx: FunctionEnvMut<'_, WasiEnv>, environ_count: WasmPtr, environ_buf_size: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { trace!( "wasi[{}:{}]::environ_sizes_get", ctx.data().pid(), @@ -692,11 +701,11 @@ pub fn environ_sizes_get( /// The advice to give pub fn fd_advise( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, - advice: __wasi_advice_t, -) -> __wasi_errno_t { + fd: WasiFd, + offset: Filesize, + len: Filesize, + advice: Advice, +) -> Errno { debug!( "wasi[{}:{}]::fd_advise: fd={}", ctx.data().pid(), @@ -720,10 +729,10 @@ pub fn fd_advise( /// The length from the offset marking the end of the allocation pub fn fd_allocate( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - offset: __wasi_filesize_t, - len: __wasi_filesize_t, -) -> __wasi_errno_t { + fd: WasiFd, + offset: Filesize, + len: Filesize, +) -> Errno { debug!( "wasi[{}:{}]::fd_allocate", ctx.data().pid(), @@ -775,7 +784,7 @@ pub fn fd_allocate( /// If `fd` is a directory /// - `Errno::Badf` /// If `fd` is invalid or not open -pub fn fd_close(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_close(ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Errno { debug!( "wasi[{}:{}]::fd_close: fd={}", ctx.data().pid(), @@ -796,7 +805,7 @@ pub fn fd_close(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_err /// Inputs: /// - `Fd fd` /// The file descriptor to sync -pub fn fd_datasync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_datasync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Errno { debug!( "wasi[{}:{}]::fd_datasync", ctx.data().pid(), @@ -854,11 +863,7 @@ pub fn fd_fdstat_get( /// The file descriptor to apply the new flags to /// - `Fdflags flags` /// The flags to apply to `fd` -pub fn fd_fdstat_set_flags( - ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - flags: __wasi_fdflags_t, -) -> __wasi_errno_t { +pub fn fd_fdstat_set_flags(ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd, flags: Fdflags) -> Errno { debug!( "wasi[{}:{}]::fd_fdstat_set_flags (fd={}, flags={})", ctx.data().pid(), @@ -869,10 +874,11 @@ pub fn fd_fdstat_set_flags( let env = ctx.data(); let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let mut fd_map = state.fs.fd_map.write().unwrap(); + let fd_entry = wasi_try!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); let fd_entry = wasi_try!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); let inode = fd_entry.inode; - if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS) { + if !fd_entry.rights.contains(Rights::FD_FDSTAT_SET_FLAGS) { debug!( "wasi[{}:{}]::fd_fdstat_set_flags (fd={}, flags={}) - access denied", ctx.data().pid(), @@ -880,7 +886,7 @@ pub fn fd_fdstat_set_flags( fd, flags ); - return __WASI_EACCES; + return Errno::Access; } { @@ -916,10 +922,10 @@ pub fn fd_fdstat_set_flags( /// The inheriting rights to apply to `fd` pub fn fd_fdstat_set_rights( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, -) -> __wasi_errno_t { + fd: WasiFd, + fs_rights_base: Rights, + fs_rights_inheriting: Rights, +) -> Errno { debug!( "wasi[{}:{}]::fd_fdstat_set_rights", ctx.data().pid(), @@ -952,10 +958,10 @@ pub fn fd_fdstat_set_rights( /// - `Filestat *buf` /// Where the metadata from `fd` will be written pub fn fd_filestat_get( - mut ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_filestat_t, M>, -) -> __wasi_errno_t { + ctx: FunctionEnvMut<'_, WasiEnv>, + fd: WasiFd, + buf: WasmPtr, +) -> Errno { fd_filestat_get_internal(&mut ctx, fd, buf) } @@ -969,9 +975,9 @@ pub fn fd_filestat_get( /// Where the metadata from `fd` will be written pub(crate) fn fd_filestat_get_internal( ctx: &mut FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_filestat_t, M>, -) -> __wasi_errno_t { + fd: WasiFd, + buf: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::fd_filestat_get", ctx.data().pid(), @@ -1001,9 +1007,9 @@ pub(crate) fn fd_filestat_get_internal( /// New size that `fd` will be set to pub fn fd_filestat_set_size( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - st_size: __wasi_filesize_t, -) -> __wasi_errno_t { + fd: WasiFd, + st_size: Filesize, +) -> Errno { debug!( "wasi[{}:{}]::fd_filestat_set_size", ctx.data().pid(), @@ -1055,11 +1061,11 @@ pub fn fd_filestat_set_size( /// Bit-vector for controlling which times get set pub fn fd_filestat_set_times( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { + fd: WasiFd, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { debug!( "wasi[{}:{}]::fd_filestat_set_times", ctx.data().pid(), @@ -1125,7 +1131,7 @@ pub fn fd_pread( iovs_len: M::Offset, offset: Filesize, nread: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { trace!( "wasi[{}:{}]::fd_pread: fd={}, offset={}", ctx.data().pid(), @@ -1136,19 +1142,23 @@ pub fn fd_pread( let env = ctx.data(); let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); - let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); + let iovs = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); let nread_ref = nread.deref(&memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_read = match fd { __WASI_STDIN_FILENO => { - let mut stdin = wasi_try_ok!( + let mut guard = wasi_try_ok!( inodes .stdin_mut(&state.fs.fd_map) .map_err(fs_error_into_wasi_err), env ); - wasi_try_ok!(read_bytes(stdin.deref_mut(), &memory, iovs_arr), env) + if let Some(ref mut stdin) = guard.deref_mut() { + wasi_try_ok!(read_bytes(stdin, &memory, iovs), env) + } else { + return Ok(Errno::Badf); + } } __WASI_STDOUT_FILENO => return Ok(Errno::Inval), __WASI_STDERR_FILENO => return Ok(Errno::Inval), @@ -1172,7 +1182,7 @@ pub fn fd_pread( .map_err(map_io_err), env ); - wasi_try_ok!(read_bytes(h.deref_mut(), &memory, iovs_arr), env) + wasi_try_ok!(read_bytes(h, &memory, iovs), env) } else { return Ok(Errno::Inval); } @@ -1181,10 +1191,10 @@ pub fn fd_pread( let mut memory = env.memory_view(&ctx); let mut max_size = 0usize; - for iovs in iovs_arr.iter() { + for iovs in iovs.iter() { let iovs = wasi_try_mem_ok!(iovs.read()); let buf_len: usize = - wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| __WASI_EOVERFLOW)); + wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow)); max_size += buf_len; } @@ -1199,15 +1209,15 @@ pub fn fd_pread( let data_len = data.len(); let mut reader = &data[..]; let bytes_read = - wasi_try_ok!(read_bytes(reader, &memory, iovs_arr).map(|_| data_len)); + wasi_try_ok!(read_bytes(reader, &memory, iovs).map(|_| data_len)); bytes_read } Kind::Pipe { pipe } => { let mut a; loop { a = wasi_try_ok!( - match pipe.recv(&memory, iovs_arr, Duration::from_millis(5)) { - Err(err) if err == __WASI_ETIMEDOUT => { + match pipe.recv(&memory, iovs, Duration::from_millis(5)) { + Err(err) if err == Errno::Timedout => { env.yield_now()?; continue; } @@ -1224,7 +1234,7 @@ pub fn fd_pread( Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pread"), Kind::Buffer { buffer } => { wasi_try_ok!( - read_bytes(&buffer[(offset as usize)..], &memory, iovs_arr), + read_bytes(&buffer[(offset as usize)..], &memory, iovs), env ) } @@ -1234,7 +1244,8 @@ pub fn fd_pread( let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow)); wasi_try_mem_ok!(nread_ref.write(bytes_read)); - Ok(__WASI_ESUCCESS) + debug!("Success: {} bytes read", bytes_read); + Ok(Errno::Success) } /// ### `fd_prestat_get()` @@ -1247,9 +1258,9 @@ pub fn fd_pread( /// Where the metadata will be written pub fn fd_prestat_get( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - buf: WasmPtr<__wasi_prestat_t, M>, -) -> __wasi_errno_t { + fd: WasiFd, + buf: WasmPtr, +) -> Errno { trace!( "wasi[{}:{}]::fd_prestat_get: fd={}", ctx.data().pid(), @@ -1294,15 +1305,17 @@ pub fn fd_prestat_dir_name( // check inode-val.is_preopened? - //trace!("=> inode: {:?}", inode_val); + trace!("=> inode: {:?}", inode_val); let guard = inode_val.read(); match guard.deref() { Kind::Dir { .. } | Kind::Root { .. } => { + // TODO: verify this: null termination, etc let path_len: u64 = path_len.into(); if (inode_val.name.len() as u64) <= path_len { wasi_try_mem!(path_chars .subslice(0..inode_val.name.len() as u64) .write_slice(inode_val.name.as_bytes())); + wasi_try_mem!(path_chars.index(inode_val.name.len() as u64).write(0)); //trace!("=> result: \"{}\"", inode_val.name); @@ -1341,7 +1354,7 @@ pub fn fd_pwrite( iovs_len: M::Offset, offset: Filesize, nwritten: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { trace!("wasi[{}:{}]::fd_pwrite", ctx.data().pid(), ctx.data().tid()); // TODO: refactor, this is just copied from `fd_write`... let env = ctx.data(); @@ -1353,13 +1366,17 @@ pub fn fd_pwrite( let bytes_written = match fd { __WASI_STDIN_FILENO => return Ok(Errno::Inval), __WASI_STDOUT_FILENO => { - let mut stdout = wasi_try_ok!( + let mut guard = wasi_try_ok!( inodes .stdout_mut(&state.fs.fd_map) .map_err(fs_error_into_wasi_err), env ); - wasi_try_ok!(write_bytes(stdout.deref_mut(), &memory, iovs_arr), env) + if let Some(ref mut stdout) = guard.deref_mut() { + wasi_try_ok!(write_bytes(stdout, &memory, iovs_arr), env) + } else { + return Ok(Errno::Badf); + } } __WASI_STDERR_FILENO => { let mut stderr = wasi_try_ok!( @@ -1368,7 +1385,11 @@ pub fn fd_pwrite( .map_err(fs_error_into_wasi_err), env ); - wasi_try_ok!(write_bytes(stderr.deref_mut(), &memory, iovs_arr), env) + if let Some(ref mut stderr) = guard.deref_mut() { + wasi_try_ok!(write_bytes(stderr, &memory, iovs_arr), env) + } else { + return Ok(Errno::Badf); + } } _ => { if !fd_entry.rights.contains(Rights::FD_WRITE | Rights::FD_SEEK) { @@ -1389,7 +1410,7 @@ pub fn fd_pwrite( .map_err(map_io_err), env ); - wasi_try_ok!(write_bytes(handle.deref_mut(), &memory, iovs_arr), env) + wasi_try_ok!(write_bytes(handle, &memory, iovs_arr), env) } else { return Ok(Errno::Inval); } @@ -1439,10 +1460,173 @@ pub fn fd_pwrite( Ok(Errno::Success) } +// FIXME: there are a lot of change to fd_read from both sides. Must be evaluated carefully! +// /// ### `fd_read()` +// /// Read data from file descriptor +// /// Inputs: +// /// - `Fd fd` +// /// File descriptor from which data will be read +// /// - `const __wasi_iovec_t *iovs` +// /// Vectors where data will be stored +// /// - `u32 iovs_len` +// /// Length of data in `iovs` +// /// Output: +// /// - `u32 *nread` +// /// Number of bytes read +// /// +// pub fn fd_read( +// ctx: FunctionEnvMut<'_, WasiEnv>, +// fd: WasiFd, +// iovs: WasmPtr<__wasi_iovec_t, M>, +// iovs_len: M::Offset, +// nread: WasmPtr, +// ) -> Result { +// trace!( +// "wasi[{}:{}]::fd_read: fd={}", +// ctx.data().pid(), +// ctx.data().tid(), +// fd +// ); +// let env = ctx.data(); +// let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); +// //let iovs_len = if iovs_len > M::Offset::from(1u32) { M::Offset::from(1u32) } else { iovs_len }; +// let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); +// let nread_ref = nread.deref(&memory); +// +// let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); +// let bytes_read = match fd { +// __WASI_STDIN_FILENO => { +// let mut guard = wasi_try_ok!( +// inodes +// .stdin_mut(&state.fs.fd_map) +// .map_err(fs_error_into_wasi_err), +// env +// ); +// if let Some(ref mut stdin) = guard.deref_mut() { +// wasi_try_ok!(read_bytes(stdin, &memory, iovs_arr), env) +// } else { +// return Ok(Errno::Badf); +// } +// } +// __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => return Ok(Errno::Inval), +// _ => { +// if !fd_entry.rights.contains(Rights::FD_READ) { +// // TODO: figure out the error to return when lacking rights +// return Ok(Errno::Access); +// } +// +// let is_non_blocking = fd_entry.flags.contains(Fdflags::NONBLOCK); +// let offset = fd_entry.offset as usize; +// let inode_idx = fd_entry.inode; +// let inode = &inodes.arena[inode_idx]; +// +// let bytes_read = { +// let mut guard = inode.write(); +// let deref_mut = guard.deref_mut(); +// match deref_mut { +// Kind::File { handle, .. } => { +// if let Some(handle) = handle { +// wasi_try_ok!( +// handle +// .seek(std::io::SeekFrom::Start(offset as u64)) +// .map_err(map_io_err), +// env +// ); +// wasi_try_ok!(read_bytes(handle, &memory, iovs_arr), env) +// } else { +// return Ok(Errno::Inval); +// } +// } +// Kind::Socket { socket } => { +// wasi_try_ok!(socket.recv(&memory, iovs_arr), env) +// } +// Kind::Pipe { pipe } => { +// wasi_try_ok!(pipe.recv(&memory, iovs_arr), env) +// } +// Kind::Dir { .. } | Kind::Root { .. } => { +// // TODO: verify +// return Ok(Errno::Isdir); +// } +// Kind::EventNotifications { +// counter, +// is_semaphore, +// wakers, +// } => { +// let counter = Arc::clone(counter); +// let is_semaphore: bool = *is_semaphore; +// let wakers = Arc::clone(wakers); +// drop(guard); +// drop(inodes); +// +// let (tx, rx) = mpsc::channel(); +// { +// let mut guard = wakers.lock().unwrap(); +// guard.push_front(tx); +// } +// +// let ret; +// loop { +// let val = counter.load(Ordering::Acquire); +// if val > 0 { +// let new_val = if is_semaphore { val - 1 } else { 0 }; +// if counter +// .compare_exchange( +// val, +// new_val, +// Ordering::AcqRel, +// Ordering::Acquire, +// ) +// .is_ok() +// { +// let reader = val.to_ne_bytes(); +// ret = wasi_try_ok!( +// read_bytes(&reader[..], &memory, iovs_arr), +// env +// ); +// break; +// } else { +// continue; +// } +// } +// +// // If its none blocking then exit +// if is_non_blocking { +// return Ok(Errno::Again); +// } +// +// // Yield for a fixed period of time and then check again +// env.yield_now()?; +// if rx.recv_timeout(Duration::from_millis(5)).is_err() { +// env.sleep(Duration::from_millis(5))?; +// } +// } +// ret +// } +// Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"), +// Kind::Buffer { buffer } => { +// wasi_try_ok!(read_bytes(&buffer[offset..], &memory, iovs_arr), env) +// } +// } +// }; +// +// // reborrow +// let mut fd_map = state.fs.fd_map.write().unwrap(); +// let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); +// fd_entry.offset += bytes_read as u64; +// +// bytes_read +// } +// }; +// let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow)); +// wasi_try_mem_ok!(nread_ref.write(bytes_read)); +// +// Ok(Errno::Success) +// } + /// ### `fd_read()` /// Read data from file descriptor /// Inputs: -/// - `Fd fd` +/// - `__wasi_fd_t fd` /// File descriptor from which data will be read /// - `const __wasi_iovec_t *iovs` /// Vectors where data will be stored @@ -1486,7 +1670,7 @@ pub fn fd_read( if is_stdio == false { if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ) { // TODO: figure out the error to return when lacking rights - return Ok(Errno::Access); + return Ok(__WASI_EACCES); } } @@ -1660,7 +1844,7 @@ pub fn fd_read( let nread_ref = nread.deref(&memory); wasi_try_mem_ok!(nread_ref.write(bytes_read)); - Ok(Errno::Success) + Ok(__WASI_ESUCCESS) } /// ### `fd_readdir()` @@ -1685,7 +1869,7 @@ pub fn fd_readdir( buf_len: M::Offset, cookie: Dircookie, bufused: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { trace!( "wasi[{}:{}]::fd_readdir", ctx.data().pid(), @@ -1815,11 +1999,7 @@ pub fn fd_readdir( /// File descriptor to copy /// - `Fd to` /// Location to copy file descriptor to -pub fn fd_renumber( - ctx: FunctionEnvMut<'_, WasiEnv>, - from: __wasi_fd_t, - to: __wasi_fd_t, -) -> __wasi_errno_t { +pub fn fd_renumber(ctx: FunctionEnvMut<'_, WasiEnv>, from: WasiFd, to: WasiFd) -> Errno { debug!( "wasi[{}:{}]::fd_renumber(from={}, to={})", ctx.data().pid(), @@ -1827,20 +2007,16 @@ pub fn fd_renumber( from, to ); - if from == to { - return __WASI_ESUCCESS; + return Errno::Success; } - let env = ctx.data(); let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&from).ok_or(Errno::Badf)); - if from != to { - fd_entry.ref_cnt.fetch_add(1, Ordering::Acquire); - } + fd_entry.ref_cnt.fetch_add(1, Ordering::Acquire); let new_fd_entry = Fd { // TODO: verify this is correct ref_cnt: fd_entry.ref_cnt.clone(), @@ -1855,8 +2031,8 @@ pub fn fd_renumber( } } fd_map.insert(to, new_fd_entry); - - __WASI_ESUCCESS + fd_map.remove(&from); + Errno::Success } /// ### `fd_dup()` @@ -1869,9 +2045,9 @@ pub fn fd_renumber( /// The new file handle that is a duplicate of the original pub fn fd_dup( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - ret_fd: WasmPtr<__wasi_fd_t, M>, -) -> __wasi_errno_t { + fd: WasiFd, + ret_fd: WasmPtr, +) -> Errno { debug!("wasi[{}:{}]::fd_dup", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); @@ -1888,9 +2064,10 @@ pub fn fd_dup( pub fn fd_event( ctx: FunctionEnvMut<'_, WasiEnv>, initial_val: u64, - flags: __wasi_eventfdflags, - ret_fd: WasmPtr<__wasi_fd_t, M>, -) -> __wasi_errno_t { + flags: EventFdFlags, + ret_fd: WasmPtr, +) -> Errno { + debug!("wasi::fd_event"); debug!("wasi[{}:{}]::fd_event", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); @@ -1903,15 +2080,16 @@ pub fn fd_event( immediate: Arc::new(AtomicBool::new(false)), }; - let inode = - state - .fs - .create_inode_with_default_stat(inodes.deref_mut(), kind, false, "event".into()); - let rights = __WASI_RIGHT_FD_READ - | __WASI_RIGHT_FD_WRITE - | __WASI_RIGHT_POLL_FD_READWRITE - | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS; - let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); + let inode = state.fs.create_inode_with_default_stat( + inodes.deref_mut(), + kind, + false, + "event".to_string(), + ); + let rights = Rights::FD_READ | Rights::FD_WRITE | Rights::POLL_FD_READWRITE; + let fd = wasi_try!(state + .fs + .create_fd(rights, rights, Fdflags::empty(), 0, inode)); debug!( "wasi[{}:{}]::fd_event - event notifications created (fd={})", @@ -1938,11 +2116,11 @@ pub fn fd_event( /// The new offset relative to the start of the file pub fn fd_seek( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - offset: __wasi_filedelta_t, - whence: __wasi_whence_t, - newoffset: WasmPtr<__wasi_filesize_t, M>, -) -> Result<__wasi_errno_t, WasiError> { + fd: WasiFd, + offset: FileDelta, + whence: Whence, + newoffset: WasmPtr, +) -> Result { trace!( "wasi[{}:{}]::fd_seek: fd={}, offset={}", ctx.data().pid(), @@ -1961,9 +2139,9 @@ pub fn fd_seek( // TODO: handle case if fd is a dir? let new_offset = match whence { - __WASI_WHENCE_CUR => { + Whence::Cur => { let mut fd_map = state.fs.fd_map.write().unwrap(); - let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); + let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); if offset > 0 { fd_entry.offset.fetch_add(offset as u64, Ordering::AcqRel) } else if offset < 0 { @@ -1978,7 +2156,8 @@ pub fn fd_seek( use std::io::SeekFrom; let inode_idx = fd_entry.inode; let mut guard = inodes.arena[inode_idx].write(); - match guard.deref_mut() { + let deref_mut = guard.deref_mut(); + match deref_mut { Kind::File { ref mut handle, .. } => { if let Some(handle) = handle { let mut handle = handle.write().unwrap(); @@ -1987,9 +2166,9 @@ pub fn fd_seek( // TODO: handle case if fd_entry.offset uses 64 bits of a u64 drop(handle); - drop(guard); let mut fd_map = state.fs.fd_map.write().unwrap(); - let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); + let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); + fd_entry.offset = (end as i64 + offset) as u64; fd_entry .offset .store((end as i64 + offset) as u64, Ordering::Release); @@ -2018,11 +2197,11 @@ pub fn fd_seek( } Whence::Set => { let mut fd_map = state.fs.fd_map.write().unwrap(); - let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); + let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); fd_entry.offset.store(offset as u64, Ordering::Release); offset as u64 } - _ => return Ok(__WASI_EINVAL), + _ => return Ok(Errno::Inval), }; // reborrow let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); @@ -2038,9 +2217,9 @@ pub fn fd_seek( /// The file descriptor to sync /// Errors: /// TODO: figure out which errors this should return -/// - `__WASI_EPERM` -/// - `__WASI_ENOTCAPABLE` -pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +/// - `Errno::Perm` +/// - `Errno::Notcapable` +pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Errno { debug!("wasi[{}:{}]::fd_sync", ctx.data().pid(), ctx.data().tid()); debug!("=> fd={}", fd); let env = ctx.data(); @@ -2053,8 +2232,8 @@ pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errn // TODO: implement this for more than files { - let mut guard = inodes.arena[inode].read(); - match guard.deref() { + let mut guard = inodes.arena[inode].write(); + match guard.deref_mut() { Kind::File { handle, .. } => { if let Some(h) = handle { let mut h = h.read().unwrap(); @@ -2085,9 +2264,10 @@ pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errn /// The offset of `fd` relative to the start of the file pub fn fd_tell( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: __wasi_fd_t, - offset: WasmPtr<__wasi_filesize_t, M>, -) -> __wasi_errno_t { + fd: WasiFd, + offset: WasmPtr, +) -> Errno { + debug!("wasi::fd_tell"); debug!("wasi[{}:{}]::fd_tell", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); @@ -2104,10 +2284,156 @@ pub fn fd_tell( Errno::Success } +// FIXME: again, plenty of distinct changes Need to evaluate! +// /// ### `fd_write()` +// /// Write data to the file descriptor +// /// Inputs: +// /// - `Fd` +// /// File descriptor (opened with writing) to write to +// /// - `const __wasi_ciovec_t *iovs` +// /// List of vectors to read data from +// /// - `u32 iovs_len` +// /// Length of data in `iovs` +// /// Output: +// /// - `u32 *nwritten` +// /// Number of bytes written +// /// Errors: +// /// +// pub fn fd_write( +// ctx: FunctionEnvMut<'_, WasiEnv>, +// fd: WasiFd, +// iovs: WasmPtr<__wasi_ciovec_t, M>, +// iovs_len: M::Offset, +// nwritten: WasmPtr, +// ) -> Result { +// trace!( +// "wasi[{}:{}]::fd_write: fd={}", +// ctx.data().pid(), +// ctx.data().tid(), +// fd +// ); +// let env = ctx.data(); +// let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); +// let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); +// let nwritten_ref = nwritten.deref(&memory); +// +// let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); +// let bytes_written = match fd { +// __WASI_STDIN_FILENO => return Ok(Errno::Inval), +// __WASI_STDOUT_FILENO => { +// let mut guard = wasi_try_ok!( +// inodes +// .stdout_mut(&state.fs.fd_map) +// .map_err(fs_error_into_wasi_err), +// env +// ); +// if let Some(ref mut stdout) = guard.deref_mut() { +// wasi_try_ok!(write_bytes(stdout, &memory, iovs_arr), env) +// } else { +// return Ok(Errno::Badf); +// } +// } +// __WASI_STDERR_FILENO => { +// let mut guard = wasi_try_ok!( +// inodes +// .stderr_mut(&state.fs.fd_map) +// .map_err(fs_error_into_wasi_err), +// env +// ); +// if let Some(ref mut stderr) = guard.deref_mut() { +// wasi_try_ok!(write_bytes(stderr, &memory, iovs_arr), env) +// } else { +// return Ok(Errno::Badf); +// } +// } +// _ => { +// if !fd_entry.rights.contains(Rights::FD_WRITE) { +// return Ok(Errno::Access); +// } +// +// let offset = fd_entry.offset as usize; +// let inode_idx = fd_entry.inode; +// let inode = &inodes.arena[inode_idx]; +// +// let bytes_written = { +// let mut guard = inode.write(); +// let deref_mut = guard.deref_mut(); +// match deref_mut { +// Kind::File { handle, .. } => { +// if let Some(handle) = handle { +// wasi_try_ok!( +// handle +// .seek(std::io::SeekFrom::Start(offset as u64)) +// .map_err(map_io_err), +// env +// ); +// wasi_try_ok!(write_bytes(handle, &memory, iovs_arr), env) +// } else { +// return Ok(Errno::Inval); +// } +// } +// Kind::Socket { socket } => { +// wasi_try_ok!(socket.send(&memory, iovs_arr), env) +// } +// Kind::Pipe { pipe } => { +// wasi_try_ok!(pipe.send(&memory, iovs_arr), env) +// } +// Kind::Dir { .. } | Kind::Root { .. } => { +// // TODO: verify +// return Ok(Errno::Isdir); +// } +// Kind::EventNotifications { +// counter, wakers, .. +// } => { +// let mut val = 0u64.to_ne_bytes(); +// let written = wasi_try_ok!(write_bytes(&mut val[..], &memory, iovs_arr)); +// if written != val.len() { +// return Ok(Errno::Inval); +// } +// let val = u64::from_ne_bytes(val); +// +// counter.fetch_add(val, Ordering::AcqRel); +// { +// let mut guard = wakers.lock().unwrap(); +// while let Some(wake) = guard.pop_back() { +// if wake.send(()).is_ok() { +// break; +// } +// } +// } +// +// written +// } +// Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_write"), +// Kind::Buffer { buffer } => { +// wasi_try_ok!(write_bytes(&mut buffer[offset..], &memory, iovs_arr), env) +// } +// } +// }; +// +// // reborrow +// { +// let mut fd_map = state.fs.fd_map.write().unwrap(); +// let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf)); +// fd_entry.offset += bytes_written as u64; +// } +// wasi_try_ok!(state.fs.filestat_resync_size(inodes.deref(), fd), env); +// +// bytes_written +// } +// }; +// +// let bytes_written: M::Offset = +// wasi_try_ok!(bytes_written.try_into().map_err(|_| Errno::Overflow)); +// wasi_try_mem_ok!(nwritten_ref.write(bytes_written)); +// +// Ok(Errno::Success) +// } + /// ### `fd_write()` /// Write data to the file descriptor /// Inputs: -/// - `Fd` +/// - `__wasi_fd_t` /// File descriptor (opened with writing) to write to /// - `const __wasi_ciovec_t *iovs` /// List of vectors to read data from @@ -2120,17 +2446,17 @@ pub fn fd_tell( /// pub fn fd_write( ctx: FunctionEnvMut<'_, WasiEnv>, - fd: WasiFd, + fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, M>, iovs_len: M::Offset, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { trace!( - "wasi[{}:{}]::fd_write: fd={}", - ctx.data().pid(), - ctx.data().tid(), - fd - ); + "wasi[{}:{}]::fd_write: fd={}", + ctx.data().pid(), + ctx.data().tid(), + fd +); let env = ctx.data(); let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); @@ -2164,11 +2490,11 @@ pub fn fd_write( let mut handle = handle.write().unwrap(); if is_stdio == false { wasi_try_ok!( - handle - .seek(std::io::SeekFrom::Start(offset as u64)) - .map_err(map_io_err), - env - ); + handle + .seek(std::io::SeekFrom::Start(offset as u64)) + .map_err(map_io_err), + env + ); } wasi_try_ok!(write_bytes(handle.deref_mut(), &memory, iovs_arr), env) } else { @@ -2188,11 +2514,11 @@ pub fn fd_write( let socket = socket.clone(); wasi_try_ok!(__asyncify( - env.tasks.clone(), - &env.thread, - None, - async move { socket.send(buf).await } - )) + env.tasks.clone(), + &env.thread, + None, + async move { socket.send(buf).await } + )) } Kind::Pipe { pipe } => { wasi_try_ok!(pipe.send(&memory, iovs_arr), env) @@ -2251,10 +2577,10 @@ pub fn fd_write( }; let bytes_written: M::Offset = - wasi_try_ok!(bytes_written.try_into().map_err(|_| Errno::Overflow)); + wasi_try_ok!(bytes_written.try_into().map_err(|_| __WASI_EOVERFLOW)); wasi_try_mem_ok!(nwritten_ref.write(bytes_written)); - Ok(Errno::Success) + Ok(__WASI_ESUCCESS) } /// ### `fd_pipe()` @@ -2266,9 +2592,9 @@ pub fn fd_write( /// Second file handle that represents the other end of the pipe pub fn fd_pipe( ctx: FunctionEnvMut<'_, WasiEnv>, - ro_fd1: WasmPtr<__wasi_fd_t, M>, - ro_fd2: WasmPtr<__wasi_fd_t, M>, -) -> __wasi_errno_t { + ro_fd1: WasmPtr, + ro_fd2: WasmPtr, +) -> Errno { trace!("wasi[{}:{}]::fd_pipe", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); @@ -2282,18 +2608,22 @@ pub fn fd_pipe( inodes.deref_mut(), Kind::Pipe { pipe: pipe1 }, false, - "pipe".into(), + "pipe".to_string(), ); let inode2 = state.fs.create_inode_with_default_stat( inodes.deref_mut(), Kind::Pipe { pipe: pipe2 }, false, - "pipe".into(), + "pipe".to_string(), ); - let rights = super::state::all_socket_rights(); - let fd1 = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode1)); - let fd2 = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode2)); + let rights = Rights::all_socket(); + let fd1 = wasi_try!(state + .fs + .create_fd(rights, rights, Fdflags::empty(), 0, inode1)); + let fd2 = wasi_try!(state + .fs + .create_fd(rights, rights, Fdflags::empty(), 0, inode2)); trace!( "wasi[{}:{}]::fd_pipe (fd1={}, fd2={})", ctx.data().pid(), @@ -2326,7 +2656,7 @@ pub fn path_create_directory( fd: WasiFd, path: WasmPtr, path_len: M::Offset, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::path_create_directory", ctx.data().pid(), @@ -2470,12 +2800,12 @@ pub fn path_filestat_get( flags: LookupFlags, path: WasmPtr, path_len: M::Offset, - buf: WasmPtr<__wasi_filestat_t, M>, -) -> __wasi_errno_t { + buf: WasmPtr, +) -> Errno { let env = ctx.data(); let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); - let mut path_string = unsafe { get_input_str!(&memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&memory, path, path_len) }; debug!( "wasi[{}:{}]::path_filestat_get (fd={}, path={})", ctx.data().pid(), @@ -2536,6 +2866,7 @@ pub fn path_filestat_get_internal( if !root_dir.rights.contains(Rights::PATH_FILESTAT_GET) { return Err(Errno::Access); } + debug!("=> base_fd: {}, path: {}", fd, path_string); let file_inode = state.fs.get_inode_at_path( inodes, @@ -2574,10 +2905,10 @@ pub fn path_filestat_set_times( flags: LookupFlags, path: WasmPtr, path_len: M::Offset, - st_atim: __wasi_timestamp_t, - st_mtim: __wasi_timestamp_t, - fst_flags: __wasi_fstflags_t, -) -> __wasi_errno_t { + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { debug!( "wasi[{}:{}]::path_filestat_set_times", ctx.data().pid(), @@ -2669,7 +3000,7 @@ pub fn path_link( new_fd: WasiFd, new_path: WasmPtr, new_path_len: M::Offset, -) -> __wasi_errno_t { +) -> Errno { debug!("wasi[{}:{}]::path_link", ctx.data().pid(), ctx.data().tid()); if old_flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0 { debug!(" - will follow symlinks when opening path"); @@ -2765,12 +3096,12 @@ pub fn path_open( dirflags: LookupFlags, path: WasmPtr, path_len: M::Offset, - o_flags: __wasi_oflags_t, - fs_rights_base: __wasi_rights_t, - fs_rights_inheriting: __wasi_rights_t, - fs_flags: __wasi_fdflags_t, - fd: WasmPtr<__wasi_fd_t, M>, -) -> __wasi_errno_t { + o_flags: Oflags, + fs_rights_base: Rights, + fs_rights_inheriting: Rights, + fs_flags: Fdflags, + fd: WasmPtr, +) -> Errno { debug!("wasi[{}:{}]::path_open", ctx.data().pid(), ctx.data().tid()); if dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0 { debug!(" - will follow symlinks when opening path"); @@ -2798,9 +3129,8 @@ pub fn path_open( if !working_dir.rights.contains(Rights::PATH_OPEN) { return Errno::Access; } - let mut path_string = unsafe { get_input_str!(&memory, path, path_len) }; - debug!("=> dirfd: {}, path: {}", dirfd, &path_string); + let mut path_string = unsafe { get_input_str!(&memory, path, path_len) }; // Convert relative paths into absolute paths if path_string.starts_with("./") { @@ -2812,6 +3142,7 @@ pub fn path_open( path_string ); } + debug!("=> path_open(): fd: {}, path: {}", dirfd, &path_string); let path_arg = std::path::PathBuf::from(&path_string); let maybe_inode = state.fs.get_inode_at_path( @@ -2883,7 +3214,8 @@ pub fn path_open( let inode = if let Ok(inode) = maybe_inode { // Happy path, we found the file we're trying to open let mut guard = inodes.arena[inode].write(); - match guard.deref_mut() { + let deref_mut = guard.deref_mut(); + match deref_mut { Kind::File { ref mut handle, path, @@ -2934,7 +3266,7 @@ pub fn path_open( // some special files will return a constant FD rather than // actually open the file (/dev/stdin, /dev/stdout, /dev/stderr) wasi_try_mem!(fd_ref.write(special_fd)); - return __WASI_ESUCCESS; + return Errno::Success; } } } @@ -3096,7 +3428,7 @@ pub fn path_readlink( buf: WasmPtr, buf_len: M::Offset, buf_used: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::path_readlink", ctx.data().pid(), @@ -3310,7 +3642,7 @@ pub fn path_rename( wasi_try!(state .fs .get_parent_inode_at_path(inodes.deref_mut(), new_fd, target_path, true)); - + let mut need_create = true; let host_adjusted_target_path = { let guard = inodes.arena[target_parent_inode].read(); match guard.deref() { @@ -3441,7 +3773,7 @@ pub fn path_symlink( fd: WasiFd, new_path: WasmPtr, new_path_len: M::Offset, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::path_symlink", ctx.data().pid(), @@ -3550,7 +3882,7 @@ pub fn path_unlink_file( fd: WasiFd, path: WasmPtr, path_len: M::Offset, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::path_unlink_file", ctx.data().pid(), @@ -3661,12 +3993,264 @@ pub fn path_unlink_file( Errno::Success } + +// FIXME: lots of changes, needs manual resolve +// /// ### `poll_oneoff()` +// /// Concurrently poll for a set of events +// /// Inputs: +// /// - `const __wasi_subscription_t *in` +// /// The events to subscribe to +// /// - `Event *out` +// /// The events that have occured +// /// - `u32 nsubscriptions` +// /// The number of subscriptions and the number of events +// /// Output: +// /// - `u32 nevents` +// /// The number of events seen +// pub fn poll_oneoff( +// ctx: FunctionEnvMut<'_, WasiEnv>, +// in_: WasmPtr, +// out_: WasmPtr, +// nsubscriptions: M::Offset, +// nevents: WasmPtr, +// ) -> Result { +// trace!("wasi::poll_oneoff"); +// trace!(" => nsubscriptions = {}", nsubscriptions); +// let env = ctx.data(); +// let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); +// +// let subscription_array = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions)); +// let event_array = wasi_try_mem_ok!(out_.slice(&memory, nsubscriptions)); +// let mut events_seen: u32 = 0; +// let out_ptr = nevents.deref(&memory); +// +// let mut fd_guards = vec![]; +// let mut clock_subs = vec![]; +// let mut in_events = vec![]; +// let mut time_to_sleep = Duration::from_millis(5); +// +// for sub in subscription_array.iter() { +// let s: Subscription = wasi_try_mem_ok!(sub.read()); +// let mut peb = PollEventBuilder::new(); +// +// let fd = match s.data { +// SubscriptionEnum::Read(SubscriptionFsReadwrite { file_descriptor }) => { +// match file_descriptor { +// __WASI_STDIN_FILENO | __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => (), +// _ => { +// let fd_entry = wasi_try_ok!(state.fs.get_fd(file_descriptor), env); +// if !fd_entry.rights.contains(Rights::FD_READ) { +// return Ok(Errno::Access); +// } +// } +// } +// in_events.push(peb.add(PollEvent::PollIn).build()); +// Some(file_descriptor) +// } +// SubscriptionEnum::Write(SubscriptionFsReadwrite { file_descriptor }) => { +// match file_descriptor { +// __WASI_STDIN_FILENO | __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => (), +// _ => { +// let fd_entry = wasi_try_ok!(state.fs.get_fd(file_descriptor), env); +// if !fd_entry.rights.contains(Rights::FD_WRITE) { +// return Ok(Errno::Access); +// } +// } +// } +// in_events.push(peb.add(PollEvent::PollOut).build()); +// Some(file_descriptor) +// } +// SubscriptionEnum::Clock(clock_info) => { +// if matches!(clock_info.clock_id, Clockid::Realtime | Clockid::Monotonic) { +// // this is a hack +// // TODO: do this properly +// time_to_sleep = Duration::from_nanos(clock_info.timeout); +// clock_subs.push((clock_info, s.userdata)); +// None +// } else { +// unimplemented!("Polling not implemented for clocks yet"); +// } +// } +// }; +// +// if let Some(fd) = fd { +// let wasi_file_ref = match fd { +// __WASI_STDERR_FILENO => { +// wasi_try_ok!( +// inodes +// .stderr(&state.fs.fd_map) +// .map_err(fs_error_into_wasi_err), +// env +// ) +// } +// __WASI_STDIN_FILENO => { +// wasi_try_ok!( +// inodes +// .stdin(&state.fs.fd_map) +// .map_err(fs_error_into_wasi_err), +// env +// ) +// } +// __WASI_STDOUT_FILENO => { +// wasi_try_ok!( +// inodes +// .stdout(&state.fs.fd_map) +// .map_err(fs_error_into_wasi_err), +// env +// ) +// } +// _ => { +// let fd_entry = wasi_try_ok!(state.fs.get_fd(fd), env); +// let inode = fd_entry.inode; +// if !fd_entry.rights.contains(Rights::POLL_FD_READWRITE) { +// return Ok(Errno::Access); +// } +// +// { +// let guard = inodes.arena[inode].read(); +// let deref = guard.deref(); +// match deref { +// Kind::File { handle, .. } => { +// if let Some(h) = handle { +// crate::state::InodeValFileReadGuard { guard } +// } else { +// return Ok(Errno::Badf); +// } +// } +// Kind::Socket { .. } +// | Kind::Pipe { .. } +// | Kind::EventNotifications { .. } => { +// return Ok(Errno::Badf); +// } +// Kind::Dir { .. } +// | Kind::Root { .. } +// | Kind::Buffer { .. } +// | Kind::Symlink { .. } => { +// unimplemented!("polling read on non-files not yet supported") +// } +// } +// } +// } +// }; +// fd_guards.push(wasi_file_ref); +// } +// } +// +// #[allow(clippy::significant_drop_in_scrutinee)] +// let fds = { +// let mut f = vec![]; +// for fd in fd_guards.iter() { +// f.push(wasi_try_ok!(fd.as_ref().ok_or(Errno::Badf)).deref()); +// } +// f +// }; +// +// let mut seen_events = vec![Default::default(); in_events.len()]; +// +// let start = platform_clock_time_get(Snapshot0Clockid::Monotonic, 1_000_000).unwrap() as u128; +// let mut triggered = 0; +// while triggered == 0 { +// let now = platform_clock_time_get(Snapshot0Clockid::Monotonic, 1_000_000).unwrap() as u128; +// let delta = match now.checked_sub(start) { +// Some(a) => Duration::from_nanos(a as u64), +// None => Duration::ZERO, +// }; +// match poll( +// fds.as_slice(), +// in_events.as_slice(), +// seen_events.as_mut_slice(), +// Duration::from_millis(1), +// ) { +// Ok(0) => { +// env.yield_now()?; +// } +// Ok(a) => { +// triggered = a; +// } +// Err(FsError::WouldBlock) => { +// env.sleep(Duration::from_millis(1))?; +// } +// Err(err) => { +// return Ok(fs_error_into_wasi_err(err)); +// } +// }; +// if delta > time_to_sleep { +// break; +// } +// } +// +// for (i, seen_event) in seen_events.into_iter().enumerate() { +// let mut flags = Eventrwflags::empty(); +// let mut error = Errno::Again; +// let mut bytes_available = 0; +// let event_iter = iterate_poll_events(seen_event); +// for event in event_iter { +// match event { +// PollEvent::PollError => error = Errno::Io, +// PollEvent::PollHangUp => flags = Eventrwflags::FD_READWRITE_HANGUP, +// PollEvent::PollInvalid => error = Errno::Inval, +// PollEvent::PollIn => { +// bytes_available = wasi_try_ok!( +// fds[i] +// .bytes_available_read() +// .map_err(fs_error_into_wasi_err), +// env +// ) +// .unwrap_or(0usize); +// error = Errno::Success; +// } +// PollEvent::PollOut => { +// bytes_available = wasi_try_ok!( +// fds[i] +// .bytes_available_write() +// .map_err(fs_error_into_wasi_err), +// env +// ) +// .unwrap_or(0usize); +// error = Errno::Success; +// } +// } +// } +// let event = Event { +// userdata: wasi_try_mem_ok!(subscription_array.index(i as u64).read()).userdata, +// error, +// data: match wasi_try_mem_ok!(subscription_array.index(i as u64).read()).data { +// SubscriptionEnum::Read(d) => EventEnum::FdRead(EventFdReadwrite { +// nbytes: bytes_available as u64, +// flags, +// }), +// SubscriptionEnum::Write(d) => EventEnum::FdWrite(EventFdReadwrite { +// nbytes: bytes_available as u64, +// flags, +// }), +// SubscriptionEnum::Clock(_) => EventEnum::Clock, +// }, +// }; +// wasi_try_mem_ok!(event_array.index(events_seen as u64).write(event)); +// events_seen += 1; +// } +// if triggered == 0 { +// for (clock_info, userdata) in clock_subs { +// let event = Event { +// userdata, +// error: Errno::Success, +// data: EventEnum::Clock, +// }; +// wasi_try_mem_ok!(event_array.index(events_seen as u64).write(event)); +// events_seen += 1; +// } +// } +// let events_seen: M::Offset = wasi_try_ok!(events_seen.try_into().map_err(|_| Errno::Overflow)); +// wasi_try_mem_ok!(out_ptr.write(events_seen)); +// Ok(Errno::Success) +// } + /// ### `poll_oneoff()` /// Concurrently poll for a set of events /// Inputs: /// - `const __wasi_subscription_t *in` /// The events to subscribe to -/// - `Event *out` +/// - `__wasi_event_t *out` /// The events that have occured /// - `u32 nsubscriptions` /// The number of subscriptions and the number of events @@ -3683,11 +4267,11 @@ pub fn poll_oneoff( let pid = ctx.data().pid(); let tid = ctx.data().tid(); trace!( - "wasi[{}:{}]::poll_oneoff (nsubscriptions={})", - pid, - tid, - nsubscriptions - ); + "wasi[{}:{}]::poll_oneoff (nsubscriptions={})", + pid, + tid, + nsubscriptions +); // These are used when we capture what clocks (timeouts) are being // subscribed too @@ -3711,30 +4295,32 @@ pub fn poll_oneoff( match fd { __WASI_STDIN_FILENO | __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => (), _ => { - let fd_entry = wasi_try_ok!(state.fs.get_fd(file_descriptor), env); - if !fd_entry.rights.contains(Rights::FD_READ) { - return Ok(Errno::Access); + let fd_entry = wasi_try_ok!(state.fs.get_fd(fd), env); + if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ) { + return Ok(__WASI_EACCES); } } } in_events.insert(peb.add(PollEvent::PollIn).build(), s); fd } - SubscriptionEnum::Write(SubscriptionFsReadwrite { file_descriptor }) => { - match file_descriptor { + EventType::Write(__wasi_subscription_fs_readwrite_t { fd }) => { + match fd { __WASI_STDIN_FILENO | __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => (), _ => { - let fd_entry = wasi_try_ok!(state.fs.get_fd(file_descriptor), env); - if !fd_entry.rights.contains(Rights::FD_WRITE) { - return Ok(Errno::Access); + let fd_entry = wasi_try_ok!(state.fs.get_fd(fd), env); + if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_WRITE) { + return Ok(__WASI_EACCES); } } } in_events.insert(peb.add(PollEvent::PollOut).build(), s); fd } - SubscriptionEnum::Clock(clock_info) => { - if matches!(clock_info.clock_id, Clockid::Realtime | Clockid::Monotonic) { + EventType::Clock(clock_info) => { + if clock_info.clock_id == __WASI_CLOCK_REALTIME + || clock_info.clock_id == __WASI_CLOCK_MONOTONIC + { // this is a hack // TODO: do this properly time_to_sleep = Some(Duration::from_nanos(clock_info.timeout)); @@ -3757,11 +4343,11 @@ pub fn poll_oneoff( // otherwise we just process all the events and wait on them indefinately if let Some(time_to_sleep) = time_to_sleep.as_ref() { tracing::trace!( - "wasi[{}:{}]::poll_oneoff wait_for_timeout={}", - pid, - tid, - time_to_sleep.as_millis() - ); + "wasi[{}:{}]::poll_oneoff wait_for_timeout={}", + pid, + tid, + time_to_sleep.as_millis() + ); } let time_to_sleep = time_to_sleep; @@ -3782,26 +4368,26 @@ pub fn poll_oneoff( let mut fd_guards = vec![]; #[allow(clippy::significant_drop_in_scrutinee)] - let fds = { + let fds = { for (fd, in_events) in subscriptions { let wasi_file_ref = match fd { __WASI_STDERR_FILENO => { wasi_try_ok!(inodes - .stderr(&state.fs.fd_map) - .map(|g| g.into_poll_guard(fd, in_events, tasks.clone())) - .map_err(fs_error_into_wasi_err)) + .stderr(&state.fs.fd_map) + .map(|g| g.into_poll_guard(fd, in_events, tasks.clone())) + .map_err(fs_error_into_wasi_err)) } __WASI_STDIN_FILENO => { wasi_try_ok!(inodes - .stdin(&state.fs.fd_map) - .map(|g| g.into_poll_guard(fd, in_events, tasks.clone())) - .map_err(fs_error_into_wasi_err)) + .stdin(&state.fs.fd_map) + .map(|g| g.into_poll_guard(fd, in_events, tasks.clone())) + .map_err(fs_error_into_wasi_err)) } __WASI_STDOUT_FILENO => { wasi_try_ok!(inodes - .stdout(&state.fs.fd_map) - .map(|g| g.into_poll_guard(fd, in_events, tasks.clone())) - .map_err(fs_error_into_wasi_err)) + .stdout(&state.fs.fd_map) + .map(|g| g.into_poll_guard(fd, in_events, tasks.clone())) + .map_err(fs_error_into_wasi_err)) } _ => { let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); @@ -3820,18 +4406,18 @@ pub fn poll_oneoff( ) { guard } else { - return Ok(Errno::Badf); + return Ok(__WASI_EBADF); } } } }; tracing::trace!( - "wasi[{}:{}]::poll_oneoff wait_for_fd={} type={:?}", - pid, - tid, - fd, - wasi_file_ref - ); + "wasi[{}:{}]::poll_oneoff wait_for_fd={} type={:?}", + pid, + tid, + fd, + wasi_file_ref + ); fd_guards.push(wasi_file_ref); } @@ -3861,12 +4447,12 @@ pub fn poll_oneoff( let evts = guard.wait().await; for evt in evts { tracing::trace!( - "wasi[{}:{}]::poll_oneoff (fd_triggered={}, type={})", - pid, - tid, - guard.fd, - evt.type_ - ); + "wasi[{}:{}]::poll_oneoff (fd_triggered={}, type={})", + pid, + tid, + guard.fd, + evt.type_ + ); triggered_events_tx.send(evt).unwrap(); } }); @@ -3938,15 +4524,16 @@ pub fn poll_oneoff( let out_ptr = nevents.deref(&memory); wasi_try_mem_ok!(out_ptr.write(events_seen)); tracing::trace!( - "wasi[{}:{}]::poll_oneoff ret={} seen={}", - pid, - tid, - ret, - events_seen - ); + "wasi[{}:{}]::poll_oneoff ret={} seen={}", + pid, + tid, + ret, + events_seen +); Ok(ret) } + /// ### `proc_exit()` /// Terminate the process normally. An exit code of 0 indicates successful /// termination of the program. The meanings of other values is dependent on @@ -4078,7 +4665,7 @@ pub fn thread_signal( /// Send a signal to the process of the calling thread. /// Note: This is similar to `raise` in POSIX. /// Inputs: -/// - `Signal` +/// - `__wasi_signal_t` /// Signal to be raised for this process pub fn proc_raise( mut ctx: FunctionEnvMut<'_, WasiEnv>, @@ -4100,14 +4687,14 @@ pub fn proc_raise( /// Send a signal to the process of the calling thread. /// Note: This is similar to `raise` in POSIX. /// Inputs: -/// - `__wasi_signal_t` +/// - `Signal` /// Signal to be raised for this process pub fn proc_raise_interval( mut ctx: FunctionEnvMut<'_, WasiEnv>, sig: __wasi_signal_t, interval: __wasi_timestamp_t, repeat: __wasi_bool_t, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { debug!( "wasi[{}:{}]::proc_raise_interval (sig={})", ctx.data().pid(), @@ -4131,8 +4718,9 @@ pub fn proc_raise_interval( /// ### `sched_yield()` /// Yields execution of the thread -pub fn sched_yield(mut ctx: FunctionEnvMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { +pub fn sched_yield(ctx: FunctionEnvMut<'_, WasiEnv>) -> Result { //trace!("wasi[{}:{}]::sched_yield", ctx.data().pid(), ctx.data().tid()); + trace!("wasi::sched_yield"); let env = ctx.data(); env.clone().yield_now_with_signals(&mut ctx)?; Ok(__WASI_ESUCCESS) @@ -4791,7 +5379,7 @@ pub fn proc_signal( mut ctx: FunctionEnvMut<'_, WasiEnv>, pid: __wasi_pid_t, sig: __wasi_signal_t, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { warn!( "wasi[{}:{}]::proc_signal(pid={}, sig={}) is not supported without 'os' feature", ctx.data().pid(), @@ -4813,7 +5401,7 @@ pub fn random_get( ctx: FunctionEnvMut<'_, WasiEnv>, buf: WasmPtr, buf_len: M::Offset, -) -> __wasi_errno_t { +) -> Errno { trace!( "wasi[{}:{}]::random_get(buf_len={})", ctx.data().pid(), @@ -4839,8 +5427,8 @@ pub fn random_get( /// Retrieves the current state of the TTY pub fn tty_get( ctx: FunctionEnvMut<'_, WasiEnv>, - tty_state: WasmPtr<__wasi_tty_t, M>, -) -> __wasi_errno_t { + tty_state: WasmPtr, +) -> Errno { debug!("wasi[{}:{}]::tty_get", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); @@ -4867,8 +5455,10 @@ pub fn tty_get( /// Updates the properties of the rect pub fn tty_set( ctx: FunctionEnvMut<'_, WasiEnv>, - tty_state: WasmPtr<__wasi_tty_t, M>, -) -> __wasi_errno_t { + tty_state: WasmPtr, +) -> Errno { + debug!("wasi::tty_set"); + let env = ctx.data(); let memory = env.memory_view(&ctx); let state = wasi_try_mem!(tty_state.read(&memory)); @@ -4897,23 +5487,11 @@ pub fn tty_set( rows: state.rows, width: state.width, height: state.height, - stdin_tty: match state.stdin_tty { - __WASI_BOOL_FALSE => false, - __WASI_BOOL_TRUE => true, - _ => return __WASI_EINVAL, - }, - stdout_tty: match state.stdout_tty { - __WASI_BOOL_FALSE => false, - __WASI_BOOL_TRUE => true, - _ => return __WASI_EINVAL, - }, - stderr_tty: match state.stderr_tty { - __WASI_BOOL_FALSE => false, - __WASI_BOOL_TRUE => true, - _ => return __WASI_EINVAL, - }, - echo, - line_buffered, + stdin_tty: state.stdin_tty, + stdout_tty: state.stdout_tty, + stderr_tty: state.stderr_tty, + echo: state.echo, + line_buffered: state.line_buffered, line_feeds, }; @@ -4930,7 +5508,7 @@ pub fn getcwd( ctx: FunctionEnvMut<'_, WasiEnv>, path: WasmPtr, path_len: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!("wasi[{}:{}]::getcwd", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); @@ -4977,7 +5555,7 @@ pub fn chdir( ctx: FunctionEnvMut<'_, WasiEnv>, path: WasmPtr, path_len: M::Offset, -) -> __wasi_errno_t { +) -> Errno { let env = ctx.data(); let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); let path = unsafe { get_input_str!(&memory, path, path_len) }; @@ -5125,6 +5703,209 @@ pub fn callback_thread_local_destroy( Ok(()) } +// FIXME: needs manual resolve +// /// ### `thread_spawn()` +// /// Creates a new thread by spawning that shares the same +// /// memory address space, file handles and main event loops. +// /// The function referenced by the fork call must be +// /// exported by the web assembly process. +// /// +// /// ## Parameters +// /// +// /// * `name` - Name of the function that will be invoked as a new thread +// /// * `user_data` - User data that will be supplied to the function when its called +// /// * `reactor` - Indicates if the function will operate as a reactor or +// /// as a normal thread. Reactors will be repeatable called +// /// whenever IO work is available to be processed. +// /// +// /// ## Return +// /// +// /// Returns the thread index of the newly created thread +// /// (indices always start from zero) +// pub fn thread_spawn( +// ctx: FunctionEnvMut<'_, WasiEnv>, +// method: WasmPtr, +// method_len: M::Offset, +// user_data: u64, +// reactor: Bool, +// ret_tid: WasmPtr, +// ) -> Errno { +// debug!("wasi::thread_spawn"); +// let env = ctx.data(); +// let memory = env.memory_view(&ctx); +// let method = unsafe { get_input_str!(&memory, method, method_len) }; +// +// // Load the callback function +// if method.as_str() != "_thread_start" { +// return Errno::Notcapable; +// }; +// /* +// let funct = unsafe { +// if env.thread_start_ref().is_none() { +// return Errno::Addrnotavail; +// } +// env.thread_start_ref_unchecked() +// }; +// */ +// +// let reactor = match reactor { +// Bool::False => false, +// Bool::True => true, +// _ => return Errno::Inval, +// }; +// +// // Create the sub-thread +// let mut sub_env = env.clone(); +// let mut sub_thread = env.new_thread(); +// sub_env.id = sub_thread.id; +// +// let child = { +// let id = sub_thread.id; +// wasi_try!(env +// .runtime +// .thread_spawn(Box::new(move || { +// /* +// if let Some(funct) = sub_env.thread_start_ref() { +// if let Err(err) = funct.call(user_data) { +// warn!("thread failed: {}", err); +// std::mem::forget(sub_thread); +// return; +// } +// } else { +// warn!("failed to start thread: missing callback '__wasix_thread_start'"); +// std::mem::forget(sub_thread); +// return; +// } +// */ +// +// let thread = { +// let mut guard = sub_env.state.threading.lock().unwrap(); +// let thread = guard.threads.remove(&id); +// drop(guard); +// thread +// }; +// +// if let Some(thread) = thread { +// let mut thread_guard = thread.exit.lock().unwrap(); +// thread_guard.take(); +// } +// drop(sub_thread); +// })) +// .map_err(|err| { +// let err: Errno = err.into(); +// err +// })); +// id +// }; +// let child: Tid = child.into(); +// +// wasi_try_mem!(ret_tid.write(&memory, child)); +// Errno::Success +// } + +/// ### `thread_local_destroy()` +/// Destroys a thread local variable +/// +/// ## Parameters +/// +/// * `user_data` - User data that will be passed to the destructor +/// when the thread variable goes out of scope +/// * `key` - Thread key that was previously created +pub fn thread_local_destroy( + mut ctx: FunctionEnvMut<'_, WasiEnv>, + key: __wasi_tl_key_t, +) -> Errno { + trace!( + "wasi[{}:{}]::thread_local_destroy (key={})", + ctx.data().pid(), + ctx.data().tid(), + key +); + let process = ctx.data().process.clone(); + let mut inner = process.write(); + if let Some(user_data) = inner.thread_local_user_data.remove(&key) { + if let Some(thread_local_destroy) = ctx + .data() + .inner() + .thread_local_destroy + .as_ref() + .map(|a| a.clone()) + { + inner + .thread_local + .iter() + .filter(|((_, k), _)| *k == key) + .for_each(|((_, _), val)| { + let user_data_low: u32 = (user_data & 0xFFFFFFFF) as u32; + let user_data_high: u32 = (user_data >> 32) as u32; + + let val_low: u32 = (val & 0xFFFFFFFF) as u32; + let val_high: u32 = (val >> 32) as u32; + + let _ = thread_local_destroy.call( + &mut ctx, + user_data_low as i32, + user_data_high as i32, + val_low as i32, + val_high as i32, + ); + }); + } + } + inner.thread_local.retain(|(_, k), _| *k != key); + Errno::Success +} + + +/// ### `thread_local_set()` +/// Sets the value of a thread local variable +/// +/// ## Parameters +/// +/// * `key` - Thread key that this local variable will be associated with +/// * `val` - Value to be set for the thread local variable +pub fn thread_local_set( + ctx: FunctionEnvMut<'_, WasiEnv>, + key: __wasi_tl_key_t, + val: __wasi_tl_val_t, +) -> Errno { + //trace!("wasi[{}:{}]::thread_local_set (key={}, val={})", ctx.data().pid(), ctx.data().tid(), key, val); + let env = ctx.data(); + + let current_thread = ctx.data().thread.tid(); + let mut inner = env.process.write(); + inner.thread_local.insert((current_thread, key), val); + Errno::Success +} + +/// ### `thread_local_get()` +/// Gets the value of a thread local variable +/// +/// ## Parameters +/// +/// * `key` - Thread key that this local variable that was previous set +pub fn thread_local_get( + ctx: FunctionEnvMut<'_, WasiEnv>, + key: __wasi_tl_key_t, + ret_val: WasmPtr<__wasi_tl_val_t, M>, +) -> __wasi_errno_t { + //trace!("wasi[{}:{}]::thread_local_get (key={})", ctx.data().pid(), ctx.data().tid(), key); + let env = ctx.data(); + + let val = { + let current_thread = ctx.data().thread.tid(); + let guard = env.process.read(); + guard + .thread_local + .get(&(current_thread, key)) + .map(|a| a.clone()) + }; + let val = val.unwrap_or_default(); + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_val.write(&memory, val)); + __WASI_ESUCCESS +} + /// ### `thread_spawn()` /// Creates a new thread by spawning that shares the same /// memory address space, file handles and main event loops. @@ -5152,14 +5933,14 @@ pub fn thread_spawn( ret_tid: WasmPtr<__wasi_tid_t, M>, ) -> __wasi_errno_t { debug!( - "wasi[{}:{}]::thread_spawn (reactor={}, thread_id={}, stack_base={}, caller_id={})", - ctx.data().pid(), - ctx.data().tid(), - reactor, - ctx.data().thread.tid().raw(), - stack_base, - current_caller_id().raw() - ); + "wasi[{}:{}]::thread_spawn (reactor={}, thread_id={}, stack_base={}, caller_id={})", + ctx.data().pid(), + ctx.data().tid(), + reactor, + ctx.data().thread.tid().raw(), + stack_base, + current_caller_id().raw() +); // Now we use the environment and memory references let env = ctx.data(); @@ -5174,17 +5955,17 @@ pub fn thread_spawn( // We need a copy of the process memory and a packaged store in order to // launch threads and reactors let thread_memory = wasi_try!(ctx.data().memory().try_clone(&ctx).ok_or_else(|| { - error!("thread failed - the memory could not be cloned"); - __WASI_ENOTCAPABLE - })); + error!("thread failed - the memory could not be cloned"); + __WASI_ENOTCAPABLE +})); #[cfg(feature = "compiler")] - let engine = ctx.as_store_ref().engine().clone(); + let engine = ctx.as_store_ref().engine().clone(); // Build a new store that will be passed to the thread #[cfg(feature = "compiler")] - let mut store = Store::new(engine); + let mut store = Store::new(engine); #[cfg(not(feature = "compiler"))] - let mut store = Store::default(); + let mut store = Store::default(); // This function takes in memory and a store and creates a context that // can be used to call back into the process @@ -5221,9 +6002,9 @@ pub fn thread_spawn( ctx.data_mut(&mut store).inner = Some(WasiEnvInner::new(module, memory, &store, &instance)); trace!( - "threading: new context created for thread_id = {}", - thread.tid().raw() - ); + "threading: new context created for thread_id = {}", + thread.tid().raw() + ); Ok(WasiThreadContext { ctx, store: RefCell::new(store), @@ -5293,17 +6074,17 @@ pub fn thread_spawn( // Otherwise we need to create a new context under a write lock debug!( - "encountered a new caller (ref={}) - creating WASM execution context...", - caller_id.raw() - ); + "encountered a new caller (ref={}) - creating WASM execution context...", + caller_id.raw() + ); // We can only create the context once per thread let memory = match memory.take() { Some(m) => m, None => { debug!( - "thread failed - memory can only be consumed once per context creation" - ); + "thread failed - memory can only be consumed once per context creation" + ); return __WASI_ENOEXEC as u32; } }; @@ -5311,8 +6092,8 @@ pub fn thread_spawn( Some(s) => s, None => { debug!( - "thread failed - store can only be consumed once per context creation" - ); + "thread failed - store can only be consumed once per context creation" + ); return __WASI_ENOEXEC as u32; } }; @@ -5350,20 +6131,20 @@ pub fn thread_spawn( trace!("threading: spawning background thread"); let thread_module = env.inner().module.clone(); wasi_try!(tasks - .task_wasm( - Box::new(move |store, module, thread_memory| { - let mut thread_memory = thread_memory; - let mut store = Some(store); - execute_module(&mut store, module, &mut thread_memory); - }), - store, - thread_module, - crate::runtime::SpawnType::NewThread(thread_memory) - ) - .map_err(|err| { - let err: __wasi_errno_t = err.into(); - err - })); + .task_wasm( + Box::new(move |store, module, thread_memory| { + let mut thread_memory = thread_memory; + let mut store = Some(store); + execute_module(&mut store, module, &mut thread_memory); + }), + store, + thread_module, + crate::runtime::SpawnType::NewThread(thread_memory) + ) + .map_err(|err| { + let err: __wasi_errno_t = err.into(); + err + })); } _ => { warn!("thread failed - invalid reactor parameter value"); @@ -5377,143 +6158,6 @@ pub fn thread_spawn( __WASI_ESUCCESS } -/// ### `thread_local_create()` -/// Create a thread local variable -/// If The web assembly process exports function named '_thread_local_destroy' -/// then it will be invoked when the thread goes out of scope and dies. -/// -/// ## Parameters -/// -/// * `user_data` - User data that will be passed to the destructor -/// when the thread variable goes out of scope -pub fn thread_local_create( - ctx: FunctionEnvMut<'_, WasiEnv>, - user_data: u64, - ret_key: WasmPtr<__wasi_tl_key_t, M>, -) -> __wasi_errno_t { - trace!( - "wasi[{}:{}]::thread_local_create (user_data={})", - ctx.data().pid(), - ctx.data().tid(), - user_data - ); - let env = ctx.data(); - - let key = { - let mut inner = env.process.write(); - inner.thread_local_seed += 1; - let key = inner.thread_local_seed; - inner.thread_local_user_data.insert(key, user_data); - key - }; - - let memory = env.memory_view(&ctx); - wasi_try_mem!(ret_key.write(&memory, key)); - __WASI_ESUCCESS -} - -/// ### `thread_local_destroy()` -/// Destroys a thread local variable -/// -/// ## Parameters -/// -/// * `user_data` - User data that will be passed to the destructor -/// when the thread variable goes out of scope -/// * `key` - Thread key that was previously created -pub fn thread_local_destroy( - mut ctx: FunctionEnvMut<'_, WasiEnv>, - key: __wasi_tl_key_t, -) -> __wasi_errno_t { - trace!( - "wasi[{}:{}]::thread_local_destroy (key={})", - ctx.data().pid(), - ctx.data().tid(), - key - ); - let process = ctx.data().process.clone(); - let mut inner = process.write(); - if let Some(user_data) = inner.thread_local_user_data.remove(&key) { - if let Some(thread_local_destroy) = ctx - .data() - .inner() - .thread_local_destroy - .as_ref() - .map(|a| a.clone()) - { - inner - .thread_local - .iter() - .filter(|((_, k), _)| *k == key) - .for_each(|((_, _), val)| { - let user_data_low: u32 = (user_data & 0xFFFFFFFF) as u32; - let user_data_high: u32 = (user_data >> 32) as u32; - - let val_low: u32 = (val & 0xFFFFFFFF) as u32; - let val_high: u32 = (val >> 32) as u32; - - let _ = thread_local_destroy.call( - &mut ctx, - user_data_low as i32, - user_data_high as i32, - val_low as i32, - val_high as i32, - ); - }); - } - } - inner.thread_local.retain(|(_, k), _| *k != key); - __WASI_ESUCCESS -} - -/// ### `thread_local_set()` -/// Sets the value of a thread local variable -/// -/// ## Parameters -/// -/// * `key` - Thread key that this local variable will be associated with -/// * `val` - Value to be set for the thread local variable -pub fn thread_local_set( - ctx: FunctionEnvMut<'_, WasiEnv>, - key: __wasi_tl_key_t, - val: __wasi_tl_val_t, -) -> __wasi_errno_t { - //trace!("wasi[{}:{}]::thread_local_set (key={}, val={})", ctx.data().pid(), ctx.data().tid(), key, val); - let env = ctx.data(); - - let current_thread = ctx.data().thread.tid(); - let mut inner = env.process.write(); - inner.thread_local.insert((current_thread, key), val); - __WASI_ESUCCESS -} - -/// ### `thread_local_get()` -/// Gets the value of a thread local variable -/// -/// ## Parameters -/// -/// * `key` - Thread key that this local variable that was previous set -pub fn thread_local_get( - ctx: FunctionEnvMut<'_, WasiEnv>, - key: __wasi_tl_key_t, - ret_val: WasmPtr<__wasi_tl_val_t, M>, -) -> __wasi_errno_t { - //trace!("wasi[{}:{}]::thread_local_get (key={})", ctx.data().pid(), ctx.data().tid(), key); - let env = ctx.data(); - - let val = { - let current_thread = ctx.data().thread.tid(); - let guard = env.process.read(); - guard - .thread_local - .get(&(current_thread, key)) - .map(|a| a.clone()) - }; - let val = val.unwrap_or_default(); - let memory = env.memory_view(&ctx); - wasi_try_mem!(ret_val.write(&memory, val)); - __WASI_ESUCCESS -} - /// ### `thread_sleep()` /// Sends the current thread to sleep for a period of time /// @@ -5521,15 +6165,15 @@ pub fn thread_local_get( /// /// * `duration` - Amount of time that the thread should sleep pub fn thread_sleep( - mut ctx: FunctionEnvMut<'_, WasiEnv>, - duration: __wasi_timestamp_t, -) -> Result<__wasi_errno_t, WasiError> { - //trace!("wasi[{}:{}]::thread_sleep", ctx.data().pid(), ctx.data().tid()); + ctx: FunctionEnvMut<'_, WasiEnv>, + duration: Timestamp, +) -> Result { + debug!("wasi::thread_sleep"); let env = ctx.data(); let duration = Duration::from_nanos(duration as u64); - env.clone().sleep(&mut ctx, duration)?; - Ok(__WASI_ESUCCESS) + env.sleep(duration)?; + Ok(Errno::Success) } /// ### `thread_id()` @@ -5537,12 +6181,14 @@ pub fn thread_sleep( /// (threads indices are sequencial from zero) pub fn thread_id( ctx: FunctionEnvMut<'_, WasiEnv>, - ret_tid: WasmPtr<__wasi_tid_t, M>, -) -> __wasi_errno_t { + ret_tid: WasmPtr, +) -> Errno { //trace!("wasi[{}:{}]::thread_id", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); - let tid: __wasi_tid_t = env.thread.tid().into(); + // FIXME: resolvE! + let tid: Tid = env.id.into(); + // let tid: Tid= env.thread.tid().into(); let memory = env.memory_view(&ctx); wasi_try_mem!(ret_tid.write(&memory, tid)); Errno::Success @@ -5555,10 +6201,8 @@ pub fn thread_id( /// ## Parameters /// /// * `tid` - Handle of the thread to wait on -pub fn thread_join( - ctx: FunctionEnvMut<'_, WasiEnv>, - tid: __wasi_tid_t, -) -> Result<__wasi_errno_t, WasiError> { +pub fn thread_join(ctx: FunctionEnvMut<'_, WasiEnv>, tid: Tid) -> Result { + debug!("wasi::thread_join"); debug!( "wasi[{}:{}]::thread_join(tid={})", ctx.data().pid(), @@ -5588,7 +6232,7 @@ pub fn thread_join( pub fn thread_parallelism( ctx: FunctionEnvMut<'_, WasiEnv>, ret_parallelism: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::thread_parallelism", ctx.data().pid(), @@ -5596,8 +6240,8 @@ pub fn thread_parallelism( ); let env = ctx.data(); - let parallelism = wasi_try!(env.tasks().thread_parallelism().map_err(|err| { - let err: __wasi_errno_t = err.into(); + let parallelism = wasi_try!(env.runtime().thread_parallelism().map_err(|err| { + let err: Errno = err.into(); err })); let parallelism: M::Offset = wasi_try!(parallelism.try_into().map_err(|_| Errno::Overflow)); @@ -5785,17 +6429,18 @@ pub fn futex_wake_all( /// ### `getpid()` /// Returns the handle of the current process -pub fn proc_id( - ctx: FunctionEnvMut<'_, WasiEnv>, - ret_pid: WasmPtr<__wasi_pid_t, M>, -) -> __wasi_errno_t { - let env = ctx.data(); - let pid = env.process.pid(); +pub fn getpid(ctx: FunctionEnvMut<'_, WasiEnv>, ret_pid: WasmPtr) -> Errno { debug!("wasi[{}:{}]::getpid", ctx.data().pid(), ctx.data().tid()); - let memory = env.memory_view(&ctx); - wasi_try_mem!(ret_pid.write(&memory, pid.raw() as __wasi_pid_t)); - __WASI_ESUCCESS + let env = ctx.data(); + let pid = env.runtime().getpid(); + if let Some(pid) = pid { + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_pid.write(&memory, pid as Pid)); + Errno::Success + } else { + Errno::Notsup + } } /// ### `getppid()` @@ -5836,7 +6481,7 @@ pub fn proc_parent( pub fn thread_exit( ctx: FunctionEnvMut<'_, WasiEnv>, exitcode: __wasi_exitcode_t, -) -> Result<(), WasiError> { +) -> Result { debug!( "wasi[{}:{}]::thread_exit", ctx.data().pid(), @@ -5909,28 +6554,28 @@ pub fn proc_fork( let ret_pid = wasi_try_mem_ok!(pid_ptr.read(&memory)); if ret_pid == 0 { trace!( - "wasi[{}:{}]::proc_{} - entering child", - ctx.data().pid(), - ctx.data().tid(), - fork_op - ); + "wasi[{}:{}]::proc_{} - entering child", + ctx.data().pid(), + ctx.data().tid(), + fork_op + ); } else { trace!( - "wasi[{}:{}]::proc_{} - entering parent(child={})", - ctx.data().pid(), - ctx.data().tid(), - fork_op, - ret_pid - ); + "wasi[{}:{}]::proc_{} - entering parent(child={})", + ctx.data().pid(), + ctx.data().tid(), + fork_op, + ret_pid + ); } return Ok(__WASI_ESUCCESS); } trace!( - "wasi[{}:{}]::proc_{} - capturing", - ctx.data().pid(), - ctx.data().tid(), - fork_op - ); + "wasi[{}:{}]::proc_{} - capturing", + ctx.data().pid(), + ctx.data().tid(), + fork_op +); // Fork the environment which will copy all the open file handlers // and associate a new context but otherwise shares things like the @@ -5990,9 +6635,9 @@ pub fn proc_fork( __WASI_ESUCCESS => OnCalledAction::InvokeAgain, err => { warn!( - "{} failed - could not rewind the stack - errno={}", - fork_op, err - ); + "{} failed - could not rewind the stack - errno={}", + fork_op, err + ); OnCalledAction::Trap(Box::new(WasiError::Exit(__WASI_EFAULT as u32))) } } @@ -6016,11 +6661,11 @@ pub fn proc_fork( .try_clone(&ctx) .ok_or_else(|| { error!( - "wasi[{}:{}]::{} failed - the memory could not be cloned", - ctx.data().pid(), - ctx.data().tid(), - fork_op - ); + "wasi[{}:{}]::{} failed - the memory could not be cloned", + ctx.data().pid(), + ctx.data().tid(), + fork_op + ); MemoryError::Generic(format!("the memory could not be cloned")) }) .and_then(|mut memory| memory.fork()) @@ -6028,25 +6673,25 @@ pub fn proc_fork( Ok(memory) => memory.into(), Err(err) => { warn!( - "wasi[{}:{}]::{} failed - could not fork the memory - {}", - ctx.data().pid(), - ctx.data().tid(), - fork_op, - err - ); + "wasi[{}:{}]::{} failed - could not fork the memory - {}", + ctx.data().pid(), + ctx.data().tid(), + fork_op, + err + ); return OnCalledAction::Trap(Box::new(WasiError::Exit(__WASI_EFAULT as u32))); } }; let fork_module = env.inner().module.clone(); #[cfg(feature = "compiler")] - let engine = ctx.as_store_ref().engine().clone(); + let engine = ctx.as_store_ref().engine().clone(); // Build a new store that will be passed to the thread #[cfg(feature = "compiler")] - let mut fork_store = Store::new(engine); + let mut fork_store = Store::new(engine); #[cfg(not(feature = "compiler"))] - let mut fork_store = Store::default(); + let mut fork_store = Store::default(); // Now we use the environment and memory references let runtime = child_env.runtime.clone(); @@ -6130,11 +6775,11 @@ pub fn proc_fork( drop(child_handle); } ), fork_store, fork_module, SpawnType::NewThread(fork_memory)) - .map_err(|err| { - warn!("wasi[{}:{}]::failed to fork as the process could not be spawned - {}", ctx.data().pid(), ctx.data().tid(), err); - err - }) - .ok() + .map_err(|err| { + warn!("wasi[{}:{}]::failed to fork as the process could not be spawned - {}", ctx.data().pid(), ctx.data().tid(), err); + err + }) + .ok() }; // Add the process to the environment state @@ -6150,11 +6795,11 @@ pub fn proc_fork( }; { trace!( - "wasi[{}:{}]::spawned sub-process (pid={})", - ctx.data().pid(), - ctx.data().tid(), - child_pid.raw() - ); + "wasi[{}:{}]::spawned sub-process (pid={})", + ctx.data().pid(), + ctx.data().tid(), + child_pid.raw() + ); let mut inner = ctx.data().process.write(); inner .bus_processes @@ -6358,9 +7003,9 @@ pub fn proc_fork( __WASI_ESUCCESS => OnCalledAction::InvokeAgain, err => { warn!( - "{} failed - could not rewind the stack - errno={}", - fork_op, err - ); + "{} failed - could not rewind the stack - errno={}", + fork_op, err + ); OnCalledAction::Trap(Box::new(WasiError::Exit(__WASI_EFAULT as u32))) } } @@ -6374,10 +7019,10 @@ pub fn proc_fork( pid_ptr: WasmPtr<__wasi_pid_t, M>, ) -> Result<__wasi_errno_t, WasiError> { warn!( - "wasi[{}:{}]::proc_fork - not supported without 'os' feature", - ctx.data().pid(), - ctx.data().tid() - ); + "wasi[{}:{}]::proc_fork - not supported without 'os' feature", + ctx.data().pid(), + ctx.data().tid() +); Ok(__WASI_ENOTSUP) } @@ -6406,11 +7051,11 @@ pub fn proc_exec( WasiError::Exit(__WASI_EFAULT as __wasi_exitcode_t) })?; trace!( - "wasi[{}:{}]::proc_exec (name={})", - ctx.data().pid(), - ctx.data().tid(), - name - ); + "wasi[{}:{}]::proc_exec (name={})", + ctx.data().pid(), + ctx.data().tid(), + name +); let args = args.read_utf8_string(&memory, args_len).map_err(|err| { warn!("failed to execve as the args could not be read - {}", err); @@ -6426,11 +7071,11 @@ pub fn proc_exec( if name.starts_with("./") { name = ctx.data().state.fs.relative_path_to_absolute(name); trace!( - "wasi[{}:{}]::rel_to_abs (name={}))", - ctx.data().pid(), - ctx.data().tid(), - name - ); + "wasi[{}:{}]::rel_to_abs (name={}))", + ctx.data().pid(), + ctx.data().tid(), + name + ); } // Convert the preopen directories @@ -6454,11 +7099,11 @@ pub fn proc_exec( // Build a new store that will be passed to the thread #[cfg(feature = "compiler")] - let engine = ctx.as_store_ref().engine().clone(); + let engine = ctx.as_store_ref().engine().clone(); #[cfg(feature = "compiler")] - let new_store = Store::new(engine); + let new_store = Store::new(engine); #[cfg(not(feature = "compiler"))] - let new_store = Store::default(); + let new_store = Store::default(); // If we are in a vfork we need to first spawn a subprocess of this type // with the forked WasiEnv, then do a longjmp back to the vfork point. @@ -6491,9 +7136,9 @@ pub fn proc_exec( .map_err(|err| { err_exit_code = conv_bus_err_to_exit_code(err); warn!( - "failed to execve as the process could not be spawned (vfork) - {}", - err - ); + "failed to execve as the process could not be spawned (vfork) - {}", + err + ); let _ = stderr_write( &ctx, format!("wasm execute failed [{}] - {}\n", name.as_str(), err).as_bytes(), @@ -6508,11 +7153,11 @@ pub fn proc_exec( Some(a) => a, None => { debug!( - "wasi[{}:{}]::process failed with (err={})", - ctx.data().pid(), - ctx.data().tid(), - err_exit_code - ); + "wasi[{}:{}]::process failed with (err={})", + ctx.data().pid(), + ctx.data().tid(), + err_exit_code + ); BusSpawnedProcess::exited_process(err_exit_code) } }; @@ -6520,11 +7165,11 @@ pub fn proc_exec( // Add the process to the environment state { trace!( - "wasi[{}:{}]::spawned sub-process (pid={})", - ctx.data().pid(), - ctx.data().tid(), - child_pid.raw() - ); + "wasi[{}:{}]::spawned sub-process (pid={})", + ctx.data().pid(), + ctx.data().tid(), + child_pid.raw() + ); let mut inner = ctx.data().process.write(); inner .bus_processes @@ -6609,9 +7254,9 @@ pub fn proc_exec( } Err(err) => { warn!( - "failed to execve as the process could not be spawned (fork) - {}", - err - ); + "failed to execve as the process could not be spawned (fork) - {}", + err + ); let exit_code = conv_bus_err_to_exit_code(err); OnCalledAction::Trap(Box::new(WasiError::Exit( __WASI_ENOEXEC as crate::syscalls::types::__wasi_exitcode_t, @@ -6634,13 +7279,135 @@ pub fn proc_exec( _args_len: M::Offset, ) -> Result<(), WasiError> { warn!( - "wasi[{}:{}]::exec is not supported in this build", - ctx.data().pid(), - ctx.data().tid() - ); + "wasi[{}:{}]::exec is not supported in this build", + ctx.data().pid(), + ctx.data().tid() +); Err(WasiError::Exit(__WASI_ENOTSUP as __wasi_exitcode_t)) } +// FIXME: resolve +// /// Spawns a new process within the context of this machine +// /// +// /// ## Parameters +// /// +// /// * `name` - Name of the process to be spawned +// /// * `chroot` - Indicates if the process will chroot or not +// /// * `args` - List of the arguments to pass the process +// /// (entries are separated by line feeds) +// /// * `preopen` - List of the preopens for this process +// /// (entries are separated by line feeds) +// /// * `stdin` - How will stdin be handled +// /// * `stdout` - How will stdout be handled +// /// * `stderr` - How will stderr be handled +// /// * `working_dir` - Working directory where this process should run +// /// (passing '.' will use the current directory) +// /// +// /// ## Return +// /// +// /// Returns a bus process id that can be used to invoke calls +// pub fn process_spawn( +// ctx: FunctionEnvMut<'_, WasiEnv>, +// name: WasmPtr, +// name_len: M::Offset, +// chroot: Bool, +// args: WasmPtr, +// args_len: M::Offset, +// preopen: WasmPtr, +// preopen_len: M::Offset, +// stdin: WasiStdioMode, +// stdout: WasiStdioMode, +// stderr: WasiStdioMode, +// working_dir: WasmPtr, +// working_dir_len: M::Offset, +// ret_handles: WasmPtr, +// ) -> BusErrno { +// let env = ctx.data(); +// let bus = env.runtime.bus(); +// let memory = env.memory_view(&ctx); +// let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; +// let args = unsafe { get_input_str_bus!(&memory, args, args_len) }; +// let preopen = unsafe { get_input_str_bus!(&memory, preopen, preopen_len) }; +// let working_dir = unsafe { get_input_str_bus!(&memory, working_dir, working_dir_len) }; +// let chroot = chroot == Bool::True; +// debug!("wasi::process_spawn (name={})", name); +// +// let args: Vec<_> = args.split(&['\n', '\r']).map(|a| a.to_string()).collect(); +// +// let preopen: Vec<_> = preopen +// .split(&['\n', '\r']) +// .map(|a| a.to_string()) +// .collect(); +// +// let conv_stdio_mode = |mode: WasiStdioMode| match mode { +// WasiStdioMode::Piped => StdioMode::Piped, +// WasiStdioMode::Inherit => StdioMode::Inherit, +// WasiStdioMode::Log => StdioMode::Log, +// /*__WASI_STDIO_MODE_NULL |*/ _ => StdioMode::Null, +// }; +// +// let process = wasi_try_bus!(bus +// .new_spawn() +// .chroot(chroot) +// .args(args) +// .preopen(preopen) +// .stdin_mode(conv_stdio_mode(stdin)) +// .stdout_mode(conv_stdio_mode(stdout)) +// .stderr_mode(conv_stdio_mode(stderr)) +// .working_dir(working_dir) +// .spawn(name.as_str()) +// .map_err(bus_error_into_wasi_err)); +// +// let conv_stdio_fd = |a: Option| match a { +// Some(fd) => OptionFd { +// tag: OptionTag::Some, +// fd: fd.into(), +// }, +// None => OptionFd { +// tag: OptionTag::None, +// fd: 0, +// }, +// }; +// +// // Create the new process +// let bus = env.runtime.bus(); +// let mut process = bus +// .spawn(child_env) +// .spawn( +// Some(&ctx), +// name.as_str(), +// new_store, +// &ctx.data().bin_factory, +// ) +// .map_err(bus_error_into_wasi_err)?; +// +// // Add the process to the environment state +// let pid = env.process.pid(); +// { +// let mut children = ctx.data().process.children.write().unwrap(); +// children.push(pid); +// } +// let env = ctx.data(); +// let memory = env.memory_view(&ctx); +// +// // Add the process to the environment state +// let bid = { +// let mut guard = env.state.threading.lock().unwrap(); +// guard.process_seed += 1; +// let bid = guard.process_seed; +// guard.processes.insert(bid.into(), process); +// bid +// }; +// +// let handles = BusHandles { +// bid, +// stdin, +// stdout, +// stderr, +// }; +// Ok((handles, ctx)) +// } + /// Spawns a new process within the context of this machine /// /// ## Parameters @@ -6664,18 +7431,18 @@ pub fn proc_spawn( mut ctx: FunctionEnvMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, - chroot: Bool, + chroot: __wasi_bool_t, args: WasmPtr, args_len: M::Offset, preopen: WasmPtr, preopen_len: M::Offset, - stdin: WasiStdioMode, - stdout: WasiStdioMode, - stderr: WasiStdioMode, + stdin: __wasi_stdiomode_t, + stdout: __wasi_stdiomode_t, + stderr: __wasi_stdiomode_t, working_dir: WasmPtr, working_dir_len: M::Offset, - ret_handles: WasmPtr, -) -> BusErrno { + ret_handles: WasmPtr<__wasi_bus_handles_t, M>, +) -> __bus_errno_t { let env = ctx.data(); let control_plane = env.process.control_plane(); let memory = env.memory_view(&ctx); @@ -6684,18 +7451,18 @@ pub fn proc_spawn( let preopen = unsafe { get_input_str_bus!(&memory, preopen, preopen_len) }; let working_dir = unsafe { get_input_str_bus!(&memory, working_dir, working_dir_len) }; debug!( - "wasi[{}:{}]::process_spawn (name={})", - ctx.data().pid(), - ctx.data().tid(), - name - ); + "wasi[{}:{}]::process_spawn (name={})", + ctx.data().pid(), + ctx.data().tid(), + name +); if chroot == __WASI_BOOL_TRUE { warn!( - "wasi[{}:{}]::chroot is not currently supported", - ctx.data().pid(), - ctx.data().tid() - ); + "wasi[{}:{}]::chroot is not currently supported", + ctx.data().pid(), + ctx.data().tid() + ); return __BUS_EUNSUPPORTED; } @@ -6733,167 +7500,6 @@ pub fn proc_spawn( __BUS_ESUCCESS } -#[cfg(feature = "os")] -pub fn proc_spawn_internal( - mut ctx: FunctionEnvMut<'_, WasiEnv>, - name: String, - args: Option>, - preopen: Option>, - working_dir: Option, - stdin: __wasi_stdiomode_t, - stdout: __wasi_stdiomode_t, - stderr: __wasi_stdiomode_t, -) -> Result<(__wasi_bus_handles_t, FunctionEnvMut<'_, WasiEnv>), __bus_errno_t> { - let env = ctx.data(); - - // Build a new store that will be passed to the thread - #[cfg(feature = "compiler")] - let engine = ctx.as_store_ref().engine().clone(); - #[cfg(feature = "compiler")] - let new_store = Store::new(engine); - #[cfg(not(feature = "compiler"))] - let new_store = Store::default(); - - // Fork the current environment and set the new arguments - let (mut child_env, handle) = ctx.data().fork(); - if let Some(args) = args { - let mut child_state = env.state.fork(); - child_state.args = args; - child_env.state = Arc::new(child_state); - } - - // Take ownership of this child - ctx.data_mut().owned_handles.push(handle); - let env = ctx.data(); - - // Preopen - if let Some(preopen) = preopen { - if preopen.is_empty() == false { - for preopen in preopen { - warn!( - "wasi[{}:{}]::preopens are not yet supported for spawned processes [{}]", - ctx.data().pid(), - ctx.data().tid(), - preopen - ); - } - return Err(__BUS_EUNSUPPORTED); - } - } - - // Change the current directory - if let Some(working_dir) = working_dir { - child_env.state.fs.set_current_dir(working_dir.as_str()); - } - - // Replace the STDIO - let (stdin, stdout, stderr) = { - let (_, child_state, mut child_inodes) = - child_env.get_memory_and_wasi_state_and_inodes_mut(&new_store, 0); - let mut conv_stdio_mode = |mode: __wasi_stdiomode_t, - fd: __wasi_fd_t| - -> Result<__wasi_option_fd_t, __bus_errno_t> { - match mode { - __WASI_STDIO_MODE_PIPED => { - let (pipe1, pipe2) = WasiPipe::new(); - let inode1 = child_state.fs.create_inode_with_default_stat( - child_inodes.deref_mut(), - Kind::Pipe { pipe: pipe1 }, - false, - "pipe".into(), - ); - let inode2 = child_state.fs.create_inode_with_default_stat( - child_inodes.deref_mut(), - Kind::Pipe { pipe: pipe2 }, - false, - "pipe".into(), - ); - - let rights = super::state::all_socket_rights(); - let pipe = ctx - .data() - .state - .fs - .create_fd(rights, rights, 0, 0, inode1)?; - child_state - .fs - .create_fd_ext(rights, rights, 0, 0, inode2, fd)?; - - trace!( - "wasi[{}:{}]::fd_pipe (fd1={}, fd2={})", - ctx.data().pid(), - ctx.data().tid(), - pipe, - fd - ); - Ok(__wasi_option_fd_t { - tag: __WASI_OPTION_SOME, - fd: pipe, - }) - } - __WASI_STDIO_MODE_INHERIT => Ok(__wasi_option_fd_t { - tag: __WASI_OPTION_NONE, - fd: u32::MAX, - }), - __WASI_STDIO_MODE_LOG | __WASI_STDIO_MODE_NULL | _ => { - child_state.fs.close_fd(child_inodes.deref(), fd); - Ok(__wasi_option_fd_t { - tag: __WASI_OPTION_NONE, - fd: u32::MAX, - }) - } - } - }; - let stdin = conv_stdio_mode(stdin, 0)?; - let stdout = conv_stdio_mode(stdout, 1)?; - let stderr = conv_stdio_mode(stderr, 2)?; - (stdin, stdout, stderr) - }; - - // Create the new process - let bus = env.runtime.bus(); - let mut process = bus - .spawn(child_env) - .spawn( - Some(&ctx), - name.as_str(), - new_store, - &ctx.data().bin_factory, - ) - .map_err(bus_error_into_wasi_err)?; - - // Add the process to the environment state - let pid = env.process.pid(); - { - let mut children = ctx.data().process.children.write().unwrap(); - children.push(pid); - } - let env = ctx.data(); - let memory = env.memory_view(&ctx); - - // Add the process to the environment state - let pid = env.process.pid(); - { - let mut children = ctx.data().process.children.write().unwrap(); - children.push(pid); - } - let env = ctx.data(); - let memory = env.memory_view(&ctx); - - { - let mut guard = env.process.write(); - guard.bus_processes.insert(pid.into(), Box::new(process)); - }; - - let handles = __wasi_bus_handles_t { - bid: pid.raw(), - stdin, - stdout, - stderr, - }; - Ok((handles, ctx)) -} - #[cfg(not(feature = "os"))] pub fn proc_spawn_internal( mut ctx: FunctionEnvMut<'_, WasiEnv>, @@ -6923,7 +7529,7 @@ pub fn proc_join( mut ctx: FunctionEnvMut<'_, WasiEnv>, pid_ptr: WasmPtr<__wasi_pid_t, M>, exit_code_ptr: WasmPtr<__wasi_exitcode_t, M>, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { let env = ctx.data(); let memory = env.memory_view(&ctx); let pid = wasi_try_mem_ok!(pid_ptr.read(&memory)); @@ -7030,14 +7636,14 @@ pub fn bus_open_local( ctx: FunctionEnvMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, - reuse: __wasi_bool_t, - ret_bid: WasmPtr<__wasi_bid_t, M>, -) -> Result<__bus_errno_t, WasiError> { + reuse: Bool, + ret_bid: WasmPtr, +) -> BusErrno { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let name = unsafe { get_input_str_bus_ok!(&memory, name, name_len) }; - let reuse = reuse == __WASI_BOOL_TRUE; + let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; + let reuse = reuse == Bool::True; debug!( "wasi[{}:{}]::bus_open_local (name={}, reuse={})", ctx.data().pid(), @@ -7072,42 +7678,43 @@ pub fn bus_open_remote( instance_len: M::Offset, token: WasmPtr, token_len: M::Offset, - ret_bid: WasmPtr<__wasi_bid_t, M>, -) -> Result<__bus_errno_t, WasiError> { + ret_bid: WasmPtr, +) -> BusErrno { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); - let name = unsafe { get_input_str_bus_ok!(&memory, name, name_len) }; - let instance = unsafe { get_input_str_bus_ok!(&memory, instance, instance_len) }; - let token = unsafe { get_input_str_bus_ok!(&memory, token, token_len) }; - let reuse = reuse == __WASI_BOOL_TRUE; + let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; + let instance = unsafe { get_input_str_bus!(&memory, instance, instance_len) }; + let token = unsafe { get_input_str_bus!(&memory, token, token_len) }; + let reuse = reuse == Bool::True; debug!( "wasi::bus_open_remote (name={}, reuse={}, instance={})", name, reuse, instance ); - bus_open_internal(ctx, name, reuse, Some(instance), Some(token), ret_bid) + bus_open_local_internal(ctx, name, reuse, Some(instance), Some(token), ret_bid) } -fn bus_open_internal( - mut ctx: FunctionEnvMut<'_, WasiEnv>, +fn bus_open_local_internal( + ctx: FunctionEnvMut<'_, WasiEnv>, name: String, reuse: bool, instance: Option, token: Option, - ret_bid: WasmPtr<__wasi_bid_t, M>, -) -> Result<__bus_errno_t, WasiError> { + ret_bid: WasmPtr, +) -> BusErrno { let env = ctx.data(); + let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); let name: Cow<'static, str> = name.into(); // Check if it already exists if reuse { - let guard = env.process.read(); + let guard = env.state.threading.lock().unwrap() if let Some(bid) = guard.bus_process_reuse.get(&name) { if guard.bus_processes.contains_key(bid) { - wasi_try_mem_bus_ok!(ret_bid.write(&memory, bid.clone().into())); - return Ok(__BUS_ESUCCESS); + wasi_try_mem_bus_ok!(ret_bid.write(&memory, (*bid).into())); + return BusErrno::Success; } } } @@ -7125,15 +7732,16 @@ fn bus_open_internal( let env = ctx.data(); let memory = env.memory_view(&ctx); - let pid: WasiProcessId = handles.bid.into(); + let pid: WasiBusProcessId = handles.bid.into(); let memory = env.memory_view(&ctx); { let mut inner = env.process.write(); inner.bus_process_reuse.insert(name, pid); }; - wasi_try_mem_bus_ok!(ret_bid.write(&memory, pid.into())); - Ok(__BUS_ESUCCESS) + wasi_try_mem_bus!(ret_bid.write(&memory, bid.into())); + + BusErrno::Success } /// Closes a bus process and releases all associated resources @@ -7141,24 +7749,24 @@ fn bus_open_internal( /// ## Parameters /// /// * `bid` - Handle of the bus process handle to be closed -pub fn bus_close(ctx: FunctionEnvMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { +pub fn bus_close(ctx: FunctionEnvMut<'_, WasiEnv>, bid: Bid) -> BusErrno { trace!( "wasi[{}:{}]::bus_close (bid={})", ctx.data().pid(), ctx.data().tid(), bid ); - let bid: WasiProcessId = bid.into(); + let bid: WasiBusProcessId = bid.into(); let env = ctx.data(); let mut inner = env.process.write(); if let Some(process) = inner.bus_processes.remove(&bid) { - // TODO: Fix this + // FIXME //let name: Cow<'static, str> = process.name.clone().into(); //inner.bus_process_reuse.remove(&name); } - __BUS_ESUCCESS + BusErrno::Success } /// Invokes a call within a running bus process. @@ -7180,6 +7788,16 @@ pub fn bus_call( buf: WasmPtr, buf_len: M::Offset, ret_cid: WasmPtr<__wasi_cid_t, M>, + // FIXME: align function signatures + // ctx: FunctionEnvMut<'_, WasiEnv>, + // bid: Bid, + // keep_alive: Bool, + // topic: WasmPtr, + // topic_len: M::Offset, + // format: BusDataFormat, + // buf: WasmPtr, + // buf_len: M::Offset, + // ret_cid: WasmPtr, ) -> Result<__bus_errno_t, WasiError> { let env = ctx.data(); let bus = env.runtime.bus(); @@ -7277,13 +7895,24 @@ pub fn bus_call( /// * `buf` - The buffer where data to be transmitted is stored pub fn bus_subcall( ctx: FunctionEnvMut<'_, WasiEnv>, - parent: __wasi_cid_t, + parent: Cid, topic_hash: WasmPtr<__wasi_hash_t>, format: __wasi_busdataformat_t, buf: WasmPtr, buf_len: M::Offset, ret_cid: WasmPtr<__wasi_cid_t, M>, -) -> Result<__bus_errno_t, WasiError> { + + // FIXME: align function signaturs + // ctx: FunctionEnvMut<'_, WasiEnv>, + // parent: Cid, + // keep_alive: Bool, + // topic: WasmPtr, + // topic_len: M::Offset, + // format: BusDataFormat, + // buf: WasmPtr, + // buf_len: M::Offset, + // ret_cid: WasmPtr, +) -> Result { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); @@ -7371,7 +8000,7 @@ fn conv_bus_format(format: BusDataFormat) -> __wasi_busdataformat_t { } } -fn conv_bus_format_from(format: __wasi_busdataformat_t) -> Result { +fn conv_bus_format_from(format: __wasi_busdataformat_t) -> Result { Ok(match format { __WASI_BUS_DATA_FORMAT_RAW => BusDataFormat::Raw, __WASI_BUS_DATA_FORMAT_BINCODE => BusDataFormat::Bincode, @@ -7401,12 +8030,19 @@ fn conv_bus_format_from(format: __wasi_busdataformat_t) -> Result( + // FIXME: align function signatures! ctx: FunctionEnvMut<'_, WasiEnv>, - timeout: __wasi_timestamp_t, events: WasmPtr<__wasi_busevent_t, M>, maxevents: M::Offset, ret_nevents: WasmPtr, -) -> Result<__bus_errno_t, WasiError> { + // ctx: FunctionEnvMut<'_, WasiEnv>, + // timeout: Timestamp, + // events: WasmPtr, + // nevents: M::Offset, + // malloc: WasmPtr, + // malloc_len: M::Offset, + // ret_nevents: WasmPtr, +) -> Result { let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory_view(&ctx); @@ -7800,7 +8436,7 @@ pub fn bus_poll( ctx.data().tid(), timeout ); - Ok(__BUS_EUNSUPPORTED) + Ok(BusErrno::Unsupported) } /// Replies to a call that was made to this process @@ -7838,9 +8474,9 @@ pub fn call_reply( let format = wasi_try_bus!(conv_bus_format_from(format)); call.reply(format, buf); - __BUS_ESUCCESS + BusErrno::Success } else { - __BUS_EBADHANDLE + BusErrno::Badhandle } } @@ -7852,7 +8488,7 @@ pub fn call_reply( /// /// * `cid` - Handle of the call to raise a fault on /// * `fault` - Fault to be raised on the bus -pub fn call_fault(ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t, fault: __bus_errno_t) { +pub fn call_fault(ctx: FunctionEnvMut<'_, WasiEnv>, cid: Cid, fault: BusErrno) -> BusErrno { let env = ctx.data(); let bus = env.runtime.bus(); debug!( @@ -7877,7 +8513,7 @@ pub fn call_fault(ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t, fault: __ /// ## Parameters /// /// * `cid` - Handle of the bus call handle to be dropped -pub fn call_close(ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t) { +pub fn call_close(ctx: FunctionEnvMut<'_, WasiEnv>, cid: Cid) -> BusErrno { let env = ctx.data(); let bus = env.runtime.bus(); trace!( @@ -7887,9 +8523,13 @@ pub fn call_close(ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t) { cid ); + BusErrno::Unsupported let mut guard = env.state.bus.protected(); guard.calls.remove(&cid); guard.called.remove(&cid); + + // FIXME: check return value + BusErrno::Success; } /// ### `ws_connect()` @@ -7906,8 +8546,8 @@ pub fn ws_connect( ctx: FunctionEnvMut<'_, WasiEnv>, url: WasmPtr, url_len: M::Offset, - ret_sock: WasmPtr<__wasi_fd_t, M>, -) -> __wasi_errno_t { + ret_sock: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::ws_connect", ctx.data().pid(), @@ -7935,8 +8575,8 @@ pub fn ws_connect( state .fs .create_inode_with_default_stat(inodes.deref_mut(), kind, false, "socket".into()); - let rights = super::state::all_socket_rights(); - let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); + let rights = Rights::all_socket(); + let fd = wasi_try!(state.fs.create_fd(rights, rights, Flags::empty(), 0, inode)); wasi_try_mem!(ret_sock.write(&memory, fd)); @@ -7967,9 +8607,9 @@ pub fn http_request( method_len: M::Offset, headers: WasmPtr, headers_len: M::Offset, - gzip: __wasi_bool_t, - ret_handles: WasmPtr<__wasi_http_handles_t, M>, -) -> __wasi_errno_t { + gzip: Bool, + ret_handles: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::http_request", ctx.data().pid(), @@ -8038,19 +8678,19 @@ pub fn http_request( inodes.deref_mut(), kind_req, false, - "http_request".into(), + "http_request".to_string(), ); let inode_res = state.fs.create_inode_with_default_stat( inodes.deref_mut(), kind_res, false, - "http_response".into(), + "http_response".to_string(), ); let inode_hdr = state.fs.create_inode_with_default_stat( inodes.deref_mut(), kind_hdr, false, - "http_headers".into(), + "http_headers".to_string(), ); let rights = Rights::all_socket(); @@ -8081,9 +8721,9 @@ pub fn http_request( /// status of this HTTP request pub fn http_status( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - status: WasmPtr<__wasi_http_status_t, M>, -) -> __wasi_errno_t { + sock: WasiFd, + status: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::http_status", ctx.data().pid(), @@ -8094,7 +8734,7 @@ pub fn http_status( let memory = env.memory_view(&ctx); let ref_status = status.deref(&memory); - let http_status = wasi_try!(__sock_actor(&ctx, sock, 0, move |socket| async move { + let http_status = wasi_try!(__sock_actor(&ctx, sock, Rights::empty(), move |socket| async move { socket.http_status() })); @@ -8128,8 +8768,8 @@ pub fn port_bridge( network_len: M::Offset, token: WasmPtr, token_len: M::Offset, - security: __wasi_streamsecurity_t, -) -> __wasi_errno_t { + security: Streamsecurity, +) -> Errno { debug!( "wasi[{}:{}]::port_bridge", ctx.data().pid(), @@ -8169,19 +8809,15 @@ pub fn port_unbridge(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { /// ### `port_dhcp_acquire()` /// Acquires a set of IP addresses using DHCP -pub fn port_dhcp_acquire(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_dhcp_acquire(ctx: FunctionEnvMut<'_, WasiEnv>) -> Errno { debug!( "wasi[{}:{}]::port_dhcp_acquire", ctx.data().pid(), ctx.data().tid() ); let env = ctx.data(); - let net = env.net(); - let tasks = env.tasks.clone(); - wasi_try!(__asyncify(tasks, &env.thread, None, async move { - net.dhcp_acquire().await.map_err(net_error_into_wasi_err) - })); - __WASI_ESUCCESS + wasi_try!(env.net().dhcp_acquire().map_err(net_error_into_wasi_err)); + Errno::Success } /// ### `port_addr_add()` @@ -8193,7 +8829,7 @@ pub fn port_dhcp_acquire(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { pub fn port_addr_add( ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_cidr_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::port_addr_add", ctx.data().pid(), @@ -8218,7 +8854,7 @@ pub fn port_addr_add( pub fn port_addr_remove( ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::port_addr_remove", ctx.data().pid(), @@ -8233,7 +8869,7 @@ pub fn port_addr_remove( /// ### `port_addr_clear()` /// Clears all the addresses on the local port -pub fn port_addr_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_addr_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> Errno { debug!( "wasi[{}:{}]::port_addr_clear", ctx.data().pid(), @@ -8249,7 +8885,7 @@ pub fn port_addr_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { pub fn port_mac( ctx: FunctionEnvMut<'_, WasiEnv>, ret_mac: WasmPtr<__wasi_hardwareaddress_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!("wasi[{}:{}]::port_mac", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); let memory = env.memory_view(&ctx); @@ -8276,7 +8912,7 @@ pub fn port_addr_list( ctx: FunctionEnvMut<'_, WasiEnv>, addrs: WasmPtr<__wasi_cidr_t, M>, naddrs: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::port_addr_list", ctx.data().pid(), @@ -8314,7 +8950,7 @@ pub fn port_addr_list( pub fn port_gateway_set( ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::port_gateway_set", ctx.data().pid(), @@ -8334,9 +8970,9 @@ pub fn port_route_add( ctx: FunctionEnvMut<'_, WasiEnv>, cidr: WasmPtr<__wasi_cidr_t, M>, via_router: WasmPtr<__wasi_addr_t, M>, - preferred_until: WasmPtr<__wasi_option_timestamp_t, M>, - expires_at: WasmPtr<__wasi_option_timestamp_t, M>, -) -> __wasi_errno_t { + preferred_until: WasmPtr, + expires_at: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::port_route_add", ctx.data().pid(), @@ -8371,7 +9007,7 @@ pub fn port_route_add( pub fn port_route_remove( ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::port_route_remove", ctx.data().pid(), @@ -8386,7 +9022,7 @@ pub fn port_route_remove( /// ### `port_route_clear()` /// Clears all the routes in the local port -pub fn port_route_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_route_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> Errno { debug!( "wasi[{}:{}]::port_route_clear", ctx.data().pid(), @@ -8410,7 +9046,7 @@ pub fn port_route_list( ctx: FunctionEnvMut<'_, WasiEnv>, routes: WasmPtr, nroutes: WasmPtr, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::port_route_list", ctx.data().pid(), @@ -8421,7 +9057,7 @@ pub fn port_route_list( let nroutes = nroutes.deref(&memory); let max_routes: usize = wasi_try!(wasi_try_mem!(nroutes.read()) .try_into() - .map_err(|_| __WASI_EINVAL)); + .map_err(|_| Errno::Inval)); let ref_routes = wasi_try_mem!(routes.slice(&memory, wasi_try!(to_offset::(max_routes)))); let routes = wasi_try!(env.net().route_list().map_err(net_error_into_wasi_err)); @@ -8451,11 +9087,7 @@ pub fn port_route_list( /// ## Parameters /// /// * `how` - Which channels on the socket to shut down. -pub fn sock_shutdown( - ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - how: __wasi_sdflags_t, -) -> __wasi_errno_t { +pub fn sock_shutdown(ctx: FunctionEnvMut<'_, WasiEnv>, sock: WasiFd, how: SdFlags) -> Errno { debug!( "wasi[{}:{}]::sock_shutdown (fd={})", ctx.data().pid(), @@ -8474,7 +9106,7 @@ pub fn sock_shutdown( wasi_try!(__sock_actor_mut( &ctx, sock, - __WASI_RIGHT_SOCK_SHUTDOWN, + Rights::SOCK_SHUTDOWN, move |socket| async move { socket.shutdown(how).await } )); @@ -8485,9 +9117,9 @@ pub fn sock_shutdown( /// Returns the current status of a socket pub fn sock_status( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - ret_status: WasmPtr<__wasi_sockstatus_t, M>, -) -> __wasi_errno_t { + sock: WasiFd, + ret_status: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::sock_status (fd={})", ctx.data().pid(), @@ -8495,7 +9127,7 @@ pub fn sock_status( sock ); - let status = wasi_try!(__sock_actor(&ctx, sock, 0, move |socket| async move { + let status = wasi_try!(__sock_actor(&ctx, sock, Rights::empty(), move |socket| async move { socket.status() })); @@ -8529,7 +9161,7 @@ pub fn sock_addr_local( ctx: FunctionEnvMut<'_, WasiEnv>, sock: WasiFd, ret_addr: WasmPtr<__wasi_addr_port_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_addr_local (fd={})", ctx.data().pid(), @@ -8565,7 +9197,7 @@ pub fn sock_addr_peer( ctx: FunctionEnvMut<'_, WasiEnv>, sock: WasiFd, ro_addr: WasmPtr<__wasi_addr_port_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_addr_peer (fd={})", ctx.data().pid(), @@ -8574,7 +9206,7 @@ pub fn sock_addr_peer( ); let env = ctx.data(); - let addr = wasi_try!(__sock_actor(&ctx, sock, 0, move |socket| async move { + let addr = wasi_try!(__sock_actor(&ctx, sock, Rights::empty(), move |socket| async move { socket.addr_peer() })); let memory = env.memory_view(&ctx); @@ -8608,11 +9240,11 @@ pub fn sock_addr_peer( /// The file descriptor of the socket that has been opened. pub fn sock_open( ctx: FunctionEnvMut<'_, WasiEnv>, - af: __wasi_addressfamily_t, - ty: __wasi_socktype_t, - pt: __wasi_sockproto_t, - ro_sock: WasmPtr<__wasi_fd_t, M>, -) -> __wasi_errno_t { + af: Addressfamily, + ty: Socktype, + pt: SockProto, + ro_sock: WasmPtr, +) -> Errno { debug!("wasi[{}:{}]::sock_open", ctx.data().pid(), ctx.data().tid()); let env = ctx.data(); @@ -8640,12 +9272,16 @@ pub fn sock_open( _ => return Errno::Notsup, }; - let inode = - state - .fs - .create_inode_with_default_stat(inodes.deref_mut(), kind, false, "socket".into()); - let rights = super::state::all_socket_rights(); - let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); + let inode = state.fs.create_inode_with_default_stat( + inodes.deref_mut(), + kind, + false, + "socket".to_string(), + ); + let rights = Rights::all_socket(); + let fd = wasi_try!(state + .fs + .create_fd(rights, rights, Fdflags::empty(), 0, inode)); wasi_try_mem!(ro_sock.write(&memory, fd)); @@ -8663,10 +9299,10 @@ pub fn sock_open( /// * `flag` - Value to set the option to pub fn sock_set_opt_flag( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - flag: __wasi_bool_t, -) -> __wasi_errno_t { + sock: WasiFd, + opt: Sockoption, + flag: Bool, +) -> Errno { debug!( "wasi[{}:{}]::sock_set_opt_flag(fd={}, ty={}, flag={})", ctx.data().pid(), @@ -8683,7 +9319,7 @@ pub fn sock_set_opt_flag( }; let option: super::state::WasiSocketOption = opt.into(); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { socket.set_opt_flag(option, flag) })); Errno::Success @@ -8699,10 +9335,10 @@ pub fn sock_set_opt_flag( /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_flag( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_flag: WasmPtr<__wasi_bool_t, M>, -) -> __wasi_errno_t { + sock: WasiFd, + opt: Sockoption, + ret_flag: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::sock_get_opt_flag(fd={}, ty={})", ctx.data().pid(), @@ -8714,7 +9350,7 @@ pub fn sock_get_opt_flag( let memory = env.memory_view(&ctx); let option: super::state::WasiSocketOption = opt.into(); - let flag = wasi_try!(__sock_actor(&ctx, sock, 0, move |socket| async move { + let flag = wasi_try!(__sock_actor(&ctx, sock, Rights::empty(), move |socket| async move { socket.get_opt_flag(option) })); let flag = match flag { @@ -8737,10 +9373,10 @@ pub fn sock_get_opt_flag( /// * `time` - Value to set the time to pub fn sock_set_opt_time( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - time: WasmPtr<__wasi_option_timestamp_t, M>, -) -> __wasi_errno_t { + sock: WasiFd, + opt: Sockoption, + time: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::sock_set_opt_time(fd={}, ty={})", ctx.data().pid(), @@ -8768,7 +9404,7 @@ pub fn sock_set_opt_time( }; let option: super::state::WasiSocketOption = opt.into(); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { socket.set_opt_time(ty, time) })); Errno::Success @@ -8783,10 +9419,10 @@ pub fn sock_set_opt_time( /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_time( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_time: WasmPtr<__wasi_option_timestamp_t, M>, -) -> __wasi_errno_t { + sock: WasiFd, + opt: Sockoption, + ret_time: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::sock_get_opt_time(fd={}, ty={})", ctx.data().pid(), @@ -8806,7 +9442,7 @@ pub fn sock_get_opt_time( _ => return Errno::Inval, }; - let time = wasi_try!(__sock_actor(&ctx, sock, 0, move |socket| async move { + let time = wasi_try!(__sock_actor(&ctx, sock, Rights::empty(), move |socket| async move { socket.opt_time(ty) })); let time = match time { @@ -8836,10 +9472,10 @@ pub fn sock_get_opt_time( /// * `size` - Buffer size pub fn sock_set_opt_size( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - size: __wasi_filesize_t, -) -> __wasi_errno_t { + sock: WasiFd, + opt: Sockoption, + size: Filesize, +) -> Errno { debug!( "wasi[{}:{}]::sock_set_opt_size(fd={}, ty={})", ctx.data().pid(), @@ -8858,7 +9494,7 @@ pub fn sock_set_opt_size( }; let option: super::state::WasiSocketOption = opt.into(); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { match opt { Sockoption::RecvBufSize => socket.set_recv_buf_size(size as usize), Sockoption::SendBufSize => socket.set_send_buf_size(size as usize), @@ -8880,10 +9516,10 @@ pub fn sock_set_opt_size( /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_size( ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - opt: __wasi_sockoption_t, - ret_size: WasmPtr<__wasi_filesize_t, M>, -) -> __wasi_errno_t { + sock: WasiFd, + opt: Sockoption, + ret_size: WasmPtr, +) -> Errno { debug!( "wasi[{}:{}]::sock_get_opt_size(fd={}, ty={})", ctx.data().pid(), @@ -8921,7 +9557,7 @@ pub fn sock_join_multicast_v4( sock: WasiFd, multiaddr: WasmPtr<__wasi_addr_ip4_t, M>, iface: WasmPtr<__wasi_addr_ip4_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_join_multicast_v4 (fd={})", ctx.data().pid(), @@ -8933,7 +9569,7 @@ pub fn sock_join_multicast_v4( let memory = env.memory_view(&ctx); let multiaddr = wasi_try!(super::state::read_ip_v4(&memory, multiaddr)); let iface = wasi_try!(super::state::read_ip_v4(&memory, iface)); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { socket.join_multicast_v4(multiaddr, iface).await })); Errno::Success @@ -8952,7 +9588,7 @@ pub fn sock_leave_multicast_v4( sock: WasiFd, multiaddr: WasmPtr<__wasi_addr_ip4_t, M>, iface: WasmPtr<__wasi_addr_ip4_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_leave_multicast_v4 (fd={})", ctx.data().pid(), @@ -8964,7 +9600,7 @@ pub fn sock_leave_multicast_v4( let memory = env.memory_view(&ctx); let multiaddr = wasi_try!(super::state::read_ip_v4(&memory, multiaddr)); let iface = wasi_try!(super::state::read_ip_v4(&memory, iface)); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { socket.leave_multicast_v4(multiaddr, iface).await })); Errno::Success @@ -8983,7 +9619,7 @@ pub fn sock_join_multicast_v6( sock: WasiFd, multiaddr: WasmPtr<__wasi_addr_ip6_t, M>, iface: u32, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_join_multicast_v6 (fd={})", ctx.data().pid(), @@ -8994,7 +9630,7 @@ pub fn sock_join_multicast_v6( let env = ctx.data(); let memory = env.memory_view(&ctx); let multiaddr = wasi_try!(super::state::read_ip_v6(&memory, multiaddr)); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { socket.join_multicast_v6(multiaddr, iface).await })); Errno::Success @@ -9013,7 +9649,7 @@ pub fn sock_leave_multicast_v6( sock: WasiFd, multiaddr: WasmPtr<__wasi_addr_ip6_t, M>, iface: u32, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_leave_multicast_v6 (fd={})", ctx.data().pid(), @@ -9024,7 +9660,7 @@ pub fn sock_leave_multicast_v6( let env = ctx.data(); let memory = env.memory_view(&ctx); let multiaddr = wasi_try!(super::state::read_ip_v6(&memory, multiaddr)); - wasi_try!(__sock_actor_mut(&ctx, sock, 0, move |socket| async move { + wasi_try!(__sock_actor_mut(&ctx, sock, Rights::empty(), move |socket| async move { socket.leave_multicast_v6(multiaddr, iface).await })); Errno::Success @@ -9042,7 +9678,7 @@ pub fn sock_bind( ctx: FunctionEnvMut<'_, WasiEnv>, sock: WasiFd, addr: WasmPtr<__wasi_addr_port_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_bind (fd={})", ctx.data().pid(), @@ -9080,7 +9716,7 @@ pub fn sock_listen( ctx: FunctionEnvMut<'_, WasiEnv>, sock: WasiFd, backlog: M::Offset, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_listen (fd={})", ctx.data().pid(), @@ -9113,12 +9749,12 @@ pub fn sock_listen( /// /// New socket connection pub fn sock_accept( - mut ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - fd_flags: __wasi_fdflags_t, - ro_fd: WasmPtr<__wasi_fd_t, M>, + ctx: FunctionEnvMut<'_, WasiEnv>, + sock: WasiFd, + fd_flags: Fdflags, + ro_fd: WasmPtr, ro_addr: WasmPtr<__wasi_addr_port_t, M>, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { debug!( "wasi[{}:{}]::sock_accept (fd={})", ctx.data().pid(), @@ -9152,14 +9788,14 @@ pub fn sock_accept( ret = a; break; } - Err(__WASI_ETIMEDOUT) => { + Err(Errno::Timeout) => { if nonblocking { trace!( "wasi[{}:{}]::sock_accept - (ret=EAGAIN)", ctx.data().pid(), ctx.data().tid() ); - return Ok(__WASI_EAGAIN); + return Ok(Errno::Again); } env.yield_now()?; continue; @@ -9229,10 +9865,10 @@ pub fn sock_accept( /// * `fd` - Socket descriptor /// * `addr` - Address of the socket to connect to pub fn sock_connect( - ctx: FunctionEnvMut, - sock: __wasi_fd_t, + ctx: FunctionEnvMut<'_, WasiEnv>, + sock: WasiFd, addr: WasmPtr<__wasi_addr_port_t, M>, -) -> __wasi_errno_t { +) -> Errno { debug!( "wasi[{}:{}]::sock_connect (fd={})", ctx.data().pid(), @@ -9248,7 +9884,7 @@ pub fn sock_connect( wasi_try!(__sock_upgrade( &ctx, sock, - __WASI_RIGHT_SOCK_CONNECT, + Rights::SOCK_CONNECT, move |socket| async move { socket.connect(net, addr).await } )); __WASI_ESUCCESS @@ -9274,15 +9910,14 @@ pub fn sock_recv( ri_data_len: M::Offset, _ri_flags: RiFlags, ro_data_len: WasmPtr, - ro_flags: WasmPtr<__wasi_roflags_t, M>, -) -> Result<__wasi_errno_t, WasiError> { + ro_flags: WasmPtr, +) -> Result { debug!( "wasi[{}:{}]::sock_recv (fd={})", ctx.data().pid(), ctx.data().tid(), sock ); - let env = ctx.data(); let memory = env.memory_view(&ctx); let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&memory, ri_data_len)); @@ -9290,7 +9925,7 @@ pub fn sock_recv( let mut max_size = 0usize; for iovs in iovs_arr.iter() { let iovs = wasi_try_mem_ok!(iovs.read()); - let buf_len: usize = wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| __WASI_EOVERFLOW)); + let buf_len: usize = wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow)); max_size += buf_len; } @@ -9303,7 +9938,7 @@ pub fn sock_recv( let data_len = data.len(); let mut reader = &data[..]; let bytes_read = wasi_try_ok!(read_bytes(reader, &memory, iovs_arr).map(|_| data_len)); - let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); + let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow)); wasi_try_mem_ok!(ro_flags.write(&memory, 0)); wasi_try_mem_ok!(ro_data_len.write(&memory, bytes_read)); @@ -9333,7 +9968,7 @@ pub fn sock_recv_from( ro_data_len: WasmPtr, ro_flags: WasmPtr, ro_addr: WasmPtr<__wasi_addr_port_t, M>, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { debug!( "wasi[{}:{}]::sock_recv_from (fd={})", ctx.data().pid(), @@ -9348,7 +9983,7 @@ pub fn sock_recv_from( let mut max_size = 0usize; for iovs in iovs_arr.iter() { let iovs = wasi_try_mem_ok!(iovs.read()); - let buf_len: usize = wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| __WASI_EOVERFLOW)); + let buf_len: usize = wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow)); max_size += buf_len; } @@ -9364,7 +9999,7 @@ pub fn sock_recv_from( let data_len = data.len(); let mut reader = &data[..]; let bytes_read = wasi_try_ok!(read_bytes(reader, &memory, iovs_arr).map(|_| data_len)); - let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); + let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow)); wasi_try_mem_ok!(ro_flags.write(&memory, 0)); wasi_try_mem_ok!(ro_data_len.write(&memory, bytes_read)); @@ -9392,14 +10027,13 @@ pub fn sock_send( si_data_len: M::Offset, _si_flags: SiFlags, ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { debug!( "wasi[{}:{}]::sock_send (fd={})", ctx.data().pid(), ctx.data().tid(), sock ); - let env = ctx.data(); let runtime = env.runtime.clone(); @@ -9411,7 +10045,7 @@ pub fn sock_send( .filter_map(|a| a.read().ok()) .map(|a| a.buf_len) .sum(); - let buf_len: usize = wasi_try_ok!(buf_len.try_into().map_err(|_| __WASI_EINVAL)); + let buf_len: usize = wasi_try_ok!(buf_len.try_into().map_err(|_| Errno::Inval)); let mut buf = Vec::with_capacity(buf_len); wasi_try_ok!(write_bytes(&mut buf, &memory, iovs_arr)); @@ -9451,7 +10085,7 @@ pub fn sock_send_to( _si_flags: SiFlags, addr: WasmPtr<__wasi_addr_port_t, M>, ret_data_len: WasmPtr, -) -> Result<__wasi_errno_t, WasiError> { +) -> Result { debug!( "wasi[{}:{}]::sock_send_to (fd={})", ctx.data().pid(), @@ -9478,7 +10112,7 @@ pub fn sock_send_to( let bytes_written = wasi_try_ok!(__sock_actor_mut( &ctx, sock, - __WASI_RIGHT_SOCK_SEND_TO, + Rights::SOCK_SEND_TO, move |socket| async move { socket.send_to::(buf, addr).await } )); @@ -9501,14 +10135,14 @@ pub fn sock_send_to( /// ## Return /// /// Number of bytes transmitted. -pub fn sock_send_file( - ctx: FunctionEnvMut<'_, WasiEnv>, - sock: __wasi_fd_t, - in_fd: __wasi_fd_t, - offset: __wasi_filesize_t, - mut count: __wasi_filesize_t, - ret_sent: WasmPtr<__wasi_filesize_t, M>, -) -> Result<__wasi_errno_t, WasiError> { +pub unsafe fn sock_send_file( + mut ctx: FunctionEnvMut<'_, WasiEnv>, + sock: WasiFd, + in_fd: WasiFd, + offset: Filesize, + mut count: Filesize, + ret_sent: WasmPtr, +) -> Result { debug!( "wasi[{}:{}]::send_file (fd={}, file_fd={})", ctx.data().pid(), @@ -9524,7 +10158,7 @@ pub fn sock_send_file( // Set the offset of the file { let mut fd_map = state.fs.fd_map.write().unwrap(); - let fd_entry = wasi_try_ok!(fd_map.get_mut(&in_fd).ok_or(__WASI_EBADF)); + let fd_entry = wasi_try_ok!(fd_map.get_mut(&in_fd).ok_or(Errno::Badf)); fd_entry.offset.store(offset as u64, Ordering::Release); } @@ -9538,13 +10172,17 @@ pub fn sock_send_file( let fd_entry = wasi_try_ok!(state.fs.get_fd(in_fd)); let bytes_read = match in_fd { __WASI_STDIN_FILENO => { - let mut stdin = wasi_try_ok!( + let mut guard = wasi_try_ok!( inodes .stdin_mut(&state.fs.fd_map) .map_err(fs_error_into_wasi_err), env ); - wasi_try_ok!(stdin.read(&mut buf).map_err(map_io_err)) + if let Some(ref mut stdin) = guard.deref_mut() { + wasi_try_ok!(stdin.read(&mut buf).map_err(map_io_err)) + } else { + return Ok(Errno::Badf); + } } __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => return Ok(Errno::Inval), _ => { @@ -9604,7 +10242,7 @@ pub fn sock_send_file( // reborrow let mut fd_map = state.fs.fd_map.write().unwrap(); - let fd_entry = wasi_try_ok!(fd_map.get_mut(&in_fd).ok_or(__WASI_EBADF)); + let fd_entry = wasi_try_ok!(fd_map.get_mut(&in_fd).ok_or(Errno::Badf)); fd_entry .offset .fetch_add(bytes_read as u64, Ordering::AcqRel); @@ -9618,7 +10256,7 @@ pub fn sock_send_file( let bytes_written = wasi_try_ok!(__sock_actor_mut( &ctx, sock, - __WASI_RIGHT_SOCK_SEND, + Rights::SOCK_SEND, move |socket| async move { socket.send(buf).await } )); total_written += bytes_written as u64; @@ -9655,8 +10293,8 @@ pub fn resolve( addrs: WasmPtr<__wasi_addr_t, M>, naddrs: M::Offset, ret_naddrs: WasmPtr, -) -> __wasi_errno_t { - let naddrs: usize = wasi_try!(naddrs.try_into().map_err(|_| __WASI_EINVAL)); +) -> Errno { + let naddrs: usize = wasi_try!(naddrs.try_into().map_err(|_| Errno::Inval)); let env = ctx.data(); let memory = env.memory_view(&ctx); let host_str = unsafe { get_input_str!(&memory, host, host_len) }; diff --git a/lib/wasi/src/syscalls/wasi.rs b/lib/wasi/src/syscalls/wasi.rs new file mode 100644 index 000000000..f90e5955b --- /dev/null +++ b/lib/wasi/src/syscalls/wasi.rs @@ -0,0 +1,449 @@ +#![deny(dead_code)] +use crate::{WasiEnv, WasiError, WasiState, WasiThread}; +use wasmer::{Memory, Memory32, MemorySize, StoreMut, WasmPtr, WasmSlice}; +use wasmer_wasi_types::{ + wasi::{Errno, Event, Fd as WasiFd, Filesize, Fstflags, Fstflags, Timestamp, Whence, Clockid}, + types::*, +}; + +type MemoryType = Memory32; +type MemoryOffset = u32; + +pub(crate) fn args_get( + ctx: FunctionEnvMut, + argv: WasmPtr, MemoryType>, + argv_buf: WasmPtr, +) -> Errno { + super::args_get::(ctx, argv, argv_buf) +} + +pub(crate) fn args_sizes_get( + ctx: FunctionEnvMut, + argc: WasmPtr, + argv_buf_size: WasmPtr, +) -> Errno { + super::args_sizes_get::(ctx, argc, argv_buf_size) +} + +pub(crate) fn clock_res_get( + ctx: FunctionEnvMut, + clock_id: Clockid, + resolution: WasmPtr, +) -> Errno { + super::clock_res_get::(ctx, clock_id, resolution) +} + +pub(crate) fn clock_time_get( + ctx: FunctionEnvMut, + clock_id: Clockid, + precision: Timestamp, + time: WasmPtr, +) -> Errno { + super::clock_time_get::(ctx, clock_id, precision, time) +} + +pub(crate) fn environ_get( + ctx: FunctionEnvMut, + environ: WasmPtr, MemoryType>, + environ_buf: WasmPtr, +) -> Errno { + super::environ_get::(ctx, environ, environ_buf) +} + +pub(crate) fn environ_sizes_get( + ctx: FunctionEnvMut, + environ_count: WasmPtr, + environ_buf_size: WasmPtr, +) -> Errno { + super::environ_sizes_get::(ctx, environ_count, environ_buf_size) +} + +pub(crate) fn fd_advise( + ctx: FunctionEnvMut, + fd: WasiFd, + offset: Filesize, + len: Filesize, + advice: __wasi_advice_t, +) -> Errno { + super::fd_advise(ctx, fd, offset, len, advice) +} + +pub(crate) fn fd_allocate( + ctx: FunctionEnvMut, + fd: WasiFd, + offset: Filesize, + len: Filesize, +) -> Errno { + super::fd_allocate(ctx, fd, offset, len) +} + +pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: WasiFd) -> Errno { + super::fd_close(ctx, fd) +} + +pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: WasiFd) -> Errno { + super::fd_datasync(ctx, fd) +} + +pub(crate) fn fd_fdstat_get( + ctx: FunctionEnvMut, + fd: WasiFd, + buf_ptr: WasmPtr, +) -> Errno { + super::fd_fdstat_get::(ctx, fd, buf_ptr) +} + +pub(crate) fn fd_fdstat_set_flags( + ctx: FunctionEnvMut, + fd: WasiFd, + flags: WasiFdflags, +) -> Errno { + super::fd_fdstat_set_flags(ctx, fd, flags) +} + +pub(crate) fn fd_fdstat_set_rights( + ctx: FunctionEnvMut, + fd: WasiFd, + fs_rights_base: __wasi_rights_t, + fs_rights_inheriting: __wasi_rights_t, +) -> Errno { + super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) +} + +pub(crate) fn fd_filestat_get( + ctx: FunctionEnvMut, + fd: WasiFd, + buf: WasmPtr, +) -> Errno { + super::fd_filestat_get::(ctx, fd, buf) +} + +pub(crate) fn fd_filestat_set_size( + ctx: FunctionEnvMut, + fd: WasiFd, + st_size: Filesize, +) -> Errno { + super::fd_filestat_set_size(ctx, fd, st_size) +} + +pub(crate) fn fd_filestat_set_times( + ctx: FunctionEnvMut, + fd: WasiFd, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { + super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) +} + +pub(crate) fn fd_pread( + ctx: FunctionEnvMut, + fd: WasiFd, + iovs: WasmPtr<__wasi_iovec_t, MemoryType>, + iovs_len: MemoryOffset, + offset: Filesize, + nread: WasmPtr, +) -> Result { + super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) +} + +pub(crate) fn fd_prestat_get( + ctx: FunctionEnvMut, + fd: WasiFd, + buf: WasmPtr, +) -> Errno { + super::fd_prestat_get::(ctx, fd, buf) +} + +pub(crate) fn fd_prestat_dir_name( + ctx: FunctionEnvMut, + fd: WasiFd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::fd_prestat_dir_name::(ctx, fd, path, path_len) +} + +pub(crate) fn fd_pwrite( + ctx: FunctionEnvMut, + fd: WasiFd, + iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, + iovs_len: MemoryOffset, + offset: Filesize, + nwritten: WasmPtr, +) -> Result { + super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) +} + +pub(crate) fn fd_read( + ctx: FunctionEnvMut, + fd: WasiFd, + iovs: WasmPtr<__wasi_iovec_t, MemoryType>, + iovs_len: MemoryOffset, + nread: WasmPtr, +) -> Result { + super::fd_read::(ctx, fd, iovs, iovs_len, nread) +} + +pub(crate) fn fd_readdir( + ctx: FunctionEnvMut, + fd: WasiFd, + buf: WasmPtr, + buf_len: MemoryOffset, + cookie: __wasi_dircookie_t, + bufused: WasmPtr, +) -> Errno { + super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) +} + +pub(crate) fn fd_renumber(ctx: FunctionEnvMut, from: WasiFd, to: WasiFd) -> Errno { + super::fd_renumber(ctx, from, to) +} + +pub(crate) fn fd_seek( + ctx: FunctionEnvMut, + fd: WasiFd, + offset: FileDelta, + whence: Whence, + newoffset: WasmPtr, +) -> Result { + super::fd_seek::(ctx, fd, offset, whence, newoffset) +} + +pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: WasiFd) -> Errno { + super::fd_sync(ctx, fd) +} + +pub(crate) fn fd_tell( + ctx: FunctionEnvMut, + fd: WasiFd, + offset: WasmPtr, +) -> Errno { + super::fd_tell::(ctx, fd, offset) +} + +pub(crate) fn fd_write( + ctx: FunctionEnvMut, + fd: WasiFd, + iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, + iovs_len: MemoryOffset, + nwritten: WasmPtr, +) -> Result { + super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) +} + +pub(crate) fn path_create_directory( + ctx: FunctionEnvMut, + fd: WasiFd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_create_directory::(ctx, fd, path, path_len) +} + +pub(crate) fn path_filestat_get( + ctx: FunctionEnvMut, + fd: WasiFd, + flags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + buf: WasmPtr, +) -> Errno { + super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) +} + +pub(crate) fn path_filestat_set_times( + ctx: FunctionEnvMut, + fd: WasiFd, + flags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { + super::path_filestat_set_times::( + ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, + ) +} + +pub(crate) fn path_link( + ctx: FunctionEnvMut, + old_fd: WasiFd, + old_flags: LookupFlags, + old_path: WasmPtr, + old_path_len: MemoryOffset, + new_fd: WasiFd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_link::( + ctx, + old_fd, + old_flags, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len, + ) +} + +pub(crate) fn path_open( + ctx: FunctionEnvMut, + dirfd: WasiFd, + dirflags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + o_flags: Oflags, + fs_rights_base: __wasi_rights_t, + fs_rights_inheriting: __wasi_rights_t, + fs_flags: WasiFdflags, + fd: WasmPtr, +) -> Errno { + super::path_open::( + ctx, + dirfd, + dirflags, + path, + path_len, + o_flags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd, + ) +} + +pub(crate) fn path_readlink( + ctx: FunctionEnvMut, + dir_fd: WasiFd, + path: WasmPtr, + path_len: MemoryOffset, + buf: WasmPtr, + buf_len: MemoryOffset, + buf_used: WasmPtr, +) -> Errno { + super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) +} + +pub(crate) fn path_remove_directory( + ctx: FunctionEnvMut, + fd: WasiFd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_remove_directory::(ctx, fd, path, path_len) +} + +pub(crate) fn path_rename( + ctx: FunctionEnvMut, + old_fd: WasiFd, + old_path: WasmPtr, + old_path_len: MemoryOffset, + new_fd: WasiFd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_rename::( + ctx, + old_fd, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len, + ) +} + +pub(crate) fn path_symlink( + ctx: FunctionEnvMut, + old_path: WasmPtr, + old_path_len: MemoryOffset, + fd: WasiFd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) +} + +pub(crate) fn path_unlink_file( + ctx: FunctionEnvMut, + fd: WasiFd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_unlink_file::(ctx, fd, path, path_len) +} + +pub(crate) fn poll_oneoff( + ctx: FunctionEnvMut, + in_: WasmPtr<__wasi_subscription_t, MemoryType>, + out_: WasmPtr, + nsubscriptions: MemoryOffset, + nevents: WasmPtr, +) -> Result { + super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) +} + +pub(crate) fn proc_exit( + ctx: FunctionEnvMut, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { + super::proc_exit(ctx, code) +} + +pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: Signal) -> Errno { + super::proc_raise(ctx, sig) +} + +pub(crate) fn random_get( + ctx: FunctionEnvMut, + buf: WasmPtr, + buf_len: MemoryOffset, +) -> Errno { + super::random_get::(ctx, buf, buf_len) +} + +pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result { + super::sched_yield(ctx) +} + +pub(crate) fn sock_recv( + ctx: FunctionEnvMut, + sock: WasiFd, + ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, + ri_data_len: MemoryOffset, + ri_flags: RiFlags, + ro_data_len: WasmPtr, + ro_flags: WasmPtr, +) -> Result { + super::sock_recv::( + ctx, + sock, + ri_data, + ri_data_len, + ri_flags, + ro_data_len, + ro_flags, + ) +} + +pub(crate) fn sock_send( + ctx: FunctionEnvMut, + sock: WasiFd, + si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, + si_data_len: MemoryOffset, + si_flags: SiFlags, + ret_data_len: WasmPtr, +) -> Result { + super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) +} + +pub(crate) fn sock_shutdown( + ctx: FunctionEnvMut, + sock: WasiFd, + how: SdFlags, +) -> Errno { + super::sock_shutdown(ctx, sock, how) +} diff --git a/lib/wasi/src/syscalls/wasix32.rs b/lib/wasi/src/syscalls/wasix32.rs new file mode 100644 index 000000000..53ca95964 --- /dev/null +++ b/lib/wasi/src/syscalls/wasix32.rs @@ -0,0 +1,1031 @@ +#![deny(dead_code)] +use crate::{WasiEnv, WasiError, WasiState, WasiThread}; +use wasmer::{FunctionEnvMut, Memory, Memory32, MemorySize, StoreMut, WasmPtr, WasmSlice}; +use wasmer_wasi_types::types::*; +use wasmer_wasi_types::wasi::{ + Addressfamily, Advice, Bid, BusDataFormat, BusErrno, BusHandles, Cid, Clockid, Dircookie, + Errno, Event, EventFdFlags, Fd, Fdflags, Fdstat, Filesize, Filestat, Fstflags, Pid, Prestat, + Rights, Sockoption, Sockstatus, Socktype, Streamsecurity, Subscription, Tid, Timestamp, Tty, + Whence, +}; + +type MemoryType = Memory32; +type MemoryOffset = u32; + +pub(crate) fn args_get( + ctx: FunctionEnvMut, + argv: WasmPtr, MemoryType>, + argv_buf: WasmPtr, +) -> Errno { + super::args_get::(ctx, argv, argv_buf) +} + +pub(crate) fn args_sizes_get( + ctx: FunctionEnvMut, + argc: WasmPtr, + argv_buf_size: WasmPtr, +) -> Errno { + super::args_sizes_get::(ctx, argc, argv_buf_size) +} + +pub(crate) fn clock_res_get( + ctx: FunctionEnvMut, + clock_id: Clockid, + resolution: WasmPtr, +) -> Errno { + super::clock_res_get::(ctx, clock_id, resolution) +} + +pub(crate) fn clock_time_get( + ctx: FunctionEnvMut, + clock_id: Clockid, + precision: Timestamp, + time: WasmPtr, +) -> Errno { + super::clock_time_get::(ctx, clock_id, precision, time) +} + +pub(crate) fn environ_get( + ctx: FunctionEnvMut, + environ: WasmPtr, MemoryType>, + environ_buf: WasmPtr, +) -> Errno { + super::environ_get::(ctx, environ, environ_buf) +} + +pub(crate) fn environ_sizes_get( + ctx: FunctionEnvMut, + environ_count: WasmPtr, + environ_buf_size: WasmPtr, +) -> Errno { + super::environ_sizes_get::(ctx, environ_count, environ_buf_size) +} + +pub(crate) fn fd_advise( + ctx: FunctionEnvMut, + fd: Fd, + offset: Filesize, + len: Filesize, + advice: Advice, +) -> Errno { + super::fd_advise(ctx, fd, offset, len, advice) +} + +pub(crate) fn fd_allocate( + ctx: FunctionEnvMut, + fd: Fd, + offset: Filesize, + len: Filesize, +) -> Errno { + super::fd_allocate(ctx, fd, offset, len) +} + +pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: Fd) -> Errno { + super::fd_close(ctx, fd) +} + +pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: Fd) -> Errno { + super::fd_datasync(ctx, fd) +} + +pub(crate) fn fd_fdstat_get( + ctx: FunctionEnvMut, + fd: Fd, + buf_ptr: WasmPtr, +) -> Errno { + super::fd_fdstat_get::(ctx, fd, buf_ptr) +} + +pub(crate) fn fd_fdstat_set_flags(ctx: FunctionEnvMut, fd: Fd, flags: Fdflags) -> Errno { + super::fd_fdstat_set_flags(ctx, fd, flags) +} + +pub(crate) fn fd_fdstat_set_rights( + ctx: FunctionEnvMut, + fd: Fd, + fs_rights_base: Rights, + fs_rights_inheriting: Rights, +) -> Errno { + super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) +} + +pub(crate) fn fd_filestat_get( + ctx: FunctionEnvMut, + fd: Fd, + buf: WasmPtr, +) -> Errno { + super::fd_filestat_get::(ctx, fd, buf) +} + +pub(crate) fn fd_filestat_set_size( + ctx: FunctionEnvMut, + fd: Fd, + st_size: Filesize, +) -> Errno { + super::fd_filestat_set_size(ctx, fd, st_size) +} + +pub(crate) fn fd_filestat_set_times( + ctx: FunctionEnvMut, + fd: Fd, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { + super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) +} + +pub(crate) fn fd_pread( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_iovec_t, MemoryType>, + iovs_len: MemoryOffset, + offset: Filesize, + nread: WasmPtr, +) -> Result { + super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) +} + +pub(crate) fn fd_prestat_get( + ctx: FunctionEnvMut, + fd: Fd, + buf: WasmPtr, +) -> Errno { + super::fd_prestat_get::(ctx, fd, buf) +} + +pub(crate) fn fd_prestat_dir_name( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::fd_prestat_dir_name::(ctx, fd, path, path_len) +} + +pub(crate) fn fd_pwrite( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, + iovs_len: MemoryOffset, + offset: Filesize, + nwritten: WasmPtr, +) -> Result { + super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) +} + +pub(crate) fn fd_read( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_iovec_t, MemoryType>, + iovs_len: MemoryOffset, + nread: WasmPtr, +) -> Result { + super::fd_read::(ctx, fd, iovs, iovs_len, nread) +} + +pub(crate) fn fd_readdir( + ctx: FunctionEnvMut, + fd: Fd, + buf: WasmPtr, + buf_len: MemoryOffset, + cookie: Dircookie, + bufused: WasmPtr, +) -> Errno { + super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) +} + +pub(crate) fn fd_renumber(ctx: FunctionEnvMut, from: Fd, to: Fd) -> Errno { + super::fd_renumber(ctx, from, to) +} + +pub(crate) fn fd_seek( + ctx: FunctionEnvMut, + fd: Fd, + offset: FileDelta, + whence: Whence, + newoffset: WasmPtr, +) -> Result { + super::fd_seek::(ctx, fd, offset, whence, newoffset) +} + +pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: Fd) -> Errno { + super::fd_sync(ctx, fd) +} + +pub(crate) fn fd_tell( + ctx: FunctionEnvMut, + fd: Fd, + offset: WasmPtr, +) -> Errno { + super::fd_tell::(ctx, fd, offset) +} + +pub(crate) fn fd_write( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, + iovs_len: MemoryOffset, + nwritten: WasmPtr, +) -> Result { + super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) +} + +pub(crate) fn path_create_directory( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_create_directory::(ctx, fd, path, path_len) +} + +pub(crate) fn path_filestat_get( + ctx: FunctionEnvMut, + fd: Fd, + flags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + buf: WasmPtr, +) -> Errno { + super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) +} + +pub(crate) fn path_filestat_set_times( + ctx: FunctionEnvMut, + fd: Fd, + flags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { + super::path_filestat_set_times::( + ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, + ) +} + +pub(crate) fn path_link( + ctx: FunctionEnvMut, + old_fd: Fd, + old_flags: LookupFlags, + old_path: WasmPtr, + old_path_len: MemoryOffset, + new_fd: Fd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_link::( + ctx, + old_fd, + old_flags, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len, + ) +} + +pub(crate) fn path_open( + ctx: FunctionEnvMut, + dirfd: Fd, + dirflags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + o_flags: Oflags, + fs_rights_base: Rights, + fs_rights_inheriting: Rights, + fs_flags: Fdflags, + fd: WasmPtr, +) -> Errno { + super::path_open::( + ctx, + dirfd, + dirflags, + path, + path_len, + o_flags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd, + ) +} + +pub(crate) fn path_readlink( + ctx: FunctionEnvMut, + dir_fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, + buf: WasmPtr, + buf_len: MemoryOffset, + buf_used: WasmPtr, +) -> Errno { + super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) +} + +pub(crate) fn path_remove_directory( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_remove_directory::(ctx, fd, path, path_len) +} + +pub(crate) fn path_rename( + ctx: FunctionEnvMut, + old_fd: Fd, + old_path: WasmPtr, + old_path_len: MemoryOffset, + new_fd: Fd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_rename::( + ctx, + old_fd, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len, + ) +} + +pub(crate) fn path_symlink( + ctx: FunctionEnvMut, + old_path: WasmPtr, + old_path_len: MemoryOffset, + fd: Fd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) +} + +pub(crate) fn path_unlink_file( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_unlink_file::(ctx, fd, path, path_len) +} + +pub(crate) fn poll_oneoff( + ctx: FunctionEnvMut, + in_: WasmPtr, + out_: WasmPtr, + nsubscriptions: MemoryOffset, + nevents: WasmPtr, +) -> Result { + super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) +} + +pub(crate) fn proc_exit( + ctx: FunctionEnvMut, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { + super::proc_exit(ctx, code) +} + +pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: Signal) -> Errno { + super::proc_raise(ctx, sig) +} + +pub(crate) fn random_get( + ctx: FunctionEnvMut, + buf: WasmPtr, + buf_len: MemoryOffset, +) -> Errno { + super::random_get::(ctx, buf, buf_len) +} + +pub(crate) fn fd_dup( + ctx: FunctionEnvMut, + fd: Fd, + ret_fd: WasmPtr, +) -> Errno { + super::fd_dup::(ctx, fd, ret_fd) +} + +pub(crate) fn fd_event( + ctx: FunctionEnvMut, + initial_val: u64, + flags: EventFdFlags, + ret_fd: WasmPtr, +) -> Errno { + super::fd_event(ctx, initial_val, flags, ret_fd) +} + +pub(crate) fn fd_pipe( + ctx: FunctionEnvMut, + ro_fd1: WasmPtr, + ro_fd2: WasmPtr, +) -> Errno { + super::fd_pipe::(ctx, ro_fd1, ro_fd2) +} + +pub(crate) fn tty_get(ctx: FunctionEnvMut, tty_state: WasmPtr) -> Errno { + super::tty_get::(ctx, tty_state) +} + +pub(crate) fn tty_set(ctx: FunctionEnvMut, tty_state: WasmPtr) -> Errno { + super::tty_set::(ctx, tty_state) +} + +pub(crate) fn getcwd( + ctx: FunctionEnvMut, + path: WasmPtr, + path_len: WasmPtr, +) -> Errno { + super::getcwd::(ctx, path, path_len) +} + +pub(crate) fn chdir( + ctx: FunctionEnvMut, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::chdir::(ctx, path, path_len) +} + +pub(crate) fn thread_spawn( + ctx: FunctionEnvMut, + method: WasmPtr, + method_len: MemoryOffset, + user_data: u64, + reactor: Bool, + ret_tid: WasmPtr, +) -> Errno { + super::thread_spawn::(ctx, method, method_len, user_data, reactor, ret_tid) +} + +pub(crate) fn thread_sleep( + ctx: FunctionEnvMut, + duration: Timestamp, +) -> Result { + super::thread_sleep(ctx, duration) +} + +pub(crate) fn thread_id(ctx: FunctionEnvMut, ret_tid: WasmPtr) -> Errno { + super::thread_id::(ctx, ret_tid) +} + +pub(crate) fn thread_join(ctx: FunctionEnvMut, tid: Tid) -> Result { + super::thread_join(ctx, tid) +} + +pub(crate) fn thread_parallelism( + ctx: FunctionEnvMut, + ret_parallelism: WasmPtr, +) -> Errno { + super::thread_parallelism::(ctx, ret_parallelism) +} + +pub(crate) fn thread_exit( + ctx: FunctionEnvMut, + exitcode: __wasi_exitcode_t, +) -> Result { + super::thread_exit(ctx, exitcode) +} + +pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result { + super::sched_yield(ctx) +} + +pub(crate) fn getpid(ctx: FunctionEnvMut, ret_pid: WasmPtr) -> Errno { + super::getpid::(ctx, ret_pid) +} + +pub(crate) fn process_spawn( + ctx: FunctionEnvMut, + name: WasmPtr, + name_len: MemoryOffset, + chroot: Bool, + args: WasmPtr, + args_len: MemoryOffset, + preopen: WasmPtr, + preopen_len: MemoryOffset, + stdin: StdioMode, + stdout: StdioMode, + stderr: StdioMode, + working_dir: WasmPtr, + working_dir_len: MemoryOffset, + ret_handles: WasmPtr, +) -> BusErrno { + super::process_spawn::( + ctx, + name, + name_len, + chroot, + args, + args_len, + preopen, + preopen_len, + stdin, + stdout, + stderr, + working_dir, + working_dir_len, + ret_handles, + ) +} + +pub(crate) fn bus_open_local( + ctx: FunctionEnvMut, + name: WasmPtr, + name_len: MemoryOffset, + reuse: Bool, + ret_bid: WasmPtr, +) -> BusErrno { + super::bus_open_local::(ctx, name, name_len, reuse, ret_bid) +} + +pub(crate) fn bus_open_remote( + ctx: FunctionEnvMut, + name: WasmPtr, + name_len: MemoryOffset, + reuse: Bool, + instance: WasmPtr, + instance_len: MemoryOffset, + token: WasmPtr, + token_len: MemoryOffset, + ret_bid: WasmPtr, +) -> BusErrno { + super::bus_open_remote::( + ctx, + name, + name_len, + reuse, + instance, + instance_len, + token, + token_len, + ret_bid, + ) +} + +pub(crate) fn bus_close(ctx: FunctionEnvMut, bid: Bid) -> BusErrno { + super::bus_close(ctx, bid) +} + +pub(crate) fn bus_call( + ctx: FunctionEnvMut, + bid: Bid, + keep_alive: Bool, + topic: WasmPtr, + topic_len: MemoryOffset, + format: BusDataFormat, + buf: WasmPtr, + buf_len: MemoryOffset, + ret_cid: WasmPtr, +) -> BusErrno { + super::bus_call::( + ctx, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ) +} + +pub(crate) fn bus_subcall( + ctx: FunctionEnvMut, + parent: Cid, + keep_alive: Bool, + topic: WasmPtr, + topic_len: MemoryOffset, + format: BusDataFormat, + buf: WasmPtr, + buf_len: MemoryOffset, + ret_cid: WasmPtr, +) -> BusErrno { + super::bus_subcall::( + ctx, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ) +} + +pub(crate) fn bus_poll( + ctx: FunctionEnvMut, + timeout: Timestamp, + events: WasmPtr, + nevents: MemoryOffset, + malloc: WasmPtr, + malloc_len: MemoryOffset, + ret_nevents: WasmPtr, +) -> BusErrno { + super::bus_poll::( + ctx, + timeout, + events, + nevents, + malloc, + malloc_len, + ret_nevents, + ) +} + +pub(crate) fn call_reply( + ctx: FunctionEnvMut, + cid: Cid, + format: BusDataFormat, + buf: WasmPtr, + buf_len: MemoryOffset, +) -> BusErrno { + super::call_reply::(ctx, cid, format, buf, buf_len) +} + +pub(crate) fn call_fault(ctx: FunctionEnvMut, cid: Cid, fault: BusErrno) -> BusErrno { + super::call_fault(ctx, cid, fault) +} + +pub(crate) fn call_close(ctx: FunctionEnvMut, cid: Cid) -> BusErrno { + super::call_close(ctx, cid) +} + +pub(crate) fn port_bridge( + ctx: FunctionEnvMut, + network: WasmPtr, + network_len: MemoryOffset, + token: WasmPtr, + token_len: MemoryOffset, + security: Streamsecurity, +) -> Errno { + super::port_bridge::(ctx, network, network_len, token, token_len, security) +} + +pub(crate) fn port_unbridge(ctx: FunctionEnvMut) -> Errno { + super::port_unbridge(ctx) +} + +pub(crate) fn port_dhcp_acquire(ctx: FunctionEnvMut) -> Errno { + super::port_dhcp_acquire(ctx) +} + +pub(crate) fn port_addr_add( + ctx: FunctionEnvMut, + addr: WasmPtr<__wasi_cidr_t, MemoryType>, +) -> Errno { + super::port_addr_add::(ctx, addr) +} + +pub(crate) fn port_addr_remove( + ctx: FunctionEnvMut, + addr: WasmPtr<__wasi_addr_t, MemoryType>, +) -> Errno { + super::port_addr_remove::(ctx, addr) +} + +pub(crate) fn port_addr_clear(ctx: FunctionEnvMut) -> Errno { + super::port_addr_clear(ctx) +} + +pub(crate) fn port_addr_list( + ctx: FunctionEnvMut, + addrs: WasmPtr<__wasi_cidr_t, MemoryType>, + naddrs: WasmPtr, +) -> Errno { + super::port_addr_list::(ctx, addrs, naddrs) +} + +pub(crate) fn port_mac( + ctx: FunctionEnvMut, + ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, +) -> Errno { + super::port_mac::(ctx, ret_mac) +} + +pub(crate) fn port_gateway_set( + ctx: FunctionEnvMut, + ip: WasmPtr<__wasi_addr_t, MemoryType>, +) -> Errno { + super::port_gateway_set::(ctx, ip) +} + +pub(crate) fn port_route_add( + ctx: FunctionEnvMut, + cidr: WasmPtr<__wasi_cidr_t, MemoryType>, + via_router: WasmPtr<__wasi_addr_t, MemoryType>, + preferred_until: WasmPtr, + expires_at: WasmPtr, +) -> Errno { + super::port_route_add::(ctx, cidr, via_router, preferred_until, expires_at) +} + +pub(crate) fn port_route_remove( + ctx: FunctionEnvMut, + ip: WasmPtr<__wasi_addr_t, MemoryType>, +) -> Errno { + super::port_route_remove::(ctx, ip) +} + +pub(crate) fn port_route_clear(ctx: FunctionEnvMut) -> Errno { + super::port_route_clear(ctx) +} + +pub(crate) fn port_route_list( + ctx: FunctionEnvMut, + routes: WasmPtr, + nroutes: WasmPtr, +) -> Errno { + super::port_route_list::(ctx, routes, nroutes) +} + +pub(crate) fn ws_connect( + ctx: FunctionEnvMut, + url: WasmPtr, + url_len: MemoryOffset, + ret_sock: WasmPtr, +) -> Errno { + super::ws_connect::(ctx, url, url_len, ret_sock) +} + +pub(crate) fn http_request( + ctx: FunctionEnvMut, + url: WasmPtr, + url_len: MemoryOffset, + method: WasmPtr, + method_len: MemoryOffset, + headers: WasmPtr, + headers_len: MemoryOffset, + gzip: Bool, + ret_handles: WasmPtr, +) -> Errno { + super::http_request::( + ctx, + url, + url_len, + method, + method_len, + headers, + headers_len, + gzip, + ret_handles, + ) +} + +pub(crate) fn http_status( + ctx: FunctionEnvMut, + sock: Fd, + status: WasmPtr, + status_text: WasmPtr, + status_text_len: WasmPtr, + headers: WasmPtr, + headers_len: WasmPtr, +) -> Errno { + super::http_status::(ctx, sock, status) +} + +pub(crate) fn sock_status( + ctx: FunctionEnvMut, + sock: Fd, + ret_status: WasmPtr, +) -> Errno { + super::sock_status::(ctx, sock, ret_status) +} + +pub(crate) fn sock_addr_local( + ctx: FunctionEnvMut, + sock: Fd, + ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_addr_local::(ctx, sock, ret_addr) +} + +pub(crate) fn sock_addr_peer( + ctx: FunctionEnvMut, + sock: Fd, + ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_addr_peer::(ctx, sock, ro_addr) +} + +pub(crate) fn sock_open( + ctx: FunctionEnvMut, + af: Addressfamily, + ty: Socktype, + pt: SockProto, + ro_sock: WasmPtr, +) -> Errno { + super::sock_open::(ctx, af, ty, pt, ro_sock) +} + +pub(crate) fn sock_set_opt_flag( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + flag: Bool, +) -> Errno { + super::sock_set_opt_flag(ctx, sock, opt, flag) +} + +pub(crate) fn sock_get_opt_flag( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + ret_flag: WasmPtr, +) -> Errno { + super::sock_get_opt_flag::(ctx, sock, opt, ret_flag) +} + +pub fn sock_set_opt_time( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + time: WasmPtr, +) -> Errno { + super::sock_set_opt_time(ctx, sock, opt, time) +} + +pub fn sock_get_opt_time( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + ret_time: WasmPtr, +) -> Errno { + super::sock_get_opt_time(ctx, sock, opt, ret_time) +} + +pub fn sock_set_opt_size( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + size: Filesize, +) -> Errno { + super::sock_set_opt_size(ctx, sock, opt, size) +} + +pub fn sock_get_opt_size( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + ret_size: WasmPtr, +) -> Errno { + super::sock_get_opt_size(ctx, sock, opt, ret_size) +} + +pub(crate) fn sock_join_multicast_v4( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, + iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, +) -> Errno { + super::sock_join_multicast_v4::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_leave_multicast_v4( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, + iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, +) -> Errno { + super::sock_leave_multicast_v4::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_join_multicast_v6( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, + iface: u32, +) -> Errno { + super::sock_join_multicast_v6::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_leave_multicast_v6( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, + iface: u32, +) -> Errno { + super::sock_leave_multicast_v6::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_bind( + ctx: FunctionEnvMut, + sock: Fd, + addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_bind::(ctx, sock, addr) +} + +pub(crate) fn sock_listen(ctx: FunctionEnvMut, sock: Fd, backlog: MemoryOffset) -> Errno { + super::sock_listen::(ctx, sock, backlog) +} + +pub(crate) fn sock_accept( + ctx: FunctionEnvMut, + sock: Fd, + fd_flags: Fdflags, + ro_fd: WasmPtr, + ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Result { + super::sock_accept::(ctx, sock, fd_flags, ro_fd, ro_addr) +} + +pub(crate) fn sock_connect( + ctx: FunctionEnvMut, + sock: Fd, + addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_connect::(ctx, sock, addr) +} + +pub(crate) fn sock_recv( + ctx: FunctionEnvMut, + sock: Fd, + ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, + ri_data_len: MemoryOffset, + ri_flags: RiFlags, + ro_data_len: WasmPtr, + ro_flags: WasmPtr, +) -> Result { + super::sock_recv::( + ctx, + sock, + ri_data, + ri_data_len, + ri_flags, + ro_data_len, + ro_flags, + ) +} + +pub(crate) fn sock_recv_from( + ctx: FunctionEnvMut, + sock: Fd, + ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, + ri_data_len: MemoryOffset, + ri_flags: RiFlags, + ro_data_len: WasmPtr, + ro_flags: WasmPtr, + ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Result { + super::sock_recv_from::( + ctx, + sock, + ri_data, + ri_data_len, + ri_flags, + ro_data_len, + ro_flags, + ro_addr, + ) +} + +pub(crate) fn sock_send( + ctx: FunctionEnvMut, + sock: Fd, + si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, + si_data_len: MemoryOffset, + si_flags: SiFlags, + ret_data_len: WasmPtr, +) -> Result { + super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) +} + +pub(crate) fn sock_send_to( + ctx: FunctionEnvMut, + sock: Fd, + si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, + si_data_len: MemoryOffset, + si_flags: SiFlags, + addr: WasmPtr<__wasi_addr_port_t, MemoryType>, + ret_data_len: WasmPtr, +) -> Result { + super::sock_send_to::( + ctx, + sock, + si_data, + si_data_len, + si_flags, + addr, + ret_data_len, + ) +} + +pub(crate) fn sock_send_file( + ctx: FunctionEnvMut, + out_fd: Fd, + in_fd: Fd, + offset: Filesize, + count: Filesize, + ret_sent: WasmPtr, +) -> Result { + unsafe { super::sock_send_file::(ctx, out_fd, in_fd, offset, count, ret_sent) } +} + +pub(crate) fn sock_shutdown(ctx: FunctionEnvMut, sock: Fd, how: SdFlags) -> Errno { + super::sock_shutdown(ctx, sock, how) +} + +pub(crate) fn resolve( + ctx: FunctionEnvMut, + host: WasmPtr, + host_len: MemoryOffset, + port: u16, + ips: WasmPtr<__wasi_addr_t, MemoryType>, + nips: MemoryOffset, + ret_nips: WasmPtr, +) -> Errno { + super::resolve::(ctx, host, host_len, port, ips, nips, ret_nips) +} diff --git a/lib/wasi/src/syscalls/wasix64.rs b/lib/wasi/src/syscalls/wasix64.rs new file mode 100644 index 000000000..df48c26a6 --- /dev/null +++ b/lib/wasi/src/syscalls/wasix64.rs @@ -0,0 +1,1031 @@ +#![deny(dead_code)] +use crate::{WasiEnv, WasiError, WasiState, WasiThread}; +use wasmer::{FunctionEnvMut, Memory, Memory64, MemorySize, StoreMut, WasmPtr, WasmSlice}; +use wasmer_wasi_types::types::*; +use wasmer_wasi_types::wasi::{ + Addressfamily, Advice, Bid, BusDataFormat, BusErrno, BusHandles, Cid, Clockid, Dircookie, + Errno, Event, EventFdFlags, Fd, Fdflags, Fdstat, Filesize, Filestat, Fstflags, Pid, Prestat, + Rights, Sockoption, Sockstatus, Socktype, Streamsecurity, Subscription, Tid, Timestamp, Tty, + Whence, +}; + +type MemoryType = Memory64; +type MemoryOffset = u64; + +pub(crate) fn args_get( + ctx: FunctionEnvMut, + argv: WasmPtr, MemoryType>, + argv_buf: WasmPtr, +) -> Errno { + super::args_get::(ctx, argv, argv_buf) +} + +pub(crate) fn args_sizes_get( + ctx: FunctionEnvMut, + argc: WasmPtr, + argv_buf_size: WasmPtr, +) -> Errno { + super::args_sizes_get::(ctx, argc, argv_buf_size) +} + +pub(crate) fn clock_res_get( + ctx: FunctionEnvMut, + clock_id: Clockid, + resolution: WasmPtr, +) -> Errno { + super::clock_res_get::(ctx, clock_id, resolution) +} + +pub(crate) fn clock_time_get( + ctx: FunctionEnvMut, + clock_id: Clockid, + precision: Timestamp, + time: WasmPtr, +) -> Errno { + super::clock_time_get::(ctx, clock_id, precision, time) +} + +pub(crate) fn environ_get( + ctx: FunctionEnvMut, + environ: WasmPtr, MemoryType>, + environ_buf: WasmPtr, +) -> Errno { + super::environ_get::(ctx, environ, environ_buf) +} + +pub(crate) fn environ_sizes_get( + ctx: FunctionEnvMut, + environ_count: WasmPtr, + environ_buf_size: WasmPtr, +) -> Errno { + super::environ_sizes_get::(ctx, environ_count, environ_buf_size) +} + +pub(crate) fn fd_advise( + ctx: FunctionEnvMut, + fd: Fd, + offset: Filesize, + len: Filesize, + advice: Advice, +) -> Errno { + super::fd_advise(ctx, fd, offset, len, advice) +} + +pub(crate) fn fd_allocate( + ctx: FunctionEnvMut, + fd: Fd, + offset: Filesize, + len: Filesize, +) -> Errno { + super::fd_allocate(ctx, fd, offset, len) +} + +pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: Fd) -> Errno { + super::fd_close(ctx, fd) +} + +pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: Fd) -> Errno { + super::fd_datasync(ctx, fd) +} + +pub(crate) fn fd_fdstat_get( + ctx: FunctionEnvMut, + fd: Fd, + buf_ptr: WasmPtr, +) -> Errno { + super::fd_fdstat_get::(ctx, fd, buf_ptr) +} + +pub(crate) fn fd_fdstat_set_flags(ctx: FunctionEnvMut, fd: Fd, flags: Fdflags) -> Errno { + super::fd_fdstat_set_flags(ctx, fd, flags) +} + +pub(crate) fn fd_fdstat_set_rights( + ctx: FunctionEnvMut, + fd: Fd, + fs_rights_base: Rights, + fs_rights_inheriting: Rights, +) -> Errno { + super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) +} + +pub(crate) fn fd_filestat_get( + ctx: FunctionEnvMut, + fd: Fd, + buf: WasmPtr, +) -> Errno { + super::fd_filestat_get::(ctx, fd, buf) +} + +pub(crate) fn fd_filestat_set_size( + ctx: FunctionEnvMut, + fd: Fd, + st_size: Filesize, +) -> Errno { + super::fd_filestat_set_size(ctx, fd, st_size) +} + +pub(crate) fn fd_filestat_set_times( + ctx: FunctionEnvMut, + fd: Fd, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { + super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) +} + +pub(crate) fn fd_pread( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_iovec_t, MemoryType>, + iovs_len: MemoryOffset, + offset: Filesize, + nread: WasmPtr, +) -> Result { + super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) +} + +pub(crate) fn fd_prestat_get( + ctx: FunctionEnvMut, + fd: Fd, + buf: WasmPtr, +) -> Errno { + super::fd_prestat_get::(ctx, fd, buf) +} + +pub(crate) fn fd_prestat_dir_name( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::fd_prestat_dir_name::(ctx, fd, path, path_len) +} + +pub(crate) fn fd_pwrite( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, + iovs_len: MemoryOffset, + offset: Filesize, + nwritten: WasmPtr, +) -> Result { + super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) +} + +pub(crate) fn fd_read( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_iovec_t, MemoryType>, + iovs_len: MemoryOffset, + nread: WasmPtr, +) -> Result { + super::fd_read::(ctx, fd, iovs, iovs_len, nread) +} + +pub(crate) fn fd_readdir( + ctx: FunctionEnvMut, + fd: Fd, + buf: WasmPtr, + buf_len: MemoryOffset, + cookie: Dircookie, + bufused: WasmPtr, +) -> Errno { + super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) +} + +pub(crate) fn fd_renumber(ctx: FunctionEnvMut, from: Fd, to: Fd) -> Errno { + super::fd_renumber(ctx, from, to) +} + +pub(crate) fn fd_seek( + ctx: FunctionEnvMut, + fd: Fd, + offset: FileDelta, + whence: Whence, + newoffset: WasmPtr, +) -> Result { + super::fd_seek::(ctx, fd, offset, whence, newoffset) +} + +pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: Fd) -> Errno { + super::fd_sync(ctx, fd) +} + +pub(crate) fn fd_tell( + ctx: FunctionEnvMut, + fd: Fd, + offset: WasmPtr, +) -> Errno { + super::fd_tell::(ctx, fd, offset) +} + +pub(crate) fn fd_write( + ctx: FunctionEnvMut, + fd: Fd, + iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, + iovs_len: MemoryOffset, + nwritten: WasmPtr, +) -> Result { + super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) +} + +pub(crate) fn path_create_directory( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_create_directory::(ctx, fd, path, path_len) +} + +pub(crate) fn path_filestat_get( + ctx: FunctionEnvMut, + fd: Fd, + flags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + buf: WasmPtr, +) -> Errno { + super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) +} + +pub(crate) fn path_filestat_set_times( + ctx: FunctionEnvMut, + fd: Fd, + flags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + st_atim: Timestamp, + st_mtim: Timestamp, + fst_flags: Fstflags, +) -> Errno { + super::path_filestat_set_times::( + ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, + ) +} + +pub(crate) fn path_link( + ctx: FunctionEnvMut, + old_fd: Fd, + old_flags: LookupFlags, + old_path: WasmPtr, + old_path_len: MemoryOffset, + new_fd: Fd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_link::( + ctx, + old_fd, + old_flags, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len, + ) +} + +pub(crate) fn path_open( + ctx: FunctionEnvMut, + dirfd: Fd, + dirflags: LookupFlags, + path: WasmPtr, + path_len: MemoryOffset, + o_flags: Oflags, + fs_rights_base: Rights, + fs_rights_inheriting: Rights, + fs_flags: Fdflags, + fd: WasmPtr, +) -> Errno { + super::path_open::( + ctx, + dirfd, + dirflags, + path, + path_len, + o_flags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd, + ) +} + +pub(crate) fn path_readlink( + ctx: FunctionEnvMut, + dir_fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, + buf: WasmPtr, + buf_len: MemoryOffset, + buf_used: WasmPtr, +) -> Errno { + super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) +} + +pub(crate) fn path_remove_directory( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_remove_directory::(ctx, fd, path, path_len) +} + +pub(crate) fn path_rename( + ctx: FunctionEnvMut, + old_fd: Fd, + old_path: WasmPtr, + old_path_len: MemoryOffset, + new_fd: Fd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_rename::( + ctx, + old_fd, + old_path, + old_path_len, + new_fd, + new_path, + new_path_len, + ) +} + +pub(crate) fn path_symlink( + ctx: FunctionEnvMut, + old_path: WasmPtr, + old_path_len: MemoryOffset, + fd: Fd, + new_path: WasmPtr, + new_path_len: MemoryOffset, +) -> Errno { + super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) +} + +pub(crate) fn path_unlink_file( + ctx: FunctionEnvMut, + fd: Fd, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::path_unlink_file::(ctx, fd, path, path_len) +} + +pub(crate) fn poll_oneoff( + ctx: FunctionEnvMut, + in_: WasmPtr, + out_: WasmPtr, + nsubscriptions: MemoryOffset, + nevents: WasmPtr, +) -> Result { + super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) +} + +pub(crate) fn proc_exit( + ctx: FunctionEnvMut, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { + super::proc_exit(ctx, code) +} + +pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: Signal) -> Errno { + super::proc_raise(ctx, sig) +} + +pub(crate) fn random_get( + ctx: FunctionEnvMut, + buf: WasmPtr, + buf_len: MemoryOffset, +) -> Errno { + super::random_get::(ctx, buf, buf_len) +} + +pub(crate) fn fd_dup( + ctx: FunctionEnvMut, + fd: Fd, + ret_fd: WasmPtr, +) -> Errno { + super::fd_dup::(ctx, fd, ret_fd) +} + +pub(crate) fn fd_event( + ctx: FunctionEnvMut, + initial_val: u64, + flags: EventFdFlags, + ret_fd: WasmPtr, +) -> Errno { + super::fd_event(ctx, initial_val, flags, ret_fd) +} + +pub(crate) fn fd_pipe( + ctx: FunctionEnvMut, + ro_fd1: WasmPtr, + ro_fd2: WasmPtr, +) -> Errno { + super::fd_pipe::(ctx, ro_fd1, ro_fd2) +} + +pub(crate) fn tty_get(ctx: FunctionEnvMut, tty_state: WasmPtr) -> Errno { + super::tty_get::(ctx, tty_state) +} + +pub(crate) fn tty_set(ctx: FunctionEnvMut, tty_state: WasmPtr) -> Errno { + super::tty_set::(ctx, tty_state) +} + +pub(crate) fn getcwd( + ctx: FunctionEnvMut, + path: WasmPtr, + path_len: WasmPtr, +) -> Errno { + super::getcwd::(ctx, path, path_len) +} + +pub(crate) fn chdir( + ctx: FunctionEnvMut, + path: WasmPtr, + path_len: MemoryOffset, +) -> Errno { + super::chdir::(ctx, path, path_len) +} + +pub(crate) fn thread_spawn( + ctx: FunctionEnvMut, + method: WasmPtr, + method_len: MemoryOffset, + user_data: u64, + reactor: Bool, + ret_tid: WasmPtr, +) -> Errno { + super::thread_spawn::(ctx, method, method_len, user_data, reactor, ret_tid) +} + +pub(crate) fn thread_sleep( + ctx: FunctionEnvMut, + duration: Timestamp, +) -> Result { + super::thread_sleep(ctx, duration) +} + +pub(crate) fn thread_id(ctx: FunctionEnvMut, ret_tid: WasmPtr) -> Errno { + super::thread_id::(ctx, ret_tid) +} + +pub(crate) fn thread_join(ctx: FunctionEnvMut, tid: Tid) -> Result { + super::thread_join(ctx, tid) +} + +pub(crate) fn thread_parallelism( + ctx: FunctionEnvMut, + ret_parallelism: WasmPtr, +) -> Errno { + super::thread_parallelism::(ctx, ret_parallelism) +} + +pub(crate) fn thread_exit( + ctx: FunctionEnvMut, + exitcode: __wasi_exitcode_t, +) -> Result { + super::thread_exit(ctx, exitcode) +} + +pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result { + super::sched_yield(ctx) +} + +pub(crate) fn getpid(ctx: FunctionEnvMut, ret_pid: WasmPtr) -> Errno { + super::getpid::(ctx, ret_pid) +} + +pub(crate) fn process_spawn( + ctx: FunctionEnvMut, + name: WasmPtr, + name_len: MemoryOffset, + chroot: Bool, + args: WasmPtr, + args_len: MemoryOffset, + preopen: WasmPtr, + preopen_len: MemoryOffset, + stdin: StdioMode, + stdout: StdioMode, + stderr: StdioMode, + working_dir: WasmPtr, + working_dir_len: MemoryOffset, + ret_handles: WasmPtr, +) -> BusErrno { + super::process_spawn::( + ctx, + name, + name_len, + chroot, + args, + args_len, + preopen, + preopen_len, + stdin, + stdout, + stderr, + working_dir, + working_dir_len, + ret_handles, + ) +} + +pub(crate) fn bus_open_local( + ctx: FunctionEnvMut, + name: WasmPtr, + name_len: MemoryOffset, + reuse: Bool, + ret_bid: WasmPtr, +) -> BusErrno { + super::bus_open_local::(ctx, name, name_len, reuse, ret_bid) +} + +pub(crate) fn bus_open_remote( + ctx: FunctionEnvMut, + name: WasmPtr, + name_len: MemoryOffset, + reuse: Bool, + instance: WasmPtr, + instance_len: MemoryOffset, + token: WasmPtr, + token_len: MemoryOffset, + ret_bid: WasmPtr, +) -> BusErrno { + super::bus_open_remote::( + ctx, + name, + name_len, + reuse, + instance, + instance_len, + token, + token_len, + ret_bid, + ) +} + +pub(crate) fn bus_close(ctx: FunctionEnvMut, bid: Bid) -> BusErrno { + super::bus_close(ctx, bid) +} + +pub(crate) fn bus_call( + ctx: FunctionEnvMut, + bid: Bid, + keep_alive: Bool, + topic: WasmPtr, + topic_len: MemoryOffset, + format: BusDataFormat, + buf: WasmPtr, + buf_len: MemoryOffset, + ret_cid: WasmPtr, +) -> BusErrno { + super::bus_call::( + ctx, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ) +} + +pub(crate) fn bus_subcall( + ctx: FunctionEnvMut, + parent: Cid, + keep_alive: Bool, + topic: WasmPtr, + topic_len: MemoryOffset, + format: BusDataFormat, + buf: WasmPtr, + buf_len: MemoryOffset, + ret_cid: WasmPtr, +) -> BusErrno { + super::bus_subcall::( + ctx, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ) +} + +pub(crate) fn bus_poll( + ctx: FunctionEnvMut, + timeout: Timestamp, + events: WasmPtr, + nevents: MemoryOffset, + malloc: WasmPtr, + malloc_len: MemoryOffset, + ret_nevents: WasmPtr, +) -> BusErrno { + super::bus_poll::( + ctx, + timeout, + events, + nevents, + malloc, + malloc_len, + ret_nevents, + ) +} + +pub(crate) fn call_reply( + ctx: FunctionEnvMut, + cid: Cid, + format: BusDataFormat, + buf: WasmPtr, + buf_len: MemoryOffset, +) -> BusErrno { + super::call_reply::(ctx, cid, format, buf, buf_len) +} + +pub(crate) fn call_fault(ctx: FunctionEnvMut, cid: Cid, fault: BusErrno) -> BusErrno { + super::call_fault(ctx, cid, fault) +} + +pub(crate) fn call_close(ctx: FunctionEnvMut, cid: Cid) -> BusErrno { + super::call_close(ctx, cid) +} + +pub(crate) fn port_bridge( + ctx: FunctionEnvMut, + network: WasmPtr, + network_len: MemoryOffset, + token: WasmPtr, + token_len: MemoryOffset, + security: Streamsecurity, +) -> Errno { + super::port_bridge::(ctx, network, network_len, token, token_len, security) +} + +pub(crate) fn port_unbridge(ctx: FunctionEnvMut) -> Errno { + super::port_unbridge(ctx) +} + +pub(crate) fn port_dhcp_acquire(ctx: FunctionEnvMut) -> Errno { + super::port_dhcp_acquire(ctx) +} + +pub(crate) fn port_addr_add( + ctx: FunctionEnvMut, + addr: WasmPtr<__wasi_cidr_t, MemoryType>, +) -> Errno { + super::port_addr_add::(ctx, addr) +} + +pub(crate) fn port_addr_remove( + ctx: FunctionEnvMut, + addr: WasmPtr<__wasi_addr_t, MemoryType>, +) -> Errno { + super::port_addr_remove::(ctx, addr) +} + +pub(crate) fn port_addr_clear(ctx: FunctionEnvMut) -> Errno { + super::port_addr_clear(ctx) +} + +pub(crate) fn port_addr_list( + ctx: FunctionEnvMut, + addrs: WasmPtr<__wasi_cidr_t, MemoryType>, + naddrs: WasmPtr, +) -> Errno { + super::port_addr_list::(ctx, addrs, naddrs) +} + +pub(crate) fn port_mac( + ctx: FunctionEnvMut, + ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, +) -> Errno { + super::port_mac::(ctx, ret_mac) +} + +pub(crate) fn port_gateway_set( + ctx: FunctionEnvMut, + ip: WasmPtr<__wasi_addr_t, MemoryType>, +) -> Errno { + super::port_gateway_set::(ctx, ip) +} + +pub(crate) fn port_route_add( + ctx: FunctionEnvMut, + cidr: WasmPtr<__wasi_cidr_t, MemoryType>, + via_router: WasmPtr<__wasi_addr_t, MemoryType>, + preferred_until: WasmPtr, + expires_at: WasmPtr, +) -> Errno { + super::port_route_add::(ctx, cidr, via_router, preferred_until, expires_at) +} + +pub(crate) fn port_route_remove( + ctx: FunctionEnvMut, + ip: WasmPtr<__wasi_addr_t, MemoryType>, +) -> Errno { + super::port_route_remove::(ctx, ip) +} + +pub(crate) fn port_route_clear(ctx: FunctionEnvMut) -> Errno { + super::port_route_clear(ctx) +} + +pub(crate) fn port_route_list( + ctx: FunctionEnvMut, + routes: WasmPtr, + nroutes: WasmPtr, +) -> Errno { + super::port_route_list::(ctx, routes, nroutes) +} + +pub(crate) fn ws_connect( + ctx: FunctionEnvMut, + url: WasmPtr, + url_len: MemoryOffset, + ret_sock: WasmPtr, +) -> Errno { + super::ws_connect::(ctx, url, url_len, ret_sock) +} + +pub(crate) fn http_request( + ctx: FunctionEnvMut, + url: WasmPtr, + url_len: MemoryOffset, + method: WasmPtr, + method_len: MemoryOffset, + headers: WasmPtr, + headers_len: MemoryOffset, + gzip: Bool, + ret_handles: WasmPtr, +) -> Errno { + super::http_request::( + ctx, + url, + url_len, + method, + method_len, + headers, + headers_len, + gzip, + ret_handles, + ) +} + +pub(crate) fn http_status( + ctx: FunctionEnvMut, + sock: Fd, + status: WasmPtr, + status_text: WasmPtr, + status_text_len: WasmPtr, + headers: WasmPtr, + headers_len: WasmPtr, +) -> Errno { + super::http_status::(ctx, sock, status) +} + +pub(crate) fn sock_status( + ctx: FunctionEnvMut, + sock: Fd, + ret_status: WasmPtr, +) -> Errno { + super::sock_status::(ctx, sock, ret_status) +} + +pub(crate) fn sock_addr_local( + ctx: FunctionEnvMut, + sock: Fd, + ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_addr_local::(ctx, sock, ret_addr) +} + +pub(crate) fn sock_addr_peer( + ctx: FunctionEnvMut, + sock: Fd, + ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_addr_peer::(ctx, sock, ro_addr) +} + +pub(crate) fn sock_open( + ctx: FunctionEnvMut, + af: Addressfamily, + ty: Socktype, + pt: SockProto, + ro_sock: WasmPtr, +) -> Errno { + super::sock_open::(ctx, af, ty, pt, ro_sock) +} + +pub(crate) fn sock_set_opt_flag( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + flag: Bool, +) -> Errno { + super::sock_set_opt_flag(ctx, sock, opt, flag) +} + +pub(crate) fn sock_get_opt_flag( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + ret_flag: WasmPtr, +) -> Errno { + super::sock_get_opt_flag::(ctx, sock, opt, ret_flag) +} + +pub fn sock_set_opt_time( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + time: WasmPtr, +) -> Errno { + super::sock_set_opt_time(ctx, sock, opt, time) +} + +pub fn sock_get_opt_time( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + ret_time: WasmPtr, +) -> Errno { + super::sock_get_opt_time(ctx, sock, opt, ret_time) +} + +pub fn sock_set_opt_size( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + size: Filesize, +) -> Errno { + super::sock_set_opt_size(ctx, sock, opt, size) +} + +pub fn sock_get_opt_size( + ctx: FunctionEnvMut, + sock: Fd, + opt: Sockoption, + ret_size: WasmPtr, +) -> Errno { + super::sock_get_opt_size(ctx, sock, opt, ret_size) +} + +pub(crate) fn sock_join_multicast_v4( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, + iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, +) -> Errno { + super::sock_join_multicast_v4::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_leave_multicast_v4( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, + iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, +) -> Errno { + super::sock_leave_multicast_v4::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_join_multicast_v6( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, + iface: u32, +) -> Errno { + super::sock_join_multicast_v6::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_leave_multicast_v6( + ctx: FunctionEnvMut, + sock: Fd, + multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, + iface: u32, +) -> Errno { + super::sock_leave_multicast_v6::(ctx, sock, multiaddr, iface) +} + +pub(crate) fn sock_bind( + ctx: FunctionEnvMut, + sock: Fd, + addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_bind::(ctx, sock, addr) +} + +pub(crate) fn sock_listen(ctx: FunctionEnvMut, sock: Fd, backlog: MemoryOffset) -> Errno { + super::sock_listen::(ctx, sock, backlog) +} + +pub(crate) fn sock_accept( + ctx: FunctionEnvMut, + sock: Fd, + fd_flags: Fdflags, + ro_fd: WasmPtr, + ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Result { + super::sock_accept::(ctx, sock, fd_flags, ro_fd, ro_addr) +} + +pub(crate) fn sock_connect( + ctx: FunctionEnvMut, + sock: Fd, + addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Errno { + super::sock_connect::(ctx, sock, addr) +} + +pub(crate) fn sock_recv( + ctx: FunctionEnvMut, + sock: Fd, + ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, + ri_data_len: MemoryOffset, + ri_flags: RiFlags, + ro_data_len: WasmPtr, + ro_flags: WasmPtr, +) -> Result { + super::sock_recv::( + ctx, + sock, + ri_data, + ri_data_len, + ri_flags, + ro_data_len, + ro_flags, + ) +} + +pub(crate) fn sock_recv_from( + ctx: FunctionEnvMut, + sock: Fd, + ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, + ri_data_len: MemoryOffset, + ri_flags: RiFlags, + ro_data_len: WasmPtr, + ro_flags: WasmPtr, + ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, +) -> Result { + super::sock_recv_from::( + ctx, + sock, + ri_data, + ri_data_len, + ri_flags, + ro_data_len, + ro_flags, + ro_addr, + ) +} + +pub(crate) fn sock_send( + ctx: FunctionEnvMut, + sock: Fd, + si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, + si_data_len: MemoryOffset, + si_flags: SiFlags, + ret_data_len: WasmPtr, +) -> Result { + super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) +} + +pub(crate) fn sock_send_to( + ctx: FunctionEnvMut, + sock: Fd, + si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, + si_data_len: MemoryOffset, + si_flags: SiFlags, + addr: WasmPtr<__wasi_addr_port_t, MemoryType>, + ret_data_len: WasmPtr, +) -> Result { + super::sock_send_to::( + ctx, + sock, + si_data, + si_data_len, + si_flags, + addr, + ret_data_len, + ) +} + +pub(crate) fn sock_send_file( + ctx: FunctionEnvMut, + out_fd: Fd, + in_fd: Fd, + offset: Filesize, + count: Filesize, + ret_sent: WasmPtr, +) -> Result { + unsafe { super::sock_send_file::(ctx, out_fd, in_fd, offset, count, ret_sent) } +} + +pub(crate) fn sock_shutdown(ctx: FunctionEnvMut, sock: Fd, how: SdFlags) -> Errno { + super::sock_shutdown(ctx, sock, how) +} + +pub(crate) fn resolve( + ctx: FunctionEnvMut, + host: WasmPtr, + host_len: MemoryOffset, + port: u16, + ips: WasmPtr<__wasi_addr_t, MemoryType>, + nips: MemoryOffset, + ret_nips: WasmPtr, +) -> Errno { + super::resolve::(ctx, host, host_len, port, ips, nips, ret_nips) +} diff --git a/lib/wasi/tests/stdio.rs b/lib/wasi/tests/stdio.rs index 34e798ef7..5983b9010 100644 --- a/lib/wasi/tests/stdio.rs +++ b/lib/wasi/tests/stdio.rs @@ -23,6 +23,7 @@ mod sys { #[cfg(feature = "js")] mod js { use wasm_bindgen_test::*; + #[wasm_bindgen_test] fn test_stdout() { super::test_stdout() @@ -72,8 +73,8 @@ fn test_stdout() { "#).unwrap(); // Create the `WasiEnv`. - let mut stdout = Pipe::default(); - let mut wasi_env = WasiState::new("command-name") + let mut pipe = WasiBidirectionalSharedPipePair::new().with_blocking(false); + let wasi_env = WasiState::new("command-name") .args(&["Gordon"]) .stdout(Box::new(pipe.clone())) .finalize(&mut store) @@ -84,7 +85,10 @@ fn test_stdout() { // Let's instantiate the module with the imports. let instance = Instance::new(&mut store, &module, &import_object).unwrap(); + // FIXME: evaluate initialize() vs below two lines wasi_env.initialize(&mut store, &instance).unwrap(); + // let memory = instance.exports.get_memory("memory").unwrap(); + // wasi_env.data_mut(&mut store).set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); @@ -116,8 +120,8 @@ fn test_env() { .env("TEST", "VALUE") .env("TEST2", "VALUE2"); // panic!("envs: {:?}", wasi_state_builder.envs); - let mut wasi_env = wasi_state_builder - .stdout(Box::new(stdout.clone())) + let wasi_env = wasi_state_builder + .stdout(Box::new(pipe.clone())) .finalize(&mut store) .unwrap(); @@ -126,7 +130,11 @@ fn test_env() { // Let's instantiate the module with the imports. let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - wasi_env.initialize(&mut store, &instance).unwrap(); + + // FIXME: evaluate initialize() vs below two lines + // wasi_env.initialize(&mut store, &instance).unwrap(); + let memory = instance.exports.get_memory("memory").unwrap(); + wasi_env.data_mut(&mut store).set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); @@ -143,11 +151,7 @@ fn test_stdin() { let module = Module::new(&store, include_bytes!("stdin-hello.wasm")).unwrap(); // Create the `WasiEnv`. - let mut stdin = Pipe::new(); - let mut wasi_env = WasiState::new("command-name") - .stdin(Box::new(stdin.clone())) - .finalize(&mut store) - .unwrap(); + let mut pipe = WasiBidirectionalSharedPipePair::new().with_blocking(false); // Write to STDIN let buf = "Hello, stdin!\n".as_bytes().to_owned(); @@ -163,7 +167,11 @@ fn test_stdin() { // Let's instantiate the module with the imports. let instance = Instance::new(&mut store, &module, &import_object).unwrap(); + + // FIXME: evaluate initialize() vs below lines wasi_env.initialize(&mut store, &instance).unwrap(); + // let memory = instance.exports.get_memory("memory").unwrap(); + // wasi_env.data_mut(&mut store).set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap();