4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 "libguestfs.org/nbdkit"
44 var pluginName
= "disk"
46 // The plugin global struct.
47 type DiskPlugin
struct {
51 // The per-client struct.
52 type DiskConnection
struct {
54 fd
*os
.File
// Per-client temporary disk.
60 // Parse the size parameter on the command line.
61 func (p
*DiskPlugin
) Config(key
string, value
string) error
{
64 size
, err
= strconv
.ParseUint(value
, 0, 64)
71 return nbdkit
.PluginError
{Errmsg
: "unknown parameter"}
75 // Make sure the user specified the size parameter.
76 func (p
*DiskPlugin
) ConfigComplete() error
{
78 return nbdkit
.PluginError
{Errmsg
: "size parameter is required"}
83 func (p
*DiskPlugin
) Open(readonly
bool) (nbdkit
.ConnectionInterface
, error
) {
84 // Open a temporary file.
85 fd
, err
:= ioutil
.TempFile("/var/tmp", "nbdkitdisk")
91 // Truncate it to the right size.
92 err
= fd
.Truncate(int64(size
))
97 // Store the file descriptor of the temporary file in the
99 return &DiskConnection
{fd
: fd
}, nil
102 func (c
*DiskConnection
) Close() {
106 // Return the size of the disk. We could just return the global
107 // "size" here, but make the example more interesting.
108 func (c
*DiskConnection
) GetSize() (uint64, error
) {
109 info
, err
:= c
.fd
.Stat()
113 return uint64(info
.Size()), nil
116 // Multi-conn is NOT safe because each client sees a different disk.
117 func (c
*DiskConnection
) CanMultiConn() (bool, error
) {
121 func (c
*DiskConnection
) PRead(buf
[]byte, offset
uint64,
122 flags
uint32) error
{
123 n
, err
:= c
.fd
.ReadAt(buf
, int64(offset
))
127 // NBD requests must always read/write the whole requested
128 // amount, or else fail. Actually we should loop here (XXX).
130 return nbdkit
.PluginError
{Errmsg
: "short read"}
135 // Note that CanWrite() is required in golang plugins that implement
136 // PWrite(), otherwise PWrite() will never be called.
137 func (c
*DiskConnection
) CanWrite() (bool, error
) {
141 func (c
*DiskConnection
) PWrite(buf
[]byte, offset
uint64,
142 flags
uint32) error
{
143 n
, err
:= c
.fd
.WriteAt(buf
, int64(offset
))
147 // NBD requests must always read/write the whole requested
148 // amount, or else fail. Actually we should loop here (XXX).
150 return nbdkit
.PluginError
{Errmsg
: "short write"}
155 // Note that CanFlush() is required in golang plugins that implement
156 // Flush(), otherwise Flush() will never be called.
157 func (c
*DiskConnection
) CanFlush() (bool, error
) {
161 // This is only an example, but if this was a real plugin, because
162 // these disks are transient and deleted when the client exits, it
163 // would make no sense to implement a Flush() callback.
164 func (c
*DiskConnection
) Flush(flags
uint32) error
{
168 //----------------------------------------------------------------------
170 // The boilerplate below this line is required by all golang plugins,
171 // as well as importing "C" and "unsafe" modules at the top of the
175 func plugin_init() unsafe
.Pointer
{
176 // If your plugin needs to do any initialization, you can
177 // either put it here or implement a Load() method.
180 // Then you must call the following function.
181 return nbdkit
.PluginInitialize(pluginName
, &DiskPlugin
{})
184 // This is never(?) called, but must exist.