bytecodealliance / bytecodealliance/wasmtime

Windows symlink oddness

Open
#12,172 2 comments 0 reactions 0 assignees View on GitHub
bug wasi wasi:impl wasi:tests
Dominant language
Rust
Stars
18.6k
Forks
1.8k
Avg merge
1d 19h
Merged PRs (30d)
121

Description

This simple test fails on Windows:

```rust
use std::process;
extern crate wit_bindgen;

wit_bindgen::generate!({
inline: r"
package test:test;

world test {
include wasi:filesystem/imports@0.3.0-rc-2025-09-16;
include wasi:cli/command@0.3.0-rc-2025-09-16;
}
",
additional_derives: [PartialEq, Eq, Hash, Clone],
// Work around https://github.com/bytecodealliance/wasm-tools/issues/2285.
features:["clocks-timezone"],
generate_all
});

async fn test_symlink() {
match &wasi::filesystem::preopens::get_directories()[..] {
[(dir, _)] => {
dir.symlink_at("..".to_string(), "t".to_string())
.await
.unwrap();
dir.unlink_file_at("t".to_string()).await.unwrap();
}
[..] => {
eprintln!("usage: run with one open dir");
process::exit(1)
}
}
}

struct Component;
export!(Component);
impl exports::wasi::cli::run::Guest for Component {
async fn run() -> Result<(), ()> {
test_symlink().await;
Ok(())
}
}

fn main() {
unreachable!("main is a stub");
}
```

The issue is that creating a symlink to `..` doesn't work and fails with `EPERM`, whereas on POSIX platforms any permission check is only made when dereferencing the symlink.

Similarly, `ln_s("does-not-exist".to_string(), "whatever".to_string).await.unwrap()` fails on Windows with `ENOENT`. I can make a symlink to a file that does exist, however. I only tested via CI, on https://github.com/WebAssembly/wasi-testsuite/pull/195.

What's going on? Is this another area of WASI in which we have to relax the requirements?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.