sausage-vfs: review fixes (fallible growth, symlink flags, stream cancel, sized reads, timestamps, error kinds, linker shadowing)
API: Layer::stat(path, follow), Layer::readlink, Open::follow, Stat::symlink and Entry::symlink. Process::idle documents the shutdown order: abort, await the task, await idle, release locks.
This commit is contained in:
+63
-4
@@ -55,6 +55,14 @@ async fn run(topic: &str, shared: Arc<Memory>) {
|
||||
let (engine, component) = guest();
|
||||
let world = tempfile::tempdir().unwrap();
|
||||
std::fs::create_dir(world.path().join("tmp")).unwrap();
|
||||
let outside = tempfile::tempdir().unwrap();
|
||||
if topic == "review_links" {
|
||||
std::fs::create_dir(world.path().join("target")).unwrap();
|
||||
std::fs::write(world.path().join("target/keep"), b"keep").unwrap();
|
||||
std::fs::write(outside.path().join("secret"), b"secret").unwrap();
|
||||
std::os::unix::fs::symlink("target", world.path().join("link")).unwrap();
|
||||
std::os::unix::fs::symlink(outside.path(), world.path().join("outside-link")).unwrap();
|
||||
}
|
||||
let mut mounts = Mounts::default();
|
||||
mounts.mount(
|
||||
"/",
|
||||
@@ -73,13 +81,20 @@ async fn run(topic: &str, shared: Arc<Memory>) {
|
||||
table: &mut s.table,
|
||||
})
|
||||
.unwrap();
|
||||
let mut wasi = WasiCtxBuilder::new();
|
||||
wasi.inherit_stdio().env("VFS_TOPIC", topic);
|
||||
if topic == "review_preopen" {
|
||||
wasi.preopened_dir(
|
||||
world.path(),
|
||||
"/native",
|
||||
wasmtime_wasi::filesystem::FsPerms::ReadWrite,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
let mut store = Store::new(
|
||||
engine,
|
||||
State {
|
||||
wasi: WasiCtxBuilder::new()
|
||||
.inherit_stdio()
|
||||
.env("VFS_TOPIC", topic)
|
||||
.build(),
|
||||
wasi: wasi.build(),
|
||||
table: ResourceTable::new(),
|
||||
fs: Adapter::new(mounts),
|
||||
},
|
||||
@@ -150,3 +165,47 @@ async fn sqlite_transactions() {
|
||||
async fn named_temporary_files() {
|
||||
isolated("tempfile").await;
|
||||
}
|
||||
|
||||
/// Stream drop preserves writes and small reads observe later mutations.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn review_streams() {
|
||||
isolated("review_streams").await;
|
||||
}
|
||||
|
||||
/// Timestamp conversion reports overflow and accepts directories.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn review_times() {
|
||||
isolated("review_times").await;
|
||||
}
|
||||
|
||||
/// Path errors distinguish trailing slashes, busy roots, and ordinary files.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn review_paths() {
|
||||
isolated("review_paths").await;
|
||||
}
|
||||
|
||||
/// Symlink traversal does not delete targets or escape the host root.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn review_links() {
|
||||
isolated("review_links").await;
|
||||
}
|
||||
|
||||
/// The guest sees only the virtual root preopen.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn review_preopen() {
|
||||
isolated("review_preopen").await;
|
||||
}
|
||||
|
||||
/// Adding the adapter restores duplicate-import errors on the caller's linker.
|
||||
#[test]
|
||||
fn linker_shadowing_is_reset() {
|
||||
let engine = Engine::default();
|
||||
let mut linker = Linker::<State>::new(&engine);
|
||||
wasmtime_wasi::p2::add_to_linker_async(&mut linker).unwrap();
|
||||
adapter::add_to_linker(&mut linker, |s| View {
|
||||
adapter: &mut s.fs,
|
||||
table: &mut s.table,
|
||||
})
|
||||
.unwrap();
|
||||
assert!(wasmtime_wasi::p2::add_to_linker_async(&mut linker).is_err());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user