2023-01-18 01:30:11 +00:00
|
|
|
package sqlite3
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2023-02-06 01:01:17 +00:00
|
|
|
"crypto/rand"
|
2023-01-19 00:18:39 +00:00
|
|
|
"errors"
|
2023-01-18 23:45:22 +00:00
|
|
|
"io"
|
2023-01-19 00:18:39 +00:00
|
|
|
"io/fs"
|
2023-01-18 18:58:49 +00:00
|
|
|
"os"
|
2023-01-18 11:40:08 +00:00
|
|
|
"path/filepath"
|
2023-01-26 18:20:54 +00:00
|
|
|
"runtime"
|
2023-01-18 01:30:11 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/ncruces/julianday"
|
|
|
|
|
"github.com/tetratelabs/wazero"
|
|
|
|
|
"github.com/tetratelabs/wazero/api"
|
|
|
|
|
"github.com/tetratelabs/wazero/sys"
|
|
|
|
|
)
|
|
|
|
|
|
2023-02-16 13:52:05 +00:00
|
|
|
func vfsInstantiate(ctx context.Context, r wazero.Runtime) {
|
2023-01-18 01:30:11 +00:00
|
|
|
wasi := r.NewHostModuleBuilder("wasi_snapshot_preview1")
|
2023-03-20 11:02:34 +00:00
|
|
|
vfsRegisterFunc(wasi, "proc_exit", vfsExit)
|
2023-02-16 13:52:05 +00:00
|
|
|
_, err := wasi.Instantiate(ctx)
|
2023-01-18 01:30:11 +00:00
|
|
|
if err != nil {
|
2023-02-16 13:52:05 +00:00
|
|
|
panic(err)
|
2023-01-18 01:30:11 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-05 11:36:02 +00:00
|
|
|
env := vfsNewEnvModuleBuilder(r)
|
|
|
|
|
_, err = env.Instantiate(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsNewEnvModuleBuilder(r wazero.Runtime) wazero.HostModuleBuilder {
|
2023-01-18 01:30:11 +00:00
|
|
|
env := r.NewHostModuleBuilder("env")
|
2023-03-20 11:02:34 +00:00
|
|
|
vfsRegisterFunc(env, "os_localtime", vfsLocaltime)
|
|
|
|
|
vfsRegisterFunc3(env, "os_randomness", vfsRandomness)
|
|
|
|
|
vfsRegisterFunc2(env, "os_sleep", vfsSleep)
|
|
|
|
|
vfsRegisterFunc2(env, "os_current_time", vfsCurrentTime)
|
|
|
|
|
vfsRegisterFunc2(env, "os_current_time_64", vfsCurrentTime64)
|
|
|
|
|
vfsRegisterFunc4(env, "os_full_pathname", vfsFullPathname)
|
|
|
|
|
vfsRegisterFunc3(env, "os_delete", vfsDelete)
|
|
|
|
|
vfsRegisterFunc4(env, "os_access", vfsAccess)
|
|
|
|
|
vfsRegisterFunc5(env, "os_open", vfsOpen)
|
|
|
|
|
vfsRegisterFunc1(env, "os_close", vfsClose)
|
|
|
|
|
vfsRegisterFuncRW(env, "os_read", vfsRead)
|
|
|
|
|
vfsRegisterFuncRW(env, "os_write", vfsWrite)
|
|
|
|
|
vfsRegisterFunc(env, "os_truncate", vfsTruncate)
|
|
|
|
|
vfsRegisterFunc2(env, "os_sync", vfsSync)
|
|
|
|
|
vfsRegisterFunc2(env, "os_file_size", vfsFileSize)
|
|
|
|
|
vfsRegisterFunc2(env, "os_lock", vfsLock)
|
|
|
|
|
vfsRegisterFunc2(env, "os_unlock", vfsUnlock)
|
|
|
|
|
vfsRegisterFunc2(env, "os_check_reserved_lock", vfsCheckReservedLock)
|
|
|
|
|
vfsRegisterFunc3(env, "os_file_control", vfsFileControl)
|
2023-03-05 11:36:02 +00:00
|
|
|
return env
|
2023-01-18 01:30:11 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-07 10:45:11 +00:00
|
|
|
// Poor man's namespaces.
|
|
|
|
|
const (
|
|
|
|
|
vfsOS vfsOSMethods = false
|
|
|
|
|
vfsFile vfsFileMethods = false
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
vfsOSMethods bool
|
|
|
|
|
vfsFileMethods bool
|
|
|
|
|
)
|
2023-02-23 13:29:51 +00:00
|
|
|
|
2023-03-07 10:45:11 +00:00
|
|
|
type vfsKey struct{}
|
|
|
|
|
type vfsState struct {
|
|
|
|
|
files []*os.File
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsContext(ctx context.Context) (context.Context, io.Closer) {
|
|
|
|
|
vfs := &vfsState{}
|
|
|
|
|
return context.WithValue(ctx, vfsKey{}, vfs), vfs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (vfs *vfsState) Close() error {
|
|
|
|
|
for _, f := range vfs.files {
|
|
|
|
|
if f != nil {
|
|
|
|
|
f.Close()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vfs.files = nil
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2023-02-23 13:29:51 +00:00
|
|
|
|
2023-01-18 01:30:11 +00:00
|
|
|
func vfsExit(ctx context.Context, mod api.Module, exitCode uint32) {
|
|
|
|
|
// Ensure other callers see the exit code.
|
|
|
|
|
_ = mod.CloseWithExitCode(ctx, exitCode)
|
|
|
|
|
// Prevent any code from executing after this function.
|
|
|
|
|
panic(sys.NewExitError(mod.Name(), exitCode))
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-24 11:17:30 -08:00
|
|
|
func vfsLocaltime(ctx context.Context, mod api.Module, t uint64, pTm uint32) uint32 {
|
|
|
|
|
tm := time.Unix(int64(t), 0)
|
|
|
|
|
var isdst int
|
|
|
|
|
if tm.IsDST() {
|
|
|
|
|
isdst = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
|
2023-01-26 14:52:38 +00:00
|
|
|
mem := memory{mod}
|
|
|
|
|
mem.writeUint32(pTm+0*ptrlen, uint32(tm.Second()))
|
|
|
|
|
mem.writeUint32(pTm+1*ptrlen, uint32(tm.Minute()))
|
|
|
|
|
mem.writeUint32(pTm+2*ptrlen, uint32(tm.Hour()))
|
|
|
|
|
mem.writeUint32(pTm+3*ptrlen, uint32(tm.Day()))
|
|
|
|
|
mem.writeUint32(pTm+4*ptrlen, uint32(tm.Month()-time.January))
|
|
|
|
|
mem.writeUint32(pTm+5*ptrlen, uint32(tm.Year()-1900))
|
|
|
|
|
mem.writeUint32(pTm+6*ptrlen, uint32(tm.Weekday()-time.Sunday))
|
|
|
|
|
mem.writeUint32(pTm+7*ptrlen, uint32(tm.YearDay()-1))
|
|
|
|
|
mem.writeUint32(pTm+8*ptrlen, uint32(isdst))
|
|
|
|
|
return _OK
|
2023-01-24 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsRandomness(ctx context.Context, mod api.Module, pVfs, nByte, zByte uint32) uint32 {
|
2023-02-27 03:20:23 +00:00
|
|
|
mem := memory{mod}.view(zByte, uint64(nByte))
|
2023-02-06 01:01:17 +00:00
|
|
|
n, _ := rand.Reader.Read(mem)
|
2023-01-18 01:30:11 +00:00
|
|
|
return uint32(n)
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-20 11:02:34 +00:00
|
|
|
func vfsSleep(ctx context.Context, mod api.Module, pVfs, nMicro uint32) uint32 {
|
2023-01-22 15:44:39 +00:00
|
|
|
time.Sleep(time.Duration(nMicro) * time.Microsecond)
|
2023-01-18 01:30:11 +00:00
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsCurrentTime(ctx context.Context, mod api.Module, pVfs, prNow uint32) uint32 {
|
2023-01-18 01:30:11 +00:00
|
|
|
day := julianday.Float(time.Now())
|
2023-01-26 14:52:38 +00:00
|
|
|
memory{mod}.writeFloat64(prNow, day)
|
2023-01-18 01:30:11 +00:00
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsCurrentTime64(ctx context.Context, mod api.Module, pVfs, piNow uint32) uint32 {
|
2023-01-18 01:30:11 +00:00
|
|
|
day, nsec := julianday.Date(time.Now())
|
|
|
|
|
msec := day*86_400_000 + nsec/1_000_000
|
2023-01-26 14:52:38 +00:00
|
|
|
memory{mod}.writeUint64(piNow, uint64(msec))
|
2023-01-18 01:30:11 +00:00
|
|
|
return _OK
|
|
|
|
|
}
|
2023-01-18 11:40:08 +00:00
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative, nFull, zFull uint32) uint32 {
|
2023-01-26 14:52:38 +00:00
|
|
|
rel := memory{mod}.readString(zRelative, _MAX_PATHNAME)
|
2023-01-22 15:44:39 +00:00
|
|
|
abs, err := filepath.Abs(rel)
|
2023-01-18 11:40:08 +00:00
|
|
|
if err != nil {
|
2023-03-16 12:27:44 +00:00
|
|
|
return uint32(CANTOPEN_FULLPATH)
|
2023-01-18 11:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
2023-02-27 03:20:23 +00:00
|
|
|
size := uint64(len(abs) + 1)
|
|
|
|
|
if size > uint64(nFull) {
|
2023-01-25 14:59:02 +00:00
|
|
|
return uint32(CANTOPEN_FULLPATH)
|
|
|
|
|
}
|
2023-02-14 11:34:24 +00:00
|
|
|
mem := memory{mod}.view(zFull, size)
|
2023-01-22 15:44:39 +00:00
|
|
|
mem[len(abs)] = 0
|
|
|
|
|
copy(mem, abs)
|
2023-03-16 12:27:44 +00:00
|
|
|
|
|
|
|
|
if fi, err := os.Lstat(abs); err == nil {
|
|
|
|
|
if fi.Mode()&fs.ModeSymlink != 0 {
|
|
|
|
|
return _OK_SYMLINK
|
|
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
} else if errors.Is(err, fs.ErrNotExist) {
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
return uint32(CANTOPEN_FULLPATH)
|
2023-01-18 11:40:08 +00:00
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32) uint32 {
|
2023-01-26 14:52:38 +00:00
|
|
|
path := memory{mod}.readString(zPath, _MAX_PATHNAME)
|
2023-01-22 15:44:39 +00:00
|
|
|
err := os.Remove(path)
|
2023-01-19 01:12:09 +00:00
|
|
|
if errors.Is(err, fs.ErrNotExist) {
|
2023-03-10 14:02:34 +00:00
|
|
|
return uint32(IOERR_DELETE_NOENT)
|
2023-01-19 01:12:09 +00:00
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_DELETE)
|
|
|
|
|
}
|
2023-01-26 18:20:54 +00:00
|
|
|
if runtime.GOOS != "windows" && syncDir != 0 {
|
2023-01-22 15:44:39 +00:00
|
|
|
f, err := os.Open(filepath.Dir(path))
|
2023-03-10 14:02:34 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return _OK
|
2023-01-19 01:12:09 +00:00
|
|
|
}
|
2023-03-10 14:02:34 +00:00
|
|
|
defer f.Close()
|
|
|
|
|
err = vfsOS.Sync(f, false, false)
|
2023-01-19 01:12:09 +00:00
|
|
|
if err != nil {
|
2023-03-10 14:02:34 +00:00
|
|
|
return uint32(IOERR_DIR_FSYNC)
|
2023-01-19 01:12:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
|
2023-02-18 03:43:17 +00:00
|
|
|
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags _AccessFlag, pResOut uint32) uint32 {
|
2023-01-26 14:52:38 +00:00
|
|
|
path := memory{mod}.readString(zPath, _MAX_PATHNAME)
|
2023-03-17 17:13:03 +00:00
|
|
|
err := vfsOS.Access(path, flags)
|
|
|
|
|
|
2023-01-19 00:18:39 +00:00
|
|
|
var res uint32
|
2023-03-17 17:13:03 +00:00
|
|
|
var rc xErrorCode
|
|
|
|
|
if flags == _ACCESS_EXISTS {
|
|
|
|
|
switch {
|
|
|
|
|
case err == nil:
|
|
|
|
|
res = 1
|
|
|
|
|
case errors.Is(err, fs.ErrNotExist):
|
|
|
|
|
res = 0
|
|
|
|
|
default:
|
|
|
|
|
rc = IOERR_ACCESS
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
switch {
|
|
|
|
|
case err == nil:
|
|
|
|
|
res = 1
|
|
|
|
|
case errors.Is(err, fs.ErrPermission):
|
|
|
|
|
res = 0
|
|
|
|
|
default:
|
|
|
|
|
rc = IOERR_ACCESS
|
|
|
|
|
}
|
2023-01-19 00:18:39 +00:00
|
|
|
}
|
2023-03-17 17:13:03 +00:00
|
|
|
|
2023-01-26 14:52:38 +00:00
|
|
|
memory{mod}.writeUint32(pResOut, res)
|
2023-03-09 01:59:46 +00:00
|
|
|
return uint32(rc)
|
2023-01-19 00:18:39 +00:00
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
|
2023-01-25 14:59:02 +00:00
|
|
|
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zName, pFile uint32, flags OpenFlag, pOutFlags uint32) uint32 {
|
2023-01-18 18:58:49 +00:00
|
|
|
var oflags int
|
2023-01-25 14:59:02 +00:00
|
|
|
if flags&OPEN_EXCLUSIVE != 0 {
|
2023-01-18 18:58:49 +00:00
|
|
|
oflags |= os.O_EXCL
|
|
|
|
|
}
|
2023-01-25 14:59:02 +00:00
|
|
|
if flags&OPEN_CREATE != 0 {
|
2023-01-18 18:58:49 +00:00
|
|
|
oflags |= os.O_CREATE
|
|
|
|
|
}
|
2023-01-25 14:59:02 +00:00
|
|
|
if flags&OPEN_READONLY != 0 {
|
2023-01-18 18:58:49 +00:00
|
|
|
oflags |= os.O_RDONLY
|
|
|
|
|
}
|
2023-01-25 14:59:02 +00:00
|
|
|
if flags&OPEN_READWRITE != 0 {
|
2023-01-18 18:58:49 +00:00
|
|
|
oflags |= os.O_RDWR
|
|
|
|
|
}
|
2023-01-25 14:59:02 +00:00
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
var file *os.File
|
|
|
|
|
if zName == 0 {
|
|
|
|
|
file, err = os.CreateTemp("", "*.db")
|
|
|
|
|
} else {
|
2023-01-26 14:52:38 +00:00
|
|
|
name := memory{mod}.readString(zName, _MAX_PATHNAME)
|
2023-03-09 01:23:52 +00:00
|
|
|
file, err = vfsOS.OpenFile(name, oflags, 0600)
|
2023-01-25 14:59:02 +00:00
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return uint32(CANTOPEN)
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-25 14:59:02 +00:00
|
|
|
if flags&OPEN_DELETEONCLOSE != 0 {
|
2023-03-09 01:23:52 +00:00
|
|
|
os.Remove(file.Name())
|
2023-01-25 14:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-07 10:45:11 +00:00
|
|
|
vfsFile.Open(ctx, mod, pFile, file)
|
2023-01-22 17:33:21 +00:00
|
|
|
|
2023-01-26 14:52:38 +00:00
|
|
|
if pOutFlags != 0 {
|
|
|
|
|
memory{mod}.writeUint32(pOutFlags, uint32(flags))
|
2023-01-19 00:25:56 +00:00
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsClose(ctx context.Context, mod api.Module, pFile uint32) uint32 {
|
2023-03-07 10:45:11 +00:00
|
|
|
err := vfsFile.Close(ctx, mod, pFile)
|
2023-01-18 18:58:49 +00:00
|
|
|
if err != nil {
|
2023-01-19 00:18:39 +00:00
|
|
|
return uint32(IOERR_CLOSE)
|
2023-01-18 18:58:49 +00:00
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst uint64) uint32 {
|
2023-02-27 03:20:23 +00:00
|
|
|
buf := memory{mod}.view(zBuf, uint64(iAmt))
|
2023-01-18 23:45:22 +00:00
|
|
|
|
2023-03-07 10:45:11 +00:00
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
2023-01-25 14:59:02 +00:00
|
|
|
n, err := file.ReadAt(buf, int64(iOfst))
|
2023-01-18 23:45:22 +00:00
|
|
|
if n == int(iAmt) {
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
if n == 0 && err != io.EOF {
|
|
|
|
|
return uint32(IOERR_READ)
|
|
|
|
|
}
|
2023-01-25 14:59:02 +00:00
|
|
|
for i := range buf[n:] {
|
2023-01-29 02:11:41 +00:00
|
|
|
buf[n+i] = 0
|
2023-01-18 23:45:22 +00:00
|
|
|
}
|
|
|
|
|
return uint32(IOERR_SHORT_READ)
|
2023-01-18 18:58:49 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf, iAmt uint32, iOfst uint64) uint32 {
|
2023-02-27 03:20:23 +00:00
|
|
|
buf := memory{mod}.view(zBuf, uint64(iAmt))
|
2023-01-19 00:58:57 +00:00
|
|
|
|
2023-03-07 10:45:11 +00:00
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
2023-01-25 14:59:02 +00:00
|
|
|
_, err := file.WriteAt(buf, int64(iOfst))
|
2023-01-19 00:58:57 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_WRITE)
|
|
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte uint64) uint32 {
|
2023-03-07 10:45:11 +00:00
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
2023-01-22 15:44:39 +00:00
|
|
|
err := file.Truncate(int64(nByte))
|
2023-01-19 01:12:09 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_TRUNCATE)
|
|
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
|
2023-03-10 14:02:34 +00:00
|
|
|
func vfsSync(ctx context.Context, mod api.Module, pFile uint32, flags _SyncFlag) uint32 {
|
|
|
|
|
dataonly := (flags & _SYNC_DATAONLY) != 0
|
|
|
|
|
fullsync := (flags & 0x0f) == _SYNC_FULL
|
2023-03-07 10:45:11 +00:00
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
2023-03-10 14:02:34 +00:00
|
|
|
err := vfsOS.Sync(file, fullsync, dataonly)
|
2023-01-19 00:58:57 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_FSYNC)
|
|
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
2023-01-18 18:58:49 +00:00
|
|
|
|
2023-01-22 15:44:39 +00:00
|
|
|
func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize uint32) uint32 {
|
2023-03-07 10:45:11 +00:00
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
2023-01-22 15:44:39 +00:00
|
|
|
off, err := file.Seek(0, io.SeekEnd)
|
2023-01-19 00:25:56 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_SEEK)
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-26 14:52:38 +00:00
|
|
|
memory{mod}.writeUint64(pSize, uint64(off))
|
2023-01-19 00:25:56 +00:00
|
|
|
return _OK
|
|
|
|
|
}
|
2023-02-13 13:52:52 +00:00
|
|
|
|
2023-03-17 13:24:15 +00:00
|
|
|
func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _FcntlOpcode, pArg uint32) uint32 {
|
|
|
|
|
switch op {
|
|
|
|
|
case _FCNTL_SIZE_HINT:
|
2023-03-17 17:13:03 +00:00
|
|
|
return vfsSizeHint(ctx, mod, pFile, pArg)
|
2023-03-17 13:24:15 +00:00
|
|
|
case _FCNTL_HAS_MOVED:
|
2023-03-17 14:00:35 +00:00
|
|
|
return vfsFileMoved(ctx, mod, pFile, pArg)
|
2023-03-17 13:24:15 +00:00
|
|
|
}
|
2023-02-13 13:52:52 +00:00
|
|
|
return uint32(NOTFOUND)
|
|
|
|
|
}
|
2023-03-17 14:00:35 +00:00
|
|
|
|
2023-03-17 17:13:03 +00:00
|
|
|
func vfsSizeHint(ctx context.Context, mod api.Module, pFile, pArg uint32) uint32 {
|
|
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
|
|
|
|
size := memory{mod}.readUint64(pArg)
|
|
|
|
|
err := vfsOS.Allocate(file, int64(size))
|
|
|
|
|
if err == notImplErr {
|
|
|
|
|
return uint32(NOTFOUND)
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_TRUNCATE)
|
|
|
|
|
}
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 14:00:35 +00:00
|
|
|
func vfsFileMoved(ctx context.Context, mod api.Module, pFile, pResOut uint32) uint32 {
|
|
|
|
|
file := vfsFile.GetOS(ctx, mod, pFile)
|
|
|
|
|
fi, err := file.Stat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return uint32(IOERR_FSTAT)
|
|
|
|
|
}
|
|
|
|
|
pi, err := os.Stat(file.Name())
|
|
|
|
|
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
|
|
|
return uint32(IOERR_FSTAT)
|
|
|
|
|
}
|
|
|
|
|
var res uint32
|
|
|
|
|
if !os.SameFile(fi, pi) {
|
|
|
|
|
res = 1
|
|
|
|
|
}
|
|
|
|
|
memory{mod}.writeUint32(pResOut, res)
|
|
|
|
|
return _OK
|
|
|
|
|
}
|
2023-03-20 11:02:34 +00:00
|
|
|
|
|
|
|
|
func vfsRegisterFunc(mod wazero.HostModuleBuilder, name string, fn any) {
|
|
|
|
|
mod.NewFunctionBuilder().WithFunc(fn).Export(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsRegisterFunc1(mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ uint32) uint32) {
|
|
|
|
|
mod.NewFunctionBuilder().
|
|
|
|
|
WithGoModuleFunction(api.GoModuleFunc(
|
|
|
|
|
func(ctx context.Context, mod api.Module, stack []uint64) {
|
|
|
|
|
stack[0] = uint64(fn(ctx, mod, uint32(stack[0])))
|
|
|
|
|
}),
|
|
|
|
|
[]api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}).
|
|
|
|
|
Export(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsRegisterFunc2[T0, T1 ~uint32](mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ T0, _ T1) uint32) {
|
|
|
|
|
mod.NewFunctionBuilder().
|
|
|
|
|
WithGoModuleFunction(api.GoModuleFunc(
|
|
|
|
|
func(ctx context.Context, mod api.Module, stack []uint64) {
|
|
|
|
|
stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1])))
|
|
|
|
|
}),
|
|
|
|
|
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}).
|
|
|
|
|
Export(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsRegisterFunc3[T0, T1, T2 ~uint32](mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ T0, _ T1, _ T2) uint32) {
|
|
|
|
|
mod.NewFunctionBuilder().
|
|
|
|
|
WithGoModuleFunction(api.GoModuleFunc(
|
|
|
|
|
func(ctx context.Context, mod api.Module, stack []uint64) {
|
|
|
|
|
stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2])))
|
|
|
|
|
}),
|
|
|
|
|
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}).
|
|
|
|
|
Export(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsRegisterFunc4[T0, T1, T2, T3 ~uint32](mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ T0, _ T1, _ T2, _ T3) uint32) {
|
|
|
|
|
mod.NewFunctionBuilder().
|
|
|
|
|
WithGoModuleFunction(api.GoModuleFunc(
|
|
|
|
|
func(ctx context.Context, mod api.Module, stack []uint64) {
|
|
|
|
|
stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3])))
|
|
|
|
|
}),
|
|
|
|
|
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}).
|
|
|
|
|
Export(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsRegisterFunc5[T0, T1, T2, T3, T4 ~uint32](mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _ T0, _ T1, _ T2, _ T3, _ T4) uint32) {
|
|
|
|
|
mod.NewFunctionBuilder().
|
|
|
|
|
WithGoModuleFunction(api.GoModuleFunc(
|
|
|
|
|
func(ctx context.Context, mod api.Module, stack []uint64) {
|
|
|
|
|
stack[0] = uint64(fn(ctx, mod, T0(stack[0]), T1(stack[1]), T2(stack[2]), T3(stack[3]), T4(stack[4])))
|
|
|
|
|
}),
|
|
|
|
|
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}).
|
|
|
|
|
Export(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func vfsRegisterFuncRW(mod wazero.HostModuleBuilder, name string, fn func(ctx context.Context, mod api.Module, _, _, _ uint32, _ uint64) uint32) {
|
|
|
|
|
mod.NewFunctionBuilder().
|
|
|
|
|
WithGoModuleFunction(api.GoModuleFunc(
|
|
|
|
|
func(ctx context.Context, mod api.Module, stack []uint64) {
|
|
|
|
|
stack[0] = uint64(fn(ctx, mod, uint32(stack[0]), uint32(stack[1]), uint32(stack[2]), stack[3]))
|
|
|
|
|
}),
|
|
|
|
|
[]api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64}, []api.ValueType{api.ValueTypeI32}).
|
|
|
|
|
Export(name)
|
|
|
|
|
}
|