Compare commits
1 commit
main
...
1.26-stabl
Author | SHA1 | Date | |
---|---|---|---|
|
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