Files
sqlite3/vfs/vfs.go

487 lines
14 KiB
Go
Raw Normal View History

2023-06-01 18:11:37 +01:00
package vfs
2023-03-29 15:01:25 +01:00
import (
"context"
"crypto/rand"
"io"
2023-05-19 03:04:07 +01:00
"reflect"
2024-10-24 00:22:20 +01:00
"strings"
2023-03-29 15:01:25 +01:00
"time"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
2024-10-18 12:20:32 +01:00
"github.com/ncruces/go-sqlite3/internal/util"
2024-10-22 23:32:57 +01:00
"github.com/ncruces/go-sqlite3/util/sql3util"
2024-10-18 12:20:32 +01:00
"github.com/ncruces/julianday"
2023-03-29 15:01:25 +01:00
)
2023-06-02 03:32:13 +01:00
// ExportHostFunctions is an internal API users need not call directly.
//
2023-05-19 13:47:12 +01:00
// ExportHostFunctions registers the required VFS host functions
// with the provided env module.
2023-05-19 03:04:07 +01:00
func ExportHostFunctions(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
2023-05-19 13:47:12 +01:00
util.ExportFuncII(env, "go_vfs_find", vfsFind)
util.ExportFuncIIJ(env, "go_localtime", vfsLocaltime)
util.ExportFuncIIII(env, "go_randomness", vfsRandomness)
util.ExportFuncIII(env, "go_sleep", vfsSleep)
util.ExportFuncIII(env, "go_current_time_64", vfsCurrentTime64)
util.ExportFuncIIIII(env, "go_full_pathname", vfsFullPathname)
util.ExportFuncIIII(env, "go_delete", vfsDelete)
util.ExportFuncIIIII(env, "go_access", vfsAccess)
util.ExportFuncIIIIIII(env, "go_open", vfsOpen)
2023-05-19 13:47:12 +01:00
util.ExportFuncII(env, "go_close", vfsClose)
util.ExportFuncIIIIJ(env, "go_read", vfsRead)
util.ExportFuncIIIIJ(env, "go_write", vfsWrite)
util.ExportFuncIIJ(env, "go_truncate", vfsTruncate)
util.ExportFuncIII(env, "go_sync", vfsSync)
util.ExportFuncIII(env, "go_file_size", vfsFileSize)
util.ExportFuncIIII(env, "go_file_control", vfsFileControl)
util.ExportFuncII(env, "go_sector_size", vfsSectorSize)
util.ExportFuncII(env, "go_device_characteristics", vfsDeviceCharacteristics)
util.ExportFuncIII(env, "go_lock", vfsLock)
util.ExportFuncIII(env, "go_unlock", vfsUnlock)
util.ExportFuncIII(env, "go_check_reserved_lock", vfsCheckReservedLock)
util.ExportFuncIIIIII(env, "go_shm_map", vfsShmMap)
util.ExportFuncIIIII(env, "go_shm_lock", vfsShmLock)
util.ExportFuncIII(env, "go_shm_unmap", vfsShmUnmap)
util.ExportFuncVI(env, "go_shm_barrier", vfsShmBarrier)
2023-03-29 15:01:25 +01:00
return env
}
2023-05-17 01:00:08 +01:00
func vfsFind(ctx context.Context, mod api.Module, zVfsName uint32) uint32 {
2023-11-24 17:25:02 +00:00
name := util.ReadString(mod, zVfsName, _MAX_NAME)
2023-06-02 03:32:13 +01:00
if vfs := Find(name); vfs != nil && vfs != (vfsOS{}) {
2023-05-17 14:04:00 +01:00
return 1
}
2023-05-17 01:00:08 +01:00
return 0
}
2023-03-29 15:01:25 +01:00
func vfsLocaltime(ctx context.Context, mod api.Module, pTm uint32, t int64) _ErrorCode {
tm := time.Unix(t, 0)
var isdst int
if tm.IsDST() {
isdst = 1
}
2023-03-31 13:48:19 +01:00
const size = 32 / 8
2023-03-29 15:01:25 +01:00
// https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
2023-03-31 13:48:19 +01:00
util.WriteUint32(mod, pTm+0*size, uint32(tm.Second()))
util.WriteUint32(mod, pTm+1*size, uint32(tm.Minute()))
util.WriteUint32(mod, pTm+2*size, uint32(tm.Hour()))
util.WriteUint32(mod, pTm+3*size, uint32(tm.Day()))
util.WriteUint32(mod, pTm+4*size, uint32(tm.Month()-time.January))
util.WriteUint32(mod, pTm+5*size, uint32(tm.Year()-1900))
util.WriteUint32(mod, pTm+6*size, uint32(tm.Weekday()-time.Sunday))
util.WriteUint32(mod, pTm+7*size, uint32(tm.YearDay()-1))
util.WriteUint32(mod, pTm+8*size, uint32(isdst))
2023-03-29 15:01:25 +01:00
return _OK
}
2024-04-11 12:00:17 +01:00
func vfsRandomness(ctx context.Context, mod api.Module, pVfs uint32, nByte int32, zByte uint32) uint32 {
2023-03-29 15:01:25 +01:00
mem := util.View(mod, zByte, uint64(nByte))
n, _ := rand.Reader.Read(mem)
return uint32(n)
}
2024-04-11 12:00:17 +01:00
func vfsSleep(ctx context.Context, mod api.Module, pVfs uint32, nMicro int32) _ErrorCode {
2024-06-05 23:12:23 +01:00
time.Sleep(time.Duration(nMicro) * time.Microsecond)
2023-03-29 15:01:25 +01:00
return _OK
}
func vfsCurrentTime64(ctx context.Context, mod api.Module, pVfs, piNow uint32) _ErrorCode {
day, nsec := julianday.Date(time.Now())
msec := day*86_400_000 + nsec/1_000_000
util.WriteUint64(mod, piNow, uint64(msec))
return _OK
}
2024-04-11 12:00:17 +01:00
func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative uint32, nFull int32, zFull uint32) _ErrorCode {
2023-05-19 13:47:12 +01:00
vfs := vfsGet(mod, pVfs)
2023-05-18 16:00:34 +01:00
path := util.ReadString(mod, zRelative, _MAX_PATHNAME)
path, err := vfs.FullPathname(path)
2023-03-29 15:01:25 +01:00
2024-04-11 12:00:17 +01:00
if len(path) >= int(nFull) {
2023-03-29 15:01:25 +01:00
return _CANTOPEN_FULLPATH
}
2024-04-11 12:00:17 +01:00
util.WriteString(mod, zFull, path)
2023-03-29 15:01:25 +01:00
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _CANTOPEN_FULLPATH)
2023-03-29 15:01:25 +01:00
}
func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath, syncDir uint32) _ErrorCode {
2023-05-19 13:47:12 +01:00
vfs := vfsGet(mod, pVfs)
2023-03-29 15:01:25 +01:00
path := util.ReadString(mod, zPath, _MAX_PATHNAME)
2023-05-18 01:34:54 +01:00
2023-05-18 16:00:34 +01:00
err := vfs.Delete(path, syncDir != 0)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_DELETE)
2023-03-29 15:01:25 +01:00
}
2023-05-19 03:04:07 +01:00
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath uint32, flags AccessFlag, pResOut uint32) _ErrorCode {
2023-05-19 13:47:12 +01:00
vfs := vfsGet(mod, pVfs)
2023-03-29 15:01:25 +01:00
path := util.ReadString(mod, zPath, _MAX_PATHNAME)
2023-05-18 16:00:34 +01:00
ok, err := vfs.Access(path, flags)
2023-03-29 15:01:25 +01:00
var res uint32
2023-05-18 16:00:34 +01:00
if ok {
res = 1
2023-03-29 15:01:25 +01:00
}
util.WriteUint32(mod, pResOut, res)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_ACCESS)
2023-03-29 15:01:25 +01:00
}
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile uint32, flags OpenFlag, pOutFlags, pOutVFS uint32) _ErrorCode {
2023-05-19 13:47:12 +01:00
vfs := vfsGet(mod, pVfs)
2024-07-26 01:23:35 +01:00
name := GetFilename(ctx, mod, zPath, flags)
2023-03-29 15:01:25 +01:00
2023-05-25 15:46:15 +01:00
var file File
var err error
if ffs, ok := vfs.(VFSFilename); ok {
file, flags, err = ffs.OpenFilename(name, flags)
2023-05-25 15:46:15 +01:00
} else {
2024-07-26 01:23:35 +01:00
file, flags, err = vfs.Open(name.String(), flags)
2023-05-25 15:46:15 +01:00
}
2023-07-03 17:21:35 +01:00
if err != nil {
return vfsErrorCode(err, _CANTOPEN)
}
2023-05-25 15:46:15 +01:00
if file, ok := file.(FilePowersafeOverwrite); ok {
2024-10-22 23:32:57 +01:00
if b, ok := sql3util.ParseBool(name.URIParameter("psow")); ok {
2023-05-25 15:46:15 +01:00
file.SetPowersafeOverwrite(b)
}
}
2024-04-28 10:33:39 +01:00
if file, ok := file.(FileSharedMemory); ok &&
pOutVFS != 0 && file.SharedMemory() != nil {
util.WriteUint32(mod, pOutVFS, 1)
}
2023-03-29 15:01:25 +01:00
if pOutFlags != 0 {
util.WriteUint32(mod, pOutFlags, uint32(flags))
}
2024-10-25 13:49:06 +01:00
file = cksmWrapFile(name, flags, file)
2023-07-03 17:21:35 +01:00
vfsFileRegister(ctx, mod, pFile, file)
2023-03-29 15:01:25 +01:00
return _OK
}
func vfsClose(ctx context.Context, mod api.Module, pFile uint32) _ErrorCode {
2023-05-18 01:34:54 +01:00
err := vfsFileClose(ctx, mod, pFile)
2024-07-26 13:29:24 +01:00
return vfsErrorCode(err, _IOERR_CLOSE)
2023-03-29 15:01:25 +01:00
}
2024-04-11 12:00:17 +01:00
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int32, iOfst int64) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-03-29 15:01:25 +01:00
buf := util.View(mod, zBuf, uint64(iAmt))
n, err := file.ReadAt(buf, iOfst)
if n == int(iAmt) {
return _OK
}
2023-06-01 15:41:20 +01:00
if err != io.EOF {
2023-05-30 11:21:14 +01:00
return vfsErrorCode(err, _IOERR_READ)
2023-03-29 15:01:25 +01:00
}
2023-05-26 04:59:54 +01:00
clear(buf[n:])
2023-03-29 15:01:25 +01:00
return _IOERR_SHORT_READ
}
2024-04-11 12:00:17 +01:00
func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf uint32, iAmt int32, iOfst int64) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-03-29 15:01:25 +01:00
buf := util.View(mod, zBuf, uint64(iAmt))
_, err := file.WriteAt(buf, iOfst)
2024-07-26 13:29:24 +01:00
return vfsErrorCode(err, _IOERR_WRITE)
2023-03-29 15:01:25 +01:00
}
func vfsTruncate(ctx context.Context, mod api.Module, pFile uint32, nByte int64) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-03-29 15:01:25 +01:00
err := file.Truncate(nByte)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_TRUNCATE)
2023-03-29 15:01:25 +01:00
}
2023-05-19 03:04:07 +01:00
func vfsSync(ctx context.Context, mod api.Module, pFile uint32, flags SyncFlag) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-18 16:00:34 +01:00
err := file.Sync(flags)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_FSYNC)
2023-03-29 15:01:25 +01:00
}
func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize uint32) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-23 16:34:09 +01:00
size, err := file.Size()
2023-05-18 16:00:34 +01:00
util.WriteUint64(mod, pSize, uint64(size))
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_SEEK)
2023-05-18 16:00:34 +01:00
}
2023-05-19 03:04:07 +01:00
func vfsLock(ctx context.Context, mod api.Module, pFile uint32, eLock LockLevel) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-18 16:00:34 +01:00
err := file.Lock(eLock)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_LOCK)
2023-05-18 16:00:34 +01:00
}
2023-05-19 03:04:07 +01:00
func vfsUnlock(ctx context.Context, mod api.Module, pFile uint32, eLock LockLevel) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-18 16:00:34 +01:00
err := file.Unlock(eLock)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_UNLOCK)
2023-05-18 16:00:34 +01:00
}
func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut uint32) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-18 16:00:34 +01:00
locked, err := file.CheckReservedLock()
var res uint32
if locked {
res = 1
2023-03-29 15:01:25 +01:00
}
2023-05-18 16:00:34 +01:00
util.WriteUint32(mod, pResOut, res)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK)
2023-03-29 15:01:25 +01:00
}
func vfsFileControl(ctx context.Context, mod api.Module, pFile uint32, op _FcntlOpcode, pArg uint32) _ErrorCode {
file := vfsFileGet(ctx, mod, pFile).(File)
2024-10-25 13:49:06 +01:00
if file, ok := file.(fileControl); ok {
return file.fileControl(ctx, mod, op, pArg)
}
return vfsFileControlImpl(ctx, mod, file, op, pArg)
}
2023-05-19 02:00:16 +01:00
2024-10-25 13:49:06 +01:00
func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _FcntlOpcode, pArg uint32) _ErrorCode {
2023-03-29 15:01:25 +01:00
switch op {
2023-04-10 19:55:44 +01:00
case _FCNTL_LOCKSTATE:
2023-05-19 03:04:07 +01:00
if file, ok := file.(FileLockState); ok {
2024-10-21 14:51:30 +01:00
if lk := file.LockState(); lk <= LOCK_EXCLUSIVE {
util.WriteUint32(mod, pArg, uint32(lk))
2024-10-17 15:39:01 +01:00
return _OK
2024-09-02 23:59:26 +01:00
}
}
2024-03-14 14:18:37 +00:00
case _FCNTL_PERSIST_WAL:
2025-01-13 09:28:47 +00:00
if file, ok := file.(FilePersistWAL); ok {
2024-03-14 14:18:37 +00:00
if i := util.ReadUint32(mod, pArg); int32(i) >= 0 {
2025-01-13 09:28:47 +00:00
file.SetPersistWAL(i != 0)
} else if file.PersistWAL() {
2024-03-14 14:18:37 +00:00
util.WriteUint32(mod, pArg, 1)
} else {
util.WriteUint32(mod, pArg, 0)
}
return _OK
}
2023-04-10 19:55:44 +01:00
case _FCNTL_POWERSAFE_OVERWRITE:
2023-05-19 03:04:07 +01:00
if file, ok := file.(FilePowersafeOverwrite); ok {
2024-03-14 14:18:37 +00:00
if i := util.ReadUint32(mod, pArg); int32(i) >= 0 {
file.SetPowersafeOverwrite(i != 0)
} else if file.PowersafeOverwrite() {
util.WriteUint32(mod, pArg, 1)
} else {
util.WriteUint32(mod, pArg, 0)
2023-04-10 19:55:44 +01:00
}
2023-05-19 02:00:16 +01:00
return _OK
2023-04-10 19:55:44 +01:00
}
2023-05-19 02:00:16 +01:00
2024-04-25 13:29:19 +01:00
case _FCNTL_CHUNK_SIZE:
if file, ok := file.(FileChunkSize); ok {
size := util.ReadUint32(mod, pArg)
file.ChunkSize(int(size))
return _OK
}
2023-03-29 15:01:25 +01:00
case _FCNTL_SIZE_HINT:
2023-05-19 03:04:07 +01:00
if file, ok := file.(FileSizeHint); ok {
2023-05-19 02:00:16 +01:00
size := util.ReadUint64(mod, pArg)
err := file.SizeHint(int64(size))
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_TRUNCATE)
2023-05-19 02:00:16 +01:00
}
2023-03-29 15:01:25 +01:00
case _FCNTL_HAS_MOVED:
2023-05-19 03:04:07 +01:00
if file, ok := file.(FileHasMoved); ok {
2023-05-19 02:00:16 +01:00
moved, err := file.HasMoved()
var res uint32
if moved {
res = 1
}
util.WriteUint32(mod, pArg, res)
2023-05-19 13:47:12 +01:00
return vfsErrorCode(err, _IOERR_FSTAT)
2023-05-19 02:00:16 +01:00
}
2023-06-02 11:13:42 +01:00
2023-09-21 02:43:45 +01:00
case _FCNTL_OVERWRITE:
if file, ok := file.(FileOverwrite); ok {
err := file.Overwrite()
return vfsErrorCode(err, _IOERR)
}
2025-01-14 10:05:54 +00:00
case _FCNTL_SYNC:
if file, ok := file.(FileSync); ok {
var name string
if pArg != 0 {
name = util.ReadString(mod, pArg, _MAX_PATHNAME)
}
err := file.SyncSuper(name)
return vfsErrorCode(err, _IOERR)
}
2023-06-02 13:40:08 +01:00
case _FCNTL_COMMIT_PHASETWO:
if file, ok := file.(FileCommitPhaseTwo); ok {
err := file.CommitPhaseTwo()
return vfsErrorCode(err, _IOERR)
}
2023-06-02 11:13:42 +01:00
case _FCNTL_BEGIN_ATOMIC_WRITE:
if file, ok := file.(FileBatchAtomicWrite); ok {
err := file.BeginAtomicWrite()
return vfsErrorCode(err, _IOERR_BEGIN_ATOMIC)
}
case _FCNTL_COMMIT_ATOMIC_WRITE:
if file, ok := file.(FileBatchAtomicWrite); ok {
err := file.CommitAtomicWrite()
return vfsErrorCode(err, _IOERR_COMMIT_ATOMIC)
}
case _FCNTL_ROLLBACK_ATOMIC_WRITE:
if file, ok := file.(FileBatchAtomicWrite); ok {
err := file.RollbackAtomicWrite()
return vfsErrorCode(err, _IOERR_ROLLBACK_ATOMIC)
}
2024-04-25 13:29:19 +01:00
2024-10-21 14:51:30 +01:00
case _FCNTL_CKPT_START:
2024-04-25 13:29:19 +01:00
if file, ok := file.(FileCheckpoint); ok {
2024-10-21 14:51:30 +01:00
file.CheckpointStart()
return _OK
2024-04-25 13:29:19 +01:00
}
2024-10-21 14:51:30 +01:00
case _FCNTL_CKPT_DONE:
2024-04-25 13:29:19 +01:00
if file, ok := file.(FileCheckpoint); ok {
2024-10-21 14:51:30 +01:00
file.CheckpointDone()
return _OK
2024-04-25 13:29:19 +01:00
}
case _FCNTL_PRAGMA:
if file, ok := file.(FilePragma); ok {
2024-04-27 12:19:46 +01:00
ptr := util.ReadUint32(mod, pArg+1*ptrlen)
name := util.ReadString(mod, ptr, _MAX_SQL_LENGTH)
var value string
if ptr := util.ReadUint32(mod, pArg+2*ptrlen); ptr != 0 {
value = util.ReadString(mod, ptr, _MAX_SQL_LENGTH)
}
2024-10-24 00:22:20 +01:00
out, err := file.Pragma(strings.ToLower(name), value)
2024-04-27 12:19:46 +01:00
ret := vfsErrorCode(err, _ERROR)
if ret == _ERROR {
2024-04-25 13:29:19 +01:00
out = err.Error()
}
if out != "" {
2024-09-09 13:21:33 +01:00
fn := mod.ExportedFunction("sqlite3_malloc64")
2024-04-25 13:29:19 +01:00
stack := [...]uint64{uint64(len(out) + 1)}
if err := fn.CallWithStack(ctx, stack[:]); err != nil {
panic(err)
}
util.WriteUint32(mod, pArg, uint32(stack[0]))
util.WriteString(mod, uint32(stack[0]), out)
}
2024-04-27 12:19:46 +01:00
return ret
2024-04-25 13:29:19 +01:00
}
2024-10-21 14:51:30 +01:00
2025-01-14 16:47:48 +00:00
case _FCNTL_BUSYHANDLER:
if file, ok := file.(FileBusyHandler); ok {
arg := util.ReadUint64(mod, pArg)
fn := mod.ExportedFunction("sqlite3_invoke_busy_handler_go")
file.BusyHandler(func() bool {
stack := [...]uint64{arg}
if err := fn.CallWithStack(ctx, stack[:]); err != nil {
panic(err)
}
return uint32(stack[0]) != 0
})
return _OK
}
2024-10-21 14:51:30 +01:00
case _FCNTL_LOCK_TIMEOUT:
if file, ok := file.(FileSharedMemory); ok {
if shm, ok := file.SharedMemory().(blockingSharedMemory); ok {
shm.shmEnableBlocking(util.ReadUint32(mod, pArg) != 0)
return _OK
}
}
2025-01-13 13:45:41 +00:00
case _FCNTL_PDB:
if file, ok := file.(filePDB); ok {
file.SetDB(ctx.Value(util.ConnKey{}))
return _OK
}
2023-03-29 15:01:25 +01:00
}
2023-05-19 02:00:16 +01:00
2023-03-29 15:01:25 +01:00
return _NOTFOUND
}
2023-04-10 19:55:44 +01:00
func vfsSectorSize(ctx context.Context, mod api.Module, pFile uint32) uint32 {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-18 16:00:34 +01:00
return uint32(file.SectorSize())
2023-04-10 19:55:44 +01:00
}
2023-05-19 03:04:07 +01:00
func vfsDeviceCharacteristics(ctx context.Context, mod api.Module, pFile uint32) DeviceCharacteristic {
file := vfsFileGet(ctx, mod, pFile).(File)
2023-05-19 02:00:16 +01:00
return file.DeviceCharacteristics()
2023-03-29 15:01:25 +01:00
}
2023-05-19 03:04:07 +01:00
2024-04-11 12:00:17 +01:00
func vfsShmBarrier(ctx context.Context, mod api.Module, pFile uint32) {
2024-10-17 15:39:01 +01:00
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
shm.shmBarrier()
2024-04-11 12:00:17 +01:00
}
func vfsShmMap(ctx context.Context, mod api.Module, pFile uint32, iRegion, szRegion int32, bExtend, pp uint32) _ErrorCode {
2024-04-28 10:33:39 +01:00
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
2024-06-06 00:09:14 +01:00
p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
util.WriteUint32(mod, pp, p)
2024-06-06 00:09:14 +01:00
return rc
}
2024-04-11 12:00:17 +01:00
func vfsShmLock(ctx context.Context, mod api.Module, pFile uint32, offset, n int32, flags _ShmFlag) _ErrorCode {
2024-04-28 10:33:39 +01:00
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
2024-06-06 00:09:14 +01:00
return shm.shmLock(offset, n, flags)
}
func vfsShmUnmap(ctx context.Context, mod api.Module, pFile, bDelete uint32) _ErrorCode {
2024-04-28 10:33:39 +01:00
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
shm.shmUnmap(bDelete != 0)
return _OK
}
2023-05-19 13:47:12 +01:00
func vfsGet(mod api.Module, pVfs uint32) VFS {
2023-06-02 03:32:13 +01:00
var name string
if pVfs != 0 {
const zNameOffset = 16
2023-11-24 17:25:02 +00:00
name = util.ReadString(mod, util.ReadUint32(mod, pVfs+zNameOffset), _MAX_NAME)
2023-05-19 13:47:12 +01:00
}
if vfs := Find(name); vfs != nil {
return vfs
2023-05-19 03:04:07 +01:00
}
2023-05-19 13:47:12 +01:00
panic(util.NoVFSErr + util.ErrorString(name))
2023-05-19 03:04:07 +01:00
}
2023-05-23 14:44:25 +01:00
func vfsFileRegister(ctx context.Context, mod api.Module, pFile uint32, file File) {
const fileHandleOffset = 4
2023-06-30 01:52:18 +01:00
id := util.AddHandle(ctx, file)
2023-05-23 14:44:25 +01:00
util.WriteUint32(mod, pFile+fileHandleOffset, id)
}
func vfsFileGet(ctx context.Context, mod api.Module, pFile uint32) any {
2023-05-23 14:44:25 +01:00
const fileHandleOffset = 4
id := util.ReadUint32(mod, pFile+fileHandleOffset)
return util.GetHandle(ctx, id)
2023-05-23 14:44:25 +01:00
}
func vfsFileClose(ctx context.Context, mod api.Module, pFile uint32) error {
const fileHandleOffset = 4
id := util.ReadUint32(mod, pFile+fileHandleOffset)
2023-06-30 01:52:18 +01:00
return util.DelHandle(ctx, id)
2023-05-23 14:44:25 +01:00
}
2023-05-19 13:47:12 +01:00
func vfsErrorCode(err error, def _ErrorCode) _ErrorCode {
2023-05-19 03:04:07 +01:00
if err == nil {
return _OK
}
switch v := reflect.ValueOf(err); v.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
return _ErrorCode(v.Uint())
}
return def
}