Compare commits

...

2 commits

Author SHA1 Message Date
Matthew Arnold
93cdaa1de1 Import nbdkit-1.23.6 2020-09-28 20:01:35 +00:00
Matthew Arnold
25cdc74820 Import nbdkit-1.23.1 2020-09-28 20:01:28 +00:00
4 changed files with 897 additions and 0 deletions

569
nbdkit.go Normal file
View 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 pkg-config: nbdkit
#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
View 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 pkg-config: nbdkit
#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
View 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 pkg-config: nbdkit
#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
View 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);