From d53f3530affc9e3fee44afd29821c69897edd47b Mon Sep 17 00:00:00 2001 From: Faruk Kasumovic Date: Thu, 16 Jul 2020 13:29:40 +0200 Subject: [PATCH] - Unpack resume information from resume token to go structure ResumeToken --- sendrecv.go | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/sendrecv.go b/sendrecv.go index 082820c..b81ef3d 100644 --- a/sendrecv.go +++ b/sendrecv.go @@ -51,6 +51,21 @@ type RecvFlags struct { ByteSwap bool } +// ResumeToken - informations extracted from resume token +type ResumeToken struct { + ToName string + FromName string + Object uint64 + Offset uint64 + ToGUID uint64 + FromGUID uint64 + Bytes uint64 + LargeBlock bool + EmbedOk bool + CompressOk bool + RawOk bool +} + func to_boolean_t(a bool) C.boolean_t { if a { return 1 @@ -282,3 +297,76 @@ func (d *Dataset) Receive(inf *os.File, flags RecvFlags) (err error) { } return } + +// Unpack unpack resume token +func (rt *ResumeToken) Unpack(token string) (err error) { + ctoken := C.CString(token) + defer C.free(unsafe.Pointer(ctoken)) + resume_nvl := C.zfs_send_resume_token_to_nvlist(C.libzfsHandle, ctoken) + defer C.nvlist_free(resume_nvl) + if resume_nvl == nil { + err = fmt.Errorf("Failed to unpack resume token: %s", LastError().Error()) + return + } + if rt.ToName, err = rt.lookupString(resume_nvl, "toname"); err != nil { + return + } + rt.FromName, _ = rt.lookupString(resume_nvl, "fromname") + + if rt.Object, err = rt.lookupUnit64(resume_nvl, "object"); err != nil { + return + } + if rt.Offset, err = rt.lookupUnit64(resume_nvl, "offset"); err != nil { + return + } + if rt.Bytes, err = rt.lookupUnit64(resume_nvl, "bytes"); err != nil { + return + } + if rt.ToGUID, err = rt.lookupUnit64(resume_nvl, "toguid"); err != nil { + return + } + + rt.FromGUID, _ = rt.lookupUnit64(resume_nvl, "fromguid") + + rt.LargeBlock = rt.exist(resume_nvl, "largeblockok") + rt.EmbedOk = rt.exist(resume_nvl, "embedok") + rt.CompressOk = rt.exist(resume_nvl, "compressok") + rt.RawOk = rt.exist(resume_nvl, "rawok") + + return +} + +func (rt *ResumeToken) lookupString(nvl *C.nvlist_t, key string) (val string, err error) { + var cstr *C.char + ckey := C.CString(key) + defer C.free(unsafe.Pointer(ckey)) + defer C.free(unsafe.Pointer(cstr)) + rc := C.nvlist_lookup_string(nvl, ckey, &cstr) + if rc != 0 { + err = fmt.Errorf("resume token is corrupt") + return + } + val = C.GoString(cstr) + return +} + +func (rt *ResumeToken) lookupUnit64(nvl *C.nvlist_t, key string) (val uint64, err error) { + var num C.uint64_t + ckey := C.CString(key) + defer C.free(unsafe.Pointer(ckey)) + rc := C.nvlist_lookup_uint64(nvl, ckey, &num) + if rc != 0 { + err = fmt.Errorf("resume token is corrupt") + return + } + val = uint64(num) + return +} + +func (rt *ResumeToken) exist(nvl *C.nvlist_t, key string) (val bool) { + ckey := C.CString(key) + defer C.free(unsafe.Pointer(ckey)) + rc := C.nvlist_exists(nvl, ckey) + val = (rc != 0) + return +}