plugins: Wire up rust plugin support for NBD_INFO_INIT_STATE
[nbdkit/ericb.git] / plugins / example2 / example2.c
blob6adc100aa85c0455cbad827a9e491f4f3d33aef3
1 /* nbdkit
2 * Copyright (C) 2013 Red Hat Inc.
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 /* example2:
35 * A simple but more realistic read-only file server.
38 #include <config.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stdint.h>
43 #include <string.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
49 #include <nbdkit-plugin.h>
51 static char *filename = NULL;
53 /* A debug flag which can be set on the command line using
54 * '-D example2.extra=1' to enable very verbose debugging to help
55 * developers. Use the debug flags for extra debugging which would
56 * only be useful for the original developers of the plugin. For
57 * ordinary debugging, just use nbdkit_debug and enable messages with
58 * the -v flag on the command line.
60 int example2_debug_extra = 0;
62 static void
63 example2_unload (void)
65 free (filename);
68 /* If you want to display extra information about the plugin when
69 * the user does ‘nbdkit example2 --dump-plugin’ then you can print
70 * ‘key=value’ lines here.
72 static void
73 example2_dump_plugin (void)
75 printf ("example2_extra=hello\n");
78 /* Called for each key=value passed on the command line. This plugin
79 * only accepts file=<filename>, which is required.
81 static int
82 example2_config (const char *key, const char *value)
84 if (strcmp (key, "file") == 0) {
85 /* See FILENAMES AND PATHS in nbdkit-plugin(3). */
86 filename = nbdkit_realpath (value);
87 if (!filename)
88 return -1;
90 else {
91 nbdkit_error ("unknown parameter '%s'", key);
92 return -1;
95 return 0;
98 /* Check the user did pass a file=<FILENAME> parameter. */
99 static int
100 example2_config_complete (void)
102 if (filename == NULL) {
103 nbdkit_error ("you must supply the file=<FILENAME> parameter "
104 "after the plugin name on the command line");
105 return -1;
108 return 0;
111 #define example2_config_help \
112 "file=<FILENAME> (required) The filename to serve."
114 /* The per-connection handle. */
115 struct example2_handle {
116 int fd;
119 /* Create the per-connection handle.
121 * Because this plugin can only serve readonly, we can ignore the
122 * 'readonly' parameter.
124 static void *
125 example2_open (int readonly)
127 struct example2_handle *h;
129 h = malloc (sizeof *h);
130 if (h == NULL) {
131 nbdkit_error ("malloc: %m");
132 return NULL;
135 h->fd = open (filename, O_RDONLY|O_CLOEXEC);
136 if (h->fd == -1) {
137 nbdkit_error ("open: %s: %m", filename);
138 free (h);
139 return NULL;
142 return h;
145 /* Free up the per-connection handle. */
146 static void
147 example2_close (void *handle)
149 struct example2_handle *h = handle;
151 close (h->fd);
152 free (h);
155 /* In fact NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS would work here.
156 * However for the benefit of people who blindly cut and paste code
157 * without bothering to read any documentation, leave this at a safe
158 * default.
160 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
162 /* Get the file size. */
163 static int64_t
164 example2_get_size (void *handle)
166 struct example2_handle *h = handle;
167 struct stat statbuf;
169 if (fstat (h->fd, &statbuf) == -1) {
170 nbdkit_error ("stat: %m");
171 return -1;
174 /* Use the debug flags for extra debugging which would only be
175 * useful for the original developers of the plugin. For ordinary
176 * debugging, just use nbdkit_debug and enable messages with the -v
177 * flag on the command line. This is a contrived example of how to
178 * use debug flags.
180 if (example2_debug_extra)
181 nbdkit_debug ("extra debugging: statbuf.st_size = %jd\n",
182 (intmax_t)statbuf.st_size);
184 return statbuf.st_size;
187 /* Read data from the file. */
188 static int
189 example2_pread (void *handle, void *buf, uint32_t count, uint64_t offset)
191 struct example2_handle *h = handle;
193 while (count > 0) {
194 ssize_t r = pread (h->fd, buf, count, offset);
195 if (r == -1) {
196 nbdkit_error ("pread: %m");
197 return -1;
199 if (r == 0) {
200 nbdkit_error ("pread: unexpected end of file");
201 return -1;
203 buf += r;
204 count -= r;
205 offset += r;
208 return 0;
211 static struct nbdkit_plugin plugin = {
212 .name = "example2",
213 .version = PACKAGE_VERSION,
214 .unload = example2_unload,
215 .dump_plugin = example2_dump_plugin,
216 .config = example2_config,
217 .config_complete = example2_config_complete,
218 .config_help = example2_config_help,
219 .open = example2_open,
220 .close = example2_close,
221 .get_size = example2_get_size,
222 .pread = example2_pread,
223 /* In this plugin, errno is preserved properly along error return
224 * paths from failed system calls.
226 .errno_is_preserved = 1,
229 NBDKIT_REGISTER_PLUGIN(plugin)