This forces all syscall functions, notably filesystem, to return numeric
codes as opposed to mapping in two different areas. The result of this
change is better consolidation in call sites of `sysfs.FS`, while
further refactoring is needed to address consolidation of file errors.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This forces all syscall functions, notably filesystem, to return numeric
codes as opposed to mapping in two different areas. The result of this
change is better consolidation in call sites of `sysfs.FS`, while
further refactoring is needed to address consolidation of file errors.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This returns stat as a value instead of a pointer param. This is both
more efficient and faster. It is also more efficient than returning a
pointer to a stat.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This adds `gojs.WithOSUser` which passes through current user IDs so
that GOOS=js compiled wasm can read them. This also adds support for
reading back the uid and gid on files. In summary, this passes
`os.TestChown` except on windows where it will not work due to lack of
support.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
In order to support more configuration, we should stop using context as
it is getting gnarly.
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
When compiled to `GOOS=js`, wasm does not maintain the working
directory: it is defined by the host. While not explicitly documented,
`os.TestDirFSRootDir` in Go suggests the working directory must be valid
to pass (literally the directory holding the file).
This adds an experimental CLI flag that gives the initial working
directory. This is experimental because while GOOS=js uses this, current
WASI compilers will not, as they maintain working directory in code
managed by wasi-libc, or as a convention (e.g. in Zig).
It is not yet known if wasi-cli will maintain working directory
externally or not.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Many tests failed in gojs due to needing to be resolved against the CWD,
which is atypically stored host side. This fixes that and renames the
"exit" scope to "proc" so we can use it for other proc concerns besides
exit.
This reduces known failures on GOOS=js from 23 to 14:
```bash
$ wazero run -mount=/usr/local/go/src/os:/:ro -mount=/tmp:/tmp -mount=/etc:/etc:ro -mount=/usr:/usr:ro -mount=/dev:/dev:ro os.wasm |grep '^--- FAIL'|wc -l
14
```
See #1222
Signed-off-by: Adrian Cole <adrian@tetrate.io>
platform: Allows sysfs to implement utimesns natively
This moves away from `syscall.UtimesNano` as it has intentionally
avoided common features in POSIX, such as handling UTIME_NOW and
UTIME_OMIT. When we eventually expose this API, users will be free to
override `UTIME_NOW` with a fake clock, possibly the same that was
supplied to wazero's `ModuleConfig`.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
Go has a test that forces us to handle Mkdir with zero as its
permissions. In GOOS=js, the result of fs.mkdir is a file descriptor,
and to open that, we can't use literally 0. Hence, to solve this we need
to coerce 0 to 0500 in GOOS=js.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This implements `platform.UtimesFile` which is similar to futimes.
Before, we were using path-based functionality even though the call site
was for a file descriptor.
Note: right now, there's no obvious code in Go to invoke the `futimens`
syscall. This means non-windows isn't implemented at nanos granularity,
so ends up falling back to the path based option.
Finally, this removes tests for the seldom supported updates with
negative epoch time. There's little impact to this as setting times on
files before 1970 isn't a typical use case.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This finishes the last remaining syscalls in `GOOS=js`. After this is
merged, further bugs are easier to hunt down as we know ENOSYS is not
expected on writeable file systems.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Before, our README said gojs `GOOS=js compiled wasm` was experimental.
However, as we head to 1.0 we should be more explicit about that.
When we started gojs, there was no likely future where `GOOS=wasi` would
happen in the standard go compiler. This has changed, so we'll only keep
the gojs package around until wasi is usable for two Go releases. Being
in an experimental package helps others know to watch out for this.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This implements the last remaining link functions using the same logic
as WASI. In doing so, this changes the signature for FS.ReadLink to be
more similar to the rest of the functions. Particularly, it stops
reading the result into a buffer.
After this, the only syscalls left to implement in gojs are chown.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
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>
This handles EOF even if current and possibly future wasi don't have a
way to propagate an EOF signal. This is mainly to match up with go
semantics and ensure we don't have any error conditions (by adding
tests).
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This adds `platform.Readdirnames` which is preparation work before doing
something similar for reading the directory. We use this in gojs as it
doesn't actually need dirents, rather just names.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
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>
This adds `FS.Chmod` and implements it for `GOOS=js`. This function
isn't defined in WASI snapshot01, but it is in `wasi-filesystem`, e.g.
`change-file-permissions-at`.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This implements `fd_datasync` in WASI, falling back to normal
`File.Sync` when unsupported. This also backfills missing usage of sync
in GOOS=js. Finally, this updates the WASI status chart based on what's
implemented.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
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>
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>
This allows you to specify the memory scope amongst existing logging scopes, both in API and the CLI.
e.g for the CLI.
```bash
$ wazero run --hostlogging=memory,filesystem --mount=.:/:ro cat.wasm
```
e.g. for Go
```go
loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{},
logging.NewHostLoggingListenerFactory(&log, logging.LogScopeMemory|logging.LogScopeFilesystem))
```
This is helpful for emscripten and gojs which have memory reset
callbacks. This will be much more interesting once #1075 is implemented.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This allows you to specify the exit scope amongst existing logging scopes, both in API and the CLI.
e.g for the CLI.
```bash
$ wazero run --hostlogging=exit,filesystem --mount=.:/:ro cat.wasm
```
e.g. for Go
```go
loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{},
logging.NewHostLoggingListenerFactory(&log, logging.LogScopeExit|logging.LogScopeFilesystem))
```
This is helpful to know if the wasm called exit or if it exited
implicitly. This is one of the few host functions that exists in three
places: assemblyscript, gojs and wasi.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This allows you to specify the poll scope amongst existing logging scopes, both in API and the CLI.
e.g for the CLI.
```bash
$ wazero run --hostlogging=poll --hostlogging=filesystem --mount=.:/:ro cat.wasm
```
e.g. for Go
```go
loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{},
logging.NewHostLoggingListenerFactory(&log, logging.LogScopePoll|logging.LogScopeFilesystem))
```
This is particularly helpful to understand side-effects of GC. For
example, in `GOOS=js` GC will trigger events and these have been tricky
to troubleshoot in the past.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This is to avoid a collision with an emerging wasi-crypto. They will
have both wasi-random and wasi-crypto
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This allows you to specify multiple logging scopes, both in API and the CLI.
e.g for the CLI.
```bash
$ wazero run --hostlogging=crypto --hostlogging=filesystem --mount=.:/:ro cat.wasm
```
e.g. for Go
```go
loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{},
logging.NewHostLoggingListenerFactory(&log, logging.LogScopeCrypto|logging.LogScopeFilesystem))
```
Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Adrian Cole <adrian@tetrate.io>
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>
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>
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>
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>
This implements stat device and inode for WASI and GOOS=js, though it
does not implement the host side for windows, yet. Doing windows
requires plumbing as the values needed aren't exposed in Go. When we
re-do the syscallfs file type to have a stat method, we can address that
glitch. Meanwhile, I can find no Go sourcebase that does any better,
though the closest is the implementation details of os.SameFile.
I verified this with wasi-testsuite which now passes all but 1 case
which is unrelated (we haven't yet implemented `lseek`).
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This implements WriterAtOffset, which supports WASI `fd_pwrite` and gojs
`fs.write` with offset, which is used to implement `syscall.Pwrite`.
I confirmed this passes the corresponding test in wasi-testsuite as
well.
Signed-off-by: Adrian Cole <adrian@tetrate.io>