Update Red Hat Copyright Notices
[nbdkit.git] / plugins / golang / examples / disk / disk.go
blob7a9315fa5ceb01c1d057ea4127ae63c2e8e56e5c
1 /* Example plugin.
2 * Copyright Red Hat
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
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
30 * SUCH DAMAGE.
33 package main
35 import (
36 "C"
37 "io/ioutil"
38 "libguestfs.org/nbdkit"
39 "os"
40 "strconv"
41 "unsafe"
44 var pluginName = "disk"
46 // The plugin global struct.
47 type DiskPlugin struct {
48 nbdkit.Plugin
51 // The per-client struct.
52 type DiskConnection struct {
53 nbdkit.Connection
54 fd *os.File // Per-client temporary disk.
57 var size uint64
58 var size_set = false
60 // Parse the size parameter on the command line.
61 func (p *DiskPlugin) Config(key string, value string) error {
62 if key == "size" {
63 var err error
64 size, err = strconv.ParseUint(value, 0, 64)
65 if err != nil {
66 return err
68 size_set = true
69 return nil
70 } else {
71 return nbdkit.PluginError{Errmsg: "unknown parameter"}
75 // Make sure the user specified the size parameter.
76 func (p *DiskPlugin) ConfigComplete() error {
77 if !size_set {
78 return nbdkit.PluginError{Errmsg: "size parameter is required"}
80 return nil
83 func (p *DiskPlugin) Open(readonly bool) (nbdkit.ConnectionInterface, error) {
84 // Open a temporary file.
85 fd, err := ioutil.TempFile("/var/tmp", "nbdkitdisk")
86 if err != nil {
87 return nil, err
89 os.Remove(fd.Name())
91 // Truncate it to the right size.
92 err = fd.Truncate(int64(size))
93 if err != nil {
94 return nil, err
97 // Store the file descriptor of the temporary file in the
98 // Connection struct.
99 return &DiskConnection{fd: fd}, nil
102 func (c *DiskConnection) Close() {
103 c.fd.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()
110 if err != nil {
111 return 0, err
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) {
118 return false, nil
121 func (c *DiskConnection) PRead(buf []byte, offset uint64,
122 flags uint32) error {
123 n, err := c.fd.ReadAt(buf, int64(offset))
124 if err != nil {
125 return err
127 // NBD requests must always read/write the whole requested
128 // amount, or else fail. Actually we should loop here (XXX).
129 if n != len(buf) {
130 return nbdkit.PluginError{Errmsg: "short read"}
132 return nil
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) {
138 return true, nil
141 func (c *DiskConnection) PWrite(buf []byte, offset uint64,
142 flags uint32) error {
143 n, err := c.fd.WriteAt(buf, int64(offset))
144 if err != nil {
145 return err
147 // NBD requests must always read/write the whole requested
148 // amount, or else fail. Actually we should loop here (XXX).
149 if n != len(buf) {
150 return nbdkit.PluginError{Errmsg: "short write"}
152 return nil
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) {
158 return true, nil
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 {
165 return c.fd.Sync()
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
172 // file.
174 //export plugin_init
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.
178 // ...
180 // Then you must call the following function.
181 return nbdkit.PluginInitialize(pluginName, &DiskPlugin{})
184 // This is never(?) called, but must exist.
185 func main() {}