summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/experimental
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/experimental')
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go48
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/close.go63
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/experimental.go41
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/features.go15
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/listener.go330
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/memory.go50
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go92
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go98
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/error.go45
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/file.go316
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go292
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go70
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go106
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go13
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go7
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go62
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/time.go10
-rw-r--r--vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go160
18 files changed, 1818 insertions, 0 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go b/vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go
new file mode 100644
index 000000000..443c5a294
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/checkpoint.go
@@ -0,0 +1,48 @@
+package experimental
+
+import (
+ "context"
+
+ "github.com/tetratelabs/wazero/internal/expctxkeys"
+)
+
+// Snapshot holds the execution state at the time of a Snapshotter.Snapshot call.
+type Snapshot interface {
+ // Restore sets the Wasm execution state to the capture. Because a host function
+ // calling this is resetting the pointer to the executation stack, the host function
+ // will not be able to return values in the normal way. ret is a slice of values the
+ // host function intends to return from the restored function.
+ Restore(ret []uint64)
+}
+
+// Snapshotter allows host functions to snapshot the WebAssembly execution environment.
+type Snapshotter interface {
+ // Snapshot captures the current execution state.
+ Snapshot() Snapshot
+}
+
+// EnableSnapshotterKey is a context key to indicate that snapshotting should be enabled.
+// The context.Context passed to a exported function invocation should have this key set
+// to a non-nil value, and host functions will be able to retrieve it using SnapshotterKey.
+//
+// Deprecated: use WithSnapshotter to enable snapshots.
+type EnableSnapshotterKey = expctxkeys.EnableSnapshotterKey
+
+// WithSnapshotter enables snapshots.
+// Passing the returned context to a exported function invocation enables snapshots,
+// and allows host functions to retrieve the Snapshotter using GetSnapshotter.
+func WithSnapshotter(ctx context.Context) context.Context {
+ return context.WithValue(ctx, expctxkeys.EnableSnapshotterKey{}, struct{}{})
+}
+
+// SnapshotterKey is a context key to access a Snapshotter from a host function.
+// It is only present if EnableSnapshotter was set in the function invocation context.
+//
+// Deprecated: use GetSnapshotter to get the snapshotter.
+type SnapshotterKey = expctxkeys.SnapshotterKey
+
+// GetSnapshotter gets the Snapshotter from a host function.
+// It is only present if WithSnapshotter was called with the function invocation context.
+func GetSnapshotter(ctx context.Context) Snapshotter {
+ return ctx.Value(expctxkeys.SnapshotterKey{}).(Snapshotter)
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/close.go b/vendor/github.com/tetratelabs/wazero/experimental/close.go
new file mode 100644
index 000000000..babecaec4
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/close.go
@@ -0,0 +1,63 @@
+package experimental
+
+import (
+ "context"
+
+ "github.com/tetratelabs/wazero/internal/expctxkeys"
+)
+
+// CloseNotifier is a notification hook, invoked when a module is closed.
+//
+// Note: This is experimental progress towards #1197, and likely to change. Do
+// not expose this in shared libraries as it can cause version locks.
+type CloseNotifier interface {
+ // CloseNotify is a notification that occurs *before* an api.Module is
+ // closed. `exitCode` is zero on success or in the case there was no exit
+ // code.
+ //
+ // Notes:
+ // - This does not return an error because the module will be closed
+ // unconditionally.
+ // - Do not panic from this function as it doing so could cause resource
+ // leaks.
+ // - While this is only called once per module, if configured for
+ // multiple modules, it will be called for each, e.g. on runtime close.
+ CloseNotify(ctx context.Context, exitCode uint32)
+}
+
+// ^-- Note: This might need to be a part of the listener or become a part of
+// host state implementation. For example, if this is used to implement state
+// cleanup for host modules, possibly something like below would be better, as
+// it could be implemented in a way that allows concurrent module use.
+//
+// // key is like a context key, stateFactory is invoked per instantiate and
+// // is associated with the key (exposed as `Module.State` similar to go
+// // context). Using a key is better than the module name because we can
+// // de-dupe it for host modules that can be instantiated into different
+// // names. Also, you can make the key package private.
+// HostModuleBuilder.WithState(key any, stateFactory func() Cleanup)`
+//
+// Such a design could work to isolate state only needed for wasip1, for
+// example the dirent cache. However, if end users use this for different
+// things, we may need separate designs.
+//
+// In summary, the purpose of this iteration is to identify projects that
+// would use something like this, and then we can figure out which way it
+// should go.
+
+// CloseNotifyFunc is a convenience for defining inlining a CloseNotifier.
+type CloseNotifyFunc func(ctx context.Context, exitCode uint32)
+
+// CloseNotify implements CloseNotifier.CloseNotify.
+func (f CloseNotifyFunc) CloseNotify(ctx context.Context, exitCode uint32) {
+ f(ctx, exitCode)
+}
+
+// WithCloseNotifier registers the given CloseNotifier into the given
+// context.Context.
+func WithCloseNotifier(ctx context.Context, notifier CloseNotifier) context.Context {
+ if notifier != nil {
+ return context.WithValue(ctx, expctxkeys.CloseNotifierKey{}, notifier)
+ }
+ return ctx
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/experimental.go b/vendor/github.com/tetratelabs/wazero/experimental/experimental.go
new file mode 100644
index 000000000..63fd564da
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/experimental.go
@@ -0,0 +1,41 @@
+// Package experimental includes features we aren't yet sure about. These are enabled with context.Context keys.
+//
+// Note: All features here may be changed or deleted at any time, so use with caution!
+package experimental
+
+import (
+ "github.com/tetratelabs/wazero/api"
+)
+
+// InternalModule is an api.Module that exposes additional
+// information.
+type InternalModule interface {
+ api.Module
+
+ // NumGlobal returns the count of all globals in the module.
+ NumGlobal() int
+
+ // Global provides a read-only view for a given global index.
+ //
+ // The methods panics if i is out of bounds.
+ Global(i int) api.Global
+}
+
+// ProgramCounter is an opaque value representing a specific execution point in
+// a module. It is meant to be used with Function.SourceOffsetForPC and
+// StackIterator.
+type ProgramCounter uint64
+
+// InternalFunction exposes some information about a function instance.
+type InternalFunction interface {
+ // Definition provides introspection into the function's names and
+ // signature.
+ Definition() api.FunctionDefinition
+
+ // SourceOffsetForPC resolves a program counter into its corresponding
+ // offset in the Code section of the module this function belongs to.
+ // The source offset is meant to help map the function calls to their
+ // location in the original source files. Returns 0 if the offset cannot
+ // be calculated.
+ SourceOffsetForPC(pc ProgramCounter) uint64
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/features.go b/vendor/github.com/tetratelabs/wazero/experimental/features.go
new file mode 100644
index 000000000..b2a5b9069
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/features.go
@@ -0,0 +1,15 @@
+package experimental
+
+import "github.com/tetratelabs/wazero/api"
+
+// CoreFeaturesThreads enables threads instructions ("threads").
+//
+// # Notes
+//
+// - The instruction list is too long to enumerate in godoc.
+// See https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md
+// - Atomic operations are guest-only until api.Memory or otherwise expose them to host functions.
+// - On systems without mmap available, the memory will pre-allocate to the maximum size. Many
+// binaries will use a theroetical maximum like 4GB, so if using such a binary on a system
+// without mmap, consider editing the binary to reduce the max size setting of memory.
+const CoreFeaturesThreads = api.CoreFeatureSIMD << 1
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/listener.go b/vendor/github.com/tetratelabs/wazero/experimental/listener.go
new file mode 100644
index 000000000..b2ba1fe83
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/listener.go
@@ -0,0 +1,330 @@
+package experimental
+
+import (
+ "context"
+
+ "github.com/tetratelabs/wazero/api"
+ "github.com/tetratelabs/wazero/internal/expctxkeys"
+)
+
+// StackIterator allows iterating on each function of the call stack, starting
+// from the top. At least one call to Next() is required to start the iteration.
+//
+// Note: The iterator provides a view of the call stack at the time of
+// iteration. As a result, parameter values may be different than the ones their
+// function was called with.
+type StackIterator interface {
+ // Next moves the iterator to the next function in the stack. Returns
+ // false if it reached the bottom of the stack.
+ Next() bool
+ // Function describes the function called by the current frame.
+ Function() InternalFunction
+ // ProgramCounter returns the program counter associated with the
+ // function call.
+ ProgramCounter() ProgramCounter
+}
+
+// FunctionListenerFactoryKey is a context.Context Value key.
+// Its associated value should be a FunctionListenerFactory.
+//
+// Deprecated: use WithFunctionListenerFactory to enable snapshots.
+type FunctionListenerFactoryKey = expctxkeys.FunctionListenerFactoryKey
+
+// WithFunctionListenerFactory registers a FunctionListenerFactory
+// with the context.
+func WithFunctionListenerFactory(ctx context.Context, factory FunctionListenerFactory) context.Context {
+ return context.WithValue(ctx, expctxkeys.FunctionListenerFactoryKey{}, factory)
+}
+
+// FunctionListenerFactory returns FunctionListeners to be notified when a
+// function is called.
+type FunctionListenerFactory interface {
+ // NewFunctionListener returns a FunctionListener for a defined function.
+ // If nil is returned, no listener will be notified.
+ NewFunctionListener(api.FunctionDefinition) FunctionListener
+ // ^^ A single instance can be returned to avoid instantiating a listener
+ // per function, especially as they may be thousands of functions. Shared
+ // listeners use their FunctionDefinition parameter to clarify.
+}
+
+// FunctionListener can be registered for any function via
+// FunctionListenerFactory to be notified when the function is called.
+type FunctionListener interface {
+ // Before is invoked before a function is called.
+ //
+ // There is always one corresponding call to After or Abort for each call to
+ // Before. This guarantee allows the listener to maintain an internal stack
+ // to perform correlations between the entry and exit of functions.
+ //
+ // # Params
+ //
+ // - ctx: the context of the caller function which must be the same
+ // instance or parent of the result.
+ // - mod: the calling module.
+ // - def: the function definition.
+ // - params: api.ValueType encoded parameters.
+ // - stackIterator: iterator on the call stack. At least one entry is
+ // guaranteed (the called function), whose Args() will be equal to
+ // params. The iterator will be reused between calls to Before.
+ //
+ // Note: api.Memory is meant for inspection, not modification.
+ // mod can be cast to InternalModule to read non-exported globals.
+ Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator StackIterator)
+
+ // After is invoked after a function is called.
+ //
+ // # Params
+ //
+ // - ctx: the context of the caller function.
+ // - mod: the calling module.
+ // - def: the function definition.
+ // - results: api.ValueType encoded results.
+ //
+ // # Notes
+ //
+ // - api.Memory is meant for inspection, not modification.
+ // - This is not called when a host function panics, or a guest function traps.
+ // See Abort for more details.
+ After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64)
+
+ // Abort is invoked when a function does not return due to a trap or panic.
+ //
+ // # Params
+ //
+ // - ctx: the context of the caller function.
+ // - mod: the calling module.
+ // - def: the function definition.
+ // - err: the error value representing the reason why the function aborted.
+ //
+ // # Notes
+ //
+ // - api.Memory is meant for inspection, not modification.
+ Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error)
+}
+
+// FunctionListenerFunc is a function type implementing the FunctionListener
+// interface, making it possible to use regular functions and methods as
+// listeners of function invocation.
+//
+// The FunctionListener interface declares two methods (Before and After),
+// but this type invokes its value only when Before is called. It is best
+// suites for cases where the host does not need to perform correlation
+// between the start and end of the function call.
+type FunctionListenerFunc func(context.Context, api.Module, api.FunctionDefinition, []uint64, StackIterator)
+
+// Before satisfies the FunctionListener interface, calls f.
+func (f FunctionListenerFunc) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, stackIterator StackIterator) {
+ f(ctx, mod, def, params, stackIterator)
+}
+
+// After is declared to satisfy the FunctionListener interface, but it does
+// nothing.
+func (f FunctionListenerFunc) After(context.Context, api.Module, api.FunctionDefinition, []uint64) {
+}
+
+// Abort is declared to satisfy the FunctionListener interface, but it does
+// nothing.
+func (f FunctionListenerFunc) Abort(context.Context, api.Module, api.FunctionDefinition, error) {
+}
+
+// FunctionListenerFactoryFunc is a function type implementing the
+// FunctionListenerFactory interface, making it possible to use regular
+// functions and methods as factory of function listeners.
+type FunctionListenerFactoryFunc func(api.FunctionDefinition) FunctionListener
+
+// NewFunctionListener satisfies the FunctionListenerFactory interface, calls f.
+func (f FunctionListenerFactoryFunc) NewFunctionListener(def api.FunctionDefinition) FunctionListener {
+ return f(def)
+}
+
+// MultiFunctionListenerFactory constructs a FunctionListenerFactory which
+// combines the listeners created by each of the factories passed as arguments.
+//
+// This function is useful when multiple listeners need to be hooked to a module
+// because the propagation mechanism based on installing a listener factory in
+// the context.Context used when instantiating modules allows for a single
+// listener to be installed.
+//
+// The stack iterator passed to the Before method is reset so that each listener
+// can iterate the call stack independently without impacting the ability of
+// other listeners to do so.
+func MultiFunctionListenerFactory(factories ...FunctionListenerFactory) FunctionListenerFactory {
+ multi := make(multiFunctionListenerFactory, len(factories))
+ copy(multi, factories)
+ return multi
+}
+
+type multiFunctionListenerFactory []FunctionListenerFactory
+
+func (multi multiFunctionListenerFactory) NewFunctionListener(def api.FunctionDefinition) FunctionListener {
+ var lstns []FunctionListener
+ for _, factory := range multi {
+ if lstn := factory.NewFunctionListener(def); lstn != nil {
+ lstns = append(lstns, lstn)
+ }
+ }
+ switch len(lstns) {
+ case 0:
+ return nil
+ case 1:
+ return lstns[0]
+ default:
+ return &multiFunctionListener{lstns: lstns}
+ }
+}
+
+type multiFunctionListener struct {
+ lstns []FunctionListener
+ stack stackIterator
+}
+
+func (multi *multiFunctionListener) Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, params []uint64, si StackIterator) {
+ multi.stack.base = si
+ for _, lstn := range multi.lstns {
+ multi.stack.index = -1
+ lstn.Before(ctx, mod, def, params, &multi.stack)
+ }
+}
+
+func (multi *multiFunctionListener) After(ctx context.Context, mod api.Module, def api.FunctionDefinition, results []uint64) {
+ for _, lstn := range multi.lstns {
+ lstn.After(ctx, mod, def, results)
+ }
+}
+
+func (multi *multiFunctionListener) Abort(ctx context.Context, mod api.Module, def api.FunctionDefinition, err error) {
+ for _, lstn := range multi.lstns {
+ lstn.Abort(ctx, mod, def, err)
+ }
+}
+
+type stackIterator struct {
+ base StackIterator
+ index int
+ pcs []uint64
+ fns []InternalFunction
+}
+
+func (si *stackIterator) Next() bool {
+ if si.base != nil {
+ si.pcs = si.pcs[:0]
+ si.fns = si.fns[:0]
+
+ for si.base.Next() {
+ si.pcs = append(si.pcs, uint64(si.base.ProgramCounter()))
+ si.fns = append(si.fns, si.base.Function())
+ }
+
+ si.base = nil
+ }
+ si.index++
+ return si.index < len(si.pcs)
+}
+
+func (si *stackIterator) ProgramCounter() ProgramCounter {
+ return ProgramCounter(si.pcs[si.index])
+}
+
+func (si *stackIterator) Function() InternalFunction {
+ return si.fns[si.index]
+}
+
+// StackFrame represents a frame on the call stack.
+type StackFrame struct {
+ Function api.Function
+ Params []uint64
+ Results []uint64
+ PC uint64
+ SourceOffset uint64
+}
+
+type internalFunction struct {
+ definition api.FunctionDefinition
+ sourceOffset uint64
+}
+
+func (f internalFunction) Definition() api.FunctionDefinition {
+ return f.definition
+}
+
+func (f internalFunction) SourceOffsetForPC(pc ProgramCounter) uint64 {
+ return f.sourceOffset
+}
+
+// stackFrameIterator is an implementation of the experimental.stackFrameIterator
+// interface.
+type stackFrameIterator struct {
+ index int
+ stack []StackFrame
+ fndef []api.FunctionDefinition
+}
+
+func (si *stackFrameIterator) Next() bool {
+ si.index++
+ return si.index < len(si.stack)
+}
+
+func (si *stackFrameIterator) Function() InternalFunction {
+ return internalFunction{
+ definition: si.fndef[si.index],
+ sourceOffset: si.stack[si.index].SourceOffset,
+ }
+}
+
+func (si *stackFrameIterator) ProgramCounter() ProgramCounter {
+ return ProgramCounter(si.stack[si.index].PC)
+}
+
+// NewStackIterator constructs a stack iterator from a list of stack frames.
+// The top most frame is the last one.
+func NewStackIterator(stack ...StackFrame) StackIterator {
+ si := &stackFrameIterator{
+ index: -1,
+ stack: make([]StackFrame, len(stack)),
+ fndef: make([]api.FunctionDefinition, len(stack)),
+ }
+ for i := range stack {
+ si.stack[i] = stack[len(stack)-(i+1)]
+ }
+ // The size of function definition is only one pointer which should allow
+ // the compiler to optimize the conversion to api.FunctionDefinition; but
+ // the presence of internal.WazeroOnlyType, despite being defined as an
+ // empty struct, forces a heap allocation that we amortize by caching the
+ // result.
+ for i, frame := range stack {
+ si.fndef[i] = frame.Function.Definition()
+ }
+ return si
+}
+
+// BenchmarkFunctionListener implements a benchmark for function listeners.
+//
+// The benchmark calls Before and After methods repeatedly using the provided
+// module an stack frames to invoke the methods.
+//
+// The stack frame is a representation of the call stack that the Before method
+// will be invoked with. The top of the stack is stored at index zero. The stack
+// must contain at least one frame or the benchmark will fail.
+func BenchmarkFunctionListener(n int, module api.Module, stack []StackFrame, listener FunctionListener) {
+ if len(stack) == 0 {
+ panic("cannot benchmark function listener with an empty stack")
+ }
+
+ ctx := context.Background()
+ def := stack[0].Function.Definition()
+ params := stack[0].Params
+ results := stack[0].Results
+ stackIterator := &stackIterator{base: NewStackIterator(stack...)}
+
+ for i := 0; i < n; i++ {
+ stackIterator.index = -1
+ listener.Before(ctx, module, def, params, stackIterator)
+ listener.After(ctx, module, def, results)
+ }
+}
+
+// TODO: the calls to Abort are not yet tested in internal/testing/enginetest,
+// but they are validated indirectly in tests which exercise host logging,
+// like Test_procExit in imports/wasi_snapshot_preview1. Eventually we should
+// add dedicated tests to validate the behavior of the interpreter and compiler
+// engines independently.
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/memory.go b/vendor/github.com/tetratelabs/wazero/experimental/memory.go
new file mode 100644
index 000000000..e379bf053
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/memory.go
@@ -0,0 +1,50 @@
+package experimental
+
+import (
+ "context"
+
+ "github.com/tetratelabs/wazero/internal/expctxkeys"
+)
+
+// MemoryAllocator is a memory allocation hook,
+// invoked to create a LinearMemory.
+type MemoryAllocator interface {
+ // Allocate should create a new LinearMemory with the given specification:
+ // cap is the suggested initial capacity for the backing []byte,
+ // and max the maximum length that will ever be requested.
+ //
+ // Notes:
+ // - To back a shared memory, the address of the backing []byte cannot
+ // change. This is checked at runtime. Implementations should document
+ // if the returned LinearMemory meets this requirement.
+ Allocate(cap, max uint64) LinearMemory
+}
+
+// MemoryAllocatorFunc is a convenience for defining inlining a MemoryAllocator.
+type MemoryAllocatorFunc func(cap, max uint64) LinearMemory
+
+// Allocate implements MemoryAllocator.Allocate.
+func (f MemoryAllocatorFunc) Allocate(cap, max uint64) LinearMemory {
+ return f(cap, max)
+}
+
+// LinearMemory is an expandable []byte that backs a Wasm linear memory.
+type LinearMemory interface {
+ // Reallocates the linear memory to size bytes in length.
+ //
+ // Notes:
+ // - To back a shared memory, Reallocate can't change the address of the
+ // backing []byte (only its length/capacity may change).
+ Reallocate(size uint64) []byte
+ // Free the backing memory buffer.
+ Free()
+}
+
+// WithMemoryAllocator registers the given MemoryAllocator into the given
+// context.Context.
+func WithMemoryAllocator(ctx context.Context, allocator MemoryAllocator) context.Context {
+ if allocator != nil {
+ return context.WithValue(ctx, expctxkeys.MemoryAllocatorKey{}, allocator)
+ }
+ return ctx
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go
new file mode 100644
index 000000000..0b997cb8f
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/dir.go
@@ -0,0 +1,92 @@
+package sys
+
+import (
+ "fmt"
+ "io/fs"
+
+ "github.com/tetratelabs/wazero/sys"
+)
+
+// FileType is fs.FileMode masked on fs.ModeType. For example, zero is a
+// regular file, fs.ModeDir is a directory and fs.ModeIrregular is unknown.
+//
+// Note: This is defined by Linux, not POSIX.
+type FileType = fs.FileMode
+
+// Dirent is an entry read from a directory via File.Readdir.
+//
+// # Notes
+//
+// - This extends `dirent` defined in POSIX with some fields defined by
+// Linux. See https://man7.org/linux/man-pages/man3/readdir.3.html and
+// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html
+// - This has a subset of fields defined in sys.Stat_t. Notably, there is no
+// field corresponding to Stat_t.Dev because that value will be constant
+// for all files in a directory. To get the Dev value, call File.Stat on
+// the directory File.Readdir was called on.
+type Dirent struct {
+ // Ino is the file serial number, or zero if not available. See Ino for
+ // more details including impact returning a zero value.
+ Ino sys.Inode
+
+ // Name is the base name of the directory entry. Empty is invalid.
+ Name string
+
+ // Type is fs.FileMode masked on fs.ModeType. For example, zero is a
+ // regular file, fs.ModeDir is a directory and fs.ModeIrregular is unknown.
+ //
+ // Note: This is defined by Linux, not POSIX.
+ Type fs.FileMode
+}
+
+func (d *Dirent) String() string {
+ return fmt.Sprintf("name=%s, type=%v, ino=%d", d.Name, d.Type, d.Ino)
+}
+
+// IsDir returns true if the Type is fs.ModeDir.
+func (d *Dirent) IsDir() bool {
+ return d.Type == fs.ModeDir
+}
+
+// DirFile is embeddable to reduce the amount of functions to implement a file.
+type DirFile struct{}
+
+// IsAppend implements File.IsAppend
+func (DirFile) IsAppend() bool {
+ return false
+}
+
+// SetAppend implements File.SetAppend
+func (DirFile) SetAppend(bool) Errno {
+ return EISDIR
+}
+
+// IsDir implements File.IsDir
+func (DirFile) IsDir() (bool, Errno) {
+ return true, 0
+}
+
+// Read implements File.Read
+func (DirFile) Read([]byte) (int, Errno) {
+ return 0, EISDIR
+}
+
+// Pread implements File.Pread
+func (DirFile) Pread([]byte, int64) (int, Errno) {
+ return 0, EISDIR
+}
+
+// Write implements File.Write
+func (DirFile) Write([]byte) (int, Errno) {
+ return 0, EISDIR
+}
+
+// Pwrite implements File.Pwrite
+func (DirFile) Pwrite([]byte, int64) (int, Errno) {
+ return 0, EISDIR
+}
+
+// Truncate implements File.Truncate
+func (DirFile) Truncate(int64) Errno {
+ return EISDIR
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go
new file mode 100644
index 000000000..238949496
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/errno.go
@@ -0,0 +1,98 @@
+package sys
+
+import "strconv"
+
+// Errno is a subset of POSIX errno used by wazero interfaces. Zero is not an
+// error. Other values should not be interpreted numerically, rather by constants
+// prefixed with 'E'.
+//
+// See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+type Errno uint16
+
+// ^-- Note: This will eventually move to the public /sys package. It is
+// experimental until we audit the socket related APIs to ensure we have all
+// the Errno it returns, and we export fs.FS. This is not in /internal/sys as
+// that would introduce a package cycle.
+
+// This is a subset of errors to reduce implementation burden. `wasip1` defines
+// almost all POSIX error numbers, but not all are used in practice. wazero
+// will add ones needed in POSIX order, as needed by functions that explicitly
+// document returning them.
+//
+// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-errno-enumu16
+const (
+ EACCES Errno = iota + 1
+ EAGAIN
+ EBADF
+ EEXIST
+ EFAULT
+ EINTR
+ EINVAL
+ EIO
+ EISDIR
+ ELOOP
+ ENAMETOOLONG
+ ENOENT
+ ENOSYS
+ ENOTDIR
+ ERANGE
+ ENOTEMPTY
+ ENOTSOCK
+ ENOTSUP
+ EPERM
+ EROFS
+
+ // NOTE ENOTCAPABLE is defined in wasip1, but not in POSIX. wasi-libc
+ // converts it to EBADF, ESPIPE or EINVAL depending on the call site.
+ // It isn't known if compilers who don't use ENOTCAPABLE would crash on it.
+)
+
+// Error implements error
+func (e Errno) Error() string {
+ switch e {
+ case 0: // not an error
+ return "success"
+ case EACCES:
+ return "permission denied"
+ case EAGAIN:
+ return "resource unavailable, try again"
+ case EBADF:
+ return "bad file descriptor"
+ case EEXIST:
+ return "file exists"
+ case EFAULT:
+ return "bad address"
+ case EINTR:
+ return "interrupted function"
+ case EINVAL:
+ return "invalid argument"
+ case EIO:
+ return "input/output error"
+ case EISDIR:
+ return "is a directory"
+ case ELOOP:
+ return "too many levels of symbolic links"
+ case ENAMETOOLONG:
+ return "filename too long"
+ case ENOENT:
+ return "no such file or directory"
+ case ENOSYS:
+ return "functionality not supported"
+ case ENOTDIR:
+ return "not a directory or a symbolic link to a directory"
+ case ERANGE:
+ return "result too large"
+ case ENOTEMPTY:
+ return "directory not empty"
+ case ENOTSOCK:
+ return "not a socket"
+ case ENOTSUP:
+ return "not supported (may be the same value as [EOPNOTSUPP])"
+ case EPERM:
+ return "operation not permitted"
+ case EROFS:
+ return "read-only file system"
+ default:
+ return "Errno(" + strconv.Itoa(int(e)) + ")"
+ }
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/error.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/error.go
new file mode 100644
index 000000000..a0c76019a
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/error.go
@@ -0,0 +1,45 @@
+package sys
+
+import (
+ "io"
+ "io/fs"
+ "os"
+)
+
+// UnwrapOSError returns an Errno or zero if the input is nil.
+func UnwrapOSError(err error) Errno {
+ if err == nil {
+ return 0
+ }
+ err = underlyingError(err)
+ switch err {
+ case nil, io.EOF:
+ return 0 // EOF is not a Errno
+ case fs.ErrInvalid:
+ return EINVAL
+ case fs.ErrPermission:
+ return EPERM
+ case fs.ErrExist:
+ return EEXIST
+ case fs.ErrNotExist:
+ return ENOENT
+ case fs.ErrClosed:
+ return EBADF
+ }
+ return errorToErrno(err)
+}
+
+// underlyingError returns the underlying error if a well-known OS error type.
+//
+// This impl is basically the same as os.underlyingError in os/error.go
+func underlyingError(err error) error {
+ switch err := err.(type) {
+ case *os.PathError:
+ return err.Err
+ case *os.LinkError:
+ return err.Err
+ case *os.SyscallError:
+ return err.Err
+ }
+ return err
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/file.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/file.go
new file mode 100644
index 000000000..b6bfbcfeb
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/file.go
@@ -0,0 +1,316 @@
+package sys
+
+import "github.com/tetratelabs/wazero/sys"
+
+// File is a writeable fs.File bridge backed by syscall functions needed for ABI
+// including WASI.
+//
+// Implementations should embed UnimplementedFile for forward compatibility. Any
+// unsupported method or parameter should return ENOSYS.
+//
+// # Errors
+//
+// All methods that can return an error return a Errno, which is zero
+// on success.
+//
+// Restricting to Errno matches current WebAssembly host functions,
+// which are constrained to well-known error codes. For example, WASI maps syscall
+// errors to u32 numeric values.
+//
+// # Notes
+//
+// - You must call Close to avoid file resource conflicts. For example,
+// Windows cannot delete the underlying directory while a handle to it
+// remains open.
+// - A writable filesystem abstraction is not yet implemented as of Go 1.20.
+// See https://github.com/golang/go/issues/45757
+type File interface {
+ // Dev returns the device ID (Stat_t.Dev) of this file, zero if unknown or
+ // an error retrieving it.
+ //
+ // # Errors
+ //
+ // Possible errors are those from Stat, except ENOSYS should not
+ // be returned. Zero should be returned if there is no implementation.
+ //
+ // # Notes
+ //
+ // - Implementations should cache this result.
+ // - This combined with Ino can implement os.SameFile.
+ Dev() (uint64, Errno)
+
+ // Ino returns the serial number (Stat_t.Ino) of this file, zero if unknown
+ // or an error retrieving it.
+ //
+ // # Errors
+ //
+ // Possible errors are those from Stat, except ENOSYS should not
+ // be returned. Zero should be returned if there is no implementation.
+ //
+ // # Notes
+ //
+ // - Implementations should cache this result.
+ // - This combined with Dev can implement os.SameFile.
+ Ino() (sys.Inode, Errno)
+
+ // IsDir returns true if this file is a directory or an error there was an
+ // error retrieving this information.
+ //
+ // # Errors
+ //
+ // Possible errors are those from Stat, except ENOSYS should not
+ // be returned. false should be returned if there is no implementation.
+ //
+ // # Notes
+ //
+ // - Implementations should cache this result.
+ IsDir() (bool, Errno)
+
+ // IsAppend returns true if the file was opened with O_APPEND, or
+ // SetAppend was successfully enabled on this file.
+ //
+ // # Notes
+ //
+ // - This might not match the underlying state of the file descriptor if
+ // the file was not opened via OpenFile.
+ IsAppend() bool
+
+ // SetAppend toggles the append mode (O_APPEND) of this file.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed.
+ //
+ // # Notes
+ //
+ // - There is no `O_APPEND` for `fcntl` in POSIX, so implementations may
+ // have to re-open the underlying file to apply this. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
+ SetAppend(enable bool) Errno
+
+ // Stat is similar to syscall.Fstat.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Fstat and `fstatat` with `AT_FDCWD` in POSIX.
+ // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html
+ // - A fs.FileInfo backed implementation sets atim, mtim and ctim to the
+ // same value.
+ // - Windows allows you to stat a closed directory.
+ Stat() (sys.Stat_t, Errno)
+
+ // Read attempts to read all bytes in the file into `buf`, and returns the
+ // count read even on error.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed or not readable.
+ // - EISDIR: the file was a directory.
+ //
+ // # Notes
+ //
+ // - This is like io.Reader and `read` in POSIX, preferring semantics of
+ // io.Reader. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
+ // - Unlike io.Reader, there is no io.EOF returned on end-of-file. To
+ // read the file completely, the caller must repeat until `n` is zero.
+ Read(buf []byte) (n int, errno Errno)
+
+ // Pread attempts to read all bytes in the file into `p`, starting at the
+ // offset `off`, and returns the count read even on error.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed or not readable.
+ // - EINVAL: the offset was negative.
+ // - EISDIR: the file was a directory.
+ //
+ // # Notes
+ //
+ // - This is like io.ReaderAt and `pread` in POSIX, preferring semantics
+ // of io.ReaderAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html
+ // - Unlike io.ReaderAt, there is no io.EOF returned on end-of-file. To
+ // read the file completely, the caller must repeat until `n` is zero.
+ Pread(buf []byte, off int64) (n int, errno Errno)
+
+ // Seek attempts to set the next offset for Read or Write and returns the
+ // resulting absolute offset or an error.
+ //
+ // # Parameters
+ //
+ // The `offset` parameters is interpreted in terms of `whence`:
+ // - io.SeekStart: relative to the start of the file, e.g. offset=0 sets
+ // the next Read or Write to the beginning of the file.
+ // - io.SeekCurrent: relative to the current offset, e.g. offset=16 sets
+ // the next Read or Write 16 bytes past the prior.
+ // - io.SeekEnd: relative to the end of the file, e.g. offset=-1 sets the
+ // next Read or Write to the last byte in the file.
+ //
+ // # Behavior when a directory
+ //
+ // The only supported use case for a directory is seeking to `offset` zero
+ // (`whence` = io.SeekStart). This should have the same behavior as
+ // os.File, which resets any internal state used by Readdir.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed or not readable.
+ // - EINVAL: the offset was negative.
+ //
+ // # Notes
+ //
+ // - This is like io.Seeker and `fseek` in POSIX, preferring semantics
+ // of io.Seeker. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fseek.html
+ Seek(offset int64, whence int) (newOffset int64, errno Errno)
+
+ // Readdir reads the contents of the directory associated with file and
+ // returns a slice of up to n Dirent values in an arbitrary order. This is
+ // a stateful function, so subsequent calls return any next values.
+ //
+ // If n > 0, Readdir returns at most n entries or an error.
+ // If n <= 0, Readdir returns all remaining entries or an error.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file was closed or not a directory.
+ // - ENOENT: the directory could not be read (e.g. deleted).
+ //
+ // # Notes
+ //
+ // - This is like `Readdir` on os.File, but unlike `readdir` in POSIX.
+ // See https://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html
+ // - Unlike os.File, there is no io.EOF returned on end-of-directory. To
+ // read the directory completely, the caller must repeat until the
+ // count read (`len(dirents)`) is less than `n`.
+ // - See /RATIONALE.md for design notes.
+ Readdir(n int) (dirents []Dirent, errno Errno)
+
+ // Write attempts to write all bytes in `p` to the file, and returns the
+ // count written even on error.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file was closed, not writeable, or a directory.
+ //
+ // # Notes
+ //
+ // - This is like io.Writer and `write` in POSIX, preferring semantics of
+ // io.Writer. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+ Write(buf []byte) (n int, errno Errno)
+
+ // Pwrite attempts to write all bytes in `p` to the file at the given
+ // offset `off`, and returns the count written even on error.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed or not writeable.
+ // - EINVAL: the offset was negative.
+ // - EISDIR: the file was a directory.
+ //
+ // # Notes
+ //
+ // - This is like io.WriterAt and `pwrite` in POSIX, preferring semantics
+ // of io.WriterAt. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html
+ Pwrite(buf []byte, off int64) (n int, errno Errno)
+
+ // Truncate truncates a file to a specified length.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed.
+ // - EINVAL: the `size` is negative.
+ // - EISDIR: the file was a directory.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Ftruncate and `ftruncate` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
+ // - Windows does not error when calling Truncate on a closed file.
+ Truncate(size int64) Errno
+
+ // Sync synchronizes changes to the file.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - EBADF: the file or directory was closed.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Fsync and `fsync` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
+ // - This returns with no error instead of ENOSYS when
+ // unimplemented. This prevents fake filesystems from erring.
+ // - Windows does not error when calling Sync on a closed file.
+ Sync() Errno
+
+ // Datasync synchronizes the data of a file.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - EBADF: the file or directory was closed.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Fdatasync and `fdatasync` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html
+ // - This returns with no error instead of ENOSYS when
+ // unimplemented. This prevents fake filesystems from erring.
+ // - As this is commonly missing, some implementations dispatch to Sync.
+ Datasync() Errno
+
+ // Utimens set file access and modification times of this file, at
+ // nanosecond precision.
+ //
+ // # Parameters
+ //
+ // The `atim` and `mtim` parameters refer to access and modification time
+ // stamps as defined in sys.Stat_t. To retain one or the other, substitute
+ // it with the pseudo-timestamp UTIME_OMIT.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EBADF: the file or directory was closed.
+ //
+ // # Notes
+ //
+ // - This is like syscall.UtimesNano and `futimens` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
+ // - Windows requires files to be open with O_RDWR, which means you
+ // cannot use this to update timestamps on a directory (EPERM).
+ Utimens(atim, mtim int64) Errno
+
+ // Close closes the underlying file.
+ //
+ // A zero Errno is returned if unimplemented or success.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Close and `close` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
+ Close() Errno
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go
new file mode 100644
index 000000000..87810510a
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/fs.go
@@ -0,0 +1,292 @@
+package sys
+
+import (
+ "io/fs"
+
+ "github.com/tetratelabs/wazero/sys"
+)
+
+// FS is a writeable fs.FS bridge backed by syscall functions needed for ABI
+// including WASI.
+//
+// Implementations should embed UnimplementedFS for forward compatibility. Any
+// unsupported method or parameter should return ENO
+//
+// # Errors
+//
+// All methods that can return an error return a Errno, which is zero
+// on success.
+//
+// Restricting to Errno matches current WebAssembly host functions,
+// which are constrained to well-known error codes. For example, WASI maps syscall
+// errors to u32 numeric values.
+//
+// # Notes
+//
+// A writable filesystem abstraction is not yet implemented as of Go 1.20. See
+// https://github.com/golang/go/issues/45757
+type FS interface {
+ // OpenFile opens a file. It should be closed via Close on File.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` or `flag` is invalid.
+ // - EISDIR: the path was a directory, but flag included O_RDWR or
+ // O_WRONLY
+ // - ENOENT: `path` doesn't exist and `flag` doesn't contain O_CREAT.
+ //
+ // # Constraints on the returned file
+ //
+ // Implementations that can read flags should enforce them regardless of
+ // the type returned. For example, while os.File implements io.Writer,
+ // attempts to write to a directory or a file opened with O_RDONLY fail
+ // with a EBADF.
+ //
+ // Some implementations choose whether to enforce read-only opens, namely
+ // fs.FS. While fs.FS is supported (Adapt), wazero cannot runtime enforce
+ // open flags. Instead, we encourage good behavior and test our built-in
+ // implementations.
+ //
+ // # Notes
+ //
+ // - This is like os.OpenFile, except the path is relative to this file
+ // system, and Errno is returned instead of os.PathError.
+ // - Implications of permissions when O_CREAT are described in Chmod notes.
+ // - This is like `open` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
+ OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno)
+
+ // Lstat gets file status without following symbolic links.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - ENOENT: `path` doesn't exist.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Lstat, except the `path` is relative to this
+ // file system.
+ // - This is like `lstat` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html
+ // - An fs.FileInfo backed implementation sets atim, mtim and ctim to the
+ // same value.
+ // - When the path is a symbolic link, the stat returned is for the link,
+ // not the file it refers to.
+ Lstat(path string) (sys.Stat_t, Errno)
+
+ // Stat gets file status.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - ENOENT: `path` doesn't exist.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Stat, except the `path` is relative to this
+ // file system.
+ // - This is like `stat` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html
+ // - An fs.FileInfo backed implementation sets atim, mtim and ctim to the
+ // same value.
+ // - When the path is a symbolic link, the stat returned is for the file
+ // it refers to.
+ Stat(path string) (sys.Stat_t, Errno)
+
+ // Mkdir makes a directory.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` is invalid.
+ // - EEXIST: `path` exists and is a directory.
+ // - ENOTDIR: `path` exists and is a file.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Mkdir, except the `path` is relative to this
+ // file system.
+ // - This is like `mkdir` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html
+ // - Implications of permissions are described in Chmod notes.
+ Mkdir(path string, perm fs.FileMode) Errno
+
+ // Chmod changes the mode of the file.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` is invalid.
+ // - ENOENT: `path` does not exist.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Chmod, except the `path` is relative to this
+ // file system.
+ // - This is like `chmod` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html
+ // - Windows ignores the execute bit, and any permissions come back as
+ // group and world. For example, chmod of 0400 reads back as 0444, and
+ // 0700 0666. Also, permissions on directories aren't supported at all.
+ Chmod(path string, perm fs.FileMode) Errno
+
+ // Rename renames file or directory.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `from` or `to` is invalid.
+ // - ENOENT: `from` or `to` don't exist.
+ // - ENOTDIR: `from` is a directory and `to` exists as a file.
+ // - EISDIR: `from` is a file and `to` exists as a directory.
+ // - ENOTEMPTY: `both from` and `to` are existing directory, but
+ // `to` is not empty.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Rename, except the paths are relative to this
+ // file system.
+ // - This is like `rename` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html
+ // - Windows doesn't let you overwrite an existing directory.
+ Rename(from, to string) Errno
+
+ // Rmdir removes a directory.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` is invalid.
+ // - ENOENT: `path` doesn't exist.
+ // - ENOTDIR: `path` exists, but isn't a directory.
+ // - ENOTEMPTY: `path` exists, but isn't empty.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Rmdir, except the `path` is relative to this
+ // file system.
+ // - This is like `rmdir` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html
+ // - As of Go 1.19, Windows maps ENOTDIR to ENOENT.
+ Rmdir(path string) Errno
+
+ // Unlink removes a directory entry.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` is invalid.
+ // - ENOENT: `path` doesn't exist.
+ // - EISDIR: `path` exists, but is a directory.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Unlink, except the `path` is relative to this
+ // file system.
+ // - This is like `unlink` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html
+ // - On Windows, syscall.Unlink doesn't delete symlink to directory unlike other platforms. Implementations might
+ // want to combine syscall.RemoveDirectory with syscall.Unlink in order to delete such links on Windows.
+ // See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya
+ Unlink(path string) Errno
+
+ // Link creates a "hard" link from oldPath to newPath, in contrast to a
+ // soft link (via Symlink).
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EPERM: `oldPath` is invalid.
+ // - ENOENT: `oldPath` doesn't exist.
+ // - EISDIR: `newPath` exists, but is a directory.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Link, except the `oldPath` is relative to this
+ // file system.
+ // - This is like `link` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html
+ Link(oldPath, newPath string) Errno
+
+ // Symlink creates a "soft" link from oldPath to newPath, in contrast to a
+ // hard link (via Link).
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EPERM: `oldPath` or `newPath` is invalid.
+ // - EEXIST: `newPath` exists.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Symlink, except the `oldPath` is relative to
+ // this file system.
+ // - This is like `symlink` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html
+ // - Only `newPath` is relative to this file system and `oldPath` is kept
+ // as-is. That is because the link is only resolved relative to the
+ // directory when dereferencing it (e.g. ReadLink).
+ // See https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409
+ // for how others implement this.
+ // - Symlinks in Windows requires `SeCreateSymbolicLinkPrivilege`.
+ // Otherwise, EPERM results.
+ // See https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
+ Symlink(oldPath, linkName string) Errno
+
+ // Readlink reads the contents of a symbolic link.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` is invalid.
+ //
+ // # Notes
+ //
+ // - This is like syscall.Readlink, except the path is relative to this
+ // filesystem.
+ // - This is like `readlink` in POSIX. See
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html
+ // - On Windows, the path separator is different from other platforms,
+ // but to provide consistent results to Wasm, this normalizes to a "/"
+ // separator.
+ Readlink(path string) (string, Errno)
+
+ // Utimens set file access and modification times on a path relative to
+ // this file system, at nanosecond precision.
+ //
+ // # Parameters
+ //
+ // If the path is a symbolic link, the target of expanding that link is
+ // updated.
+ //
+ // The `atim` and `mtim` parameters refer to access and modification time
+ // stamps as defined in sys.Stat_t. To retain one or the other, substitute
+ // it with the pseudo-timestamp UTIME_OMIT.
+ //
+ // # Errors
+ //
+ // A zero Errno is success. The below are expected otherwise:
+ // - ENOSYS: the implementation does not support this function.
+ // - EINVAL: `path` is invalid.
+ // - EEXIST: `path` exists and is a directory.
+ // - ENOTDIR: `path` exists and is a file.
+ //
+ // # Notes
+ //
+ // - This is like syscall.UtimesNano and `utimensat` with `AT_FDCWD` in
+ // POSIX. See https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
+ Utimens(path string, atim, mtim int64) Errno
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go
new file mode 100644
index 000000000..39ebd378f
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/oflag.go
@@ -0,0 +1,70 @@
+package sys
+
+// Oflag are flags used for FS.OpenFile. Values, including zero, should not be
+// interpreted numerically. Instead, use by constants prefixed with 'O_' with
+// special casing noted below.
+//
+// # Notes
+//
+// - O_RDONLY, O_RDWR and O_WRONLY are mutually exclusive, while the other
+// flags can coexist bitwise.
+// - This is like `flag` in os.OpenFile and `oflag` in POSIX. See
+// https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
+type Oflag uint32
+
+// This is a subset of oflags to reduce implementation burden. `wasip1` splits
+// these across `oflags` and `fdflags`. We can't rely on the Go `os` package,
+// as it is missing some values. Any flags added will be defined in POSIX
+// order, as needed by functions that explicitly document accepting them.
+//
+// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16
+// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fdflags-flagsu16
+const (
+ // O_RDONLY is like os.O_RDONLY
+ O_RDONLY Oflag = iota
+
+ // O_RDWR is like os.O_RDWR
+ O_RDWR
+
+ // O_WRONLY is like os.O_WRONLY
+ O_WRONLY
+
+ // Define bitflags as they are in POSIX `open`: alphabetically
+
+ // O_APPEND is like os.O_APPEND
+ O_APPEND Oflag = 1 << iota
+
+ // O_CREAT is link os.O_CREATE
+ O_CREAT
+
+ // O_DIRECTORY is defined on some platforms as syscall.O_DIRECTORY.
+ //
+ // Note: This ensures that the opened file is a directory. Those emulating
+ // on platforms that don't support the O_DIRECTORY, can double-check the
+ // result with File.IsDir (or stat) and err if not a directory.
+ O_DIRECTORY
+
+ // O_DSYNC is defined on some platforms as syscall.O_DSYNC.
+ O_DSYNC
+
+ // O_EXCL is defined on some platforms as syscall.O_EXCL.
+ O_EXCL
+
+ // O_NOFOLLOW is defined on some platforms as syscall.O_NOFOLLOW.
+ //
+ // Note: This allows programs to ensure that if the opened file is a
+ // symbolic link, the link itself is opened instead of its target.
+ O_NOFOLLOW
+
+ // O_NONBLOCK is defined on some platforms as syscall.O_NONBLOCK.
+ O_NONBLOCK
+
+ // O_RSYNC is defined on some platforms as syscall.O_RSYNC.
+ O_RSYNC
+
+ // O_SYNC is defined on some platforms as syscall.O_SYNC.
+ O_SYNC
+
+ // O_TRUNC is defined on some platforms as syscall.O_TRUNC.
+ O_TRUNC
+)
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go
new file mode 100644
index 000000000..ea511ec25
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno.go
@@ -0,0 +1,106 @@
+//go:build !plan9 && !aix
+
+package sys
+
+import "syscall"
+
+func syscallToErrno(err error) (Errno, bool) {
+ errno, ok := err.(syscall.Errno)
+ if !ok {
+ return 0, false
+ }
+ switch errno {
+ case 0:
+ return 0, true
+ case syscall.EACCES:
+ return EACCES, true
+ case syscall.EAGAIN:
+ return EAGAIN, true
+ case syscall.EBADF:
+ return EBADF, true
+ case syscall.EEXIST:
+ return EEXIST, true
+ case syscall.EFAULT:
+ return EFAULT, true
+ case syscall.EINTR:
+ return EINTR, true
+ case syscall.EINVAL:
+ return EINVAL, true
+ case syscall.EIO:
+ return EIO, true
+ case syscall.EISDIR:
+ return EISDIR, true
+ case syscall.ELOOP:
+ return ELOOP, true
+ case syscall.ENAMETOOLONG:
+ return ENAMETOOLONG, true
+ case syscall.ENOENT:
+ return ENOENT, true
+ case syscall.ENOSYS:
+ return ENOSYS, true
+ case syscall.ENOTDIR:
+ return ENOTDIR, true
+ case syscall.ERANGE:
+ return ERANGE, true
+ case syscall.ENOTEMPTY:
+ return ENOTEMPTY, true
+ case syscall.ENOTSOCK:
+ return ENOTSOCK, true
+ case syscall.ENOTSUP:
+ return ENOTSUP, true
+ case syscall.EPERM:
+ return EPERM, true
+ case syscall.EROFS:
+ return EROFS, true
+ default:
+ return EIO, true
+ }
+}
+
+// Unwrap is a convenience for runtime.GOOS which define syscall.Errno.
+func (e Errno) Unwrap() error {
+ switch e {
+ case 0:
+ return nil
+ case EACCES:
+ return syscall.EACCES
+ case EAGAIN:
+ return syscall.EAGAIN
+ case EBADF:
+ return syscall.EBADF
+ case EEXIST:
+ return syscall.EEXIST
+ case EFAULT:
+ return syscall.EFAULT
+ case EINTR:
+ return syscall.EINTR
+ case EINVAL:
+ return syscall.EINVAL
+ case EIO:
+ return syscall.EIO
+ case EISDIR:
+ return syscall.EISDIR
+ case ELOOP:
+ return syscall.ELOOP
+ case ENAMETOOLONG:
+ return syscall.ENAMETOOLONG
+ case ENOENT:
+ return syscall.ENOENT
+ case ENOSYS:
+ return syscall.ENOSYS
+ case ENOTDIR:
+ return syscall.ENOTDIR
+ case ENOTEMPTY:
+ return syscall.ENOTEMPTY
+ case ENOTSOCK:
+ return syscall.ENOTSOCK
+ case ENOTSUP:
+ return syscall.ENOTSUP
+ case EPERM:
+ return syscall.EPERM
+ case EROFS:
+ return syscall.EROFS
+ default:
+ return syscall.EIO
+ }
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go
new file mode 100644
index 000000000..8a88ed765
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_notwindows.go
@@ -0,0 +1,13 @@
+//go:build !windows
+
+package sys
+
+func errorToErrno(err error) Errno {
+ if errno, ok := err.(Errno); ok {
+ return errno
+ }
+ if errno, ok := syscallToErrno(err); ok {
+ return errno
+ }
+ return EIO
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go
new file mode 100644
index 000000000..1c6d423d0
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_unsupported.go
@@ -0,0 +1,7 @@
+//go:build plan9 || aix
+
+package sys
+
+func syscallToErrno(err error) (Errno, bool) {
+ return 0, false
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go
new file mode 100644
index 000000000..761a1f9dc
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/syscall_errno_windows.go
@@ -0,0 +1,62 @@
+package sys
+
+import "syscall"
+
+// These are errors not defined in the syscall package. They are prefixed with
+// underscore to avoid exporting them.
+//
+// See https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
+const (
+ // _ERROR_INVALID_HANDLE is a Windows error returned by syscall.Write
+ // instead of syscall.EBADF
+ _ERROR_INVALID_HANDLE = syscall.Errno(6)
+
+ // _ERROR_INVALID_NAME is a Windows error returned by open when a file
+ // path has a trailing slash
+ _ERROR_INVALID_NAME = syscall.Errno(0x7B)
+
+ // _ERROR_NEGATIVE_SEEK is a Windows error returned by os.Truncate
+ // instead of syscall.EINVAL
+ _ERROR_NEGATIVE_SEEK = syscall.Errno(0x83)
+
+ // _ERROR_DIRECTORY is a Windows error returned by syscall.Rmdir
+ // instead of syscall.ENOTDIR
+ _ERROR_DIRECTORY = syscall.Errno(0x10B)
+
+ // _ERROR_INVALID_SOCKET is a Windows error returned by winsock_select
+ // when a given handle is not a socket.
+ _ERROR_INVALID_SOCKET = syscall.Errno(0x2736)
+)
+
+func errorToErrno(err error) Errno {
+ switch err := err.(type) {
+ case Errno:
+ return err
+ case syscall.Errno:
+ // Note: In windows, _ERROR_PATH_NOT_FOUND(0x3) maps to syscall.ENOTDIR
+ switch err {
+ case syscall.ERROR_ALREADY_EXISTS:
+ return EEXIST
+ case _ERROR_DIRECTORY:
+ return ENOTDIR
+ case syscall.ERROR_DIR_NOT_EMPTY:
+ return ENOTEMPTY
+ case syscall.ERROR_FILE_EXISTS:
+ return EEXIST
+ case _ERROR_INVALID_HANDLE, _ERROR_INVALID_SOCKET:
+ return EBADF
+ case syscall.ERROR_ACCESS_DENIED:
+ // POSIX read and write functions expect EBADF, not EACCES when not
+ // open for reading or writing.
+ return EBADF
+ case syscall.ERROR_PRIVILEGE_NOT_HELD:
+ return EPERM
+ case _ERROR_NEGATIVE_SEEK, _ERROR_INVALID_NAME:
+ return EINVAL
+ }
+ errno, _ := syscallToErrno(err)
+ return errno
+ default:
+ return EIO
+ }
+}
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/time.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/time.go
new file mode 100644
index 000000000..4f3e01fef
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/time.go
@@ -0,0 +1,10 @@
+package sys
+
+import "math"
+
+// UTIME_OMIT is a special constant for use in updating times via FS.Utimens
+// or File.Utimens. When used for atim or mtim, the value is retained.
+//
+// Note: This may be implemented via a stat when the underlying filesystem
+// does not support this value.
+const UTIME_OMIT int64 = math.MinInt64
diff --git a/vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go b/vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go
new file mode 100644
index 000000000..d853d9e8f
--- /dev/null
+++ b/vendor/github.com/tetratelabs/wazero/experimental/sys/unimplemented.go
@@ -0,0 +1,160 @@
+package sys
+
+import (
+ "io/fs"
+
+ "github.com/tetratelabs/wazero/sys"
+)
+
+// UnimplementedFS is an FS that returns ENOSYS for all functions,
+// This should be embedded to have forward compatible implementations.
+type UnimplementedFS struct{}
+
+// OpenFile implements FS.OpenFile
+func (UnimplementedFS) OpenFile(path string, flag Oflag, perm fs.FileMode) (File, Errno) {
+ return nil, ENOSYS
+}
+
+// Lstat implements FS.Lstat
+func (UnimplementedFS) Lstat(path string) (sys.Stat_t, Errno) {
+ return sys.Stat_t{}, ENOSYS
+}
+
+// Stat implements FS.Stat
+func (UnimplementedFS) Stat(path string) (sys.Stat_t, Errno) {
+ return sys.Stat_t{}, ENOSYS
+}
+
+// Readlink implements FS.Readlink
+func (UnimplementedFS) Readlink(path string) (string, Errno) {
+ return "", ENOSYS
+}
+
+// Mkdir implements FS.Mkdir
+func (UnimplementedFS) Mkdir(path string, perm fs.FileMode) Errno {
+ return ENOSYS
+}
+
+// Chmod implements FS.Chmod
+func (UnimplementedFS) Chmod(path string, perm fs.FileMode) Errno {
+ return ENOSYS
+}
+
+// Rename implements FS.Rename
+func (UnimplementedFS) Rename(from, to string) Errno {
+ return ENOSYS
+}
+
+// Rmdir implements FS.Rmdir
+func (UnimplementedFS) Rmdir(path string) Errno {
+ return ENOSYS
+}
+
+// Link implements FS.Link
+func (UnimplementedFS) Link(_, _ string) Errno {
+ return ENOSYS
+}
+
+// Symlink implements FS.Symlink
+func (UnimplementedFS) Symlink(_, _ string) Errno {
+ return ENOSYS
+}
+
+// Unlink implements FS.Unlink
+func (UnimplementedFS) Unlink(path string) Errno {
+ return ENOSYS
+}
+
+// Utimens implements FS.Utimens
+func (UnimplementedFS) Utimens(path string, atim, mtim int64) Errno {
+ return ENOSYS
+}
+
+// UnimplementedFile is a File that returns ENOSYS for all functions,
+// except where no-op are otherwise documented.
+//
+// This should be embedded to have forward compatible implementations.
+type UnimplementedFile struct{}
+
+// Dev implements File.Dev
+func (UnimplementedFile) Dev() (uint64, Errno) {
+ return 0, 0
+}
+
+// Ino implements File.Ino
+func (UnimplementedFile) Ino() (sys.Inode, Errno) {
+ return 0, 0
+}
+
+// IsDir implements File.IsDir
+func (UnimplementedFile) IsDir() (bool, Errno) {
+ return false, 0
+}
+
+// IsAppend implements File.IsAppend
+func (UnimplementedFile) IsAppend() bool {
+ return false
+}
+
+// SetAppend implements File.SetAppend
+func (UnimplementedFile) SetAppend(bool) Errno {
+ return ENOSYS
+}
+
+// Stat implements File.Stat
+func (UnimplementedFile) Stat() (sys.Stat_t, Errno) {
+ return sys.Stat_t{}, ENOSYS
+}
+
+// Read implements File.Read
+func (UnimplementedFile) Read([]byte) (int, Errno) {
+ return 0, ENOSYS
+}
+
+// Pread implements File.Pread
+func (UnimplementedFile) Pread([]byte, int64) (int, Errno) {
+ return 0, ENOSYS
+}
+
+// Seek implements File.Seek
+func (UnimplementedFile) Seek(int64, int) (int64, Errno) {
+ return 0, ENOSYS
+}
+
+// Readdir implements File.Readdir
+func (UnimplementedFile) Readdir(int) (dirents []Dirent, errno Errno) {
+ return nil, ENOSYS
+}
+
+// Write implements File.Write
+func (UnimplementedFile) Write([]byte) (int, Errno) {
+ return 0, ENOSYS
+}
+
+// Pwrite implements File.Pwrite
+func (UnimplementedFile) Pwrite([]byte, int64) (int, Errno) {
+ return 0, ENOSYS
+}
+
+// Truncate implements File.Truncate
+func (UnimplementedFile) Truncate(int64) Errno {
+ return ENOSYS
+}
+
+// Sync implements File.Sync
+func (UnimplementedFile) Sync() Errno {
+ return 0 // not ENOSYS
+}
+
+// Datasync implements File.Datasync
+func (UnimplementedFile) Datasync() Errno {
+ return 0 // not ENOSYS
+}
+
+// Utimens implements File.Utimens
+func (UnimplementedFile) Utimens(int64, int64) Errno {
+ return ENOSYS
+}
+
+// Close implements File.Close
+func (UnimplementedFile) Close() (errno Errno) { return }