Skip to content

Commit

Permalink
[wasi] Update wasi runtime to use preopens properly
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer committed Nov 8, 2024
1 parent a703c0d commit 6ed46eb
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 4 deletions.
16 changes: 16 additions & 0 deletions apps/Cat/Cat.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2022 Ben L. Titzer. All rights reserved.
// See LICENSE for details of Apache 2.0 license.

def main(args: Array<string>) -> int {
for (i = 0; i < args.length; i++) {
var data = System.fileLoad(args[i]);
if (data == null) {
System.puts("cat: ");
System.puts(args[i]);
System.puts(": no such file or directory\n");
} else {
System.puts(data);
}
}
return 0;
}
1 change: 1 addition & 0 deletions apps/Cat/DEPS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

2 changes: 2 additions & 0 deletions apps/Cat/foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Foobartext
Foobartext2
19 changes: 15 additions & 4 deletions rt/wasm-wasi1/System.v3
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ component System {
}
// open a file
def fileOpen(path: string, read: bool) -> int {
var r = wasi_snapshot_preview1.path_open(3, 0, Pointer.atContents(path), path.length, 0, 0, 0, 0, Pointer.atContents(retbuf));
var pre_fd = WasiPreopens.find(path);
if (pre_fd < 0) return -1;
var rights = (1 << if(read, wasi_rights.fd_read, wasi_rights.fd_write).tag) |
(1 << wasi_rights.fd_seek.tag);
var r = wasi_snapshot_preview1.path_open(pre_fd, 0, Pointer.atContents(path), path.length, 0, rights, rights, 0, Pointer.atContents(retbuf));
if (r != 0) return -1;
return Pointer.atContents(retbuf).load<int>();
}
Expand Down Expand Up @@ -47,13 +51,14 @@ component System {
def fileLoad(path: string) -> Array<byte> {
var fd = fileOpen(path, true);
if (fd < 0) return null;
var r = wasi_snapshot_preview1.fd_seek(fd, 0, wasi_whence.END.tag, Pointer.atContents(retbuf));
var bufptr = aligned_sizeptr();
var r = wasi_snapshot_preview1.fd_seek(fd, 0, wasi_whence.END.tag, bufptr);
if (r < 0) {
wasi_snapshot_preview1.fd_close(fd);
return null;
}
var len = int.!(Pointer.atContents(retbuf).load<u64>());
r = wasi_snapshot_preview1.fd_seek(fd, 0, wasi_whence.SET.tag, Pointer.atContents(retbuf));
var len = int.!(bufptr.load<u64>());
r = wasi_snapshot_preview1.fd_seek(fd, 0, wasi_whence.SET.tag, bufptr);
if (r < 0) {
wasi_snapshot_preview1.fd_close(fd);
return null;
Expand Down Expand Up @@ -134,6 +139,7 @@ component System {
def STDIN = 0;
def STDOUT = 1;
def STDERR = 2;
def MAX_PREOPEN = 10;

// @thread-local @lazy buffer for write integers and chars to System.out
def numbuf = Array<byte>.new(16);
Expand Down Expand Up @@ -164,3 +170,8 @@ def fs_read(fd: int, data: Pointer, len: int) -> int {
var r = wasi_snapshot_preview1.fd_read(fd, p, 1, sizeptr);
return if(r == 0, sizeptr.load<int>());
}
def aligned_sizeptr() -> Pointer {
var addr = Pointer.atContents(retbuf) - Pointer.NULL;
addr = (addr + 7) & ~7;
return Pointer.NULL + addr;
}
50 changes: 50 additions & 0 deletions rt/wasm-wasi1/WasiPreopens.v3
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2024 Virgil authors. All rights reserved.
// See LICENSE for details of Apache 2.0 license.

def FIRST_PREOPEN = 3;
def MAX_PREOPENS = 10;
var preopenCount = -1;
var relativeFd = -1;
var preopens = Array<(string, int)>.new(MAX_PREOPENS);
def buf = Array<int>.new(2);

// Scans the preopens and populates the array of (name, fd) pairs.
def init() {
preopenCount = 0;
for (i = FIRST_PREOPEN; i < (FIRST_PREOPEN + MAX_PREOPENS); i++) {
var r = wasi_snapshot_preview1.fd_prestat_get(i, Pointer.atContents(buf));
if (r != 0) break;
var len = buf[1];
if (len == 0) break;
var name = Array<byte>.new(len);
r = wasi_snapshot_preview1.fd_prestat_dir_name(i, Pointer.atContents(name), name.length);
if (r != 0) break;
preopens[preopenCount++] = (name, i);
if (len == 1 && name[0] == '.') relativeFd = i;
}
}

// Lazily scans WASI pre-opened directories and matches paths to preopens.
component WasiPreopens {
def find(path: string) -> int {
if (path.length == 0) return -1;
if (preopenCount < 0) init();
// If the path is not absolute and there is a '.' preopened, use that.
if (path[0] != '/' && relativeFd >= 0) return relativeFd;
// Search for an absolute or relative match
for (i < preopenCount) {
var t = preopens[i];
if (checkPrefix(t.0, path)) return t.1;
}
return -1;
}
}
def checkPrefix(prefix: string, path: string) -> bool {
if (prefix.length > path.length) return false;
for (i < prefix.length) {
if (path[i] != prefix[i]) return false;
}
if (prefix[prefix.length - 1] == '/') return true;
if (path.length > prefix.length && path[prefix.length] == '/') return true;
return false;
}

0 comments on commit 6ed46eb

Please sign in to comment.