Tweak nbdkit-1.26.0 for CDI build
This commit is contained in:
parent
eb6880b5b1
commit
1a1359d6e5
5 changed files with 901 additions and 0 deletions
4
go.mod
Normal file
4
go.mod
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module libguestfs.org/nbdkit
|
||||||
|
|
||||||
|
// First version of golang with working module support.
|
||||||
|
go 1.13
|
569
nbdkit.go
Normal file
569
nbdkit.go
Normal file
|
@ -0,0 +1,569 @@
|
||||||
|
/* Go helper functions.
|
||||||
|
* Copyright (C) 2013-2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Red Hat nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nbdkit
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -lnbdkit
|
||||||
|
#cgo LDFLAGS: -Wl,--unresolved-symbols=ignore-in-object-files
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define NBDKIT_API_VERSION 2
|
||||||
|
#include <nbdkit-plugin.h>
|
||||||
|
#include "wrappers.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The plugin may raise errors by returning this struct (instead of nil).
|
||||||
|
type PluginError struct {
|
||||||
|
Errmsg string // string (passed to nbdkit_error)
|
||||||
|
Errno syscall.Errno // errno (optional, use 0 if not available)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e PluginError) String() string {
|
||||||
|
if e.Errno != 0 {
|
||||||
|
return e.Errmsg
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s (errno %d)", e.Errmsg, e.Errno)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e PluginError) Error() string {
|
||||||
|
return e.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags and other constants.
|
||||||
|
const (
|
||||||
|
ThreadModelSerializeConnections = uint32(C.NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS)
|
||||||
|
ThreadModelSerializeAllRequests = uint32(C.NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS)
|
||||||
|
ThreadModelSerializeRequests = uint32(C.NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS)
|
||||||
|
ThreadModelParallel = uint32(C.NBDKIT_THREAD_MODEL_PARALLEL)
|
||||||
|
|
||||||
|
FlagMayTrim = uint32(C.NBDKIT_FLAG_MAY_TRIM)
|
||||||
|
FlagFUA = uint32(C.NBDKIT_FLAG_FUA)
|
||||||
|
FlagReqOne = uint32(C.NBDKIT_FLAG_REQ_ONE)
|
||||||
|
FlagFastZero = uint32(C.NBDKIT_FLAG_FAST_ZERO)
|
||||||
|
|
||||||
|
FUANone = uint32(C.NBDKIT_FUA_NONE)
|
||||||
|
FUAEmulate = uint32(C.NBDKIT_FUA_EMULATE)
|
||||||
|
FUANative = uint32(C.NBDKIT_FUA_NATIVE)
|
||||||
|
|
||||||
|
CacheNone = uint32(C.NBDKIT_CACHE_NONE)
|
||||||
|
CacheEmulate = uint32(C.NBDKIT_CACHE_EMULATE)
|
||||||
|
CacheNative = uint32(C.NBDKIT_CACHE_NATIVE)
|
||||||
|
|
||||||
|
ExtentHole = uint32(C.NBDKIT_EXTENT_HOLE)
|
||||||
|
ExtentZero = uint32(C.NBDKIT_EXTENT_ZERO)
|
||||||
|
|
||||||
|
// This is not defined by the header, but by this file. It
|
||||||
|
// might be useful for plugins to know this (even though they
|
||||||
|
// probably wouldn't be source-compatible with other API
|
||||||
|
// versions) so we expose it to golang code.
|
||||||
|
APIVersion = uint32(C.NBDKIT_API_VERSION)
|
||||||
|
)
|
||||||
|
|
||||||
|
// The plugin interface.
|
||||||
|
type PluginInterface interface {
|
||||||
|
Load()
|
||||||
|
Unload()
|
||||||
|
|
||||||
|
DumpPlugin()
|
||||||
|
|
||||||
|
Config(key string, value string) error
|
||||||
|
ConfigComplete() error
|
||||||
|
GetReady() error
|
||||||
|
|
||||||
|
PreConnect(readonly bool) error
|
||||||
|
Open(readonly bool) (ConnectionInterface, error) // required
|
||||||
|
}
|
||||||
|
|
||||||
|
// The client connection interface.
|
||||||
|
type ConnectionInterface interface {
|
||||||
|
GetSize() (uint64, error) // required
|
||||||
|
IsRotational() (bool, error)
|
||||||
|
CanMultiConn() (bool, error)
|
||||||
|
|
||||||
|
PRead(buf []byte, offset uint64, flags uint32) error // required
|
||||||
|
|
||||||
|
// NB: PWrite will NOT be called unless CanWrite returns true.
|
||||||
|
CanWrite() (bool, error)
|
||||||
|
PWrite(buf []byte, offset uint64, flags uint32) error
|
||||||
|
|
||||||
|
// NB: Flush will NOT be called unless CanFlush returns true.
|
||||||
|
CanFlush() (bool, error)
|
||||||
|
Flush(flags uint32) error
|
||||||
|
|
||||||
|
// NB: Trim will NOT be called unless CanTrim returns true.
|
||||||
|
CanTrim() (bool, error)
|
||||||
|
Trim(count uint32, offset uint64, flags uint32) error
|
||||||
|
|
||||||
|
// NB: Zero will NOT be called unless CanZero returns true.
|
||||||
|
CanZero() (bool, error)
|
||||||
|
Zero(count uint32, offset uint64, flags uint32) error
|
||||||
|
|
||||||
|
Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default implementations for plugin interface methods.
|
||||||
|
type Plugin struct{}
|
||||||
|
type Connection struct{}
|
||||||
|
|
||||||
|
func (p *Plugin) Load() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Unload() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) DumpPlugin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Config(key string, value string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) ConfigComplete() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) GetReady() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) PreConnect(readonly bool) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Open(readonly bool) (ConnectionInterface, error) {
|
||||||
|
panic("plugin must implement Open()")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) GetSize() (uint64, error) {
|
||||||
|
panic("plugin must implement GetSize()")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) CanWrite() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) CanFlush() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) IsRotational() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) CanTrim() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) CanZero() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) CanMultiConn() (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) PRead(buf []byte, offset uint64, flags uint32) error {
|
||||||
|
panic("plugin must implement PRead()")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) PWrite(buf []byte, offset uint64, flags uint32) error {
|
||||||
|
panic("plugin CanWrite returns true, but no PWrite() function")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Flush(flags uint32) error {
|
||||||
|
panic("plugin CanFlush returns true, but no Flush() function")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Trim(count uint32, offset uint64, flags uint32) error {
|
||||||
|
panic("plugin CanTrim returns true, but no Trim() function")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Zero(count uint32, offset uint64, flags uint32) error {
|
||||||
|
panic("plugin CanZero returns true, but no Zero() function")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The implementation of the user plugin.
|
||||||
|
var pluginImpl PluginInterface
|
||||||
|
var nextConnectionId uintptr
|
||||||
|
var connectionMap map[uintptr]ConnectionInterface
|
||||||
|
|
||||||
|
// Callbacks from the server. These translate C to Go and back.
|
||||||
|
|
||||||
|
func set_error(err error) {
|
||||||
|
perr, ok := err.(PluginError)
|
||||||
|
if ok {
|
||||||
|
if perr.Errno != 0 {
|
||||||
|
SetError(perr.Errno)
|
||||||
|
}
|
||||||
|
Error(perr.Errmsg)
|
||||||
|
} else {
|
||||||
|
Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implLoad
|
||||||
|
func implLoad() {
|
||||||
|
pluginImpl.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implUnload
|
||||||
|
func implUnload() {
|
||||||
|
pluginImpl.Unload()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implDumpPlugin
|
||||||
|
func implDumpPlugin() {
|
||||||
|
pluginImpl.DumpPlugin()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implConfig
|
||||||
|
func implConfig(key *C.char, value *C.char) C.int {
|
||||||
|
err := pluginImpl.Config(C.GoString(key), C.GoString(value))
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implConfigComplete
|
||||||
|
func implConfigComplete() C.int {
|
||||||
|
err := pluginImpl.ConfigComplete()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implGetReady
|
||||||
|
func implGetReady() C.int {
|
||||||
|
err := pluginImpl.GetReady()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implPreConnect
|
||||||
|
func implPreConnect(c_readonly C.int) C.int {
|
||||||
|
readonly := false
|
||||||
|
if c_readonly != 0 {
|
||||||
|
readonly = true
|
||||||
|
}
|
||||||
|
err := pluginImpl.PreConnect(readonly)
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implOpen
|
||||||
|
func implOpen(c_readonly C.int) unsafe.Pointer {
|
||||||
|
readonly := false
|
||||||
|
if c_readonly != 0 {
|
||||||
|
readonly = true
|
||||||
|
}
|
||||||
|
h, err := pluginImpl.Open(readonly)
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
id := nextConnectionId
|
||||||
|
nextConnectionId++
|
||||||
|
connectionMap[id] = h
|
||||||
|
return unsafe.Pointer(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConn(handle unsafe.Pointer) ConnectionInterface {
|
||||||
|
id := uintptr(handle)
|
||||||
|
h, ok := connectionMap[id]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("connection %d was not open", id))
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implClose
|
||||||
|
func implClose(handle unsafe.Pointer) {
|
||||||
|
h := getConn(handle)
|
||||||
|
h.Close()
|
||||||
|
id := uintptr(handle)
|
||||||
|
delete(connectionMap, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implGetSize
|
||||||
|
func implGetSize(handle unsafe.Pointer) C.int64_t {
|
||||||
|
h := getConn(handle)
|
||||||
|
size, err := h.GetSize()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return C.int64_t(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implCanWrite
|
||||||
|
func implCanWrite(handle unsafe.Pointer) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
b, err := h.CanWrite()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implCanFlush
|
||||||
|
func implCanFlush(handle unsafe.Pointer) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
b, err := h.CanFlush()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implIsRotational
|
||||||
|
func implIsRotational(handle unsafe.Pointer) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
b, err := h.IsRotational()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implCanTrim
|
||||||
|
func implCanTrim(handle unsafe.Pointer) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
b, err := h.CanTrim()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implCanZero
|
||||||
|
func implCanZero(handle unsafe.Pointer) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
b, err := h.CanZero()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implCanMultiConn
|
||||||
|
func implCanMultiConn(handle unsafe.Pointer) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
b, err := h.CanMultiConn()
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implPRead
|
||||||
|
func implPRead(handle unsafe.Pointer, c_buf unsafe.Pointer,
|
||||||
|
count C.uint32_t, offset C.uint64_t, flags C.uint32_t) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
// https://github.com/golang/go/issues/13656
|
||||||
|
// https://stackoverflow.com/a/25776046
|
||||||
|
hdr := reflect.SliceHeader{
|
||||||
|
Data: uintptr(c_buf),
|
||||||
|
Len: int(count),
|
||||||
|
Cap: int(count),
|
||||||
|
}
|
||||||
|
buf := *(*[]byte)(unsafe.Pointer(&hdr))
|
||||||
|
err := h.PRead(buf, uint64(offset), uint32(flags))
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implPWrite
|
||||||
|
func implPWrite(handle unsafe.Pointer, c_buf unsafe.Pointer,
|
||||||
|
count C.uint32_t, offset C.uint64_t, flags C.uint32_t) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
// https://github.com/golang/go/issues/13656
|
||||||
|
// https://stackoverflow.com/a/25776046
|
||||||
|
hdr := reflect.SliceHeader{
|
||||||
|
Data: uintptr(c_buf),
|
||||||
|
Len: int(count),
|
||||||
|
Cap: int(count),
|
||||||
|
}
|
||||||
|
buf := *(*[]byte)(unsafe.Pointer(&hdr))
|
||||||
|
err := h.PWrite(buf, uint64(offset), uint32(flags))
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implFlush
|
||||||
|
func implFlush(handle unsafe.Pointer, flags C.uint32_t) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
err := h.Flush(uint32(flags))
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implTrim
|
||||||
|
func implTrim(handle unsafe.Pointer,
|
||||||
|
count C.uint32_t, offset C.uint64_t, flags C.uint32_t) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
err := h.Trim(uint32(count), uint64(offset), uint32(flags))
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//export implZero
|
||||||
|
func implZero(handle unsafe.Pointer,
|
||||||
|
count C.uint32_t, offset C.uint64_t, flags C.uint32_t) C.int {
|
||||||
|
h := getConn(handle)
|
||||||
|
err := h.Zero(uint32(count), uint64(offset), uint32(flags))
|
||||||
|
if err != nil {
|
||||||
|
set_error(err)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from C plugin_init function.
|
||||||
|
func PluginInitialize(name string, impl PluginInterface) unsafe.Pointer {
|
||||||
|
// Initialize the connection map. Note that connection IDs
|
||||||
|
// must start counting from 1 since we must never return what
|
||||||
|
// looks like a NULL pointer to the C code.
|
||||||
|
connectionMap = make(map[uintptr]ConnectionInterface)
|
||||||
|
nextConnectionId = 1
|
||||||
|
|
||||||
|
pluginImpl = impl
|
||||||
|
|
||||||
|
plugin := C.struct_nbdkit_plugin{}
|
||||||
|
|
||||||
|
// Set up the hidden plugin fields as for C.
|
||||||
|
struct_size := C.ulong(unsafe.Sizeof(plugin))
|
||||||
|
plugin._struct_size = C.uint64_t(struct_size)
|
||||||
|
plugin._api_version = C.NBDKIT_API_VERSION
|
||||||
|
plugin._thread_model = C.NBDKIT_THREAD_MODEL_PARALLEL
|
||||||
|
|
||||||
|
// Set up the other fields.
|
||||||
|
plugin.name = C.CString(name)
|
||||||
|
plugin.load = (*[0]byte)(C.wrapper_load)
|
||||||
|
plugin.unload = (*[0]byte)(C.wrapper_unload)
|
||||||
|
plugin.dump_plugin = (*[0]byte)(C.wrapper_dump_plugin)
|
||||||
|
plugin.config = (*[0]byte)(C.wrapper_config)
|
||||||
|
plugin.config_complete = (*[0]byte)(C.wrapper_config_complete)
|
||||||
|
plugin.get_ready = (*[0]byte)(C.wrapper_get_ready)
|
||||||
|
plugin.preconnect = (*[0]byte)(C.wrapper_preconnect)
|
||||||
|
plugin.open = (*[0]byte)(C.wrapper_open)
|
||||||
|
plugin.close = (*[0]byte)(C.wrapper_close)
|
||||||
|
plugin.get_size = (*[0]byte)(C.wrapper_get_size)
|
||||||
|
plugin.can_write = (*[0]byte)(C.wrapper_can_write)
|
||||||
|
plugin.can_flush = (*[0]byte)(C.wrapper_can_flush)
|
||||||
|
plugin.is_rotational = (*[0]byte)(C.wrapper_is_rotational)
|
||||||
|
plugin.can_trim = (*[0]byte)(C.wrapper_can_trim)
|
||||||
|
plugin.can_zero = (*[0]byte)(C.wrapper_can_zero)
|
||||||
|
plugin.can_multi_conn = (*[0]byte)(C.wrapper_can_multi_conn)
|
||||||
|
plugin.pread = (*[0]byte)(C.wrapper_pread)
|
||||||
|
plugin.pwrite = (*[0]byte)(C.wrapper_pwrite)
|
||||||
|
plugin.flush = (*[0]byte)(C.wrapper_flush)
|
||||||
|
plugin.trim = (*[0]byte)(C.wrapper_trim)
|
||||||
|
plugin.zero = (*[0]byte)(C.wrapper_zero)
|
||||||
|
|
||||||
|
// Golang plugins don't preserve errno correctly.
|
||||||
|
plugin.errno_is_preserved = 0
|
||||||
|
|
||||||
|
// Return a newly malloced copy of the struct. This must be
|
||||||
|
// globally available to the C code in the server, so it is
|
||||||
|
// never freed.
|
||||||
|
p := (*C.struct_nbdkit_plugin)(C.malloc(C.size_t(struct_size)))
|
||||||
|
*p = plugin
|
||||||
|
return unsafe.Pointer(p)
|
||||||
|
}
|
75
utils.go
Normal file
75
utils.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/* cgo wrappers.
|
||||||
|
* Copyright (C) 2013-2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Red Hat nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nbdkit
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -lnbdkit
|
||||||
|
|
||||||
|
#define NBDKIT_API_VERSION 2
|
||||||
|
#include <nbdkit-plugin.h>
|
||||||
|
|
||||||
|
// cgo cannot call varargs functions.
|
||||||
|
void
|
||||||
|
_nbdkit_debug (const char *s)
|
||||||
|
{
|
||||||
|
nbdkit_debug ("%s", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cgo cannot call varargs functions.
|
||||||
|
void
|
||||||
|
_nbdkit_error (const char *s)
|
||||||
|
{
|
||||||
|
nbdkit_error ("%s", s);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
// Utility functions.
|
||||||
|
|
||||||
|
func Debug(s string) {
|
||||||
|
C._nbdkit_debug(C.CString(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is provided but plugins would rarely need to call
|
||||||
|
// this explicitly since returning an error from a plugin callback
|
||||||
|
// will call it implicitly.
|
||||||
|
func Error(s string) {
|
||||||
|
C._nbdkit_error(C.CString(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same applies as for Error(). Callers should not usually need to
|
||||||
|
// call this.
|
||||||
|
func SetError(err syscall.Errno) {
|
||||||
|
C.nbdkit_set_error(C.int(err))
|
||||||
|
}
|
196
wrappers.go
Normal file
196
wrappers.go
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/* cgo wrappers.
|
||||||
|
* Copyright (C) 2013-2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Red Hat nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nbdkit
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -lnbdkit
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define NBDKIT_API_VERSION 2
|
||||||
|
#include <nbdkit-plugin.h>
|
||||||
|
#include "wrappers.h"
|
||||||
|
|
||||||
|
extern void implLoad ();
|
||||||
|
void
|
||||||
|
wrapper_load (void)
|
||||||
|
{
|
||||||
|
implLoad ();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void implUnload ();
|
||||||
|
void
|
||||||
|
wrapper_unload (void)
|
||||||
|
{
|
||||||
|
implUnload ();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void implDumpPlugin ();
|
||||||
|
void
|
||||||
|
wrapper_dump_plugin (void)
|
||||||
|
{
|
||||||
|
implDumpPlugin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implConfig ();
|
||||||
|
int
|
||||||
|
wrapper_config (const char *key, const char *value)
|
||||||
|
{
|
||||||
|
return implConfig (key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implConfigComplete ();
|
||||||
|
int
|
||||||
|
wrapper_config_complete (void)
|
||||||
|
{
|
||||||
|
return implConfigComplete ();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implGetReady ();
|
||||||
|
int
|
||||||
|
wrapper_get_ready (void)
|
||||||
|
{
|
||||||
|
return implGetReady ();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implPreConnect ();
|
||||||
|
int
|
||||||
|
wrapper_preconnect (int readonly)
|
||||||
|
{
|
||||||
|
return implPreConnect (readonly);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void *implOpen ();
|
||||||
|
void *
|
||||||
|
wrapper_open (int readonly)
|
||||||
|
{
|
||||||
|
return implOpen (readonly);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void implClose ();
|
||||||
|
void
|
||||||
|
wrapper_close (void *handle)
|
||||||
|
{
|
||||||
|
return implClose (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int64_t implGetSize ();
|
||||||
|
int64_t
|
||||||
|
wrapper_get_size (void *handle)
|
||||||
|
{
|
||||||
|
return implGetSize (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implCanWrite ();
|
||||||
|
int
|
||||||
|
wrapper_can_write (void *handle)
|
||||||
|
{
|
||||||
|
return implCanWrite (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implCanFlush ();
|
||||||
|
int
|
||||||
|
wrapper_can_flush (void *handle)
|
||||||
|
{
|
||||||
|
return implCanFlush (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implIsRotational ();
|
||||||
|
int
|
||||||
|
wrapper_is_rotational (void *handle)
|
||||||
|
{
|
||||||
|
return implIsRotational (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implCanTrim ();
|
||||||
|
int
|
||||||
|
wrapper_can_trim (void *handle)
|
||||||
|
{
|
||||||
|
return implCanTrim (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implCanZero ();
|
||||||
|
int
|
||||||
|
wrapper_can_zero (void *handle)
|
||||||
|
{
|
||||||
|
return implCanZero (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implCanMultiConn ();
|
||||||
|
int
|
||||||
|
wrapper_can_multi_conn (void *handle)
|
||||||
|
{
|
||||||
|
return implCanMultiConn (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implPRead ();
|
||||||
|
int
|
||||||
|
wrapper_pread (void *handle, void *buf,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags)
|
||||||
|
{
|
||||||
|
return implPRead (handle, buf, count, offset, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implPWrite ();
|
||||||
|
int
|
||||||
|
wrapper_pwrite (void *handle, const void *buf,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags)
|
||||||
|
{
|
||||||
|
return implPWrite (handle, buf, count, offset, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implFlush ();
|
||||||
|
int
|
||||||
|
wrapper_flush (void *handle, uint32_t flags)
|
||||||
|
{
|
||||||
|
return implFlush (handle, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implTrim ();
|
||||||
|
int
|
||||||
|
wrapper_trim (void *handle,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags)
|
||||||
|
{
|
||||||
|
return implTrim (handle, count, offset, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int implZero ();
|
||||||
|
int
|
||||||
|
wrapper_zero (void *handle,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags)
|
||||||
|
{
|
||||||
|
return implZero (handle, count, offset, flags);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
57
wrappers.h
Normal file
57
wrappers.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/* cgo wrappers.
|
||||||
|
* Copyright (C) 2013-2020 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of Red Hat nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern void wrapper_load ();
|
||||||
|
extern void wrapper_unload ();
|
||||||
|
extern void wrapper_dump_plugin ();
|
||||||
|
extern int wrapper_config (const char *key, const char *value);
|
||||||
|
extern int wrapper_config_complete (void);
|
||||||
|
extern int wrapper_get_ready (void);
|
||||||
|
extern int wrapper_preconnect (int readonly);
|
||||||
|
extern void * wrapper_open (int readonly);
|
||||||
|
extern void wrapper_close (void *handle);
|
||||||
|
extern int64_t wrapper_get_size (void *handle);
|
||||||
|
extern int wrapper_can_write (void *handle);
|
||||||
|
extern int wrapper_can_flush (void *handle);
|
||||||
|
extern int wrapper_is_rotational (void *handle);
|
||||||
|
extern int wrapper_can_trim (void *handle);
|
||||||
|
extern int wrapper_can_zero (void *handle);
|
||||||
|
extern int wrapper_can_multi_conn (void *handle);
|
||||||
|
extern int wrapper_pread (void *handle, void *buf,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags);
|
||||||
|
extern int wrapper_pwrite (void *handle, const void *buf,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags);
|
||||||
|
extern int wrapper_flush (void *handle, uint32_t flags);
|
||||||
|
extern int wrapper_trim (void *handle,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags);
|
||||||
|
extern int wrapper_zero (void *handle,
|
||||||
|
uint32_t count, uint64_t offset, uint32_t flags);
|
Loading…
Reference in a new issue