Refactor WASI preopened files
I realized that in C/Rust you can casually use the open system call and things just... work. That seemed surprising to me, since all WASI gives us is path_open, similar to openat, not open. I thought open was impossible with WASI. That said, I did some digging into wasi-libc's implementation of open. It's a couple layers deep, but you can find the important bit here: https://github.com/WebAssembly/wasi-libc/blob/659ff414560721b1660a19685110e484a081c3d4/libc-bottom-half/sources/preopens.c#L212
I don't know if it's documented anywhere, but I've been under the assumption (and it seems further documented in code here) that preopened directories are numbered starting at descriptor 3 and going up from there, but descriptors obtained after the preopened ones are random. wasi-libc just scans descriptors until it hits a bad one to find all of the preopens, and then when open is called it tries to open files relative to all of the preopened dirs.
We don't yet have an implementation of open (that would probably exist in higher-level file API) but sys/file provides cwdfd which points at where the first preopened dir would be. The Grain CLI always preopens the current directory, but for other runtimes it's a bit misleading as you would have to also preopen that directory to make it work.
Here some options that I think make sense:
- Just have
sys/fileprovide anopenutility and get rid ofcwdfd. This is sort of nice since we'd just have a useful system call insys/file, especially since it deals with some fairly low-level behavior, and often what people are expecting. I dislike it because I see all of thesyslibraries as pure WASI and this would stray from that. - Get rid of
cwdfd, but add apreopenedutility:
let preopened = idx => {
// skip stdin, stdout, stderr
let fd = idx + 3
// validate that the preopen is good
// ... call wasi fd_prestat etc
Ok(FileDescriptor(fd))
}
This lets you ask for a preopened directory, positionally.
3. Get rid of cwdfd, but add a getPreopenedDirectories utility. Similar to the preopened utility, but provides you with a list.
4. Get rid of cwdfd, ignore any preopen utility nonsense. Just implement the high-level API, and if anyone is trying to do something low level they can just name the file descriptors themselves.
I think the answer is 2 + high-level API.