//go:build !octopus && !pacific && !quincy && ceph_preview package rbd // #cgo LDFLAGS: -lrbd // /* force XSI-complaint strerror_r() */ // #define _POSIX_C_SOURCE 200112L // #undef _GNU_SOURCE // #include // #include // #include import "C" import ( "unsafe" ) type encryptionOptions2 interface { EncryptionOptions writeEncryptionSpec(spec *C.rbd_encryption_spec_t) func() } func (opts EncryptionOptionsLUKS1) writeEncryptionSpec(spec *C.rbd_encryption_spec_t) func() { /* only C memory should be attached to spec */ cPassphrase := (*C.char)(C.CBytes(opts.Passphrase)) cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks1_format_options_t) cOpts := (*C.rbd_encryption_luks1_format_options_t)(C.malloc(cOptsSize)) cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg) cOpts.passphrase = cPassphrase cOpts.passphrase_size = C.size_t(len(opts.Passphrase)) spec.format = C.RBD_ENCRYPTION_FORMAT_LUKS1 spec.opts = C.rbd_encryption_options_t(cOpts) spec.opts_size = cOptsSize return func() { C.free(unsafe.Pointer(cOpts.passphrase)) C.free(unsafe.Pointer(cOpts)) } } func (opts EncryptionOptionsLUKS2) writeEncryptionSpec(spec *C.rbd_encryption_spec_t) func() { /* only C memory should be attached to spec */ cPassphrase := (*C.char)(C.CBytes(opts.Passphrase)) cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks2_format_options_t) cOpts := (*C.rbd_encryption_luks2_format_options_t)(C.malloc(cOptsSize)) cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg) cOpts.passphrase = cPassphrase cOpts.passphrase_size = C.size_t(len(opts.Passphrase)) spec.format = C.RBD_ENCRYPTION_FORMAT_LUKS2 spec.opts = C.rbd_encryption_options_t(cOpts) spec.opts_size = cOptsSize return func() { C.free(unsafe.Pointer(cOpts.passphrase)) C.free(unsafe.Pointer(cOpts)) } } // EncryptionLoad2 enables IO on an open encrypted image. Multiple encryption // option values can be passed to this call in a slice. For more information // about how items in the slice are applied to images, and possibly ancestor // images refer to the documentation in the C api for rbd_encryption_load2. // // Implements: // // int rbd_encryption_load2(rbd_image_t image, // const rbd_encryption_spec_t *specs, // size_t spec_count); func (image *Image) EncryptionLoad2(opts []EncryptionOptions) error { if image.image == nil { return ErrImageNotOpen } for _, o := range opts { if _, ok := o.(encryptionOptions2); !ok { // this should not happen unless someone adds a new type // implementing EncryptionOptions but fails to add a // writeEncryptionSpec such that the type is not also implementing // encryptionOptions2. return getError(C.EINVAL) } } length := len(opts) cspecs := (*C.rbd_encryption_spec_t)(C.malloc( C.size_t(C.sizeof_rbd_encryption_spec_t * length))) specs := unsafe.Slice(cspecs, length) freeFuncs := make([]func(), length) for idx, option := range opts { f := option.(encryptionOptions2).writeEncryptionSpec(&specs[idx]) freeFuncs[idx] = f } defer func() { for _, f := range freeFuncs { f() } C.free(unsafe.Pointer(cspecs)) }() ret := C.rbd_encryption_load2( image.image, cspecs, C.size_t(length)) return getError(ret) }