wasi: unexports errno and re-uses constants for logging (#971)
We originally exported WASI errno as we originally supported invoking host functions directly (e.g. without a guest). This was an invalid call pattern, and we removed that. However, we left the errnos exported even though the caller of a guest won't ever see them. This prevented us from re-using them cleanly in features such as logging. This moves all constants including function names and flag enums internal so that there is less duplication between logging and implementation of wasi functions. This also helps in reference searches, as we can analyze uses of a particular function name. The only constant left exported is the module name, as there's a use case for that (overriding implementations via FunctionBuilder). Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/experimental"
|
||||
wasilogging "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1/logging"
|
||||
gologging "github.com/tetratelabs/wazero/internal/gojs/logging"
|
||||
"github.com/tetratelabs/wazero/internal/logging"
|
||||
"github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
wasilogging "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1/logging"
|
||||
)
|
||||
|
||||
type Writer interface {
|
||||
@@ -78,7 +78,7 @@ func (f *loggingListenerFactory) NewListener(fnd api.FunctionDefinition) experim
|
||||
var pSampler logging.ParamSampler
|
||||
var rLoggers []logging.ResultLogger
|
||||
switch fnd.ModuleName() {
|
||||
case wasi_snapshot_preview1.ModuleName:
|
||||
case wasi_snapshot_preview1.InternalModuleName:
|
||||
if f.fsOnly && !wasilogging.IsFilesystemFunction(fnd) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
wasi "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
|
||||
|
||||
func Test_loggingListener(t *testing.T) {
|
||||
wasiFuncName := "random_get"
|
||||
wasiFuncName := wasi.RandomGetName
|
||||
wasiFuncType := &wasm.FunctionType{
|
||||
Params: []api.ValueType{api.ValueTypeI32, api.ValueTypeI32},
|
||||
Results: []api.ValueType{api.ValueTypeI32},
|
||||
@@ -63,13 +63,13 @@ func Test_loggingListener(t *testing.T) {
|
||||
{
|
||||
name: "wasi",
|
||||
functype: wasiFuncType,
|
||||
moduleName: wasi_snapshot_preview1.ModuleName,
|
||||
moduleName: wasi.InternalModuleName,
|
||||
funcName: wasiFuncName,
|
||||
paramNames: wasiParamNames,
|
||||
resultNames: wasiResultNames,
|
||||
isHostFunc: true,
|
||||
params: wasiParams,
|
||||
results: []uint64{uint64(wasi_snapshot_preview1.ErrnoSuccess)},
|
||||
results: []uint64{uint64(wasi.ErrnoSuccess)},
|
||||
expected: `==> wasi_snapshot_preview1.random_get(buf=0,buf_len=8)
|
||||
<== errno=ESUCCESS
|
||||
`,
|
||||
@@ -77,13 +77,13 @@ func Test_loggingListener(t *testing.T) {
|
||||
{
|
||||
name: "wasi errno",
|
||||
functype: wasiFuncType,
|
||||
moduleName: wasi_snapshot_preview1.ModuleName,
|
||||
moduleName: wasi.InternalModuleName,
|
||||
funcName: wasiFuncName,
|
||||
paramNames: wasiParamNames,
|
||||
resultNames: wasiResultNames,
|
||||
isHostFunc: true,
|
||||
params: wasiParams,
|
||||
results: []uint64{uint64(wasi_snapshot_preview1.ErrnoFault)},
|
||||
results: []uint64{uint64(wasi.ErrnoFault)},
|
||||
expected: `==> wasi_snapshot_preview1.random_get(buf=0,buf_len=8)
|
||||
<== errno=EFAULT
|
||||
`,
|
||||
@@ -91,7 +91,7 @@ func Test_loggingListener(t *testing.T) {
|
||||
{
|
||||
name: "wasi error",
|
||||
functype: wasiFuncType,
|
||||
moduleName: wasi_snapshot_preview1.ModuleName,
|
||||
moduleName: wasi.InternalModuleName,
|
||||
funcName: wasiFuncName,
|
||||
paramNames: wasiParamNames,
|
||||
resultNames: wasiResultNames,
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
const (
|
||||
argsGetName = "args_get"
|
||||
argsSizesGetName = "args_sizes_get"
|
||||
)
|
||||
|
||||
// argsGet is the WASI function named argsGetName that reads command-line
|
||||
// argsGet is the WASI function named ArgsGetName that reads command-line
|
||||
// argument data.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -44,7 +40,7 @@ const (
|
||||
// See argsSizesGet
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_get
|
||||
// See https://en.wikipedia.org/wiki/Null-terminated_string
|
||||
var argsGet = newHostFunc(argsGetName, argsGetFn, []api.ValueType{i32, i32}, "argv", "argv_buf")
|
||||
var argsGet = newHostFunc(ArgsGetName, argsGetFn, []api.ValueType{i32, i32}, "argv", "argv_buf")
|
||||
|
||||
func argsGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
@@ -52,7 +48,7 @@ func argsGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return writeOffsetsAndNullTerminatedValues(mod.Memory(), sysCtx.Args(), argv, argvBuf, sysCtx.ArgsSize())
|
||||
}
|
||||
|
||||
// argsSizesGet is the WASI function named argsSizesGetName that reads
|
||||
// argsSizesGet is the WASI function named ArgsSizesGetName that reads
|
||||
// command-line argument sizes.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -81,7 +77,7 @@ func argsGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
// See argsGet
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_sizes_get
|
||||
// See https://en.wikipedia.org/wiki/Null-terminated_string
|
||||
var argsSizesGet = newHostFunc(argsSizesGetName, argsSizesGetFn, []api.ValueType{i32, i32}, "result.argc", "result.argv_len")
|
||||
var argsSizesGet = newHostFunc(ArgsSizesGetName, argsSizesGetFn, []api.ValueType{i32, i32}, "result.argc", "result.argv_len")
|
||||
|
||||
func argsSizesGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
func Test_argsGet(t *testing.T) {
|
||||
@@ -25,7 +26,7 @@ func Test_argsGet(t *testing.T) {
|
||||
maskMemory(t, mod, len(expectedMemory)+int(argvBuf))
|
||||
|
||||
// Invoke argsGet and check the memory side effects.
|
||||
requireErrno(t, ErrnoSuccess, mod, argsGetName, uint64(argv), uint64(argvBuf))
|
||||
requireErrno(t, ErrnoSuccess, mod, ArgsGetName, uint64(argv), uint64(argvBuf))
|
||||
require.Equal(t, `
|
||||
==> wasi_snapshot_preview1.args_get(argv=22,argv_buf=16)
|
||||
<== errno=ESUCCESS
|
||||
@@ -94,7 +95,7 @@ func Test_argsGet_Errors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, ErrnoFault, mod, argsGetName, uint64(tc.argv), uint64(tc.argvBuf))
|
||||
requireErrno(t, ErrnoFault, mod, ArgsGetName, uint64(tc.argv), uint64(tc.argvBuf))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
@@ -117,7 +118,7 @@ func Test_argsSizesGet(t *testing.T) {
|
||||
maskMemory(t, mod, int(resultArgc)+len(expectedMemory))
|
||||
|
||||
// Invoke argsSizesGet and check the memory side effects.
|
||||
requireErrno(t, ErrnoSuccess, mod, argsSizesGetName, uint64(resultArgc), uint64(resultArgvLen))
|
||||
requireErrno(t, ErrnoSuccess, mod, ArgsSizesGetName, uint64(resultArgc), uint64(resultArgvLen))
|
||||
require.Equal(t, `
|
||||
==> wasi_snapshot_preview1.args_sizes_get(result.argc=16,result.argv_len=21)
|
||||
<== errno=ESUCCESS
|
||||
@@ -184,7 +185,7 @@ func Test_argsSizesGet_Errors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, ErrnoFault, mod, argsSizesGetName, uint64(tc.argc), uint64(tc.argvLen))
|
||||
requireErrno(t, ErrnoFault, mod, ArgsSizesGetName, uint64(tc.argc), uint64(tc.argvLen))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,25 +5,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
const (
|
||||
clockResGetName = "clock_res_get"
|
||||
clockTimeGetName = "clock_time_get"
|
||||
)
|
||||
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clockid-enumu32
|
||||
const (
|
||||
// clockIDRealtime is the name ID named "realtime" like sys.Walltime
|
||||
clockIDRealtime = iota
|
||||
// clockIDMonotonic is the name ID named "monotonic" like sys.Nanotime
|
||||
clockIDMonotonic
|
||||
// Note: clockIDProcessCputime and clockIDThreadCputime were removed by
|
||||
// WASI maintainers: https://github.com/WebAssembly/wasi-libc/pull/294
|
||||
)
|
||||
|
||||
// clockResGet is the WASI function named clockResGetName that returns the
|
||||
// clockResGet is the WASI function named ClockResGetName that returns the
|
||||
// resolution of time values returned by clockTimeGet.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -51,7 +37,7 @@ const (
|
||||
// Note: This is similar to `clock_getres` in POSIX.
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_res_getid-clockid---errno-timestamp
|
||||
// See https://linux.die.net/man/3/clock_getres
|
||||
var clockResGet = newHostFunc(clockResGetName, clockResGetFn, []api.ValueType{i32, i32}, "id", "result.resolution")
|
||||
var clockResGet = newHostFunc(ClockResGetName, clockResGetFn, []api.ValueType{i32, i32}, "id", "result.resolution")
|
||||
|
||||
func clockResGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
@@ -59,9 +45,9 @@ func clockResGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
|
||||
var resolution uint64 // ns
|
||||
switch id {
|
||||
case clockIDRealtime:
|
||||
case ClockIDRealtime:
|
||||
resolution = uint64(sysCtx.WalltimeResolution())
|
||||
case clockIDMonotonic:
|
||||
case ClockIDMonotonic:
|
||||
resolution = uint64(sysCtx.NanotimeResolution())
|
||||
default:
|
||||
return ErrnoInval
|
||||
@@ -73,7 +59,7 @@ func clockResGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// clockTimeGet is the WASI function named clockTimeGetName that returns
|
||||
// clockTimeGet is the WASI function named ClockTimeGetName that returns
|
||||
// the time value of a name (time.Now).
|
||||
//
|
||||
// # Parameters
|
||||
@@ -104,7 +90,7 @@ func clockResGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
// Note: This is similar to `clock_gettime` in POSIX.
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp
|
||||
// See https://linux.die.net/man/3/clock_gettime
|
||||
var clockTimeGet = newHostFunc(clockTimeGetName, clockTimeGetFn, []api.ValueType{i32, i64, i32}, "id", "precision", "result.timestamp")
|
||||
var clockTimeGet = newHostFunc(ClockTimeGetName, clockTimeGetFn, []api.ValueType{i32, i64, i32}, "id", "precision", "result.timestamp")
|
||||
|
||||
func clockTimeGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
@@ -115,10 +101,10 @@ func clockTimeGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
|
||||
var val int64
|
||||
switch id {
|
||||
case clockIDRealtime:
|
||||
case ClockIDRealtime:
|
||||
sec, nsec := sysCtx.Walltime()
|
||||
val = (sec * time.Second.Nanoseconds()) + int64(nsec)
|
||||
case clockIDMonotonic:
|
||||
case ClockIDMonotonic:
|
||||
val = sysCtx.Nanotime()
|
||||
default:
|
||||
return ErrnoInval
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
func Test_clockResGet(t *testing.T) {
|
||||
@@ -32,7 +33,7 @@ func Test_clockResGet(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "Realtime",
|
||||
clockID: clockIDRealtime,
|
||||
clockID: ClockIDRealtime,
|
||||
expectedMemory: expectedMemoryMicro,
|
||||
expectedLog: `
|
||||
==> wasi_snapshot_preview1.clock_res_get(id=0,result.resolution=16)
|
||||
@@ -41,7 +42,7 @@ func Test_clockResGet(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Monotonic",
|
||||
clockID: clockIDMonotonic,
|
||||
clockID: ClockIDMonotonic,
|
||||
expectedMemory: expectedMemoryNano,
|
||||
expectedLog: `
|
||||
==> wasi_snapshot_preview1.clock_res_get(id=1,result.resolution=16)
|
||||
@@ -59,7 +60,7 @@ func Test_clockResGet(t *testing.T) {
|
||||
resultResolution := 16 // arbitrary offset
|
||||
maskMemory(t, mod, resultResolution+len(tc.expectedMemory))
|
||||
|
||||
requireErrno(t, ErrnoSuccess, mod, clockResGetName, uint64(tc.clockID), uint64(resultResolution))
|
||||
requireErrno(t, ErrnoSuccess, mod, ClockResGetName, uint64(tc.clockID), uint64(resultResolution))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
|
||||
actual, ok := mod.Memory().Read(uint32(resultResolution-1), uint32(len(tc.expectedMemory)))
|
||||
@@ -115,7 +116,7 @@ func Test_clockResGet_Unsupported(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
resultResolution := 16 // arbitrary offset
|
||||
requireErrno(t, tc.expectedErrno, mod, clockResGetName, uint64(tc.clockID), uint64(resultResolution))
|
||||
requireErrno(t, tc.expectedErrno, mod, ClockResGetName, uint64(tc.clockID), uint64(resultResolution))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
@@ -133,7 +134,7 @@ func Test_clockTimeGet(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "Realtime",
|
||||
clockID: clockIDRealtime,
|
||||
clockID: ClockIDRealtime,
|
||||
expectedMemory: []byte{
|
||||
'?', // resultTimestamp is after this
|
||||
0x0, 0x0, 0x1f, 0xa6, 0x70, 0xfc, 0xc5, 0x16, // little endian-encoded epochNanos
|
||||
@@ -146,7 +147,7 @@ func Test_clockTimeGet(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Monotonic",
|
||||
clockID: clockIDMonotonic,
|
||||
clockID: ClockIDMonotonic,
|
||||
expectedMemory: []byte{
|
||||
'?', // resultTimestamp is after this
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // fake nanotime starts at zero
|
||||
@@ -167,7 +168,7 @@ func Test_clockTimeGet(t *testing.T) {
|
||||
resultTimestamp := 16 // arbitrary offset
|
||||
maskMemory(t, mod, resultTimestamp+len(tc.expectedMemory))
|
||||
|
||||
requireErrno(t, ErrnoSuccess, mod, clockTimeGetName, uint64(tc.clockID), 0 /* TODO: precision */, uint64(resultTimestamp))
|
||||
requireErrno(t, ErrnoSuccess, mod, ClockTimeGetName, uint64(tc.clockID), 0 /* TODO: precision */, uint64(resultTimestamp))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
|
||||
actual, ok := mod.Memory().Read(uint32(resultTimestamp-1), uint32(len(tc.expectedMemory)))
|
||||
@@ -223,7 +224,7 @@ func Test_clockTimeGet_Unsupported(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
resultTimestamp := 16 // arbitrary offset
|
||||
requireErrno(t, tc.expectedErrno, mod, clockTimeGetName, uint64(tc.clockID), uint64(0) /* TODO: precision */, uint64(resultTimestamp))
|
||||
requireErrno(t, tc.expectedErrno, mod, ClockTimeGetName, uint64(tc.clockID), uint64(0) /* TODO: precision */, uint64(resultTimestamp))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
@@ -264,7 +265,7 @@ func Test_clockTimeGet_Errors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, ErrnoFault, mod, clockTimeGetName, uint64(0) /* TODO: id */, uint64(0) /* TODO: precision */, uint64(tc.resultTimestamp))
|
||||
requireErrno(t, ErrnoFault, mod, ClockTimeGetName, uint64(0) /* TODO: id */, uint64(0) /* TODO: precision */, uint64(tc.resultTimestamp))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,15 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
const (
|
||||
environGetName = "environ_get"
|
||||
environSizesGetName = "environ_sizes_get"
|
||||
)
|
||||
|
||||
// environGet is the WASI function named environGetName that reads
|
||||
// environGet is the WASI function named EnvironGetName that reads
|
||||
// environment variables.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -44,7 +40,7 @@ const (
|
||||
// See environSizesGet
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_get
|
||||
// See https://en.wikipedia.org/wiki/Null-terminated_string
|
||||
var environGet = newHostFunc(environGetName, environGetFn, []api.ValueType{i32, i32}, "environ", "environ_buf")
|
||||
var environGet = newHostFunc(EnvironGetName, environGetFn, []api.ValueType{i32, i32}, "environ", "environ_buf")
|
||||
|
||||
func environGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
@@ -53,7 +49,7 @@ func environGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return writeOffsetsAndNullTerminatedValues(mod.Memory(), sysCtx.Environ(), environ, environBuf, sysCtx.EnvironSize())
|
||||
}
|
||||
|
||||
// environSizesGet is the WASI function named environSizesGetName that
|
||||
// environSizesGet is the WASI function named EnvironSizesGetName that
|
||||
// reads environment variable sizes.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -84,7 +80,7 @@ func environGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
// See environGet
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_sizes_get
|
||||
// and https://en.wikipedia.org/wiki/Null-terminated_string
|
||||
var environSizesGet = newHostFunc(environSizesGetName, environSizesGetFn, []api.ValueType{i32, i32}, "result.environc", "result.environv_len")
|
||||
var environSizesGet = newHostFunc(EnvironSizesGetName, environSizesGetFn, []api.ValueType{i32, i32}, "result.environc", "result.environv_len")
|
||||
|
||||
func environSizesGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
func Test_environGet(t *testing.T) {
|
||||
@@ -27,7 +28,7 @@ func Test_environGet(t *testing.T) {
|
||||
maskMemory(t, mod, len(expectedMemory)+int(resultEnvironBuf))
|
||||
|
||||
// Invoke environGet and check the memory side effects.
|
||||
requireErrno(t, ErrnoSuccess, mod, environGetName, uint64(resultEnviron), uint64(resultEnvironBuf))
|
||||
requireErrno(t, ErrnoSuccess, mod, EnvironGetName, uint64(resultEnviron), uint64(resultEnvironBuf))
|
||||
require.Equal(t, `
|
||||
==> wasi_snapshot_preview1.environ_get(environ=26,environ_buf=16)
|
||||
<== errno=ESUCCESS
|
||||
@@ -97,7 +98,7 @@ func Test_environGet_Errors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, ErrnoFault, mod, environGetName, uint64(tc.environ), uint64(tc.environBuf))
|
||||
requireErrno(t, ErrnoFault, mod, EnvironGetName, uint64(tc.environ), uint64(tc.environBuf))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
@@ -121,7 +122,7 @@ func Test_environSizesGet(t *testing.T) {
|
||||
maskMemory(t, mod, len(expectedMemory)+int(resultEnvironc))
|
||||
|
||||
// Invoke environSizesGet and check the memory side effects.
|
||||
requireErrno(t, ErrnoSuccess, mod, environSizesGetName, uint64(resultEnvironc), uint64(resultEnvironvLen))
|
||||
requireErrno(t, ErrnoSuccess, mod, EnvironSizesGetName, uint64(resultEnvironc), uint64(resultEnvironvLen))
|
||||
require.Equal(t, `
|
||||
==> wasi_snapshot_preview1.environ_sizes_get(result.environc=16,result.environv_len=21)
|
||||
<== errno=ESUCCESS
|
||||
@@ -189,7 +190,7 @@ func Test_environSizesGet_Errors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, ErrnoFault, mod, environSizesGetName, uint64(tc.environc), uint64(tc.environLen))
|
||||
requireErrno(t, ErrnoFault, mod, EnvironSizesGetName, uint64(tc.environc), uint64(tc.environLen))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
@@ -27,13 +28,10 @@ func Example() {
|
||||
|
||||
// Create a new WebAssembly Runtime.
|
||||
r := wazero.NewRuntime(ctx)
|
||||
defer r.Close(ctx)
|
||||
|
||||
// Instantiate WASI, which implements system I/O such as console output.
|
||||
wm, err := Instantiate(ctx, r)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
defer wm.Close(testCtx)
|
||||
wasi_snapshot_preview1.MustInstantiate(ctx, r)
|
||||
|
||||
// Compile the WebAssembly module using the default configuration.
|
||||
code, err := r.CompileModule(ctx, exitOnStartWasm)
|
||||
|
||||
@@ -8,70 +8,34 @@ import (
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"syscall"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
internalsys "github.com/tetratelabs/wazero/internal/sys"
|
||||
"github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/sys"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
const (
|
||||
fdAdviseName = "fd_advise"
|
||||
fdAllocateName = "fd_allocate"
|
||||
fdCloseName = "fd_close"
|
||||
fdDatasyncName = "fd_datasync"
|
||||
fdFdstatGetName = "fd_fdstat_get"
|
||||
fdFdstatSetFlagsName = "fd_fdstat_set_flags"
|
||||
fdFdstatSetRightsName = "fd_fdstat_set_rights"
|
||||
fdFilestatGetName = "fd_filestat_get"
|
||||
fdFilestatSetSizeName = "fd_filestat_set_size"
|
||||
fdFilestatSetTimesName = "fd_filestat_set_times"
|
||||
fdPreadName = "fd_pread"
|
||||
fdPrestatGetName = "fd_prestat_get"
|
||||
fdPrestatDirNameName = "fd_prestat_dir_name"
|
||||
fdPwriteName = "fd_pwrite"
|
||||
fdReadName = "fd_read"
|
||||
fdReaddirName = "fd_readdir"
|
||||
fdRenumberName = "fd_renumber"
|
||||
fdSeekName = "fd_seek"
|
||||
fdSyncName = "fd_sync"
|
||||
fdTellName = "fd_tell"
|
||||
fdWriteName = "fd_write"
|
||||
|
||||
pathCreateDirectoryName = "path_create_directory"
|
||||
pathFilestatGetName = "path_filestat_get"
|
||||
pathFilestatSetTimesName = "path_filestat_set_times"
|
||||
pathLinkName = "path_link"
|
||||
pathOpenName = "path_open"
|
||||
pathReadlinkName = "path_readlink"
|
||||
pathRemoveDirectoryName = "path_remove_directory"
|
||||
pathRenameName = "path_rename"
|
||||
pathSymlinkName = "path_symlink"
|
||||
pathUnlinkFileName = "path_unlink_file"
|
||||
)
|
||||
|
||||
// fdAdvise is the WASI function named fdAdviseName which provides file
|
||||
// fdAdvise is the WASI function named FdAdviseName which provides file
|
||||
// advisory information on a file descriptor.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_advisefd-fd-offset-filesize-len-filesize-advice-advice---errno
|
||||
var fdAdvise = stubFunction(
|
||||
fdAdviseName,
|
||||
FdAdviseName,
|
||||
[]wasm.ValueType{i32, i64, i64, i32},
|
||||
"fd", "offset", "len", "advice",
|
||||
)
|
||||
|
||||
// fdAllocate is the WASI function named fdAllocateName which forces the
|
||||
// fdAllocate is the WASI function named FdAllocateName which forces the
|
||||
// allocation of space in a file.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_allocatefd-fd-offset-filesize-len-filesize---errno
|
||||
var fdAllocate = stubFunction(
|
||||
fdAllocateName,
|
||||
FdAllocateName,
|
||||
[]wasm.ValueType{i32, i64, i64},
|
||||
"fd", "offset", "len",
|
||||
)
|
||||
|
||||
// fdClose is the WASI function named fdCloseName which closes a file
|
||||
// fdClose is the WASI function named FdCloseName which closes a file
|
||||
// descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -86,7 +50,7 @@ var fdAllocate = stubFunction(
|
||||
// Note: This is similar to `close` in POSIX.
|
||||
// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_close
|
||||
// and https://linux.die.net/man/3/close
|
||||
var fdClose = newHostFunc(fdCloseName, fdCloseFn, []api.ValueType{i32}, "fd")
|
||||
var fdClose = newHostFunc(FdCloseName, fdCloseFn, []api.ValueType{i32}, "fd")
|
||||
|
||||
func fdCloseFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
@@ -98,13 +62,13 @@ func fdCloseFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// fdDatasync is the WASI function named fdDatasyncName which synchronizes
|
||||
// fdDatasync is the WASI function named FdDatasyncName which synchronizes
|
||||
// the data of a file to disk.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_datasyncfd-fd---errno
|
||||
var fdDatasync = stubFunction(fdDatasyncName, []api.ValueType{i32}, "fd")
|
||||
var fdDatasync = stubFunction(FdDatasyncName, []api.ValueType{i32}, "fd")
|
||||
|
||||
// fdFdstatGet is the WASI function named fdFdstatGetName which returns the
|
||||
// fdFdstatGet is the WASI function named FdFdstatGetName which returns the
|
||||
// attributes of a file descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -141,7 +105,7 @@ var fdDatasync = stubFunction(fdDatasyncName, []api.ValueType{i32}, "fd")
|
||||
// well as additional fields.
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdstat
|
||||
// and https://linux.die.net/man/3/fsync
|
||||
var fdFdstatGet = newHostFunc(fdFdstatGetName, fdFdstatGetFn, []api.ValueType{i32, i32}, "fd", "result.stat")
|
||||
var fdFdstatGet = newHostFunc(FdFdstatGetName, fdFdstatGetFn, []api.ValueType{i32, i32}, "fd", "result.stat")
|
||||
|
||||
// fdFdstatGetFn cannot currently use proxyResultParams because fdstat is larger
|
||||
// than api.ValueTypeI64 (i64 == 8 bytes, but fdstat is 24).
|
||||
@@ -158,7 +122,7 @@ func fdFdstatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
|
||||
stat, err := fsc.StatFile(fd)
|
||||
if err != nil {
|
||||
return toErrno(err)
|
||||
return ToErrno(err)
|
||||
}
|
||||
|
||||
filetype := getWasiFiletype(stat.Mode())
|
||||
@@ -167,7 +131,7 @@ func fdFdstatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
// Determine if it is writeable
|
||||
if w := fsc.FdWriter(fd); w != nil {
|
||||
// TODO: maybe cache flags to open instead
|
||||
fdflags = wasi_snapshot_preview1.FD_APPEND
|
||||
fdflags = FD_APPEND
|
||||
}
|
||||
|
||||
writeFdstat(buf, filetype, fdflags)
|
||||
@@ -176,7 +140,7 @@ func fdFdstatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
}
|
||||
|
||||
var blockFdstat = []byte{
|
||||
wasi_snapshot_preview1.FILETYPE_BLOCK_DEVICE, 0, // filetype
|
||||
FILETYPE_BLOCK_DEVICE, 0, // filetype
|
||||
0, 0, 0, 0, 0, 0, // fdflags
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // fs_rights_base
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // fs_rights_inheriting
|
||||
@@ -189,22 +153,22 @@ func writeFdstat(buf []byte, filetype uint8, fdflags uint16) {
|
||||
buf[2] = byte(fdflags)
|
||||
}
|
||||
|
||||
// fdFdstatSetFlags is the WASI function named fdFdstatSetFlagsName which
|
||||
// fdFdstatSetFlags is the WASI function named FdFdstatSetFlagsName which
|
||||
// adjusts the flags associated with a file descriptor.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_set_flagsfd-fd-flags-fdflags---errnoand is stubbed for GrainLang per #271
|
||||
var fdFdstatSetFlags = stubFunction(fdFdstatSetFlagsName, []wasm.ValueType{i32, i32}, "fd", "flags")
|
||||
var fdFdstatSetFlags = stubFunction(FdFdstatSetFlagsName, []wasm.ValueType{i32, i32}, "fd", "flags")
|
||||
|
||||
// fdFdstatSetRights will not be implemented as rights were removed from WASI.
|
||||
//
|
||||
// See https://github.com/bytecodealliance/wasmtime/pull/4666
|
||||
var fdFdstatSetRights = stubFunction(
|
||||
fdFdstatSetRightsName,
|
||||
FdFdstatSetRightsName,
|
||||
[]wasm.ValueType{i32, i64, i64},
|
||||
"fd", "fs_rights_base", "fs_rights_inheriting",
|
||||
)
|
||||
|
||||
// fdFilestatGet is the WASI function named fdFilestatGetName which returns
|
||||
// fdFilestatGet is the WASI function named FdFilestatGetName which returns
|
||||
// the stat attributes of an open file.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -251,7 +215,7 @@ var fdFdstatSetRights = stubFunction(
|
||||
// Note: This is similar to `fstat` in POSIX.
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_getfd-fd---errno-filestat
|
||||
// and https://linux.die.net/man/3/fstat
|
||||
var fdFilestatGet = newHostFunc(fdFilestatGetName, fdFilestatGetFn, []api.ValueType{i32, i32}, "fd", "result.filestat")
|
||||
var fdFilestatGet = newHostFunc(FdFilestatGetName, fdFilestatGetFn, []api.ValueType{i32, i32}, "fd", "result.filestat")
|
||||
|
||||
// fdFilestatGetFn cannot currently use proxyResultParams because filestat is
|
||||
// larger than api.ValueTypeI64 (i64 == 8 bytes, but filestat is 64).
|
||||
@@ -270,7 +234,7 @@ func fdFilestatGetFunc(mod api.Module, fd, resultBuf uint32) Errno {
|
||||
|
||||
stat, err := fsc.StatFile(fd)
|
||||
if err != nil {
|
||||
return toErrno(err)
|
||||
return ToErrno(err)
|
||||
}
|
||||
|
||||
writeFilestat(buf, stat)
|
||||
@@ -279,17 +243,17 @@ func fdFilestatGetFunc(mod api.Module, fd, resultBuf uint32) Errno {
|
||||
}
|
||||
|
||||
func getWasiFiletype(fileMode fs.FileMode) uint8 {
|
||||
wasiFileType := wasi_snapshot_preview1.FILETYPE_UNKNOWN
|
||||
wasiFileType := FILETYPE_UNKNOWN
|
||||
if fileMode&fs.ModeDevice != 0 {
|
||||
wasiFileType = wasi_snapshot_preview1.FILETYPE_BLOCK_DEVICE
|
||||
wasiFileType = FILETYPE_BLOCK_DEVICE
|
||||
} else if fileMode&fs.ModeCharDevice != 0 {
|
||||
wasiFileType = wasi_snapshot_preview1.FILETYPE_CHARACTER_DEVICE
|
||||
wasiFileType = FILETYPE_CHARACTER_DEVICE
|
||||
} else if fileMode&fs.ModeDir != 0 {
|
||||
wasiFileType = wasi_snapshot_preview1.FILETYPE_DIRECTORY
|
||||
wasiFileType = FILETYPE_DIRECTORY
|
||||
} else if fileMode&fs.ModeType == 0 {
|
||||
wasiFileType = wasi_snapshot_preview1.FILETYPE_REGULAR_FILE
|
||||
wasiFileType = FILETYPE_REGULAR_FILE
|
||||
} else if fileMode&fs.ModeSymlink != 0 {
|
||||
wasiFileType = wasi_snapshot_preview1.FILETYPE_SYMBOLIC_LINK
|
||||
wasiFileType = FILETYPE_SYMBOLIC_LINK
|
||||
}
|
||||
return wasiFileType
|
||||
}
|
||||
@@ -297,7 +261,7 @@ func getWasiFiletype(fileMode fs.FileMode) uint8 {
|
||||
var blockFilestat = []byte{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // device
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // inode
|
||||
wasi_snapshot_preview1.FILETYPE_BLOCK_DEVICE, 0, 0, 0, 0, 0, 0, 0, // filetype
|
||||
FILETYPE_BLOCK_DEVICE, 0, 0, 0, 0, 0, 0, 0, // filetype
|
||||
1, 0, 0, 0, 0, 0, 0, 0, // nlink
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // filesize
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // atim
|
||||
@@ -319,30 +283,30 @@ func writeFilestat(buf []byte, stat fs.FileInfo) {
|
||||
le.PutUint64(buf[56:], uint64(mtim)) // ctim
|
||||
}
|
||||
|
||||
// fdFilestatSetSize is the WASI function named fdFilestatSetSizeName which
|
||||
// fdFilestatSetSize is the WASI function named FdFilestatSetSizeName which
|
||||
// adjusts the size of an open file.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_sizefd-fd-size-filesize---errno
|
||||
var fdFilestatSetSize = stubFunction(fdFilestatSetSizeName, []wasm.ValueType{i32, i64}, "fd", "size")
|
||||
var fdFilestatSetSize = stubFunction(FdFilestatSetSizeName, []wasm.ValueType{i32, i64}, "fd", "size")
|
||||
|
||||
// fdFilestatSetTimes is the WASI function named functionFdFilestatSetTimes
|
||||
// which adjusts the times of an open file.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_timesfd-fd-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno
|
||||
var fdFilestatSetTimes = stubFunction(
|
||||
fdFilestatSetTimesName,
|
||||
FdFilestatSetTimesName,
|
||||
[]wasm.ValueType{i32, i64, i64, i32},
|
||||
"fd", "atim", "mtim", "fst_flags",
|
||||
)
|
||||
|
||||
// fdPread is the WASI function named fdPreadName which reads from a file
|
||||
// fdPread is the WASI function named FdPreadName which reads from a file
|
||||
// descriptor, without using and updating the file descriptor's offset.
|
||||
//
|
||||
// Except for handling offset, this implementation is identical to fdRead.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_preadfd-fd-iovs-iovec_array-offset-filesize---errno-size
|
||||
var fdPread = newHostFunc(
|
||||
fdPreadName, fdPreadFn,
|
||||
FdPreadName, fdPreadFn,
|
||||
[]api.ValueType{i32, i32, i32, i64, i32},
|
||||
"fd", "iovs", "iovs_len", "offset", "result.nread",
|
||||
)
|
||||
@@ -351,7 +315,7 @@ func fdPreadFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return fdReadOrPread(mod, params, true)
|
||||
}
|
||||
|
||||
// fdPrestatGet is the WASI function named fdPrestatGetName which returns
|
||||
// fdPrestatGet is the WASI function named FdPrestatGetName which returns
|
||||
// the prestat data of a file descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -382,14 +346,14 @@ func fdPreadFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
//
|
||||
// See fdPrestatDirName and
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#prestat
|
||||
var fdPrestatGet = newHostFunc(fdPrestatGetName, fdPrestatGetFn, []api.ValueType{i32, i32}, "fd", "result.prestat")
|
||||
var fdPrestatGet = newHostFunc(FdPrestatGetName, fdPrestatGetFn, []api.ValueType{i32, i32}, "fd", "result.prestat")
|
||||
|
||||
func fdPrestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
fd, resultPrestat := uint32(params[0]), uint32(params[1])
|
||||
|
||||
// Currently, we only pre-open the root file descriptor.
|
||||
if fd != internalsys.FdRoot {
|
||||
if fd != sys.FdRoot {
|
||||
return ErrnoBadf
|
||||
}
|
||||
|
||||
@@ -407,7 +371,7 @@ func fdPrestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// fdPrestatDirName is the WASI function named fdPrestatDirNameName which
|
||||
// fdPrestatDirName is the WASI function named FdPrestatDirNameName which
|
||||
// returns the path of the pre-opened directory of a file descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -438,7 +402,7 @@ func fdPrestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
// See fdPrestatGet
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_dir_name
|
||||
var fdPrestatDirName = newHostFunc(
|
||||
fdPrestatDirNameName, fdPrestatDirNameFn,
|
||||
FdPrestatDirNameName, fdPrestatDirNameFn,
|
||||
[]api.ValueType{i32, i32, i32},
|
||||
"fd", "result.path", "result.path_len",
|
||||
)
|
||||
@@ -448,7 +412,7 @@ func fdPrestatDirNameFn(_ context.Context, mod api.Module, params []uint64) Errn
|
||||
fd, path, pathLen := uint32(params[0]), uint32(params[1]), uint32(params[2])
|
||||
|
||||
// Currently, we only pre-open the root file descriptor.
|
||||
if fd != internalsys.FdRoot {
|
||||
if fd != sys.FdRoot {
|
||||
return ErrnoBadf
|
||||
}
|
||||
|
||||
@@ -468,17 +432,17 @@ func fdPrestatDirNameFn(_ context.Context, mod api.Module, params []uint64) Errn
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// fdPwrite is the WASI function named fdPwriteName which writes to a file
|
||||
// fdPwrite is the WASI function named FdPwriteName which writes to a file
|
||||
// descriptor, without using and updating the file descriptor's offset.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_pwritefd-fd-iovs-ciovec_array-offset-filesize---errno-size
|
||||
var fdPwrite = stubFunction(
|
||||
fdPwriteName,
|
||||
FdPwriteName,
|
||||
[]wasm.ValueType{i32, i32, i32, i64, i32},
|
||||
"fd", "iovs", "iovs_len", "offset", "result.nwritten",
|
||||
)
|
||||
|
||||
// fdRead is the WASI function named fdReadName which reads from a file
|
||||
// fdRead is the WASI function named FdReadName which reads from a file
|
||||
// descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -528,7 +492,7 @@ var fdPwrite = stubFunction(
|
||||
// See fdWrite
|
||||
// and https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read
|
||||
var fdRead = newHostFunc(
|
||||
fdReadName, fdReadFn,
|
||||
FdReadName, fdReadFn,
|
||||
[]api.ValueType{i32, i32, i32, i32},
|
||||
"fd", "iovs", "iovs_len", "result.nread",
|
||||
)
|
||||
@@ -619,12 +583,12 @@ func fdRead_shouldContinueRead(n, l uint32, err error) (bool, Errno) {
|
||||
return n == l && n != 0, ErrnoSuccess
|
||||
}
|
||||
|
||||
// fdReaddir is the WASI function named fdReaddirName which reads directory
|
||||
// fdReaddir is the WASI function named FdReaddirName which reads directory
|
||||
// entries from a directory.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_readdirfd-fd-buf-pointeru8-buf_len-size-cookie-dircookie---errno-size
|
||||
var fdReaddir = newHostFunc(
|
||||
fdReaddirName, fdReaddirFn,
|
||||
FdReaddirName, fdReaddirFn,
|
||||
[]wasm.ValueType{i32, i32, i32, i64, i32},
|
||||
"fd", "buf", "buf_len", "cookie", "result.bufused",
|
||||
)
|
||||
@@ -644,7 +608,7 @@ func fdReaddirFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
|
||||
// The bufLen must be enough to write a dirent. Otherwise, the caller can't
|
||||
// read what the next cookie is.
|
||||
if bufLen < direntSize {
|
||||
if bufLen < DirentSize {
|
||||
return ErrnoInval
|
||||
}
|
||||
|
||||
@@ -660,10 +624,10 @@ func fdReaddirFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
}
|
||||
|
||||
// First, determine the maximum directory entries that can be encoded as
|
||||
// dirents. The total size is direntSize(24) + nameSize, for each file.
|
||||
// dirents. The total size is DirentSize(24) + nameSize, for each file.
|
||||
// Since a zero-length file name is invalid, the minimum size entry is
|
||||
// 25 (direntSize + 1 character).
|
||||
maxDirEntries := int(bufLen/direntSize + 1)
|
||||
// 25 (DirentSize + 1 character).
|
||||
maxDirEntries := int(bufLen/DirentSize + 1)
|
||||
|
||||
// While unlikely maxDirEntries will fit into bufLen, add one more just in
|
||||
// case, as we need to know if we hit the end of the directory or not to
|
||||
@@ -719,10 +683,10 @@ func fdReaddirFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
const largestDirent = int64(math.MaxUint32 - direntSize)
|
||||
const largestDirent = int64(math.MaxUint32 - DirentSize)
|
||||
|
||||
// lastDirEntries is broken out from fdReaddirFn for testability.
|
||||
func lastDirEntries(dir *internalsys.ReadDir, cookie int64) (entries []fs.DirEntry, errno Errno) {
|
||||
func lastDirEntries(dir *sys.ReadDir, cookie int64) (entries []fs.DirEntry, errno Errno) {
|
||||
if cookie < 0 {
|
||||
errno = ErrnoInval // invalid as we will never send a negative cookie.
|
||||
return
|
||||
@@ -757,10 +721,6 @@ func lastDirEntries(dir *internalsys.ReadDir, cookie int64) (entries []fs.DirEnt
|
||||
return
|
||||
}
|
||||
|
||||
// direntSize is the size of the dirent struct, which should be followed by the
|
||||
// length of a file name.
|
||||
const direntSize = uint32(24)
|
||||
|
||||
// maxDirents returns the maximum count and total entries that can fit in
|
||||
// maxLen bytes.
|
||||
//
|
||||
@@ -773,7 +733,7 @@ const direntSize = uint32(24)
|
||||
func maxDirents(entries []fs.DirEntry, bufLen uint32) (bufused, direntCount uint32, writeTruncatedEntry bool) {
|
||||
lenRemaining := bufLen
|
||||
for _, e := range entries {
|
||||
if lenRemaining < direntSize {
|
||||
if lenRemaining < DirentSize {
|
||||
// We don't have enough space in bufLen for another struct,
|
||||
// entry. A caller who wants more will retry.
|
||||
|
||||
@@ -787,9 +747,9 @@ func maxDirents(entries []fs.DirEntry, bufLen uint32) (bufused, direntCount uint
|
||||
nameLen := int64(len(e.Name()))
|
||||
var entryLen uint32
|
||||
|
||||
// Check to see if direntSize + nameLen overflows, or if it would be
|
||||
// Check to see if DirentSize + nameLen overflows, or if it would be
|
||||
// larger than possible to encode.
|
||||
if el := int64(direntSize) + nameLen; el < 0 || el > largestDirent {
|
||||
if el := int64(DirentSize) + nameLen; el < 0 || el > largestDirent {
|
||||
// panic, as testing is difficult. ex we would have to extract a
|
||||
// function to get size of a string or allocate a 2^32 size one!
|
||||
panic("invalid filename: too large")
|
||||
@@ -801,8 +761,8 @@ func maxDirents(entries []fs.DirEntry, bufLen uint32) (bufused, direntCount uint
|
||||
// We haven't room to write the entry, and docs say to write the
|
||||
// header. This helps especially when there is an entry with a very
|
||||
// long filename. Ex if bufLen is 4096 and the filename is 4096,
|
||||
// we need to write direntSize(24) + 4096 bytes to write the entry.
|
||||
// In this case, we only write up to direntSize(24) to allow the
|
||||
// we need to write DirentSize(24) + 4096 bytes to write the entry.
|
||||
// In this case, we only write up to DirentSize(24) to allow the
|
||||
// caller to resize.
|
||||
|
||||
// bufused == bufLen means more entries exist, which is the case
|
||||
@@ -839,7 +799,7 @@ func writeDirents(
|
||||
nameLen := uint32(len(e.Name()))
|
||||
|
||||
writeDirent(dirents[pos:], d_next, nameLen, e.IsDir())
|
||||
pos += direntSize
|
||||
pos += DirentSize
|
||||
|
||||
copy(dirents[pos:], e.Name())
|
||||
pos += nameLen
|
||||
@@ -851,7 +811,7 @@ func writeDirents(
|
||||
}
|
||||
|
||||
// Write a dirent without its name
|
||||
dirent := make([]byte, direntSize)
|
||||
dirent := make([]byte, DirentSize)
|
||||
e := entries[i]
|
||||
writeDirent(dirent, d_next, uint32(len(e.Name())), e.IsDir())
|
||||
|
||||
@@ -859,21 +819,21 @@ func writeDirents(
|
||||
copy(dirents[pos:], dirent)
|
||||
}
|
||||
|
||||
// writeDirent writes direntSize bytes
|
||||
// writeDirent writes DirentSize bytes
|
||||
func writeDirent(buf []byte, dNext uint64, dNamlen uint32, dType bool) {
|
||||
le.PutUint64(buf, dNext) // d_next
|
||||
le.PutUint64(buf[8:], 0) // no d_ino
|
||||
le.PutUint32(buf[16:], dNamlen) // d_namlen
|
||||
|
||||
filetype := wasi_snapshot_preview1.FILETYPE_REGULAR_FILE
|
||||
filetype := FILETYPE_REGULAR_FILE
|
||||
if dType {
|
||||
filetype = wasi_snapshot_preview1.FILETYPE_DIRECTORY
|
||||
filetype = FILETYPE_DIRECTORY
|
||||
}
|
||||
le.PutUint32(buf[20:], uint32(filetype)) // d_type
|
||||
}
|
||||
|
||||
// openedDir returns the directory and ErrnoSuccess if the fd points to a readable directory.
|
||||
func openedDir(fsc *internalsys.FSContext, fd uint32) (fs.ReadDirFile, *internalsys.ReadDir, Errno) {
|
||||
func openedDir(fsc *sys.FSContext, fd uint32) (fs.ReadDirFile, *sys.ReadDir, Errno) {
|
||||
if f, ok := fsc.OpenedFile(fd); !ok {
|
||||
return nil, nil, ErrnoBadf
|
||||
} else if d, ok := f.File.(fs.ReadDirFile); !ok {
|
||||
@@ -886,19 +846,19 @@ func openedDir(fsc *internalsys.FSContext, fd uint32) (fs.ReadDirFile, *internal
|
||||
return nil, nil, ErrnoBadf
|
||||
} else {
|
||||
if f.ReadDir == nil {
|
||||
f.ReadDir = &internalsys.ReadDir{}
|
||||
f.ReadDir = &sys.ReadDir{}
|
||||
}
|
||||
return d, f.ReadDir, ErrnoSuccess
|
||||
}
|
||||
}
|
||||
|
||||
// fdRenumber is the WASI function named fdRenumberName which atomically
|
||||
// fdRenumber is the WASI function named FdRenumberName which atomically
|
||||
// replaces a file descriptor by renumbering another file descriptor.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_renumberfd-fd-to-fd---errno
|
||||
var fdRenumber = stubFunction(fdRenumberName, []wasm.ValueType{i32, i32}, "fd", "to")
|
||||
var fdRenumber = stubFunction(FdRenumberName, []wasm.ValueType{i32, i32}, "fd", "to")
|
||||
|
||||
// fdSeek is the WASI function named fdSeekName which moves the offset of a
|
||||
// fdSeek is the WASI function named FdSeekName which moves the offset of a
|
||||
// file descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -936,7 +896,7 @@ var fdRenumber = stubFunction(fdRenumberName, []wasm.ValueType{i32, i32}, "fd",
|
||||
// See io.Seeker
|
||||
// and https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_seek
|
||||
var fdSeek = newHostFunc(
|
||||
fdSeekName, fdSeekFn,
|
||||
FdSeekName, fdSeekFn,
|
||||
[]api.ValueType{i32, i64, i32, i32},
|
||||
"fd", "offset", "whence", "result.newoffset",
|
||||
)
|
||||
@@ -948,7 +908,7 @@ func fdSeekFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
whence := uint32(params[2])
|
||||
resultNewoffset := uint32(params[3])
|
||||
|
||||
if fd == internalsys.FdRoot {
|
||||
if fd == sys.FdRoot {
|
||||
return ErrnoBadf // cannot seek a directory
|
||||
}
|
||||
|
||||
@@ -976,19 +936,19 @@ func fdSeekFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// fdSync is the WASI function named fdSyncName which synchronizes the data
|
||||
// fdSync is the WASI function named FdSyncName which synchronizes the data
|
||||
// and metadata of a file to disk.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_syncfd-fd---errno
|
||||
var fdSync = stubFunction(fdSyncName, []api.ValueType{i32}, "fd")
|
||||
var fdSync = stubFunction(FdSyncName, []api.ValueType{i32}, "fd")
|
||||
|
||||
// fdTell is the WASI function named fdTellName which returns the current
|
||||
// fdTell is the WASI function named FdTellName which returns the current
|
||||
// offset of a file descriptor.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_tellfd-fd---errno-filesize
|
||||
var fdTell = stubFunction(fdTellName, []wasm.ValueType{i32, i32}, "fd", "result.offset")
|
||||
var fdTell = stubFunction(FdTellName, []wasm.ValueType{i32, i32}, "fd", "result.offset")
|
||||
|
||||
// fdWrite is the WASI function named fdWriteName which writes to a file
|
||||
// fdWrite is the WASI function named FdWriteName which writes to a file
|
||||
// descriptor.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -1047,7 +1007,7 @@ var fdTell = stubFunction(fdTellName, []wasm.ValueType{i32, i32}, "fd", "result.
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#ciovec
|
||||
// and https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_write
|
||||
var fdWrite = newHostFunc(
|
||||
fdWriteName, fdWriteFn,
|
||||
FdWriteName, fdWriteFn,
|
||||
[]api.ValueType{i32, i32, i32, i32},
|
||||
"fd", "iovs", "iovs_len", "result.nwritten",
|
||||
)
|
||||
@@ -1100,17 +1060,17 @@ func fdWriteFn(ctx context.Context, mod api.Module, params []uint64) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// pathCreateDirectory is the WASI function named pathCreateDirectoryName
|
||||
// pathCreateDirectory is the WASI function named PathCreateDirectoryName
|
||||
// which creates a directory.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_create_directoryfd-fd-path-string---errno
|
||||
var pathCreateDirectory = stubFunction(
|
||||
pathCreateDirectoryName,
|
||||
PathCreateDirectoryName,
|
||||
[]wasm.ValueType{i32, i32, i32},
|
||||
"fd", "path", "path_len",
|
||||
)
|
||||
|
||||
// pathFilestatGet is the WASI function named pathFilestatGetName which
|
||||
// pathFilestatGet is the WASI function named PathFilestatGetName which
|
||||
// returns the stat attributes of a file or directory.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -1139,7 +1099,7 @@ var pathCreateDirectory = stubFunction(
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_getfd-fd-flags-lookupflags-path-string---errno-filestat
|
||||
// and https://linux.die.net/man/2/fstatat
|
||||
var pathFilestatGet = newHostFunc(
|
||||
pathFilestatGetName, pathFilestatGetFn,
|
||||
PathFilestatGetName, pathFilestatGetFn,
|
||||
[]api.ValueType{i32, i32, i32, i32, i32},
|
||||
"fd", "flags", "path", "path_len", "result.filestat",
|
||||
)
|
||||
@@ -1192,27 +1152,27 @@ func pathFilestatGetFn(_ context.Context, mod api.Module, params []uint64) Errno
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// pathFilestatSetTimes is the WASI function named pathFilestatSetTimesName
|
||||
// pathFilestatSetTimes is the WASI function named PathFilestatSetTimesName
|
||||
// which adjusts the timestamps of a file or directory.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_set_timesfd-fd-flags-lookupflags-path-string-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno
|
||||
var pathFilestatSetTimes = stubFunction(
|
||||
pathFilestatSetTimesName,
|
||||
PathFilestatSetTimesName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i64, i64, i32},
|
||||
"fd", "flags", "path", "path_len", "atim", "mtim", "fst_flags",
|
||||
)
|
||||
|
||||
// pathLink is the WASI function named pathLinkName which adjusts the
|
||||
// pathLink is the WASI function named PathLinkName which adjusts the
|
||||
// timestamps of a file or directory.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_link
|
||||
var pathLink = stubFunction(
|
||||
pathLinkName,
|
||||
PathLinkName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i32, i32, i32},
|
||||
"old_fd", "old_flags", "old_path", "old_path_len", "new_fd", "new_path", "new_path_len",
|
||||
)
|
||||
|
||||
// pathOpen is the WASI function named pathOpenName which opens a file or
|
||||
// pathOpen is the WASI function named PathOpenName which opens a file or
|
||||
// directory. This returns ErrnoBadf if the fd is invalid.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -1266,7 +1226,7 @@ var pathLink = stubFunction(
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#path_open
|
||||
var pathOpen = newHostFunc(
|
||||
pathOpenName, pathOpenFn,
|
||||
PathOpenName, pathOpenFn,
|
||||
[]api.ValueType{i32, i32, i32, i32, i32, i64, i64, i32, i32},
|
||||
"fd", "dirflags", "path", "path_len", "oflags", "fs_rights_base", "fs_rights_inheriting", "fdflags", "result.opened_fd",
|
||||
)
|
||||
@@ -1319,14 +1279,14 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
pathName := string(b)
|
||||
var newFD uint32
|
||||
var err error
|
||||
if isDir && oflags&wasi_snapshot_preview1.O_CREAT != 0 {
|
||||
if isDir && oflags&O_CREAT != 0 {
|
||||
newFD, err = fsc.Mkdir(pathName, 0o700)
|
||||
} else {
|
||||
newFD, err = fsc.OpenFile(pathName, fileOpenFlags, 0o600)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return toErrno(err)
|
||||
return ToErrno(err)
|
||||
}
|
||||
|
||||
// Check any flags that require the file to evaluate.
|
||||
@@ -1344,9 +1304,9 @@ func pathOpenFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
}
|
||||
|
||||
func openFlags(oflags, fdflags uint16) (openFlags int, isDir bool) {
|
||||
isDir = oflags&wasi_snapshot_preview1.O_DIRECTORY != 0
|
||||
isDir = oflags&O_DIRECTORY != 0
|
||||
openFlags = os.O_RDONLY
|
||||
if oflags&wasi_snapshot_preview1.O_CREAT != 0 {
|
||||
if oflags&O_CREAT != 0 {
|
||||
if !isDir { // assume read write
|
||||
openFlags = os.O_RDWR
|
||||
}
|
||||
@@ -1355,19 +1315,19 @@ func openFlags(oflags, fdflags uint16) (openFlags int, isDir bool) {
|
||||
if isDir {
|
||||
return
|
||||
}
|
||||
if oflags&wasi_snapshot_preview1.O_EXCL != 0 {
|
||||
if oflags&O_EXCL != 0 {
|
||||
openFlags |= os.O_EXCL
|
||||
}
|
||||
if oflags&wasi_snapshot_preview1.O_TRUNC != 0 {
|
||||
if oflags&O_TRUNC != 0 {
|
||||
openFlags |= os.O_TRUNC
|
||||
}
|
||||
if fdflags&wasi_snapshot_preview1.FD_APPEND != 0 {
|
||||
if fdflags&FD_APPEND != 0 {
|
||||
openFlags |= os.O_APPEND
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func failIfNotDirectory(fsc *internalsys.FSContext, fd uint32) Errno {
|
||||
func failIfNotDirectory(fsc *sys.FSContext, fd uint32) Errno {
|
||||
// Lookup the previous file
|
||||
if f, ok := fsc.OpenedFile(fd); !ok {
|
||||
return ErrnoBadf
|
||||
@@ -1378,86 +1338,61 @@ func failIfNotDirectory(fsc *internalsys.FSContext, fd uint32) Errno {
|
||||
return ErrnoSuccess
|
||||
}
|
||||
|
||||
// pathReadlink is the WASI function named pathReadlinkName that reads the
|
||||
// pathReadlink is the WASI function named PathReadlinkName that reads the
|
||||
// contents of a symbolic link.
|
||||
//
|
||||
// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_readlinkfd-fd-path-string-buf-pointeru8-buf_len-size---errno-size
|
||||
var pathReadlink = stubFunction(
|
||||
pathReadlinkName,
|
||||
PathReadlinkName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i32, i32},
|
||||
"fd", "path", "path_len", "buf", "buf_len", "result.bufused",
|
||||
)
|
||||
|
||||
// pathRemoveDirectory is the WASI function named pathRemoveDirectoryName
|
||||
// pathRemoveDirectory is the WASI function named PathRemoveDirectoryName
|
||||
// which removes a directory.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_remove_directoryfd-fd-path-string---errno
|
||||
var pathRemoveDirectory = stubFunction(
|
||||
pathRemoveDirectoryName,
|
||||
PathRemoveDirectoryName,
|
||||
[]wasm.ValueType{i32, i32, i32},
|
||||
"fd", "path", "path_len",
|
||||
)
|
||||
|
||||
// pathRename is the WASI function named pathRenameName which renames a
|
||||
// pathRename is the WASI function named PathRenameName which renames a
|
||||
// file or directory.
|
||||
var pathRename = stubFunction(
|
||||
pathRenameName,
|
||||
PathRenameName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i32, i32},
|
||||
"fd", "old_path", "old_path_len", "new_fd", "new_path", "new_path_len",
|
||||
)
|
||||
|
||||
// pathSymlink is the WASI function named pathSymlinkName which creates a
|
||||
// pathSymlink is the WASI function named PathSymlinkName which creates a
|
||||
// symbolic link.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_symlink
|
||||
var pathSymlink = stubFunction(
|
||||
pathSymlinkName,
|
||||
PathSymlinkName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i32},
|
||||
"old_path", "old_path_len", "fd", "new_path", "new_path_len",
|
||||
)
|
||||
|
||||
// pathUnlinkFile is the WASI function named pathUnlinkFileName which
|
||||
// pathUnlinkFile is the WASI function named PathUnlinkFileName which
|
||||
// unlinks a file.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_unlink_filefd-fd-path-string---errno
|
||||
var pathUnlinkFile = stubFunction(
|
||||
pathUnlinkFileName,
|
||||
PathUnlinkFileName,
|
||||
[]wasm.ValueType{i32, i32, i32},
|
||||
"fd", "path", "path_len",
|
||||
)
|
||||
|
||||
// statFile attempts to stat the file at the given path. Errors coerce to WASI
|
||||
// Errno.
|
||||
func statFile(fsc *internalsys.FSContext, name string) (stat fs.FileInfo, errno Errno) {
|
||||
func statFile(fsc *sys.FSContext, name string) (stat fs.FileInfo, errno Errno) {
|
||||
var err error
|
||||
stat, err = fsc.StatPath(name)
|
||||
if err != nil {
|
||||
errno = toErrno(err)
|
||||
errno = ToErrno(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// toErrno coerces the error to a WASI Errno.
|
||||
//
|
||||
// Note: Coercion isn't centralized in sys.FSContext because ABI use different
|
||||
// error codes. For example, wasi-filesystem and GOOS=js don't map to these
|
||||
// Errno.
|
||||
func toErrno(err error) Errno {
|
||||
// handle all the cases of FS.Open or internal to FSContext.OpenFile
|
||||
switch {
|
||||
case errors.Is(err, syscall.ENOSYS):
|
||||
return ErrnoNosys
|
||||
case errors.Is(err, fs.ErrInvalid):
|
||||
return ErrnoInval
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
// fs.FS is allowed to return this instead of ErrInvalid on an invalid path
|
||||
return ErrnoNoent
|
||||
case errors.Is(err, fs.ErrExist):
|
||||
return ErrnoExist
|
||||
case errors.Is(err, syscall.EBADF):
|
||||
// fsc.OpenFile currently returns this on out of file descriptors
|
||||
return ErrnoBadf
|
||||
default:
|
||||
return ErrnoIo
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
361
imports/wasi_snapshot_preview1/fs_unit_test.go
Normal file
361
imports/wasi_snapshot_preview1/fs_unit_test.go
Normal file
@@ -0,0 +1,361 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/sys"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
func Test_fdRead_shouldContinueRead(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
n, l uint32
|
||||
err error
|
||||
expectedOk bool
|
||||
expectedErrno Errno
|
||||
}{
|
||||
{
|
||||
name: "break when nothing to read",
|
||||
n: 0,
|
||||
l: 0,
|
||||
},
|
||||
{
|
||||
name: "break when nothing read",
|
||||
n: 0,
|
||||
l: 4,
|
||||
},
|
||||
{
|
||||
name: "break on partial read",
|
||||
n: 3,
|
||||
l: 4,
|
||||
},
|
||||
{
|
||||
name: "continue on full read",
|
||||
n: 4,
|
||||
l: 4,
|
||||
expectedOk: true,
|
||||
},
|
||||
{
|
||||
name: "break on EOF on nothing to read",
|
||||
err: io.EOF,
|
||||
},
|
||||
{
|
||||
name: "break on EOF on nothing read",
|
||||
l: 4,
|
||||
err: io.EOF,
|
||||
},
|
||||
{
|
||||
name: "break on EOF on partial read",
|
||||
n: 3,
|
||||
l: 4,
|
||||
err: io.EOF,
|
||||
},
|
||||
{
|
||||
name: "break on EOF on full read",
|
||||
n: 4,
|
||||
l: 4,
|
||||
err: io.EOF,
|
||||
},
|
||||
{
|
||||
name: "return ErrnoIo on error on nothing to read",
|
||||
err: io.ErrClosedPipe,
|
||||
expectedErrno: ErrnoIo,
|
||||
},
|
||||
{
|
||||
name: "return ErrnoIo on error on nothing read",
|
||||
l: 4,
|
||||
err: io.ErrClosedPipe,
|
||||
expectedErrno: ErrnoIo,
|
||||
},
|
||||
{ // Special case, allows processing data before err
|
||||
name: "break on error on partial read",
|
||||
n: 3,
|
||||
l: 4,
|
||||
err: io.ErrClosedPipe,
|
||||
},
|
||||
{ // Special case, allows processing data before err
|
||||
name: "break on error on full read",
|
||||
n: 4,
|
||||
l: 4,
|
||||
err: io.ErrClosedPipe,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ok, errno := fdRead_shouldContinueRead(tc.n, tc.l, tc.err)
|
||||
require.Equal(t, tc.expectedOk, ok)
|
||||
require.Equal(t, tc.expectedErrno, errno)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_lastDirEntries(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
f *sys.ReadDir
|
||||
cookie int64
|
||||
expectedEntries []fs.DirEntry
|
||||
expectedErrno Errno
|
||||
}{
|
||||
{
|
||||
name: "no prior call",
|
||||
},
|
||||
{
|
||||
name: "no prior call, but passed a cookie",
|
||||
cookie: 1,
|
||||
expectedErrno: ErrnoInval,
|
||||
},
|
||||
{
|
||||
name: "cookie is negative",
|
||||
f: &sys.ReadDir{
|
||||
CountRead: 3,
|
||||
Entries: testDirEntries,
|
||||
},
|
||||
cookie: -1,
|
||||
expectedErrno: ErrnoInval,
|
||||
},
|
||||
{
|
||||
name: "cookie is greater than last d_next",
|
||||
f: &sys.ReadDir{
|
||||
CountRead: 3,
|
||||
Entries: testDirEntries,
|
||||
},
|
||||
cookie: 5,
|
||||
expectedErrno: ErrnoInval,
|
||||
},
|
||||
{
|
||||
name: "cookie is last pos",
|
||||
f: &sys.ReadDir{
|
||||
CountRead: 3,
|
||||
Entries: testDirEntries,
|
||||
},
|
||||
cookie: 3,
|
||||
expectedEntries: nil,
|
||||
},
|
||||
{
|
||||
name: "cookie is one before last pos",
|
||||
f: &sys.ReadDir{
|
||||
CountRead: 3,
|
||||
Entries: testDirEntries,
|
||||
},
|
||||
cookie: 2,
|
||||
expectedEntries: testDirEntries[2:],
|
||||
},
|
||||
{
|
||||
name: "cookie is before current entries",
|
||||
f: &sys.ReadDir{
|
||||
CountRead: 5,
|
||||
Entries: testDirEntries,
|
||||
},
|
||||
cookie: 1,
|
||||
expectedErrno: ErrnoNosys, // not implemented
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
f := tc.f
|
||||
if f == nil {
|
||||
f = &sys.ReadDir{}
|
||||
}
|
||||
entries, errno := lastDirEntries(f, tc.cookie)
|
||||
require.Equal(t, tc.expectedErrno, errno)
|
||||
require.Equal(t, tc.expectedEntries, entries)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_maxDirents(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
entries []fs.DirEntry
|
||||
maxLen uint32
|
||||
expectedCount uint32
|
||||
expectedwriteTruncatedEntry bool
|
||||
expectedBufused uint32
|
||||
}{
|
||||
{
|
||||
name: "no entries",
|
||||
},
|
||||
{
|
||||
name: "can't fit one",
|
||||
entries: testDirEntries,
|
||||
maxLen: 23,
|
||||
expectedBufused: 23,
|
||||
expectedwriteTruncatedEntry: false,
|
||||
},
|
||||
{
|
||||
name: "only fits header",
|
||||
entries: testDirEntries,
|
||||
maxLen: 24,
|
||||
expectedBufused: 24,
|
||||
expectedwriteTruncatedEntry: true,
|
||||
},
|
||||
{
|
||||
name: "one",
|
||||
entries: testDirEntries,
|
||||
maxLen: 25,
|
||||
expectedCount: 1,
|
||||
expectedBufused: 25,
|
||||
},
|
||||
{
|
||||
name: "one but not room for two's name",
|
||||
entries: testDirEntries,
|
||||
maxLen: 25 + 25,
|
||||
expectedCount: 1,
|
||||
expectedwriteTruncatedEntry: true, // can write DirentSize
|
||||
expectedBufused: 25 + 25,
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
entries: testDirEntries,
|
||||
maxLen: 25 + 26,
|
||||
expectedCount: 2,
|
||||
expectedBufused: 25 + 26,
|
||||
},
|
||||
{
|
||||
name: "two but not three's dirent",
|
||||
entries: testDirEntries,
|
||||
maxLen: 25 + 26 + 20,
|
||||
expectedCount: 2,
|
||||
expectedwriteTruncatedEntry: false, // 20 + 4 == DirentSize
|
||||
expectedBufused: 25 + 26 + 20,
|
||||
},
|
||||
{
|
||||
name: "two but not three's name",
|
||||
entries: testDirEntries,
|
||||
maxLen: 25 + 26 + 26,
|
||||
expectedCount: 2,
|
||||
expectedwriteTruncatedEntry: true, // can write DirentSize
|
||||
expectedBufused: 25 + 26 + 26,
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
entries: testDirEntries,
|
||||
maxLen: 25 + 26 + 27,
|
||||
expectedCount: 3,
|
||||
expectedwriteTruncatedEntry: false, // end of dir
|
||||
expectedBufused: 25 + 26 + 27,
|
||||
},
|
||||
{
|
||||
name: "max",
|
||||
entries: testDirEntries,
|
||||
maxLen: 100,
|
||||
expectedCount: 3,
|
||||
expectedwriteTruncatedEntry: false, // end of dir
|
||||
expectedBufused: 25 + 26 + 27,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
bufused, direntCount, writeTruncatedEntry := maxDirents(tc.entries, tc.maxLen)
|
||||
require.Equal(t, tc.expectedCount, direntCount)
|
||||
require.Equal(t, tc.expectedwriteTruncatedEntry, writeTruncatedEntry)
|
||||
require.Equal(t, tc.expectedBufused, bufused)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
fdReadDirFs = fstest.MapFS{
|
||||
"notdir": {},
|
||||
"emptydir": {Mode: fs.ModeDir},
|
||||
"dir": {Mode: fs.ModeDir},
|
||||
"dir/-": {}, // len = 24+1 = 25
|
||||
"dir/a-": {Mode: fs.ModeDir}, // len = 24+2 = 26
|
||||
"dir/ab-": {}, // len = 24+3 = 27
|
||||
}
|
||||
|
||||
testDirEntries = func() []fs.DirEntry {
|
||||
entries, err := fdReadDirFs.ReadDir("dir")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return entries
|
||||
}()
|
||||
|
||||
dirent1 = []byte{
|
||||
1, 0, 0, 0, 0, 0, 0, 0, // d_next = 1
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // d_ino = 0
|
||||
1, 0, 0, 0, // d_namlen = 1 character
|
||||
4, 0, 0, 0, // d_type = regular_file
|
||||
'-', // name
|
||||
}
|
||||
dirent2 = []byte{
|
||||
2, 0, 0, 0, 0, 0, 0, 0, // d_next = 2
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // d_ino = 0
|
||||
2, 0, 0, 0, // d_namlen = 1 character
|
||||
3, 0, 0, 0, // d_type = directory
|
||||
'a', '-', // name
|
||||
}
|
||||
dirent3 = []byte{
|
||||
3, 0, 0, 0, 0, 0, 0, 0, // d_next = 3
|
||||
0, 0, 0, 0, 0, 0, 0, 0, // d_ino = 0
|
||||
3, 0, 0, 0, // d_namlen = 3 characters
|
||||
4, 0, 0, 0, // d_type = regular_file
|
||||
'a', 'b', '-', // name
|
||||
}
|
||||
)
|
||||
|
||||
func Test_writeDirents(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
entries []fs.DirEntry
|
||||
entryCount uint32
|
||||
writeTruncatedEntry bool
|
||||
expectedEntriesBuf []byte
|
||||
}{
|
||||
{
|
||||
name: "none",
|
||||
entries: testDirEntries,
|
||||
},
|
||||
{
|
||||
name: "one",
|
||||
entries: testDirEntries,
|
||||
entryCount: 1,
|
||||
expectedEntriesBuf: dirent1,
|
||||
},
|
||||
{
|
||||
name: "two",
|
||||
entries: testDirEntries,
|
||||
entryCount: 2,
|
||||
expectedEntriesBuf: append(dirent1, dirent2...),
|
||||
},
|
||||
{
|
||||
name: "two with truncated",
|
||||
entries: testDirEntries,
|
||||
entryCount: 2,
|
||||
writeTruncatedEntry: true,
|
||||
expectedEntriesBuf: append(append(dirent1, dirent2...), dirent3[0:10]...),
|
||||
},
|
||||
{
|
||||
name: "three",
|
||||
entries: testDirEntries,
|
||||
entryCount: 3,
|
||||
expectedEntriesBuf: append(append(dirent1, dirent2...), dirent3...),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cookie := uint64(1)
|
||||
entriesBuf := make([]byte, len(tc.expectedEntriesBuf))
|
||||
writeDirents(tc.entries, tc.entryCount, tc.writeTruncatedEntry, entriesBuf, cookie)
|
||||
require.Equal(t, tc.expectedEntriesBuf, entriesBuf)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -4,22 +4,11 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
const pollOneoffName = "poll_oneoff"
|
||||
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-eventtype-enumu8
|
||||
const (
|
||||
// eventTypeClock is the timeout event named "name".
|
||||
eventTypeClock = iota
|
||||
// eventTypeFdRead is the data available event named "fd_read".
|
||||
eventTypeFdRead
|
||||
// eventTypeFdWrite is the capacity available event named "fd_write".
|
||||
eventTypeFdWrite
|
||||
)
|
||||
|
||||
// pollOneoff is the WASI function named pollOneoffName that concurrently
|
||||
// pollOneoff is the WASI function named PollOneoffName that concurrently
|
||||
// polls for the occurrence of a set of events.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -46,7 +35,7 @@ const (
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#poll_oneoff
|
||||
// See https://linux.die.net/man/3/poll
|
||||
var pollOneoff = newHostFunc(
|
||||
pollOneoffName, pollOneoffFn,
|
||||
PollOneoffName, pollOneoffFn,
|
||||
[]api.ValueType{i32, i32, i32, i32},
|
||||
"in", "out", "nsubscriptions", "result.nevents",
|
||||
)
|
||||
@@ -87,10 +76,10 @@ func pollOneoffFn(ctx context.Context, mod api.Module, params []uint64) Errno {
|
||||
eventType := inBuf[inOffset+8] // +8 past userdata
|
||||
var errno Errno // errno for this specific event
|
||||
switch eventType {
|
||||
case eventTypeClock: // handle later
|
||||
case EventTypeClock: // handle later
|
||||
// +8 past userdata +8 name alignment
|
||||
errno = processClockEvent(ctx, mod, inBuf[inOffset+8+8:])
|
||||
case eventTypeFdRead, eventTypeFdWrite:
|
||||
case EventTypeFdRead, EventTypeFdWrite:
|
||||
// +8 past userdata +4 FD alignment
|
||||
errno = processFDEvent(mod, eventType, inBuf[inOffset+8+4:])
|
||||
default:
|
||||
@@ -110,7 +99,7 @@ func pollOneoffFn(ctx context.Context, mod api.Module, params []uint64) Errno {
|
||||
|
||||
// processClockEvent supports only relative name events, as that's what's used
|
||||
// to implement sleep in various compilers including Rust, Zig and TinyGo.
|
||||
func processClockEvent(ctx context.Context, mod api.Module, inBuf []byte) Errno {
|
||||
func processClockEvent(_ context.Context, mod api.Module, inBuf []byte) Errno {
|
||||
_ /* ID */ = le.Uint32(inBuf[0:8]) // See below
|
||||
timeout := le.Uint64(inBuf[8:16]) // nanos if relative
|
||||
_ /* precision */ = le.Uint64(inBuf[16:24]) // Unused
|
||||
@@ -143,9 +132,9 @@ func processFDEvent(mod api.Module, eventType byte, inBuf []byte) Errno {
|
||||
// Choose the best error, which falls back to unsupported, until we support
|
||||
// files.
|
||||
errno := ErrnoNotsup
|
||||
if eventType == eventTypeFdRead && fsc.FdReader(fd) == nil {
|
||||
if eventType == EventTypeFdRead && fsc.FdReader(fd) == nil {
|
||||
errno = ErrnoBadf
|
||||
} else if eventType == eventTypeFdWrite && fsc.FdWriter(fd) == nil {
|
||||
} else if eventType == EventTypeFdWrite && fsc.FdWriter(fd) == nil {
|
||||
errno = ErrnoBadf
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
internalsys "github.com/tetratelabs/wazero/internal/sys"
|
||||
"github.com/tetratelabs/wazero/internal/sys"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
@@ -15,8 +16,8 @@ func Test_pollOneoff(t *testing.T) {
|
||||
|
||||
mem := []byte{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata
|
||||
eventTypeClock, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // event type and padding
|
||||
clockIDMonotonic, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // clockID
|
||||
EventTypeClock, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // event type and padding
|
||||
ClockIDMonotonic, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // clockID
|
||||
0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // timeout (ns)
|
||||
0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // precision (ns)
|
||||
0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // flags (relative)
|
||||
@@ -26,7 +27,7 @@ func Test_pollOneoff(t *testing.T) {
|
||||
expectedMem := []byte{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata
|
||||
byte(ErrnoSuccess), 0x0, // errno is 16 bit
|
||||
eventTypeClock, 0x0, 0x0, 0x0, // 4 bytes for type enum
|
||||
EventTypeClock, 0x0, 0x0, 0x0, // 4 bytes for type enum
|
||||
'?', // stopped after encoding
|
||||
}
|
||||
|
||||
@@ -38,7 +39,7 @@ func Test_pollOneoff(t *testing.T) {
|
||||
maskMemory(t, mod, 1024)
|
||||
mod.Memory().Write(in, mem)
|
||||
|
||||
requireErrno(t, ErrnoSuccess, mod, pollOneoffName, uint64(in), uint64(out), uint64(nsubscriptions),
|
||||
requireErrno(t, ErrnoSuccess, mod, PollOneoffName, uint64(in), uint64(out), uint64(nsubscriptions),
|
||||
uint64(resultNevents))
|
||||
require.Equal(t, `
|
||||
==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=1,result.nevents=512)
|
||||
@@ -110,12 +111,12 @@ func Test_pollOneoff_Errors(t *testing.T) {
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "unsupported eventTypeFdRead",
|
||||
name: "unsupported EventTypeFdRead",
|
||||
nsubscriptions: 1,
|
||||
mem: []byte{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata
|
||||
eventTypeFdRead, 0x0, 0x0, 0x0,
|
||||
byte(internalsys.FdStdin), 0x0, 0x0, 0x0, // valid readable FD
|
||||
EventTypeFdRead, 0x0, 0x0, 0x0,
|
||||
byte(sys.FdStdin), 0x0, 0x0, 0x0, // valid readable FD
|
||||
'?', // stopped after encoding
|
||||
},
|
||||
expectedErrno: ErrnoSuccess,
|
||||
@@ -124,7 +125,7 @@ func Test_pollOneoff_Errors(t *testing.T) {
|
||||
expectedMem: []byte{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata
|
||||
byte(ErrnoNotsup), 0x0, // errno is 16 bit
|
||||
eventTypeFdRead, 0x0, 0x0, 0x0, // 4 bytes for type enum
|
||||
EventTypeFdRead, 0x0, 0x0, 0x0, // 4 bytes for type enum
|
||||
'?', // stopped after encoding
|
||||
},
|
||||
expectedLog: `
|
||||
@@ -145,7 +146,7 @@ func Test_pollOneoff_Errors(t *testing.T) {
|
||||
mod.Memory().Write(tc.in, tc.mem)
|
||||
}
|
||||
|
||||
requireErrno(t, tc.expectedErrno, mod, pollOneoffName, uint64(tc.in), uint64(tc.out),
|
||||
requireErrno(t, tc.expectedErrno, mod, PollOneoffName, uint64(tc.in), uint64(tc.out),
|
||||
uint64(tc.nsubscriptions), uint64(tc.resultNevents))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
|
||||
|
||||
@@ -4,16 +4,12 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
const (
|
||||
procExitName = "proc_exit"
|
||||
procRaiseName = "proc_raise"
|
||||
)
|
||||
|
||||
// procExit is the WASI function named procExitName that terminates the
|
||||
// procExit is the WASI function named ProcExitName that terminates the
|
||||
// execution of the module with an exit code. The only successful exit code is
|
||||
// zero.
|
||||
//
|
||||
@@ -23,8 +19,8 @@ const (
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit
|
||||
var procExit = &wasm.HostFunc{
|
||||
ExportNames: []string{procExitName},
|
||||
Name: procExitName,
|
||||
ExportNames: []string{ProcExitName},
|
||||
Name: ProcExitName,
|
||||
ParamTypes: []api.ValueType{i32},
|
||||
ParamNames: []string{"rval"},
|
||||
Code: &wasm.Code{
|
||||
@@ -48,4 +44,4 @@ func procExitFn(ctx context.Context, mod api.Module, params []uint64) {
|
||||
// procRaise is stubbed and will never be supported, as it was removed.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/pull/136
|
||||
var procRaise = stubFunction(procRaiseName, []api.ValueType{i32}, "sig")
|
||||
var procRaise = stubFunction(ProcRaiseName, []api.ValueType{i32}, "sig")
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
@@ -40,7 +41,7 @@ func Test_procExit(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
// Since procExit panics, any opcodes afterwards cannot be reached.
|
||||
_, err := mod.ExportedFunction(procExitName).Call(testCtx, uint64(tc.exitCode))
|
||||
_, err := mod.ExportedFunction(ProcExitName).Call(testCtx, uint64(tc.exitCode))
|
||||
require.Error(t, err)
|
||||
sysErr, ok := err.(*sys.ExitError)
|
||||
require.True(t, ok, err)
|
||||
@@ -52,7 +53,7 @@ func Test_procExit(t *testing.T) {
|
||||
|
||||
// Test_procRaise only tests it is stubbed for GrainLang per #271
|
||||
func Test_procRaise(t *testing.T) {
|
||||
log := requireErrnoNosys(t, procRaiseName, 0)
|
||||
log := requireErrnoNosys(t, ProcRaiseName, 0)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.proc_raise(sig=0)
|
||||
<-- errno=ENOSYS
|
||||
|
||||
@@ -5,12 +5,11 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
const randomGetName = "random_get"
|
||||
|
||||
// randomGet is the WASI function named randomGetName which writes random
|
||||
// randomGet is the WASI function named RandomGetName which writes random
|
||||
// data to a buffer.
|
||||
//
|
||||
// # Parameters
|
||||
@@ -34,7 +33,7 @@ const randomGetName = "random_get"
|
||||
// buf --^
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-bufLen-size---errno
|
||||
var randomGet = newHostFunc(randomGetName, randomGetFn, []api.ValueType{i32, i32}, "buf", "buf_len")
|
||||
var randomGet = newHostFunc(RandomGetName, randomGetFn, []api.ValueType{i32, i32}, "buf", "buf_len")
|
||||
|
||||
func randomGetFn(_ context.Context, mod api.Module, params []uint64) Errno {
|
||||
sysCtx := mod.(*wasm.CallContext).Sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
func Test_randomGet(t *testing.T) {
|
||||
@@ -27,7 +28,7 @@ func Test_randomGet(t *testing.T) {
|
||||
maskMemory(t, mod, len(expectedMemory))
|
||||
|
||||
// Invoke randomGet and check the memory side effects!
|
||||
requireErrno(t, ErrnoSuccess, mod, randomGetName, uint64(offset), uint64(length))
|
||||
requireErrno(t, ErrnoSuccess, mod, RandomGetName, uint64(offset), uint64(length))
|
||||
require.Equal(t, `
|
||||
==> wasi_snapshot_preview1.random_get(buf=1,buf_len=5)
|
||||
<== errno=ESUCCESS
|
||||
@@ -75,7 +76,7 @@ func Test_randomGet_Errors(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer log.Reset()
|
||||
|
||||
requireErrno(t, ErrnoFault, mod, randomGetName, uint64(tc.offset), uint64(tc.length))
|
||||
requireErrno(t, ErrnoFault, mod, RandomGetName, uint64(tc.offset), uint64(tc.length))
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
@@ -112,7 +113,7 @@ func Test_randomGet_SourceError(t *testing.T) {
|
||||
WithRandSource(tc.randSource))
|
||||
defer r.Close(testCtx)
|
||||
|
||||
requireErrno(t, ErrnoIo, mod, randomGetName, uint64(1), uint64(5)) // arbitrary offset and length
|
||||
requireErrno(t, ErrnoIo, mod, RandomGetName, uint64(1), uint64(5)) // arbitrary offset and length
|
||||
require.Equal(t, tc.expectedLog, "\n"+log.String())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const schedYieldName = "sched_yield"
|
||||
import (
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// schedYield is the WASI function named schedYieldName which temporarily
|
||||
// schedYield is the WASI function named SchedYieldName which temporarily
|
||||
// yields execution of the calling thread.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sched_yield---errno
|
||||
var schedYield = stubFunction(schedYieldName, nil)
|
||||
var schedYield = stubFunction(SchedYieldName, nil)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// Test_schedYield only tests it is stubbed for GrainLang per #271
|
||||
func Test_schedYield(t *testing.T) {
|
||||
log := requireErrnoNosys(t, schedYieldName)
|
||||
log := requireErrnoNosys(t, SchedYieldName)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.sched_yield()
|
||||
<-- errno=ENOSYS
|
||||
|
||||
@@ -1,47 +1,43 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
import "github.com/tetratelabs/wazero/internal/wasm"
|
||||
|
||||
const (
|
||||
sockAcceptName = "sock_accept"
|
||||
sockRecvName = "sock_recv"
|
||||
sockSendName = "sock_send"
|
||||
sockShutdownName = "sock_shutdown"
|
||||
import (
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
// sockAccept is the WASI function named sockAcceptName which accepts a new
|
||||
// sockAccept is the WASI function named SockAcceptName which accepts a new
|
||||
// incoming connection.
|
||||
//
|
||||
// See: https://github.com/WebAssembly/WASI/blob/0ba0c5e2e37625ca5a6d3e4255a998dfaa3efc52/phases/snapshot/docs.md#sock_accept
|
||||
// and https://github.com/WebAssembly/WASI/pull/458
|
||||
var sockAccept = stubFunction(
|
||||
sockAcceptName,
|
||||
SockAcceptName,
|
||||
[]wasm.ValueType{i32, i32, i32},
|
||||
"fd", "flags", "result.fd",
|
||||
)
|
||||
|
||||
// sockRecv is the WASI function named sockRecvName which receives a
|
||||
// sockRecv is the WASI function named SockRecvName which receives a
|
||||
// message from a socket.
|
||||
//
|
||||
// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_recvfd-fd-ri_data-iovec_array-ri_flags-riflags---errno-size-roflags
|
||||
var sockRecv = stubFunction(
|
||||
sockRecvName,
|
||||
SockRecvName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i32, i32},
|
||||
"fd", "ri_data", "ri_data_count", "ri_flags", "result.ro_datalen", "result.ro_flags",
|
||||
)
|
||||
|
||||
// sockSend is the WASI function named sockSendName which sends a message
|
||||
// sockSend is the WASI function named SockSendName which sends a message
|
||||
// on a socket.
|
||||
//
|
||||
// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_sendfd-fd-si_data-ciovec_array-si_flags-siflags---errno-size
|
||||
var sockSend = stubFunction(
|
||||
sockSendName,
|
||||
SockSendName,
|
||||
[]wasm.ValueType{i32, i32, i32, i32, i32},
|
||||
"fd", "si_data", "si_data_count", "si_flags", "result.so_datalen",
|
||||
)
|
||||
|
||||
// sockShutdown is the WASI function named sockShutdownName which shuts
|
||||
// sockShutdown is the WASI function named SockShutdownName which shuts
|
||||
// down socket send and receive channels.
|
||||
//
|
||||
// See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_shutdownfd-fd-how-sdflags---errno
|
||||
var sockShutdown = stubFunction(sockShutdownName, []wasm.ValueType{i32, i32}, "fd", "how")
|
||||
var sockShutdown = stubFunction(SockShutdownName, []wasm.ValueType{i32, i32}, "fd", "how")
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// Test_sockAccept only tests it is stubbed for GrainLang per #271
|
||||
func Test_sockAccept(t *testing.T) {
|
||||
log := requireErrnoNosys(t, sockAcceptName, 0, 0, 0)
|
||||
log := requireErrnoNosys(t, SockAcceptName, 0, 0, 0)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.sock_accept(fd=0,flags=0,result.fd=0)
|
||||
<-- errno=ENOSYS
|
||||
@@ -17,7 +18,7 @@ func Test_sockAccept(t *testing.T) {
|
||||
|
||||
// Test_sockRecv only tests it is stubbed for GrainLang per #271
|
||||
func Test_sockRecv(t *testing.T) {
|
||||
log := requireErrnoNosys(t, sockRecvName, 0, 0, 0, 0, 0, 0)
|
||||
log := requireErrnoNosys(t, SockRecvName, 0, 0, 0, 0, 0, 0)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.sock_recv(fd=0,ri_data=0,ri_data_count=0,ri_flags=0,result.ro_datalen=0,result.ro_flags=0)
|
||||
<-- errno=ENOSYS
|
||||
@@ -26,7 +27,7 @@ func Test_sockRecv(t *testing.T) {
|
||||
|
||||
// Test_sockSend only tests it is stubbed for GrainLang per #271
|
||||
func Test_sockSend(t *testing.T) {
|
||||
log := requireErrnoNosys(t, sockSendName, 0, 0, 0, 0, 0)
|
||||
log := requireErrnoNosys(t, SockSendName, 0, 0, 0, 0, 0)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.sock_send(fd=0,si_data=0,si_data_count=0,si_flags=0,result.so_datalen=0)
|
||||
<-- errno=ENOSYS
|
||||
@@ -35,7 +36,7 @@ func Test_sockSend(t *testing.T) {
|
||||
|
||||
// Test_sockShutdown only tests it is stubbed for GrainLang per #271
|
||||
func Test_sockShutdown(t *testing.T) {
|
||||
log := requireErrnoNosys(t, sockShutdownName, 0, 0)
|
||||
log := requireErrnoNosys(t, SockShutdownName, 0, 0)
|
||||
require.Equal(t, `
|
||||
--> wasi_snapshot_preview1.sock_shutdown(fd=0,how=0)
|
||||
<-- errno=ENOSYS
|
||||
|
||||
@@ -22,17 +22,16 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
// ModuleName is the module name WASI functions are exported into.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md
|
||||
const (
|
||||
ModuleName = wasi_snapshot_preview1.ModuleName
|
||||
i32, i64 = wasm.ValueTypeI32, wasm.ValueTypeI64
|
||||
)
|
||||
const ModuleName = InternalModuleName
|
||||
|
||||
const i32, i64 = wasm.ValueTypeI32, wasm.ValueTypeI64
|
||||
|
||||
var le = binary.LittleEndian
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"embed"
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/sys"
|
||||
"github.com/tetratelabs/wazero/internal/testing/proxy"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
)
|
||||
|
||||
@@ -30,10 +32,10 @@ func Benchmark_ArgsEnviron(b *testing.B) {
|
||||
}
|
||||
|
||||
for _, n := range []string{
|
||||
argsGetName,
|
||||
argsSizesGetName,
|
||||
environGetName,
|
||||
environSizesGetName,
|
||||
ArgsGetName,
|
||||
ArgsSizesGetName,
|
||||
EnvironGetName,
|
||||
EnvironSizesGetName,
|
||||
} {
|
||||
n := n
|
||||
fn := mod.ExportedFunction(n)
|
||||
@@ -69,7 +71,7 @@ func Benchmark_fdRead(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
fn := mod.ExportedFunction(fdReadName)
|
||||
fn := mod.ExportedFunction(FdReadName)
|
||||
|
||||
mod.Memory().Write(0, []byte{
|
||||
32, 0, 0, 0, // = iovs[0].offset
|
||||
@@ -168,7 +170,7 @@ func Benchmark_fdReaddir(b *testing.B) {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
fn := mod.ExportedFunction(fdReaddirName)
|
||||
fn := mod.ExportedFunction(FdReaddirName)
|
||||
|
||||
// Open the root directory as a file-descriptor.
|
||||
fsc := mod.(*wasm.CallContext).Sys.FS()
|
||||
@@ -285,7 +287,7 @@ func Benchmark_pathFilestat(b *testing.B) {
|
||||
defer fsc.CloseFile(fd)
|
||||
}
|
||||
|
||||
fn := mod.ExportedFunction(pathFilestatGetName)
|
||||
fn := mod.ExportedFunction(PathFilestatGetName)
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -338,7 +340,7 @@ func Benchmark_fdWrite(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
fn := mod.ExportedFunction(fdWriteName)
|
||||
fn := mod.ExportedFunction(FdWriteName)
|
||||
|
||||
iovs := uint32(1) // arbitrary offset
|
||||
mod.Memory().Write(0, []byte{
|
||||
@@ -389,7 +391,7 @@ func Benchmark_fdWrite(b *testing.B) {
|
||||
|
||||
// instantiateProxyModule instantiates a guest that re-exports WASI functions.
|
||||
func instantiateProxyModule(r wazero.Runtime, config wazero.ModuleConfig) (api.Module, error) {
|
||||
wasiModuleCompiled, err := (&builder{r}).hostModuleBuilder().Compile(testCtx)
|
||||
wasiModuleCompiled, err := wasi_snapshot_preview1.NewBuilder(r).Compile(testCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -398,7 +400,7 @@ func instantiateProxyModule(r wazero.Runtime, config wazero.ModuleConfig) (api.M
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxyBin := proxy.NewModuleBinary(ModuleName, wasiModuleCompiled)
|
||||
proxyBin := proxy.NewModuleBinary(wasi_snapshot_preview1.ModuleName, wasiModuleCompiled)
|
||||
|
||||
proxyCompiled, err := r.CompileModule(testCtx, proxyBin)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// package wasi_snapshot_preview1 ensures that the behavior we've implemented
|
||||
// not only matches the wasi spec, but also at least two compilers use of sdks.
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -12,10 +10,14 @@ import (
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
// This file ensures that the behavior we've implemented not only the wasi
|
||||
// spec, but also at least two compilers use of sdks.
|
||||
|
||||
// wasmCargoWasi was compiled from testdata/cargo-wasi/wasi.rs
|
||||
//
|
||||
//go:embed testdata/cargo-wasi/wasi.wasm
|
||||
@@ -126,7 +128,7 @@ func compileAndRun(t *testing.T, config wazero.ModuleConfig, bin []byte) (consol
|
||||
r := wazero.NewRuntime(testCtx)
|
||||
defer r.Close(testCtx)
|
||||
|
||||
_, err := Instantiate(testCtx, r)
|
||||
_, err := wasi_snapshot_preview1.Instantiate(testCtx, r)
|
||||
require.NoError(t, err)
|
||||
|
||||
compiled, err := r.CompileModule(testCtx, bin)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package wasi_snapshot_preview1
|
||||
package wasi_snapshot_preview1_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/testing/proxy"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
@@ -34,7 +36,7 @@ func TestNewFunctionExporter(t *testing.T) {
|
||||
// Instantiate the current WASI functions under the wasi_unstable
|
||||
// instead of wasi_snapshot_preview1.
|
||||
wasiBuilder := r.NewHostModuleBuilder("wasi_unstable")
|
||||
NewFunctionExporter().ExportFunctions(wasiBuilder)
|
||||
wasi_snapshot_preview1.NewFunctionExporter().ExportFunctions(wasiBuilder)
|
||||
_, err := wasiBuilder.Instantiate(testCtx, r)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -50,8 +52,8 @@ func TestNewFunctionExporter(t *testing.T) {
|
||||
defer r.Close(testCtx)
|
||||
|
||||
// Export the default WASI functions
|
||||
wasiBuilder := r.NewHostModuleBuilder(ModuleName)
|
||||
NewFunctionExporter().ExportFunctions(wasiBuilder)
|
||||
wasiBuilder := r.NewHostModuleBuilder(wasi_snapshot_preview1.ModuleName)
|
||||
wasi_snapshot_preview1.NewFunctionExporter().ExportFunctions(wasiBuilder)
|
||||
|
||||
// Override proc_exit to prove the point that you can add or replace
|
||||
// functions like this.
|
||||
@@ -88,13 +90,13 @@ func requireProxyModule(t *testing.T, config wazero.ModuleConfig) (api.Module, a
|
||||
|
||||
r := wazero.NewRuntime(ctx)
|
||||
|
||||
wasiModuleCompiled, err := (&builder{r}).hostModuleBuilder().Compile(ctx)
|
||||
wasiModuleCompiled, err := wasi_snapshot_preview1.NewBuilder(r).Compile(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.InstantiateModule(ctx, wasiModuleCompiled, config)
|
||||
require.NoError(t, err)
|
||||
|
||||
proxyBin := proxy.NewModuleBinary(ModuleName, wasiModuleCompiled)
|
||||
proxyBin := proxy.NewModuleBinary(wasi_snapshot_preview1.ModuleName, wasiModuleCompiled)
|
||||
|
||||
proxyCompiled, err := r.CompileModule(ctx, proxyBin)
|
||||
require.NoError(t, err)
|
||||
@@ -118,13 +120,13 @@ func requireErrnoNosys(t *testing.T, funcName string, params ...uint64) string {
|
||||
defer r.Close(ctx)
|
||||
|
||||
// Instantiate the wasi module.
|
||||
wasiModuleCompiled, err := (&builder{r}).hostModuleBuilder().Compile(ctx)
|
||||
wasiModuleCompiled, err := wasi_snapshot_preview1.NewBuilder(r).Compile(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.InstantiateModule(ctx, wasiModuleCompiled, wazero.NewModuleConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
proxyBin := proxy.NewModuleBinary(ModuleName, wasiModuleCompiled)
|
||||
proxyBin := proxy.NewModuleBinary(wasi_snapshot_preview1.ModuleName, wasiModuleCompiled)
|
||||
|
||||
proxyCompiled, err := r.CompileModule(ctx, proxyBin)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
var testCtx = context.Background()
|
||||
@@ -64,7 +65,7 @@ func (fs *wasiFs) Open(name string) (fs.File, error) {
|
||||
uint64(fd), uint64(dirflags), uint64(pathPtr), uint64(pathLen), uint64(oflags),
|
||||
fsRightsBase, fsRightsInheriting, uint64(fdflags), uint64(resultOpenedFd))
|
||||
require.NoError(fs.t, err)
|
||||
require.Equal(fs.t, uint64(wasi_snapshot_preview1.ErrnoSuccess), res[0])
|
||||
require.Equal(fs.t, uint64(ErrnoSuccess), res[0])
|
||||
|
||||
resFd, ok := fs.memory.ReadUint32Le(resultOpenedFd)
|
||||
require.True(fs.t, ok)
|
||||
@@ -105,7 +106,7 @@ func (f *wasiFile) Read(bytes []byte) (int, error) {
|
||||
res, err := f.fs.fdRead.Call(testCtx, uint64(f.fd), uint64(iovsOff), uint64(iovsCount), uint64(resultSizeOff))
|
||||
require.NoError(f.fs.t, err)
|
||||
|
||||
require.NotEqual(f.fs.t, uint64(wasi_snapshot_preview1.ErrnoFault), res[0])
|
||||
require.NotEqual(f.fs.t, uint64(ErrnoFault), res[0])
|
||||
|
||||
numRead, ok := f.fs.memory.ReadUint32Le(resultSizeOff)
|
||||
require.True(f.fs.t, ok)
|
||||
@@ -114,7 +115,7 @@ func (f *wasiFile) Read(bytes []byte) (int, error) {
|
||||
if len(bytes) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if wasi_snapshot_preview1.Errno(res[0]) == wasi_snapshot_preview1.ErrnoSuccess {
|
||||
if Errno(res[0]) == ErrnoSuccess {
|
||||
return 0, io.EOF
|
||||
} else {
|
||||
return 0, fmt.Errorf("could not read from file")
|
||||
@@ -130,7 +131,7 @@ func (f *wasiFile) Read(bytes []byte) (int, error) {
|
||||
func (f *wasiFile) Close() error {
|
||||
res, err := f.fs.fdClose.Call(testCtx, uint64(f.fd))
|
||||
require.NoError(f.fs.t, err)
|
||||
require.NotEqual(f.fs.t, uint64(wasi_snapshot_preview1.ErrnoFault), res[0])
|
||||
require.NotEqual(f.fs.t, uint64(ErrnoFault), res[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -140,7 +141,7 @@ func (f *wasiFile) Seek(offset int64, whence int) (int64, error) {
|
||||
|
||||
res, err := f.fs.fdSeek.Call(testCtx, uint64(f.fd), uint64(offset), uint64(whence), uint64(resultNewoffsetOff))
|
||||
require.NoError(f.fs.t, err)
|
||||
require.NotEqual(f.fs.t, uint64(wasi_snapshot_preview1.ErrnoFault), res[0])
|
||||
require.NotEqual(f.fs.t, uint64(ErrnoFault), res[0])
|
||||
|
||||
newOffset, ok := f.fs.memory.ReadUint32Le(resultNewoffsetOff)
|
||||
require.True(f.fs.t, ok)
|
||||
|
||||
6
internal/wasi_snapshot_preview1/args.go
Normal file
6
internal/wasi_snapshot_preview1/args.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const (
|
||||
ArgsGetName = "args_get"
|
||||
ArgsSizesGetName = "args_sizes_get"
|
||||
)
|
||||
16
internal/wasi_snapshot_preview1/clock.go
Normal file
16
internal/wasi_snapshot_preview1/clock.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const (
|
||||
ClockResGetName = "clock_res_get"
|
||||
ClockTimeGetName = "clock_time_get"
|
||||
)
|
||||
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clockid-enumu32
|
||||
const (
|
||||
// ClockIDRealtime is the name ID named "realtime" like sys.Walltime
|
||||
ClockIDRealtime = iota
|
||||
// ClockIDMonotonic is the name ID named "monotonic" like sys.Nanotime
|
||||
ClockIDMonotonic
|
||||
// Note: clockIDProcessCputime and clockIDThreadCputime were removed by
|
||||
// WASI maintainers: https://github.com/WebAssembly/wasi-libc/pull/294
|
||||
)
|
||||
6
internal/wasi_snapshot_preview1/environ.go
Normal file
6
internal/wasi_snapshot_preview1/environ.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const (
|
||||
EnvironGetName = "environ_get"
|
||||
EnvironSizesGetName = "environ_sizes_get"
|
||||
)
|
||||
@@ -1,24 +1,22 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
import (
|
||||
internalwasi "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Errno are the error codes returned by WASI functions.
|
||||
//
|
||||
// # Notes
|
||||
//
|
||||
// - This is not always an error, as ErrnoSuccess is a valid code.
|
||||
// - Codes are defined even when not relevant to WASI for use in higher-level
|
||||
// libraries or alignment with POSIX.
|
||||
//
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-errno-enumu16 and
|
||||
// https://linux.die.net/man/3/errno
|
||||
type Errno = uint32 // neither uint16 nor an alias for parity with wasm.ValueType
|
||||
// Errno is neither uint16 nor an alias for parity with wasm.ValueType.
|
||||
type Errno = uint32
|
||||
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. e.g. Errno2big -> "E2BIG"
|
||||
func ErrnoName(errno Errno) string {
|
||||
return internalwasi.ErrnoName(errno)
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is
|
||||
// not an error. e.g. Errno2big -> "E2BIG"
|
||||
func ErrnoName(errno uint32) string {
|
||||
if int(errno) < len(errnoToString) {
|
||||
return errnoToString[errno]
|
||||
}
|
||||
return fmt.Sprintf("errno(%d)", errno)
|
||||
}
|
||||
|
||||
// Note: Below prefers POSIX symbol names over WASI ones, even if the docs are from WASI.
|
||||
@@ -181,3 +179,108 @@ const (
|
||||
// Note: ErrnoNotcapable was removed by WASI maintainers.
|
||||
// See https://github.com/WebAssembly/wasi-libc/pull/294
|
||||
)
|
||||
|
||||
var errnoToString = [...]string{
|
||||
"ESUCCESS",
|
||||
"E2BIG",
|
||||
"EACCES",
|
||||
"EADDRINUSE",
|
||||
"EADDRNOTAVAIL",
|
||||
"EAFNOSUPPORT",
|
||||
"EAGAIN",
|
||||
"EALREADY",
|
||||
"EBADF",
|
||||
"EBADMSG",
|
||||
"EBUSY",
|
||||
"ECANCELED",
|
||||
"ECHILD",
|
||||
"ECONNABORTED",
|
||||
"ECONNREFUSED",
|
||||
"ECONNRESET",
|
||||
"EDEADLK",
|
||||
"EDESTADDRREQ",
|
||||
"EDOM",
|
||||
"EDQUOT",
|
||||
"EEXIST",
|
||||
"EFAULT",
|
||||
"EFBIG",
|
||||
"EHOSTUNREACH",
|
||||
"EIDRM",
|
||||
"EILSEQ",
|
||||
"EINPROGRESS",
|
||||
"EINTR",
|
||||
"EINVAL",
|
||||
"EIO",
|
||||
"EISCONN",
|
||||
"EISDIR",
|
||||
"ELOOP",
|
||||
"EMFILE",
|
||||
"EMLINK",
|
||||
"EMSGSIZE",
|
||||
"EMULTIHOP",
|
||||
"ENAMETOOLONG",
|
||||
"ENETDOWN",
|
||||
"ENETRESET",
|
||||
"ENETUNREACH",
|
||||
"ENFILE",
|
||||
"ENOBUFS",
|
||||
"ENODEV",
|
||||
"ENOENT",
|
||||
"ENOEXEC",
|
||||
"ENOLCK",
|
||||
"ENOLINK",
|
||||
"ENOMEM",
|
||||
"ENOMSG",
|
||||
"ENOPROTOOPT",
|
||||
"ENOSPC",
|
||||
"ENOSYS",
|
||||
"ENOTCONN",
|
||||
"ENOTDIR",
|
||||
"ENOTEMPTY",
|
||||
"ENOTRECOVERABLE",
|
||||
"ENOTSOCK",
|
||||
"ENOTSUP",
|
||||
"ENOTTY",
|
||||
"ENXIO",
|
||||
"EOVERFLOW",
|
||||
"EOWNERDEAD",
|
||||
"EPERM",
|
||||
"EPIPE",
|
||||
"EPROTO",
|
||||
"EPROTONOSUPPORT",
|
||||
"EPROTOTYPE",
|
||||
"ERANGE",
|
||||
"EROFS",
|
||||
"ESPIPE",
|
||||
"ESRCH",
|
||||
"ESTALE",
|
||||
"ETIMEDOUT",
|
||||
"ETXTBSY",
|
||||
"EXDEV",
|
||||
"ENOTCAPABLE",
|
||||
}
|
||||
|
||||
// ToErrno coerces the error to a WASI Errno.
|
||||
//
|
||||
// Note: Coercion isn't centralized in sys.FSContext because ABI use different
|
||||
// error codes. For example, wasi-filesystem and GOOS=js don't map to these
|
||||
// Errno.
|
||||
func ToErrno(err error) Errno {
|
||||
// handle all the cases of FS.Open or wasi_snapshot_preview1 to FSContext.OpenFile
|
||||
switch {
|
||||
case errors.Is(err, syscall.ENOSYS):
|
||||
return ErrnoNosys
|
||||
case errors.Is(err, fs.ErrInvalid):
|
||||
return ErrnoInval
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
// fs.FS is allowed to return this instead of ErrInvalid on an invalid path
|
||||
return ErrnoNoent
|
||||
case errors.Is(err, fs.ErrExist):
|
||||
return ErrnoExist
|
||||
case errors.Is(err, syscall.EBADF):
|
||||
// fsc.OpenFile currently returns this on out of file descriptors
|
||||
return ErrnoBadf
|
||||
default:
|
||||
return ErrnoIo
|
||||
}
|
||||
}
|
||||
135
internal/wasi_snapshot_preview1/fs.go
Normal file
135
internal/wasi_snapshot_preview1/fs.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
FdAdviseName = "fd_advise"
|
||||
FdAllocateName = "fd_allocate"
|
||||
FdCloseName = "fd_close"
|
||||
FdDatasyncName = "fd_datasync"
|
||||
FdFdstatGetName = "fd_fdstat_get"
|
||||
FdFdstatSetFlagsName = "fd_fdstat_set_flags"
|
||||
FdFdstatSetRightsName = "fd_fdstat_set_rights"
|
||||
FdFilestatGetName = "fd_filestat_get"
|
||||
FdFilestatSetSizeName = "fd_filestat_set_size"
|
||||
FdFilestatSetTimesName = "fd_filestat_set_times"
|
||||
FdPreadName = "fd_pread"
|
||||
FdPrestatGetName = "fd_prestat_get"
|
||||
FdPrestatDirNameName = "fd_prestat_dir_name"
|
||||
FdPwriteName = "fd_pwrite"
|
||||
FdReadName = "fd_read"
|
||||
FdReaddirName = "fd_readdir"
|
||||
FdRenumberName = "fd_renumber"
|
||||
FdSeekName = "fd_seek"
|
||||
FdSyncName = "fd_sync"
|
||||
FdTellName = "fd_tell"
|
||||
FdWriteName = "fd_write"
|
||||
|
||||
PathCreateDirectoryName = "path_create_directory"
|
||||
PathFilestatGetName = "path_filestat_get"
|
||||
PathFilestatSetTimesName = "path_filestat_set_times"
|
||||
PathLinkName = "path_link"
|
||||
PathOpenName = "path_open"
|
||||
PathReadlinkName = "path_readlink"
|
||||
PathRemoveDirectoryName = "path_remove_directory"
|
||||
PathRenameName = "path_rename"
|
||||
PathSymlinkName = "path_symlink"
|
||||
PathUnlinkFileName = "path_unlink_file"
|
||||
)
|
||||
|
||||
// oflags are open flags used by path_open
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16
|
||||
const (
|
||||
// O_CREAT creates a file if it does not exist.
|
||||
O_CREAT uint16 = 1 << iota //nolint
|
||||
// O_DIRECTORY fails if not a directory.
|
||||
O_DIRECTORY
|
||||
// O_EXCL fails if file already exists.
|
||||
O_EXCL //nolint
|
||||
// O_TRUNC truncates the file to size 0.
|
||||
O_TRUNC //nolint
|
||||
)
|
||||
|
||||
func OflagsString(oflags int) string {
|
||||
return flagsString(oflagNames[:], oflags)
|
||||
}
|
||||
|
||||
var oflagNames = [...]string{
|
||||
"CREAT",
|
||||
"DIRECTORY",
|
||||
"EXCL",
|
||||
"TRUNC",
|
||||
}
|
||||
|
||||
// file descriptor flags
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdflags
|
||||
const (
|
||||
FD_APPEND uint16 = 1 << iota //nolint
|
||||
FD_DSYNC
|
||||
FD_NONBLOCK
|
||||
FD_RSYNC
|
||||
FD_SYNC
|
||||
)
|
||||
|
||||
func FdFlagsString(fdflags int) string {
|
||||
return flagsString(fdflagNames[:], fdflags)
|
||||
}
|
||||
|
||||
var fdflagNames = [...]string{
|
||||
"APPEND",
|
||||
"DSYNC",
|
||||
"NONBLOCK",
|
||||
"RSYNC",
|
||||
"SYNC",
|
||||
}
|
||||
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags
|
||||
const (
|
||||
// LOOKUP_SYMLINK_FOLLOW expands a path if it resolves into a symbolic
|
||||
// link.
|
||||
LOOKUP_SYMLINK_FOLLOW uint16 = 1 << iota //nolint
|
||||
)
|
||||
|
||||
var lookupflagNames = [...]string{
|
||||
"SYMLINK_FOLLOW",
|
||||
}
|
||||
|
||||
func LookupflagsString(lookupflags int) string {
|
||||
return flagsString(lookupflagNames[:], lookupflags)
|
||||
}
|
||||
|
||||
// DirentSize is the size of the dirent struct, which should be followed by the
|
||||
// length of a file name.
|
||||
const DirentSize = uint32(24)
|
||||
|
||||
const (
|
||||
FILETYPE_UNKNOWN uint8 = iota
|
||||
FILETYPE_BLOCK_DEVICE
|
||||
FILETYPE_CHARACTER_DEVICE
|
||||
FILETYPE_DIRECTORY
|
||||
FILETYPE_REGULAR_FILE
|
||||
FILETYPE_SOCKET_DGRAM
|
||||
FILETYPE_SOCKET_STREAM
|
||||
FILETYPE_SYMBOLIC_LINK
|
||||
)
|
||||
|
||||
// FiletypeName returns string name of the file type.
|
||||
func FiletypeName(filetype uint8) string {
|
||||
if int(filetype) < len(filetypeToString) {
|
||||
return filetypeToString[filetype]
|
||||
}
|
||||
return fmt.Sprintf("filetype(%d)", filetype)
|
||||
}
|
||||
|
||||
var filetypeToString = [...]string{
|
||||
"UNKNOWN",
|
||||
"BLOCK_DEVICE",
|
||||
"CHARACTER_DEVICE",
|
||||
"DIRECTORY",
|
||||
"REGULAR_FILE",
|
||||
"SOCKET_DGRAM",
|
||||
"SOCKET_STREAM",
|
||||
"SYMBOLIC_LINK",
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/logging"
|
||||
"github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
var le = binary.LittleEndian
|
||||
@@ -25,11 +25,11 @@ func IsFilesystemFunction(fnd api.FunctionDefinition) bool {
|
||||
|
||||
func Config(fnd api.FunctionDefinition) (pLoggers []logging.ParamLogger, rLoggers []logging.ResultLogger) {
|
||||
switch fnd.Name() {
|
||||
case "fd_prestat_get":
|
||||
case FdPrestatGetName:
|
||||
pLoggers = []logging.ParamLogger{logging.NewParamLogger(0, "fd", logging.ValueTypeI32)}
|
||||
rLoggers = []logging.ResultLogger{resultParamLogger("prestat", logPrestat(1).Log), logErrno}
|
||||
return
|
||||
case "proc_exit":
|
||||
case ProcExitName:
|
||||
return logging.ValueLoggers(fnd)
|
||||
}
|
||||
|
||||
@@ -94,18 +94,18 @@ func Config(fnd api.FunctionDefinition) (pLoggers []logging.ParamLogger, rLogger
|
||||
|
||||
func isLookupFlags(fnd api.FunctionDefinition, name string) bool {
|
||||
switch fnd.Name() {
|
||||
case "path_filestat_get", "path_filestat_set_times":
|
||||
case PathFilestatGetName, PathFilestatSetTimesName:
|
||||
return name == "flags"
|
||||
case "path_link":
|
||||
case PathLinkName:
|
||||
return name == "old_flags"
|
||||
case "path_open":
|
||||
case PathOpenName:
|
||||
return name == "dirflags"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func logErrno(_ context.Context, _ api.Module, w logging.Writer, _, results []uint64) {
|
||||
errno := wasi_snapshot_preview1.ErrnoName(uint32(results[0]))
|
||||
errno := ErrnoName(uint32(results[0]))
|
||||
w.WriteString("errno=") //nolint
|
||||
w.WriteString(errno) //nolint
|
||||
}
|
||||
@@ -123,9 +123,9 @@ type logFilestat uint32
|
||||
func (i logFilestat) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) {
|
||||
offset, byteCount := uint32(params[i]), uint32(64)
|
||||
if buf, ok := mod.Memory().Read(offset, byteCount); ok {
|
||||
w.WriteString("{filetype=") //nolint
|
||||
w.WriteString(wasi_snapshot_preview1.FiletypeName(buf[16])) //nolint
|
||||
w.WriteString(",size=") //nolint
|
||||
w.WriteString("{filetype=") //nolint
|
||||
w.WriteString(FiletypeName(buf[16])) //nolint
|
||||
w.WriteString(",size=") //nolint
|
||||
writeI64(w, le.Uint64(buf[32:]))
|
||||
w.WriteString(",mtim=") //nolint
|
||||
writeI64(w, le.Uint64(buf[40:]))
|
||||
@@ -138,15 +138,15 @@ type logFdstat uint32
|
||||
func (i logFdstat) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) {
|
||||
offset, byteCount := uint32(params[i]), uint32(24)
|
||||
if buf, ok := mod.Memory().Read(offset, byteCount); ok {
|
||||
w.WriteString("{filetype=") //nolint
|
||||
w.WriteString(wasi_snapshot_preview1.FiletypeName(buf[0])) //nolint
|
||||
w.WriteString(",fdflags=") //nolint
|
||||
writeFlags(w, fdflagNames[:], int(le.Uint16(buf[2:])))
|
||||
w.WriteString(",fs_rights_base=") //nolint
|
||||
writeFlags(w, rightNames[:], int(le.Uint16(buf[8:])))
|
||||
w.WriteString(",fs_rights_inheriting=") //nolint
|
||||
writeFlags(w, rightNames[:], int(le.Uint16(buf[16:])))
|
||||
w.WriteString("}") //nolint
|
||||
w.WriteString("{filetype=") //nolint
|
||||
w.WriteString(FiletypeName(buf[0])) //nolint
|
||||
w.WriteString(",fdflags=") //nolint
|
||||
w.WriteString(FdFlagsString(int(le.Uint16(buf[2:])))) //nolint
|
||||
w.WriteString(",fs_rights_base=") //nolint
|
||||
w.WriteString(RightsString(int(le.Uint16(buf[8:])))) //nolint
|
||||
w.WriteString(",fs_rights_inheriting=") //nolint
|
||||
w.WriteString(RightsString(int(le.Uint16(buf[16:])))) //nolint
|
||||
w.WriteString("}") //nolint
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ func resultParamLogger(name string, pLogger logging.ParamLogger) logging.ResultL
|
||||
prefix := name + "="
|
||||
return func(ctx context.Context, mod api.Module, w logging.Writer, params, results []uint64) {
|
||||
w.WriteString(prefix) //nolint
|
||||
if results[0] == 0 { // ESUCCESS
|
||||
if Errno(results[0]) == ErrnoSuccess {
|
||||
pLogger(ctx, mod, w, params)
|
||||
}
|
||||
}
|
||||
@@ -186,8 +186,8 @@ func resultParamLogger(name string, pLogger logging.ParamLogger) logging.ResultL
|
||||
type logFdflags int
|
||||
|
||||
func (i logFdflags) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
|
||||
w.WriteString("fdflags=") //nolint
|
||||
writeFlags(w, fdflagNames[:], int(params[i]))
|
||||
w.WriteString("fdflags=") //nolint
|
||||
w.WriteString(FdFlagsString(int(params[i]))) //nolint
|
||||
}
|
||||
|
||||
type logLookupflags struct {
|
||||
@@ -196,96 +196,30 @@ type logLookupflags struct {
|
||||
}
|
||||
|
||||
func (l *logLookupflags) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
|
||||
w.WriteString(l.name) //nolint
|
||||
w.WriteByte('=') //nolint
|
||||
writeFlags(w, lookupflagNames[:], int(params[l.i]))
|
||||
w.WriteString(l.name) //nolint
|
||||
w.WriteByte('=') //nolint
|
||||
w.WriteString(LookupflagsString(int(params[l.i]))) //nolint
|
||||
}
|
||||
|
||||
type logFsRightsBase uint32
|
||||
|
||||
func (i logFsRightsBase) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
|
||||
w.WriteString("fs_rights_base=") //nolint
|
||||
writeFlags(w, rightNames[:], int(params[i]))
|
||||
w.WriteString("fs_rights_base=") //nolint
|
||||
w.WriteString(RightsString(int(params[i]))) //nolint
|
||||
}
|
||||
|
||||
type logFsRightsInheriting uint32
|
||||
|
||||
func (i logFsRightsInheriting) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
|
||||
w.WriteString("fs_rights_inheriting=") //nolint
|
||||
writeFlags(w, rightNames[:], int(params[i]))
|
||||
w.WriteString("fs_rights_inheriting=") //nolint
|
||||
w.WriteString(RightsString(int(params[i]))) //nolint
|
||||
}
|
||||
|
||||
type logOflags int
|
||||
|
||||
func (i logOflags) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
|
||||
w.WriteString("oflags=") //nolint
|
||||
writeFlags(w, oflagNames[:], int(params[i]))
|
||||
}
|
||||
|
||||
func writeFlags(w logging.Writer, names []string, f int) {
|
||||
first := true
|
||||
for i, sf := range names {
|
||||
target := 1 << i
|
||||
if target&f != 0 {
|
||||
if !first {
|
||||
w.WriteByte('|') //nolint
|
||||
} else {
|
||||
first = false
|
||||
}
|
||||
w.WriteString(sf) //nolint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var oflagNames = [...]string{
|
||||
"CREAT",
|
||||
"DIRECTORY",
|
||||
"EXCL",
|
||||
"TRUNC",
|
||||
}
|
||||
|
||||
var fdflagNames = [...]string{
|
||||
"APPEND",
|
||||
"DSYNC",
|
||||
"NONBLOCK",
|
||||
"RSYNC",
|
||||
"SYNC",
|
||||
}
|
||||
|
||||
var lookupflagNames = [...]string{
|
||||
"SYMLINK_FOLLOW",
|
||||
}
|
||||
|
||||
var rightNames = [...]string{
|
||||
"FD_DATASYNC",
|
||||
"FD_READ",
|
||||
"FD_SEEK",
|
||||
"FDSTAT_SET_FLAGS",
|
||||
"FD_SYNC",
|
||||
"FD_TELL",
|
||||
"FD_WRITE",
|
||||
"FD_ADVISE",
|
||||
"FD_ALLOCATE",
|
||||
"PATH_CREATE_DIRECTORY",
|
||||
"PATH_CREATE_FILE",
|
||||
"PATH_LINK_SOURCE",
|
||||
"PATH_LINK_TARGET",
|
||||
"PATH_OPEN",
|
||||
"FD_READDIR",
|
||||
"PATH_READLINK",
|
||||
"PATH_RENAME_SOURCE",
|
||||
"PATH_RENAME_TARGET",
|
||||
"PATH_FILESTAT_GET",
|
||||
"PATH_FILESTAT_SET_SIZE",
|
||||
"PATH_FILESTAT_SET_TIMES",
|
||||
"FD_FILESTAT_GET",
|
||||
"FD_FILESTAT_SET_SIZE",
|
||||
"FD_FILESTAT_SET_TIMES",
|
||||
"PATH_SYMLINK",
|
||||
"PATH_REMOVE_DIRECTORY",
|
||||
"PATH_UNLINK_FILE",
|
||||
"POLL_FD_READWRITE",
|
||||
"SOCK_SHUTDOWN",
|
||||
w.WriteString("oflags=") //nolint
|
||||
w.WriteString(OflagsString(int(params[i]))) //nolint
|
||||
}
|
||||
|
||||
func resultParamName(name string) string {
|
||||
15
internal/wasi_snapshot_preview1/poll.go
Normal file
15
internal/wasi_snapshot_preview1/poll.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
// https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-eventtype-enumu8
|
||||
const (
|
||||
// EventTypeClock is the timeout event named "name".
|
||||
EventTypeClock = iota
|
||||
// EventTypeFdRead is the data available event named "fd_read".
|
||||
EventTypeFdRead
|
||||
// EventTypeFdWrite is the capacity available event named "fd_write".
|
||||
EventTypeFdWrite
|
||||
)
|
||||
|
||||
const (
|
||||
PollOneoffName = "poll_oneoff"
|
||||
)
|
||||
6
internal/wasi_snapshot_preview1/proc.go
Normal file
6
internal/wasi_snapshot_preview1/proc.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const (
|
||||
ProcExitName = "proc_exit"
|
||||
ProcRaiseName = "proc_raise"
|
||||
)
|
||||
3
internal/wasi_snapshot_preview1/random.go
Normal file
3
internal/wasi_snapshot_preview1/random.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const RandomGetName = "random_get"
|
||||
148
internal/wasi_snapshot_preview1/rights.go
Normal file
148
internal/wasi_snapshot_preview1/rights.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-rights-flagsu64
|
||||
const (
|
||||
// RIGHT_FD_DATASYNC is the right to invoke fd_datasync. If RIGHT_PATH_OPEN
|
||||
// is set, includes the right to invoke path_open with FD_DSYNC.
|
||||
RIGHT_FD_DATASYNC uint32 = 1 << iota //nolint
|
||||
|
||||
// RIGHT_FD_READ is he right to invoke fd_read and sock_recv. If
|
||||
// RIGHT_FD_SYNC is set, includes the right to invoke fd_pread.
|
||||
RIGHT_FD_READ
|
||||
|
||||
// RIGHT_FD_SEEK is the right to invoke fd_seek. This flag implies
|
||||
// RIGHT_FD_TELL.
|
||||
RIGHT_FD_SEEK
|
||||
|
||||
// RIGHT_FDSTAT_SET_FLAGS is the right to invoke fd_fdstat_set_flags.
|
||||
RIGHT_FDSTAT_SET_FLAGS
|
||||
|
||||
// RIGHT_FD_SYNC The right to invoke fd_sync. If path_open is set, includes
|
||||
// the right to invoke path_open with FD_RSYNC and FD_DSYNC.
|
||||
RIGHT_FD_SYNC
|
||||
|
||||
// RIGHT_FD_TELL is the right to invoke fd_seek in such a way that the file
|
||||
// offset remains unaltered (i.e., whence::cur with offset zero), or to
|
||||
// invoke fd_tell.
|
||||
RIGHT_FD_TELL
|
||||
|
||||
// RIGHT_FD_WRITE is the right to invoke fd_write and sock_send. If
|
||||
// RIGHT_FD_SEEK is set, includes the right to invoke fd_pwrite.
|
||||
RIGHT_FD_WRITE
|
||||
|
||||
// RIGHT_FD_ADVISE is the right to invoke fd_advise.
|
||||
RIGHT_FD_ADVISE
|
||||
|
||||
// RIGHT_FD_ALLOCATE is the right to invoke fd_allocate.
|
||||
RIGHT_FD_ALLOCATE
|
||||
|
||||
// RIGHT_PATH_CREATE_DIRECTORY is the right to invoke
|
||||
// path_create_directory.
|
||||
RIGHT_PATH_CREATE_DIRECTORY
|
||||
|
||||
// RIGHT_PATH_CREATE_FILE when RIGHT_PATH_OPEN is set, the right to invoke
|
||||
// path_open with O_CREATE.
|
||||
RIGHT_PATH_CREATE_FILE
|
||||
|
||||
// RIGHT_PATH_LINK_SOURCE is the right to invoke path_link with the file
|
||||
// descriptor as the source directory.
|
||||
RIGHT_PATH_LINK_SOURCE
|
||||
|
||||
// RIGHT_PATH_LINK_TARGET is the right to invoke path_link with the file
|
||||
// descriptor as the target directory.
|
||||
RIGHT_PATH_LINK_TARGET
|
||||
|
||||
// RIGHT_PATH_OPEN is the right to invoke path_open.
|
||||
RIGHT_PATH_OPEN
|
||||
|
||||
// RIGHT_FD_READDIR is the right to invoke fd_readdir.
|
||||
RIGHT_FD_READDIR
|
||||
|
||||
// RIGHT_PATH_READLINK is the right to invoke path_readlink.
|
||||
RIGHT_PATH_READLINK
|
||||
|
||||
// RIGHT_PATH_RENAME_SOURCE is the right to invoke path_rename with the
|
||||
// file descriptor as the source directory.
|
||||
RIGHT_PATH_RENAME_SOURCE
|
||||
|
||||
// RIGHT_PATH_RENAME_TARGET is the right to invoke path_rename with the
|
||||
// file descriptor as the target directory.
|
||||
RIGHT_PATH_RENAME_TARGET
|
||||
|
||||
// RIGHT_PATH_FILESTAT_GET is the right to invoke path_filestat_get.
|
||||
RIGHT_PATH_FILESTAT_GET
|
||||
|
||||
// RIGHT_PATH_FILESTAT_SET_SIZE is the right to change a file's size (there
|
||||
// is no path_filestat_set_size). If RIGHT_PATH_OPEN is set, includes the
|
||||
// right to invoke path_open with O_TRUNC.
|
||||
RIGHT_PATH_FILESTAT_SET_SIZE
|
||||
|
||||
// RIGHT_PATH_FILESTAT_SET_TIMES is the right to invoke
|
||||
// path_filestat_set_times.
|
||||
RIGHT_PATH_FILESTAT_SET_TIMES
|
||||
|
||||
// RIGHT_FD_FILESTAT_GET is the right to invoke fd_filestat_get.
|
||||
RIGHT_FD_FILESTAT_GET
|
||||
|
||||
// RIGHT_FD_FILESTAT_SET_SIZE is the right to invoke fd_filestat_set_size.
|
||||
RIGHT_FD_FILESTAT_SET_SIZE
|
||||
|
||||
// RIGHT_FD_FILESTAT_SET_TIMES is the right to invoke
|
||||
// fd_filestat_set_times.
|
||||
RIGHT_FD_FILESTAT_SET_TIMES
|
||||
|
||||
// RIGHT_PATH_SYMLINK is the right to invoke path_symlink.
|
||||
RIGHT_PATH_SYMLINK
|
||||
|
||||
// RIGHT_PATH_REMOVE_DIRECTORY is the right to invoke
|
||||
// path_remove_directory.
|
||||
RIGHT_PATH_REMOVE_DIRECTORY
|
||||
|
||||
// RIGHT_PATH_UNLINK_FILE is the right to invoke path_unlink_file.
|
||||
RIGHT_PATH_UNLINK_FILE
|
||||
|
||||
// RIGHT_POLL_FD_READWRITE when RIGHT_FD_READ is set, includes the right to
|
||||
// invoke poll_oneoff to subscribe to eventtype::fd_read. If RIGHT_FD_WRITE
|
||||
// is set, includes the right to invoke poll_oneoff to subscribe to
|
||||
// eventtype::fd_write.
|
||||
RIGHT_POLL_FD_READWRITE
|
||||
|
||||
// RIGHT_SOCK_SHUTDOWN is the right to invoke sock_shutdown.
|
||||
RIGHT_SOCK_SHUTDOWN
|
||||
)
|
||||
|
||||
func RightsString(rights int) string {
|
||||
return flagsString(rightNames[:], rights)
|
||||
}
|
||||
|
||||
var rightNames = [...]string{
|
||||
"FD_DATASYNC",
|
||||
"FD_READ",
|
||||
"FD_SEEK",
|
||||
"FDSTAT_SET_FLAGS",
|
||||
"FD_SYNC",
|
||||
"FD_TELL",
|
||||
"FD_WRITE",
|
||||
"FD_ADVISE",
|
||||
"FD_ALLOCATE",
|
||||
"PATH_CREATE_DIRECTORY",
|
||||
"PATH_CREATE_FILE",
|
||||
"PATH_LINK_SOURCE",
|
||||
"PATH_LINK_TARGET",
|
||||
"PATH_OPEN",
|
||||
"FD_READDIR",
|
||||
"PATH_READLINK",
|
||||
"PATH_RENAME_SOURCE",
|
||||
"PATH_RENAME_TARGET",
|
||||
"PATH_FILESTAT_GET",
|
||||
"PATH_FILESTAT_SET_SIZE",
|
||||
"PATH_FILESTAT_SET_TIMES",
|
||||
"FD_FILESTAT_GET",
|
||||
"FD_FILESTAT_SET_SIZE",
|
||||
"FD_FILESTAT_SET_TIMES",
|
||||
"PATH_SYMLINK",
|
||||
"PATH_REMOVE_DIRECTORY",
|
||||
"PATH_UNLINK_FILE",
|
||||
"POLL_FD_READWRITE",
|
||||
"SOCK_SHUTDOWN",
|
||||
}
|
||||
3
internal/wasi_snapshot_preview1/sched.go
Normal file
3
internal/wasi_snapshot_preview1/sched.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const SchedYieldName = "sched_yield"
|
||||
8
internal/wasi_snapshot_preview1/sock.go
Normal file
8
internal/wasi_snapshot_preview1/sock.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
const (
|
||||
SockAcceptName = "sock_accept"
|
||||
SockRecvName = "sock_recv"
|
||||
SockSendName = "sock_send"
|
||||
SockShutdownName = "sock_shutdown"
|
||||
)
|
||||
@@ -1,268 +1,27 @@
|
||||
// Package wasi_snapshot_preview1 is an internal helper to remove package
|
||||
// cycles re-using errno
|
||||
// Package wasi_snapshot_preview1 is a helper to remove package cycles re-using
|
||||
// constants.
|
||||
package wasi_snapshot_preview1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const ModuleName = "wasi_snapshot_preview1"
|
||||
// InternalModuleName is not named ModuleName, to avoid a clash on dot imports.
|
||||
const InternalModuleName = "wasi_snapshot_preview1"
|
||||
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. e.g. Errno2big -> "E2BIG"
|
||||
func ErrnoName(errno uint32) string {
|
||||
if int(errno) < len(errnoToString) {
|
||||
return errnoToString[errno]
|
||||
func flagsString(names []string, f int) string {
|
||||
var builder strings.Builder
|
||||
first := true
|
||||
for i, sf := range names {
|
||||
target := 1 << i
|
||||
if target&f != 0 {
|
||||
if !first {
|
||||
builder.WriteByte('|')
|
||||
} else {
|
||||
first = false
|
||||
}
|
||||
builder.WriteString(sf)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("errno(%d)", errno)
|
||||
}
|
||||
|
||||
var errnoToString = [...]string{
|
||||
"ESUCCESS",
|
||||
"E2BIG",
|
||||
"EACCES",
|
||||
"EADDRINUSE",
|
||||
"EADDRNOTAVAIL",
|
||||
"EAFNOSUPPORT",
|
||||
"EAGAIN",
|
||||
"EALREADY",
|
||||
"EBADF",
|
||||
"EBADMSG",
|
||||
"EBUSY",
|
||||
"ECANCELED",
|
||||
"ECHILD",
|
||||
"ECONNABORTED",
|
||||
"ECONNREFUSED",
|
||||
"ECONNRESET",
|
||||
"EDEADLK",
|
||||
"EDESTADDRREQ",
|
||||
"EDOM",
|
||||
"EDQUOT",
|
||||
"EEXIST",
|
||||
"EFAULT",
|
||||
"EFBIG",
|
||||
"EHOSTUNREACH",
|
||||
"EIDRM",
|
||||
"EILSEQ",
|
||||
"EINPROGRESS",
|
||||
"EINTR",
|
||||
"EINVAL",
|
||||
"EIO",
|
||||
"EISCONN",
|
||||
"EISDIR",
|
||||
"ELOOP",
|
||||
"EMFILE",
|
||||
"EMLINK",
|
||||
"EMSGSIZE",
|
||||
"EMULTIHOP",
|
||||
"ENAMETOOLONG",
|
||||
"ENETDOWN",
|
||||
"ENETRESET",
|
||||
"ENETUNREACH",
|
||||
"ENFILE",
|
||||
"ENOBUFS",
|
||||
"ENODEV",
|
||||
"ENOENT",
|
||||
"ENOEXEC",
|
||||
"ENOLCK",
|
||||
"ENOLINK",
|
||||
"ENOMEM",
|
||||
"ENOMSG",
|
||||
"ENOPROTOOPT",
|
||||
"ENOSPC",
|
||||
"ENOSYS",
|
||||
"ENOTCONN",
|
||||
"ENOTDIR",
|
||||
"ENOTEMPTY",
|
||||
"ENOTRECOVERABLE",
|
||||
"ENOTSOCK",
|
||||
"ENOTSUP",
|
||||
"ENOTTY",
|
||||
"ENXIO",
|
||||
"EOVERFLOW",
|
||||
"EOWNERDEAD",
|
||||
"EPERM",
|
||||
"EPIPE",
|
||||
"EPROTO",
|
||||
"EPROTONOSUPPORT",
|
||||
"EPROTOTYPE",
|
||||
"ERANGE",
|
||||
"EROFS",
|
||||
"ESPIPE",
|
||||
"ESRCH",
|
||||
"ESTALE",
|
||||
"ETIMEDOUT",
|
||||
"ETXTBSY",
|
||||
"EXDEV",
|
||||
"ENOTCAPABLE",
|
||||
}
|
||||
|
||||
// oflags are open flags used by path_open
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16
|
||||
const (
|
||||
// O_CREAT creates a file if it does not exist.
|
||||
O_CREAT uint16 = 1 << iota //nolint
|
||||
// O_DIRECTORY fails if not a directory.
|
||||
O_DIRECTORY
|
||||
// O_EXCL fails if file already exists.
|
||||
O_EXCL //nolint
|
||||
// O_TRUNC truncates the file to size 0.
|
||||
O_TRUNC //nolint
|
||||
)
|
||||
|
||||
// file descriptor flags
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdflags
|
||||
const (
|
||||
FD_APPEND uint16 = 1 << iota //nolint
|
||||
FD_DSYNC
|
||||
FD_NONBLOCK
|
||||
FD_RSYNC
|
||||
FD_SYNC
|
||||
)
|
||||
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#lookupflags
|
||||
const (
|
||||
// LOOKUP_SYMLINK_FOLLOW expands a path if it resolves into a symbolic
|
||||
// link.
|
||||
LOOKUP_SYMLINK_FOLLOW uint16 = 1 << iota //nolint
|
||||
)
|
||||
|
||||
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-rights-flagsu64
|
||||
const (
|
||||
// RIGHT_FD_DATASYNC is the right to invoke fd_datasync. If RIGHT_PATH_OPEN
|
||||
// is set, includes the right to invoke path_open with FD_DSYNC.
|
||||
RIGHT_FD_DATASYNC uint32 = 1 << iota //nolint
|
||||
|
||||
// RIGHT_FD_READ is he right to invoke fd_read and sock_recv. If
|
||||
// RIGHT_FD_SYNC is set, includes the right to invoke fd_pread.
|
||||
RIGHT_FD_READ
|
||||
|
||||
// RIGHT_FD_SEEK is the right to invoke fd_seek. This flag implies
|
||||
// RIGHT_FD_TELL.
|
||||
RIGHT_FD_SEEK
|
||||
|
||||
// RIGHT_FDSTAT_SET_FLAGS is the right to invoke fd_fdstat_set_flags.
|
||||
RIGHT_FDSTAT_SET_FLAGS
|
||||
|
||||
// RIGHT_FD_SYNC The right to invoke fd_sync. If path_open is set, includes
|
||||
// the right to invoke path_open with FD_RSYNC and FD_DSYNC.
|
||||
RIGHT_FD_SYNC
|
||||
|
||||
// RIGHT_FD_TELL is the right to invoke fd_seek in such a way that the file
|
||||
// offset remains unaltered (i.e., whence::cur with offset zero), or to
|
||||
// invoke fd_tell.
|
||||
RIGHT_FD_TELL
|
||||
|
||||
// RIGHT_FD_WRITE is the right to invoke fd_write and sock_send. If
|
||||
// RIGHT_FD_SEEK is set, includes the right to invoke fd_pwrite.
|
||||
RIGHT_FD_WRITE
|
||||
|
||||
// RIGHT_FD_ADVISE is the right to invoke fd_advise.
|
||||
RIGHT_FD_ADVISE
|
||||
|
||||
// RIGHT_FD_ALLOCATE is the right to invoke fd_allocate.
|
||||
RIGHT_FD_ALLOCATE
|
||||
|
||||
// RIGHT_PATH_CREATE_DIRECTORY is the right to invoke
|
||||
// path_create_directory.
|
||||
RIGHT_PATH_CREATE_DIRECTORY
|
||||
|
||||
// RIGHT_PATH_CREATE_FILE when RIGHT_PATH_OPEN is set, the right to invoke
|
||||
// path_open with O_CREATE.
|
||||
RIGHT_PATH_CREATE_FILE
|
||||
|
||||
// RIGHT_PATH_LINK_SOURCE is the right to invoke path_link with the file
|
||||
// descriptor as the source directory.
|
||||
RIGHT_PATH_LINK_SOURCE
|
||||
|
||||
// RIGHT_PATH_LINK_TARGET is the right to invoke path_link with the file
|
||||
// descriptor as the target directory.
|
||||
RIGHT_PATH_LINK_TARGET
|
||||
|
||||
// RIGHT_PATH_OPEN is the right to invoke path_open.
|
||||
RIGHT_PATH_OPEN
|
||||
|
||||
// RIGHT_FD_READDIR is the right to invoke fd_readdir.
|
||||
RIGHT_FD_READDIR
|
||||
|
||||
// RIGHT_PATH_READLINK is the right to invoke path_readlink.
|
||||
RIGHT_PATH_READLINK
|
||||
|
||||
// RIGHT_PATH_RENAME_SOURCE is the right to invoke path_rename with the
|
||||
// file descriptor as the source directory.
|
||||
RIGHT_PATH_RENAME_SOURCE
|
||||
|
||||
// RIGHT_PATH_RENAME_TARGET is the right to invoke path_rename with the
|
||||
// file descriptor as the target directory.
|
||||
RIGHT_PATH_RENAME_TARGET
|
||||
|
||||
// RIGHT_PATH_FILESTAT_GET is the right to invoke path_filestat_get.
|
||||
RIGHT_PATH_FILESTAT_GET
|
||||
|
||||
// RIGHT_PATH_FILESTAT_SET_SIZE is the right to change a file's size (there
|
||||
// is no path_filestat_set_size). If RIGHT_PATH_OPEN is set, includes the
|
||||
// right to invoke path_open with O_TRUNC.
|
||||
RIGHT_PATH_FILESTAT_SET_SIZE
|
||||
|
||||
// RIGHT_PATH_FILESTAT_SET_TIMES is the right to invoke
|
||||
// path_filestat_set_times.
|
||||
RIGHT_PATH_FILESTAT_SET_TIMES
|
||||
|
||||
// RIGHT_FD_FILESTAT_GET is the right to invoke fd_filestat_get.
|
||||
RIGHT_FD_FILESTAT_GET
|
||||
|
||||
// RIGHT_FD_FILESTAT_SET_SIZE is the right to invoke fd_filestat_set_size.
|
||||
RIGHT_FD_FILESTAT_SET_SIZE
|
||||
|
||||
// RIGHT_FD_FILESTAT_SET_TIMES is the right to invoke
|
||||
// fd_filestat_set_times.
|
||||
RIGHT_FD_FILESTAT_SET_TIMES
|
||||
|
||||
// RIGHT_PATH_SYMLINK is the right to invoke path_symlink.
|
||||
RIGHT_PATH_SYMLINK
|
||||
|
||||
// RIGHT_PATH_REMOVE_DIRECTORY is the right to invoke
|
||||
// path_remove_directory.
|
||||
RIGHT_PATH_REMOVE_DIRECTORY
|
||||
|
||||
// RIGHT_PATH_UNLINK_FILE is the right to invoke path_unlink_file.
|
||||
RIGHT_PATH_UNLINK_FILE
|
||||
|
||||
// RIGHT_POLL_FD_READWRITE when RIGHT_FD_READ is set, includes the right to
|
||||
// invoke poll_oneoff to subscribe to eventtype::fd_read. If RIGHT_FD_WRITE
|
||||
// is set, includes the right to invoke poll_oneoff to subscribe to
|
||||
// eventtype::fd_write.
|
||||
RIGHT_POLL_FD_READWRITE
|
||||
|
||||
// RIGHT_SOCK_SHUTDOWN is the right to invoke sock_shutdown.
|
||||
RIGHT_SOCK_SHUTDOWN
|
||||
)
|
||||
|
||||
const (
|
||||
FILETYPE_UNKNOWN uint8 = iota
|
||||
FILETYPE_BLOCK_DEVICE
|
||||
FILETYPE_CHARACTER_DEVICE
|
||||
FILETYPE_DIRECTORY
|
||||
FILETYPE_REGULAR_FILE
|
||||
FILETYPE_SOCKET_DGRAM
|
||||
FILETYPE_SOCKET_STREAM
|
||||
FILETYPE_SYMBOLIC_LINK
|
||||
)
|
||||
|
||||
// FiletypeName returns string name of the file type.
|
||||
func FiletypeName(filetype uint8) string {
|
||||
if int(filetype) < len(filetypeToString) {
|
||||
return filetypeToString[filetype]
|
||||
}
|
||||
return fmt.Sprintf("filetype(%d)", filetype)
|
||||
}
|
||||
|
||||
var filetypeToString = [...]string{
|
||||
"UNKNOWN",
|
||||
"BLOCK_DEVICE",
|
||||
"CHARACTER_DEVICE",
|
||||
"DIRECTORY",
|
||||
"REGULAR_FILE",
|
||||
"SOCKET_DGRAM",
|
||||
"SOCKET_STREAM",
|
||||
"SYMBOLIC_LINK",
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
. "github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
func argsSizesGet(ctx context.Context, mod api.Module, resultArgc, resultArgvBufSize uint32) uint32 {
|
||||
@@ -22,8 +22,6 @@ func swap(ctx context.Context, x, y uint32) (uint32, uint32) {
|
||||
}
|
||||
|
||||
func TestNewHostModule(t *testing.T) {
|
||||
argsSizesGetName := "args_sizes_get"
|
||||
fdWriteName := "fd_write"
|
||||
swapName := "swap"
|
||||
|
||||
tests := []struct {
|
||||
@@ -43,19 +41,19 @@ func TestNewHostModule(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "funcs",
|
||||
moduleName: wasi_snapshot_preview1.ModuleName,
|
||||
moduleName: InternalModuleName,
|
||||
nameToGoFunc: map[string]interface{}{
|
||||
argsSizesGetName: argsSizesGet,
|
||||
fdWriteName: fdWrite,
|
||||
ArgsSizesGetName: argsSizesGet,
|
||||
FdWriteName: fdWrite,
|
||||
},
|
||||
funcToNames: map[string]*HostFuncNames{
|
||||
argsSizesGetName: {
|
||||
Name: argsSizesGetName,
|
||||
ArgsSizesGetName: {
|
||||
Name: ArgsSizesGetName,
|
||||
ParamNames: []string{"result.argc", "result.argv_len"},
|
||||
ResultNames: []string{"errno"},
|
||||
},
|
||||
fdWriteName: {
|
||||
Name: fdWriteName,
|
||||
FdWriteName: {
|
||||
Name: FdWriteName,
|
||||
ParamNames: []string{"fd", "iovs", "iovs_len", "result.size"},
|
||||
ResultNames: []string{"errno"},
|
||||
},
|
||||
@@ -68,14 +66,14 @@ func TestNewHostModule(t *testing.T) {
|
||||
FunctionSection: []Index{0, 1},
|
||||
CodeSection: []*Code{MustParseGoReflectFuncCode(argsSizesGet), MustParseGoReflectFuncCode(fdWrite)},
|
||||
ExportSection: []*Export{
|
||||
{Name: "args_sizes_get", Type: ExternTypeFunc, Index: 0},
|
||||
{Name: "fd_write", Type: ExternTypeFunc, Index: 1},
|
||||
{Name: ArgsSizesGetName, Type: ExternTypeFunc, Index: 0},
|
||||
{Name: FdWriteName, Type: ExternTypeFunc, Index: 1},
|
||||
},
|
||||
NameSection: &NameSection{
|
||||
ModuleName: wasi_snapshot_preview1.ModuleName,
|
||||
ModuleName: InternalModuleName,
|
||||
FunctionNames: NameMap{
|
||||
{Index: 0, Name: "args_sizes_get"},
|
||||
{Index: 1, Name: "fd_write"},
|
||||
{Index: 0, Name: ArgsSizesGetName},
|
||||
{Index: 1, Name: FdWriteName},
|
||||
},
|
||||
LocalNames: IndirectNameMap{
|
||||
{Index: 0, NameMap: NameMap{
|
||||
|
||||
Reference in New Issue
Block a user