Commit Graph

112 Commits

Author SHA1 Message Date
Crypt Keeper
3d5b6d609a implements lstat and fixes inode stat on windows go 1.20 (#1168)
gojs: implements lstat

This implements platform.Lstat and uses it in GOOS=js. Notably,
directory listings need to run lstat on their entries to get the correct
inodes back. In GOOS=js, directories are a fan-out of names, then lstat.

This also fixes stat for inodes on directories. We were missing a test
so we didn't know it was broken on windows. The approach used now is
reliable on go 1.20, and we should suggest anyone using windows to
compile with go 1.20.

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-02-28 07:20:31 +08:00
Crypt Keeper
1e7660fc4f wasi: shares more cached stat info to reduce impact of inode requirement (#1161)
We formerly cached only the directory type, to avoid re-stat'ing the
same directory many times. Since we are there, we can also cache the
inode, which is strictly required by wasi and costly to fetch. Note:
this only affects the directory: its contents still need a potential
fan-out of stats which will be handled in another change.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-25 07:28:45 +08:00
Achille
9ebbb41adb sys.FileTable => descriptor.Table (#1155)
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-02-24 08:37:24 +08:00
Crypt Keeper
bb002c862f wasi: adds platform.Dirent in preparation of inode fetching (#1154)
wasi_snapshot_preview1 recently requires fd_readdir to return actual
inode values. On zero, wasi-libc will call fdstat to retrieve them.

This introduces our own `platform.Dirent` type and `Readdir` function
which a later change will allow fetching of inodes.

See https://github.com/WebAssembly/wasi-libc/pull/345

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-23 18:56:27 +08:00
Crypt Keeper
3a06ae38e7 wasi: manually adds dot and dot-dot directory entries (#1152)
This manually adds dot and dot-dot directory entries discarded by
compilers like Go. Doing so complies with the latest interpretation of
wasi preview1 without forcing us to do the same in preview2 or in
GOOS=js. There's a cost penalty of one stat per directory list, which
will be only measurable when using real file I/O.

This should result in us being able to remove the exclusion here
https://github.com/WebAssembly/wasi-testsuite/pull/55/files#diff-8a3ffd323d75a12f8deb01b053f062876d83dda0b89c1fa24b293cee4195bcfd

See https://github.com/WebAssembly/wasi-testsuite/issues/52

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-23 07:24:05 +08:00
Crypt Keeper
4ca0858e57 sysfs: adds FS.Stat and companions in platform (#1140)
This centralizes filestat logic by making our own `Stat_t` similar to
`syscall.Stat_t`. This exposes utilities in the platform package and
adds a new function `FS.Stat` which avoids having to use `fs.File` to
get the same info. Doing so at the FS abstraction allows us to optimize
how it is implemented internally using portable means (e.g.
`os.StatFile`) or OS-specific means where necessary, e.g. in windows.

This also ensures `platform.OpenFile` returns syscall.Errno and
centralizes error checking with a new `require.EqualErrno` test.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-21 10:13:37 +08:00
Crypt Keeper
3d72f2cb90 wasi: implements sched_yield with sys.Osyield (#1131)
This implements WASI `sched_yield` with `sys.Osyield` that defaults to
return immediately. This is intentionally left without a built-in
alternative as common platforms such as darwin implement
`runtime.osyield` by sleeping for a microsecond. If we implemented that,
user code would be slowed down without a clear reason why.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-15 15:57:24 -10:00
Crypt Keeper
882b764437 sysfs: consolidates errno coersion and maps EAGAIN and EINTR (#1113)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-02-10 14:50:05 +09:00
Crypt Keeper
f18bb221c4 gojs: backfills errno tests and updates links (#1110)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-09 07:38:22 -10:00
Crypt Keeper
8918d73020 ci: supports building with Go 1.20 and raises floor version to 1.18 (#1096)
This moves our floor version to the same we'll release 1.0 with: 1.18.
This is congruent with our version policy which is current-2.

Fixes #921

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-06 17:29:08 +02:00
Takeshi Yoneda
4464d0f4e3 wasi: implements filestatset (#1100)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-02-06 14:22:22 +09:00
Takeshi Yoneda
f719b49d1e wasi: implements fd_renumber (#1095)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-02-03 13:57:52 +09:00
Crypt Keeper
043da0d8b0 wasi: prohibits closing pre-opens (#1085)
See https://github.com/WebAssembly/wasi-testsuite/issues/50

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-31 11:55:12 +02:00
Crypt Keeper
67125fcaa4 wasi: supports rewinding a directory and fixes seek error (#1084)
This allows rewinding a directory by specifying the cookie 0, after
already scrolling a directory. This allows zig and clang functionality
to work which expect this.

This also fixes the case where a directory was allowed to be seeked.
This is prohibited by the current version of wasi-testsuite.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-31 10:22:48 +02:00
Crypt Keeper
a60debc8d2 wasi: implements fd_filestat_set_size and fd_filestat_set_times (#1082)
This implements fd_filestat_set_size and fd_filestat_set_times, which
passes one more test in the rust wasi-testsuite.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-30 19:08:10 +02:00
Crypt Keeper
d04199d1c3 cli,wasi: passes mounts directly as preopens to run rust wasi-testsuite (#1078)
This allows wasi to see mounts as individual preopens instead of
virtualized under a root. (GOOS=js doesn't use pre-opens so it still
sees a virtual root). This allows us to progress wasi-testsuite rust
tests, but acknowledges a current glitch in zig support, which is
tracked separately as #1077

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-30 08:11:16 +02:00
Crypt Keeper
574b2a70ab wasi: prepares for native support of preopens (#1067)
This makes all the code changes necessary to enable multiple pre-opens
once #1077 is fixed.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-29 11:31:40 +02:00
Crypt Keeper
cc68f8ee12 fs: adds FSConfig to replace experimental writefs (#1061)
This adds a new top-level type FSConfig, which is configured via
`ModuleConfig.WithFSConfig(fcfg)`. This implements read-only and
read-write directory mounts, something not formally supported before. It
also implements `WithFS` which adapts a normal `fs.FS`. For convenience,
we retain the old `ModuleConfig.WithFS` signature so as to not affect
existing users much. A new configuration for our emerging raw
filesystem, `FSConfig.WithSysfs()` will happen later without breaking
this API.

Here's an example:
```
moduleConfig = wazero.NewModuleConfig().
	// Make the current directory read-only accessible to the guest.
	WithReadOnlyDirMount(".", "/")
	// Make "/tmp/wasm" accessible to the guest as "/tmp".
	WithDirMount("/tmp/wasm", "/tmp")
```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-25 10:09:40 -10:00
Crypt Keeper
cb97d7a488 fs: decouples sysfs from fs.FS and consolidates guest path logic (#1058)
This decouples sysfs.FS from fs.FS by introducing a temporary type
FSHolder, which will be removed when we top-level FSConfig (shortly).

This further reduces complexity by consolidating guest path
configuration into the only type that uses it: CompositeFS.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-23 17:49:51 -10:00
Crypt Keeper
2a584a8937 fs: renames internal syscallfs package to sysfs and notes RATIONALE (#1056)
It will help for us to rename earlier vs later, and syscallfs will be
laborious, especially after we introduce an FSConfig type and need to
declare a method name that differentiates from normal fs.FS. e.g. WithFS
vs WithSysFS reads nicer than WithSyscallFS, and meanwhile sys is
already a public package.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-23 11:11:35 +08:00
Crypt Keeper
319d6cca62 fs: adds base UnimplementedFS type and unwraps PathError (#1046)
This reduces some boilerplate by extracting UnimplementedFS from the
existing FS implementations, such that it returns ENOSYS. This also
removes inconsistency where some methods on FS returned syscall.Errno
and others PathError.

Note: this doesn't get rid of all PathError, yet. We still need to
create a syscallfs.File type which would be able to do that. This is
just one preliminary cleanup before refactoring out the `fs.FS`
embedding from `syscallfs.DS`.

P.S. naming convention is arbitrary, so I took UnimplementedXXX from
grpc. This pattern is used a lot of places, also proxy-wasm-go-sdk, e.g.
`DefaultVMContext`.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-18 09:37:12 -06:00
Crypt Keeper
3cf29f9f76 fs: adds string for better error experience (#1042)
This prepares for pseudo-root when the CLI doesn't provide one by
improving the error messages in general, as well being consistent about
parameter order.

Signed-off-by: Adrian Cole <adrian@tetrate.io>

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-17 10:01:51 -06:00
Crypt Keeper
105cdcdef7 cli: rewrites compositeFS to syscallfs and adds read-only (:ro) mounts (#1030)
This rewrites compositeFS to syscallfs.FS following wasi-sdk preopen
rules. Notably, this allows use of read-only mounts now.

For example,
```bash
$ GOOS=js GOARCH=wasm bin/go test -c -o template.wasm text/template
$ wazero run -mount=src/text/template:/ -mount=/tmp:/tmp template.wasm -test.v
=== RUN   TestExecute
--- PASS: TestExecute (0.07s)
--snip--
```

This is the first step to native WASI handling of multiple pre-opens.
After this change, it is still the case that there's only one pre-open
FD visible to wasm. A later change will make it possible for WASI to see
multiple pre-opens while `GOOS=js` which doesn't use preopens, remains
on a rootFS.

A future PR may need to add a CLI flag to disable escaping directories,
(e.g. make ../.. EINVAL), similar to `fs.FS` in Go. The simplest way to
allow this is to use a host-side RootFS even in WASI, and wrap that with
a `syscallfs` filename filter.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-13 15:50:11 +08:00
Crypt Keeper
bedde6dc7a Clarifies at semantics and preopen semantics in WASI (#1009)
This adds FS.Path which holds the pre-open path currently only used in
WASI. It also fixes a TODO where we didn't know for sure if the FD
parameter for `path_` functions must always be a pre-open. The TL;DR; is
that usually it is, but it may not be (e.g. in our zig-cc example we can
see any directory FD, not just pre-opens).

Finally, this fixes a bug in our path resolution where we mistook paths
like "foo/foo" for "foo" because we only considered basenames instead of
the full path from the pre-open root.

This also makes pre-open directory lookup lazy because I noticed in
Trivy specifically, this is unnecessary for us to do eagerly, as they
change the FS at runtime per-call. In other words, any value from init
time is invalid later.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-05 18:59:55 +08:00
Crypt Keeper
83e4b66659 Consolidates internal code to syscallfs (#1003)
This consolidates internal code to syscallfs, which removes the fs.FS
specific path rules, except when adapting one to syscallfs. For example,
this allows the underlying filesystem to decide if relative paths are
supported or not, as well any EINVAL related concerns.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-04 13:53:53 +08:00
Crypt Keeper
65c7d9dd1b gojs: stubs all remaining filesystem calls to ENOSYS (#1001)
This stubs all remaining syscalls for `GOARCH=wasm GOOS=js` to return
ENOSYS, instead of panic'ing. This allows us to see the parameters it
receives.

For example:
```
==> go.syscall/js.valueCall(fs.truncate(path=/tmp/_Go_TestTruncate135754730,length=0))
<== (err=function not implemented,ok=false)
```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-03 15:54:29 +08:00
Crypt Keeper
4197caa05b Ensures 32-bit platforms build (#996)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-02 11:03:23 +09:00
Crypt Keeper
94491fef0b Implements rename in GOOS=js and WASI (#991)
This implements rename, which is the last function needed to pass TinyGo
os package tests:

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 16:37:28 +08:00
Crypt Keeper
c9868d89cb Removes internal dependency on fs.FS (#987)
As noted in slack, we are unlikley to long term use fs.FS internally.
This ensures we attempt to cast to syscallfs.FS for all I/O by panicing
on fs.Open.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 13:27:54 +08:00
Achille
1db5433154 add internal/sys.FileTable (#975)
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2022-12-31 06:34:25 +08:00
Crypt Keeper
4495979cf0 wasi: fixes open flags (#981)
This fixes and backfills tests for open flags, notably O_CREAT. I
verified this with TinyGo tests, which now proceed when attempting to
create new files.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-30 19:32:18 +08:00
Crypt Keeper
9a4a372642 renames writefs to syscallfs and implements utimes in gojs (#979)
This renames the internal writefs package to syscallfs as it is largely
dependent on syscall signatures. This also implements utimes in gojs.
WASI will be a follow-up change as it requires more infrastructure.
Notably, we also need non-TinyGo tests because TinyGo doesn't yet
support os.Chtimes or corresponding syscalls.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-30 14:18:06 +08:00
Crypt Keeper
6d53a0033a wasi: implements path_(create|remove)_directory path_unlink_file (#976)
This implements path_(create|remove)_directory path_unlink_file in wasi, particularly needed to use TinyGo tests to verify our interpretation of WASI. Use of this requires the experimental `writefs.DirFS`.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-30 07:30:21 +08:00
Crypt Keeper
3f578ddac3 fs: splits unlink and rmdir from remove (#973)
This splits unlink and rmdir from remove, as it is not only more precise
in GOOS=js, but it is also needed to implement wasi. I verified this
works by running go unit tests with logging.

```
==> go.syscall/js.valueCall(fs.open(name=/tmp/TestErrIsNotExist1062486353,flags=,perm=----------))
<== (err=<nil>,fd=10)
==> go.syscall/js.valueCall(fs.fstat(fd=10))
<== (err=<nil>,stat={isDir=true,mode=-rwx------,size=96,mtimeMs=1672285985206})
==> go.syscall/js.valueCall(fs.readdir(name=/tmp/TestErrIsNotExist1062486353))
<== (err=<nil>,dirents=&{[001]})
==> go.syscall/js.valueCall(fs.unlink(path=/tmp/TestErrIsNotExist1062486353/001))
<== (err=is a directory,ok=true)
==> go.syscall/js.valueCall(fs.rmdir(path=/tmp/TestErrIsNotExist1062486353/001))
<== (err=<nil>,ok=false)
```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 15:39:45 +08:00
Crypt Keeper
07a814a105 Exposes experimental writefs.DirFS, but hides implementation (#972)
The type we use to expose write operations is still evolving. It might
be a single writefs.FS interface, or similar to go where we have an
interface per feature (e.g. writefs.MkdirFS). These choices are all
implementation details for DirFS and won't be settled before the end of
the month version cutoff. Instead, this only exposes the ability to
create a DirFS, not an arbitrary implementation of writefs.FS. This does
so by making `writefs.FS` an internal type.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 10:39:04 +08:00
Crypt Keeper
15dc3d7d37 Adds experimental write support and implements on gojs (#970)
This adds writefs.FS, allowing functions to create and delete files.
This begins by implementing them on `GOARCH=js GOOS=wasm`. The current
status is a lot farther than before, even if completing write on WASI is
left for a later PR (possibly by another volunteer).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-28 19:49:46 +08:00
Crypt Keeper
b02b516807 wasi: allows closing stdio file descriptors (#954)
Allows wasm to close stdio file descriptors

This allows wasm to close stdio file descriptors such as STDOUT(1).
This will not close the underlying host resource as that would break a
lot of folks doing logging to the console.

Fixes #953

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-22 08:01:13 +08:00
Crypt Keeper
407f3ea3c0 wasi: detect if stdio are char devices instead of assuming (#935)
This uses ioctl syscalls or appropriate alternative, to detect if
stdin/out/err are character devices or not. This caches the result, to
ensure performance is ok at runtime as executing stat can approach
microsecond overhead.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-16 16:06:54 +09:00
Crypt Keeper
126bd9050d Removes context parameter from instruction-scoped operations (#923)
We originally had a `context.Context` for anything that might be
traced, but it turned out to be only useful for lifecycle and host functions.

For instruction-scoped aspects like memory updates, a context parameter is too
fine-grained and also invisible in practice. For example, most users will use
the compiler engine, and its memory, global or table access will never use go's
context.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-14 16:08:07 +09:00
Crypt Keeper
0ed4002549 Removes experimental.WithFS (#922)
This removes the ability to override the current file system with Go
context, allowing us to simplify common paths and improve performance.

The context override was only used once in GitHub, in Trivy, and we
found another way to do that without it.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-14 15:00:17 +09:00
Crypt Keeper
2e13f57f56 wasi: enforce fd_preXXX functions only work on pre-opened files (#919)
At the moment, the only pre-open support we have is the file system
itself (root a.k.a. / or file-descriptor 3). We may in the future add
the ability to pre-open sockets, but in any case, this is where we are
today.

This change hardens logic around fd_preXXX functions, ensuring they only
work on actual pre-opens. This also fixes the path returned in filestat
as we sometimes returned a full path, when typically the basename is the
only part that can be returned.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-13 16:42:53 +09:00
Crypt Keeper
3b70504f3f wasi: ensure someone can tell if root is a real file (#918)
`os.DirFS` ironically doesn't implement `fs.ReadDirFS`, so we cannot
open a directory this way. This blindly attempts to open "." regardless
of if the `fs.FS` implementation is a `fs.ReadDirFS` or not, and if
successful, enforces that the file returned is a directory. If not, a
fake directory is returned.

Doing so allows real stat to be returned for root, and also a chance to
know if a filesystem configured is real or not. Later, we'll need this
to implement open flags.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-13 13:50:00 +09:00
Crypt Keeper
ce62d77ef0 wasi: allows stat on root file descriptor (3) (#917)
Before, we didn't allow a real stat on the root file descriptor. Now,
those that pass fs.ReadDirFS will return the stat of the root file
(which is implemented by a open against ".").

This also simplifies logic as we always have a file representing root,
even if faked.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-13 11:00:05 +09:00
Crypt Keeper
3dabad8c16 wasi: skips fd allocation on path_filestat_get and backfills benchmarks (#914)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-12 16:17:29 +09:00
Crypt Keeper
6f30a42828 wasi: optimizes args/environ parsing (#885)
While most compilers will only read args/environ once, tools like WAGI
make heavy use of environment, possibly dozens of long variables. This
optimizes both args and environ for this reason and also to setup for
optimizing other functions.

Here are the notable changes:
* eagerly coerce to byte slices instead of strings
* re-use null terminated length for writing values
* avoid loops that call mem.WriteXXX internally

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-05 11:07:51 +08:00
Crypt Keeper
b4f3371a16 wasi: adds fd_readdir (#865)
This adds an implementation of `fd_readdir` for WASI, which ensures a
very large directory is not kept in host memory until its directory is
closed.

Original implementation and test data are with thanks from @jerbob92.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
Co-authored-by: jerbob92 <jerbob92@users.noreply.github.com>
2022-12-01 10:19:21 +08:00
Crypt Keeper
8990932a12 wasi: adds path_filestat_get (#858)
This adds path_filestat_get which is needed for PDFium and zig's
fstatatWasi.

aea617c60b/lib/std/os.zig (L4171)


Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: jerbob92 <jerbob92@users.noreply.github.com>
2022-11-25 14:49:14 +07:00
Crypt Keeper
329ccca6b1 Switches from gofmt to gofumpt (#848)
This switches to gofumpt and applies changes, as I've noticed working
in dapr (who uses this) that it finds some things that are annoying,
such as inconsistent block formatting in test tables.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-11-09 05:48:24 +01:00
Crypt Keeper
d108ce4c43 Restores ability to define host functions w/o context via reflection (#832)
This restores the ability to leave out the initial context parameter
when defining functions with reflection. This is important because some
projects are porting from a different library to wazero, and all the
alternatives are not contextualized.

For example, this project is porting envoy host functions, and the
original definitions (in mosn) don't have a context parameter. By being
lenient, they can migrate easier.

See 6b813482b6/pkg/proxywasm/wazero/imports_v1.go

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-10-28 12:44:12 -07:00
Crypt Keeper
1cbb496c26 Stops using "ex." to abbreviate "for example" (#827)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-10-24 11:51:48 +09:00