Update Red Hat Copyright Notices
[nbdkit.git] / plugins / example3 / example3.c
bloba2c8d311fed1d98a59aae81a3744adf8f37891b3
1 /* nbdkit
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 /* example3:
35 * A simple read-write filesystem which stores all changes in
36 * a temporary file that is thrown away after each connection.
39 #include <config.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <stdint.h>
44 #include <string.h>
45 #include <fcntl.h>
46 #include <unistd.h>
48 #define NBDKIT_API_VERSION 2
49 #include <nbdkit-plugin.h>
51 #ifndef HAVE_FDATASYNC
52 #define fdatasync fsync
53 #endif
55 /* The size of disk in bytes (initialized by size=<SIZE> parameter).
56 * If size parameter is not specified, it defaults to 100M.
58 static uint64_t size = 100 * 1024 * 1024;
60 /* If you want to display extra information about the plugin when
61 * the user does ‘nbdkit example3 --dump-plugin’ then you can print
62 * ‘key=value’ lines here.
64 static void
65 example3_dump_plugin (void)
67 printf ("example3_extra=hello\n");
70 /* Called for each key=value passed on the command line. This plugin
71 * only accepts optional size=<SIZE> parameter.
73 static int
74 example3_config (const char *key, const char *value)
76 int64_t r;
78 if (strcmp (key, "size") == 0) {
79 r = nbdkit_parse_size (value);
80 if (r == -1)
81 return -1;
82 size = (uint64_t) r;
84 else {
85 nbdkit_error ("unknown parameter '%s'", key);
86 return -1;
89 return 0;
92 #define example3_config_help \
93 "size=<SIZE> (optional) Size of the backing disk (default: 100M)"
95 /* The per-connection handle. */
96 struct example3_handle {
97 int fd;
100 /* Create the per-connection handle.
102 * Note we ignore the 'readonly' parameter. In effect this means that
103 * we ignore the -r option on the nbdkit command line, which sort of
104 * makes sense for this particular plugin.
106 static void *
107 example3_open (int readonly)
109 struct example3_handle *h;
110 char template[] = LARGE_TMPDIR "/diskXXXXXX";
112 h = malloc (sizeof *h);
113 if (h == NULL) {
114 nbdkit_error ("malloc: %m");
115 return NULL;
118 h->fd = mkstemp (template);
119 if (h->fd == -1) {
120 nbdkit_error ("mkstemp: %s: %m", template);
121 free (h);
122 return NULL;
125 unlink (template);
127 /* This creates a raw-format sparse file of the required size. */
128 if (ftruncate (h->fd, size) == -1) {
129 nbdkit_error ("ftruncate: %m");
130 close (h->fd);
131 free (h);
132 return NULL;
135 return h;
138 /* Free up the per-connection handle. */
139 static void
140 example3_close (void *handle)
142 struct example3_handle *h = handle;
144 close (h->fd);
145 free (h);
148 /* In fact NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS would work here.
149 * However for the benefit of people who blindly cut and paste code
150 * without bothering to read any documentation, leave this at a safe
151 * default.
153 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
155 /* Get the file size. */
156 static int64_t
157 example3_get_size (void *handle)
159 return (int64_t) size;
162 /* Read data from the file. */
163 static int
164 example3_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
165 uint32_t flags)
167 struct example3_handle *h = handle;
169 while (count > 0) {
170 ssize_t r = pread (h->fd, buf, count, offset);
171 if (r == -1) {
172 nbdkit_error ("pead: %m");
173 return -1;
175 if (r == 0) {
176 nbdkit_error ("pread: unexpected end of file");
177 return -1;
179 buf += r;
180 count -= r;
181 offset += r;
184 return 0;
187 /* Write data to the file. */
188 static int
189 example3_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset,
190 uint32_t flags)
192 struct example3_handle *h = handle;
194 while (count > 0) {
195 ssize_t r = pwrite (h->fd, buf, count, offset);
196 if (r == -1) {
197 nbdkit_error ("pwrite: %m");
198 return -1;
200 buf += r;
201 count -= r;
202 offset += r;
205 return 0;
208 /* Flush the file to disk. */
209 static int
210 example3_flush (void *handle, uint32_t flags)
212 struct example3_handle *h = handle;
214 if (fdatasync (h->fd) == -1) {
215 nbdkit_error ("fdatasync: %m");
216 return -1;
219 return 0;
222 static struct nbdkit_plugin plugin = {
223 .name = "example3",
224 .version = PACKAGE_VERSION,
225 .dump_plugin = example3_dump_plugin,
226 .config = example3_config,
227 .config_help = example3_config_help,
228 .open = example3_open,
229 .close = example3_close,
230 .get_size = example3_get_size,
231 .pread = example3_pread,
232 .pwrite = example3_pwrite,
233 .flush = example3_flush,
234 /* In this plugin, errno is preserved properly along error return
235 * paths from failed system calls.
237 .errno_is_preserved = 1,
240 NBDKIT_REGISTER_PLUGIN (plugin)