package openngvfs import ( "context" "encoding/binary" "fmt" "git.swzry.com/zry/GoHiedaLogger/hiedalog" go_int32_handle "git.swzry.com/zry/go-int32-handle" "github.com/bep/overlayfs" "github.com/spf13/afero" wa_api "github.com/tetratelabs/wazero/api" "os" "regexp" "time" ) func (a *InitWAVMHostModuleAdapter) mfaAddAfs() { a.addFunc("afs_free", a.efnAfsFree, []wa_api.ValueType{wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_mkdir", a.efnAfsMkdir, []wa_api.ValueType{ wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32, }, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_osfs", a.efnAfsCreateOsFs, []wa_api.ValueType{}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_memfs", a.efnAfsCreateMemFs, []wa_api.ValueType{}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_bpfs", a.efnAfsCreateBpFs, []wa_api.ValueType{wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_regfs", a.efnAfsCreateRegFs, []wa_api.ValueType{wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_rofs", a.efnAfsCreateRoFs, []wa_api.ValueType{wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_cowfs", a.efnAfsCreateCowFs, []wa_api.ValueType{wa_api.ValueTypeI32, wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_corfs", a.efnAfsCreateCorFs, []wa_api.ValueType{wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) a.addFunc("afs_create_bep_ovfs", a.efnAfsCreateBepOvFs, []wa_api.ValueType{wa_api.ValueTypeI32, wa_api.ValueTypeI32, wa_api.ValueTypeI32}, []wa_api.ValueType{wa_api.ValueTypeI32}) } func (a *InitWAVMHostModuleAdapter) efnAfsFree(_ context.Context, _ wa_api.Module, stack []uint64) { hAfs := int32(stack[0]) if hAfs <= 0 { var neg1 int32 = -1 stack[0] = uint64(neg1) return } _, ok := a.api.AferoFsInstancesMgr.Release(hAfs) if !ok { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_release_error", "handle": fmt.Sprintf("%d", hAfs), }) var neg1 int32 = -1 stack[0] = uint64(neg1) return } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_free_ok", "handle": fmt.Sprintf("%d", hAfs), }) stack[0] = 0 return } func (a *InitWAVMHostModuleAdapter) efnAfsMkdir(_ context.Context, mod wa_api.Module, stack []uint64) { hAfs := int32(stack[0]) ptrPath := uint32(stack[1]) lenPath := uint32(stack[2]) perm := uint32(stack[3]) dirPath, ok := mod.Memory().Read(ptrPath, lenPath) if !ok { var ecode int32 = -3 stack[0] = uint64(ecode) return } if hAfs <= 0 { var ecode int32 = -2 stack[0] = uint64(ecode) return } objAfs, ok := a.api.AferoFsInstancesMgr.Get(hAfs) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } err := objAfs.Fs.MkdirAll(string(dirPath), os.FileMode(perm)) if err != nil { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_mkdir_error", "dir-path": string(dirPath), "afs": fmt.Sprintf("%d", hAfs), "perm": fmt.Sprintf("%04o", perm), "raw-err": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } a.logger.LogComplex("ngvfs", hiedalog.DLN_VERBOSE, map[string]string{ "type": "afs_mkdir_ok", "afs": fmt.Sprintf("%d", hAfs), "path": string(dirPath), }) stack[0] = 0 return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateOsFs(_ context.Context, _ wa_api.Module, stack []uint64) { osfs := afero.NewOsFs() afsObj := &AferoFsInstance{ Fs: osfs, TypeDescription: "afero-osfs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_osfs_ok", "handle": fmt.Sprintf("%d", h), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateMemFs(_ context.Context, _ wa_api.Module, stack []uint64) { memfs := afero.NewMemMapFs() afsObj := &AferoFsInstance{ Fs: memfs, TypeDescription: "afero-memfs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_memfs_ok", "handle": fmt.Sprintf("%d", h), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateBpFs(_ context.Context, mod wa_api.Module, stack []uint64) { hBaseAfs := int32(stack[0]) ptrBasePath := uint32(stack[1]) lenBasePath := uint32(stack[2]) basePath, ok := mod.Memory().Read(ptrBasePath, lenBasePath) if !ok { var ecode int32 = -3 stack[0] = uint64(ecode) return } if hBaseAfs <= 0 { var ecode int32 = -2 stack[0] = uint64(ecode) return } objBaseAfs, ok := a.api.AferoFsInstancesMgr.Get(hBaseAfs) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } bpfs := afero.NewBasePathFs(objBaseAfs.Fs, string(basePath)) afsObj := &AferoFsInstance{ Fs: bpfs, TypeDescription: "afero-base-path-fs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_bpfs_ok", "handle": fmt.Sprintf("%d", h), "base-afs": fmt.Sprintf("%d", hBaseAfs), "base-path": string(basePath), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateRegFs(_ context.Context, mod wa_api.Module, stack []uint64) { hBaseAfs := int32(stack[0]) ptrRegExp := uint32(stack[1]) lenRegExp := uint32(stack[2]) strRegExp, ok := mod.Memory().Read(ptrRegExp, lenRegExp) if !ok { var ecode int32 = -3 stack[0] = uint64(ecode) return } if hBaseAfs <= 0 { var ecode int32 = -2 stack[0] = uint64(ecode) return } objBaseAfs, ok := a.api.AferoFsInstancesMgr.Get(hBaseAfs) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } cpdRegExp, err := regexp.Compile(string(strRegExp)) if err != nil { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_regfs_regexp_compile_error", "msg": err.Error(), }) var ecode int32 = -4 stack[0] = uint64(ecode) return } regfs := afero.NewRegexpFs(objBaseAfs.Fs, cpdRegExp) afsObj := &AferoFsInstance{ Fs: regfs, TypeDescription: "afero-regexp-fs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_regfs_ok", "handle": fmt.Sprintf("%d", h), "base-afs": fmt.Sprintf("%d", hBaseAfs), "regexp": string(strRegExp), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateRoFs(_ context.Context, _ wa_api.Module, stack []uint64) { hBaseAfs := int32(stack[0]) if hBaseAfs <= 0 { var ecode int32 = -2 stack[0] = uint64(ecode) return } objBaseAfs, ok := a.api.AferoFsInstancesMgr.Get(hBaseAfs) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } rofs := afero.NewReadOnlyFs(objBaseAfs.Fs) afsObj := &AferoFsInstance{ Fs: rofs, TypeDescription: "afero-readonly-fs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_rofs_ok", "handle": fmt.Sprintf("%d", h), "base-afs": fmt.Sprintf("%d", hBaseAfs), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateCowFs(_ context.Context, _ wa_api.Module, stack []uint64) { hRoAfs := int32(stack[0]) hWrAfs := int32(stack[1]) if hRoAfs <= 0 { var ecode int32 = -2 stack[0] = uint64(ecode) return } objRoAfs, ok := a.api.AferoFsInstancesMgr.Get(hRoAfs) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } if hWrAfs <= 0 { var ecode int32 = -3 stack[0] = uint64(ecode) return } objWrAfs, ok := a.api.AferoFsInstancesMgr.Get(hWrAfs) if !ok { var ecode int32 = -3 stack[0] = uint64(ecode) return } cowfs := afero.NewCopyOnWriteFs(objRoAfs.Fs, objWrAfs.Fs) afsObj := &AferoFsInstance{ Fs: cowfs, TypeDescription: "afero-copy-on-write-fs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_cowfs_ok", "handle": fmt.Sprintf("%d", h), "base-ro-afs": fmt.Sprintf("%d", hRoAfs), "base-wr-afs": fmt.Sprintf("%d", hWrAfs), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateCorFs(_ context.Context, _ wa_api.Module, stack []uint64) { hRoAfs := int32(stack[0]) hWrAfs := int32(stack[1]) cacheTime := int32(stack[3]) if cacheTime < 0 { var ecode int32 = -4 stack[0] = uint64(ecode) return } if hRoAfs <= 0 { var ecode int32 = -2 stack[0] = uint64(ecode) return } objRoAfs, ok := a.api.AferoFsInstancesMgr.Get(hRoAfs) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } if hWrAfs <= 0 { var ecode int32 = -3 stack[0] = uint64(ecode) return } objWrAfs, ok := a.api.AferoFsInstancesMgr.Get(hWrAfs) if !ok { var ecode int32 = -3 stack[0] = uint64(ecode) return } cacheTimeDuration := time.Duration(cacheTime) * time.Second corfs := afero.NewCacheOnReadFs(objRoAfs.Fs, objWrAfs.Fs, cacheTimeDuration) afsObj := &AferoFsInstance{ Fs: corfs, TypeDescription: "afero-cache-on-read-fs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -1 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -1 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_corfs_ok", "handle": fmt.Sprintf("%d", h), "base-ro-afs": fmt.Sprintf("%d", hRoAfs), "base-wr-afs": fmt.Sprintf("%d", hWrAfs), "cache-time": cacheTimeDuration.String(), }) stack[0] = uint64(h) return } func (a *InitWAVMHostModuleAdapter) efnAfsCreateBepOvFs(_ context.Context, mod wa_api.Module, stack []uint64) { ptrAfsArray := uint32(stack[0]) lenAfsArray := uint32(stack[1]) intIsWritable := int32(stack[2]) boolIsWritable := intIsWritable > 0 if lenAfsArray == 0 { var ecode int32 = -1 stack[0] = uint64(ecode) return } sliceAfsHandleArray := make([]int32, lenAfsArray) var i uint32 for i = 0; i < lenAfsArray; i++ { offset := ptrAfsArray + i*4 b, ok := mod.Memory().Read(offset, 4) if !ok { var ecode int32 = -2 stack[0] = uint64(ecode) return } if len(b) != 4 { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_create_bep_ovfs_error", "sub-type": "read_fs_layer_array_error", "msg": "the length of the array element is not 4", "i": fmt.Sprintf("%d", i), "offset": fmt.Sprintf("%d", offset), "len": fmt.Sprintf("%d", len(b)), }) var ecode int32 = -3 stack[0] = uint64(ecode) return } sliceAfsHandleArray[i] = int32(binary.LittleEndian.Uint32(b)) } afsObjArray := make([]afero.Fs, lenAfsArray) for i, v := range sliceAfsHandleArray { if v <= 0 { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_create_bep_ovfs_error", "sub-type": "read_fs_layer_invalid_handle", "msg": "the value of this element is a invalid handle", "i": fmt.Sprintf("%d", i), "handle": fmt.Sprintf("%d", v), }) var ecode int32 = -4 stack[0] = uint64(ecode) return } objV, ok := a.api.AferoFsInstancesMgr.Get(v) if !ok { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_create_bep_ovfs_error", "sub-type": "read_fs_layer_invalid_handle", "msg": "the value of this element is a invalid handle", "i": fmt.Sprintf("%d", i), "handle": fmt.Sprintf("%d", v), }) var ecode int32 = -4 stack[0] = uint64(ecode) return } a.logger.LogComplex("ngvfs", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_bep_ovfs_debug", "sub-type": "get_valid_fs_layer", "i": fmt.Sprintf("%d", i), "handle": fmt.Sprintf("%d", v), "fs-name": objV.Fs.Name(), "fs-desc": objV.TypeDescription, }) afsObjArray[i] = objV.Fs } ovfsOpt := overlayfs.Options{ Fss: afsObjArray, FirstWritable: boolIsWritable, DirsMerger: nil, } ovfs := overlayfs.New(ovfsOpt) afsObj := &AferoFsInstance{ Fs: ovfs, TypeDescription: "3rd-party-bep-overlayfs", } h, err := a.api.AferoFsInstancesMgr.AllocateAndPut(afsObj) if err != nil { if err == go_int32_handle.ErrHandleExceedMax { a.logger.LogComplex("ngvfs", hiedalog.DLN_WARN, map[string]string{ "type": "afs_handle_alloc_error", "msg": "handle exceed max", }) var ecode int32 = -5 stack[0] = uint64(ecode) return } else { a.logger.LogComplex("ngvfs", hiedalog.DLN_ERROR, map[string]string{ "type": "afs_handle_alloc_error", "msg": err.Error(), }) var ecode int32 = -5 stack[0] = uint64(ecode) return } } a.logger.LogComplex("ngvfs-debug", hiedalog.DLN_DEBUG, map[string]string{ "type": "afs_create_bep_ovfs_ok", "handle": fmt.Sprintf("%d", h), }) stack[0] = uint64(h) return }