package openngvfs import ( "context" "fmt" "git.swzry.com/ProjectNagae/FsUtils/amntfs" "git.swzry.com/zry/GoHiedaLogger/hiedalog" "git.swzry.com/zry/go-int32-handle" "github.com/spf13/afero" "github.com/tetratelabs/wazero" wa_api "github.com/tetratelabs/wazero/api" "os" ) const API_VERSION_MAJOR = 1 const API_VERSION_MINOR = 1 const API_VERSION_PATCH = 0 type AferoFsInstance struct { Fs afero.Fs TypeDescription string } type InitWAVMHostAPI struct { Root *amntfs.AMNTFS AferoFsInstancesMgr *go_int32_handle.HandleManager[*AferoFsInstance] } func NewWAVMHostAPI(root *amntfs.AMNTFS) *InitWAVMHostAPI { return &InitWAVMHostAPI{ Root: root, AferoFsInstancesMgr: go_int32_handle.New[*AferoFsInstance](), } } type InitWAVMHostModuleAdapter struct { api *InitWAVMHostAPI builder wazero.HostModuleBuilder rawFsTab *RawFsTab processedFsTab *ProcessedFsTab logger *hiedalog.HiedaLogger } func NewInitWAVMHostModuleAdapter(builder wazero.HostModuleBuilder, api *InitWAVMHostAPI, fstab *RawFsTab, logger *hiedalog.HiedaLogger, appName string) *InitWAVMHostModuleAdapter { localKV := make(map[string]string) for k, v := range fstab.ExKV.Default { localKV[k] = v } appKV, ok := fstab.ExKV.App[appName] if ok { for k, v := range appKV { localKV[k] = v } } processedFsTab := &ProcessedFsTab{ ExKV: localKV, } return &InitWAVMHostModuleAdapter{ api: api, builder: builder, rawFsTab: fstab, processedFsTab: processedFsTab, logger: logger, } } func (a *InitWAVMHostModuleAdapter) addFunc( name string, f func(ctx context.Context, mod wa_api.Module, params []uint64), param []wa_api.ValueType, result []wa_api.ValueType, ) { a.builder = a.builder.NewFunctionBuilder(). WithGoModuleFunction(wa_api.GoModuleFunc(f), param, result).Export(name) } func (a *InitWAVMHostModuleAdapter) Instantiate(ctx context.Context) (wa_api.Module, error) { a.addFunc("api_ver_get", a.efnApiVerGet, []wa_api.ValueType{ wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, }, []wa_api.ValueType{}) a.addFunc("exkv_get_len", a.efnExkvGetLen, []wa_api.ValueType{wa_api.ValueTypeI32, wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("exkv_get_val", a.efnExkvGetVal, []wa_api.ValueType{ wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, }, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("vfs_mount", a.efnVfsMount, []wa_api.ValueType{ wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, }, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("vfs_mkdir", a.efnVfsMkdir, []wa_api.ValueType{ wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, }, []wa_api.ValueType{wa_api.ValueTypeI32}) a.mfaAddAfs() return a.builder.Instantiate(ctx) } func (a *InitWAVMHostModuleAdapter) efnApiVerGet(_ context.Context, mod wa_api.Module, stack []uint64) { ptrMaj := uint32(stack[0]) ptrMin := uint32(stack[1]) ptrPat := uint32(stack[2]) mod.Memory().WriteUint32Le(ptrMaj, API_VERSION_MAJOR) mod.Memory().WriteUint32Le(ptrMin, API_VERSION_MINOR) mod.Memory().WriteUint32Le(ptrPat, API_VERSION_PATCH) } func (a *InitWAVMHostModuleAdapter) efnExkvGetLen(_ context.Context, mod wa_api.Module, stack []uint64) { ptrKey := uint32(stack[0]) lenKey := uint32(stack[1]) key, ok := mod.Memory().Read(ptrKey, lenKey) if !ok { var neg1 int32 = -1 stack[0] = uint64(neg1) return } v, ok := a.processedFsTab.ExKV[string(key)] if !ok { var neg2 int32 = -2 stack[0] = uint64(neg2) } else { stack[0] = uint64(len([]byte(v))) } } func (a *InitWAVMHostModuleAdapter) efnExkvGetVal(_ context.Context, mod wa_api.Module, stack []uint64) { ptrKey := uint32(stack[0]) lenKey := uint32(stack[1]) ptrBuf := uint32(stack[2]) lenBuf := uint32(stack[3]) if lenBuf <= 0 { stack[0] = 0 return } key, ok := mod.Memory().Read(ptrKey, lenKey) if !ok { var neg1 int32 = -1 stack[0] = uint64(neg1) return } v, ok := a.processedFsTab.ExKV[string(key)] if !ok { var neg2 int32 = -2 stack[0] = uint64(neg2) return } vb := []byte(v) ok = mod.Memory().Write(ptrBuf, vb[:lenBuf]) if !ok { var neg3 int32 = -3 stack[0] = uint64(neg3) return } stack[0] = uint64(lenBuf) return } func (a *InitWAVMHostModuleAdapter) efnVfsMount(_ context.Context, mod wa_api.Module, stack []uint64) { hAfs := int32(stack[0]) ptrMntPath := uint32(stack[1]) lenMntPath := uint32(stack[2]) mntPath, ok := mod.Memory().Read(ptrMntPath, lenMntPath) if !ok { var neg2 int32 = -2 stack[0] = uint64(neg2) return } if hAfs <= 0 { var neg1 int32 = -1 stack[0] = uint64(neg1) return } objAfs, ok := a.api.AferoFsInstancesMgr.Get(hAfs) if !ok { var neg1 int32 = -1 stack[0] = uint64(neg1) return } err := a.api.Root.Mount(string(mntPath), objAfs.Fs, false) if err != nil { if aErr, ok := err.(*amntfs.AMNTFSError); ok { rawErr := aErr.GetRawError() var rawErrStr string if rawErr != nil { rawErrStr = rawErr.Error() } else { rawErrStr = "" } if aErr.GetErrNo() == amntfs.ErrMountPointAlreadyMounted { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "mount_error", "sub-type": "mount_point_already_mounted", "mnt-point": string(mntPath), "afs-name": objAfs.Fs.Name(), "afs-type-desc": objAfs.TypeDescription, }) var neg3 int32 = -3 stack[0] = uint64(neg3) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "mount_error", "sub-type": "internal_error", "mnt-point": string(mntPath), "afs-name": objAfs.Fs.Name(), "afs-type-desc": objAfs.TypeDescription, "raw-err": rawErrStr, }) var neg4 int32 = -4 stack[0] = uint64(neg4) return } } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "mount_error", "sub-type": "internal_error", "mnt-point": string(mntPath), "afs-name": objAfs.Fs.Name(), "afs-type-desc": objAfs.TypeDescription, "raw-err": err.Error(), }) var neg4 int32 = -4 stack[0] = uint64(neg4) return } } a.logger.LogComplex("ngvfs", hiedalog.DLN_VERBOSE, map[string]string{ "type": "mount_ok", "mnt-point": string(mntPath), "afs-name": objAfs.Fs.Name(), "afs-type-desc": objAfs.TypeDescription, }) stack[0] = 0 return } func (a *InitWAVMHostModuleAdapter) efnVfsMkdir(_ context.Context, mod wa_api.Module, stack []uint64) { ptrPath := uint32(stack[0]) lenPath := uint32(stack[1]) perm := uint32(stack[2]) dirPath, ok := mod.Memory().Read(ptrPath, lenPath) if !ok { var neg2 int32 = -1 stack[0] = uint64(neg2) return } err := a.api.Root.MkdirAll(string(dirPath), os.FileMode(perm)) if err != nil { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "vfs_mkdir_error", "dir-path": string(dirPath), "perm": fmt.Sprintf("%04o", perm), "raw-err": err.Error(), }) var ecode int32 = -2 stack[0] = uint64(ecode) return } a.logger.LogComplex("ngvfs", hiedalog.DLN_VERBOSE, map[string]string{ "type": "vfs_mkdir_ok", "path": string(dirPath), }) stack[0] = 0 return }