Update Red Hat Copyright Notices
[nbdkit.git] / plugins / example2 / example2.c
blob933cb06fba41ecd9f85b80f7a05d58447f88341c
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 /* 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 #define NBDKIT_API_VERSION 2
50 #include <nbdkit-plugin.h>
52 static char *filename = NULL;
54 /* A debug flag which can be set on the command line using
55 * '-D example2.extra=1' to enable very verbose debugging to help
56 * developers. Use the debug flags for extra debugging which would
57 * only be useful for the original developers of the plugin. For
58 * ordinary debugging, just use nbdkit_debug and enable messages with
59 * the -v flag on the command line.
61 NBDKIT_DLL_PUBLIC int example2_debug_extra = 0;
63 static void
64 example2_unload (void)
66 free (filename);
69 /* If you want to display extra information about the plugin when
70 * the user does ‘nbdkit example2 --dump-plugin’ then you can print
71 * ‘key=value’ lines here.
73 static void
74 example2_dump_plugin (void)
76 printf ("example2_extra=hello\n");
79 /* Called for each key=value passed on the command line. This plugin
80 * only accepts file=<filename>, which is required.
82 static int
83 example2_config (const char *key, const char *value)
85 if (strcmp (key, "file") == 0) {
86 /* See FILENAMES AND PATHS in nbdkit-plugin(3). */
87 filename = nbdkit_realpath (value);
88 if (!filename)
89 return -1;
91 else {
92 nbdkit_error ("unknown parameter '%s'", key);
93 return -1;
96 return 0;
99 /* Check the user did pass a file=<FILENAME> parameter. */
100 static int
101 example2_config_complete (void)
103 if (filename == NULL) {
104 nbdkit_error ("you must supply the file=<FILENAME> parameter "
105 "after the plugin name on the command line");
106 return -1;
109 return 0;
112 #define example2_config_help \
113 "file=<FILENAME> (required) The filename to serve."
115 /* The per-connection handle. */
116 struct example2_handle {
117 int fd;
120 /* Create the per-connection handle.
122 * Because this plugin can only serve readonly, we can ignore the
123 * 'readonly' parameter.
125 static void *
126 example2_open (int readonly)
128 struct example2_handle *h;
130 h = malloc (sizeof *h);
131 if (h == NULL) {
132 nbdkit_error ("malloc: %m");
133 return NULL;
136 h->fd = open (filename, O_RDONLY|O_CLOEXEC);
137 if (h->fd == -1) {
138 nbdkit_error ("open: %s: %m", filename);
139 free (h);
140 return NULL;
143 return h;
146 /* Free up the per-connection handle. */
147 static void
148 example2_close (void *handle)
150 struct example2_handle *h = handle;
152 close (h->fd);
153 free (h);
156 /* In fact NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS would work here.
157 * However for the benefit of people who blindly cut and paste code
158 * without bothering to read any documentation, leave this at a safe
159 * default.
161 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
163 /* Get the file size. */
164 static int64_t
165 example2_get_size (void *handle)
167 struct example2_handle *h = handle;
168 struct stat statbuf;
170 if (fstat (h->fd, &statbuf) == -1) {
171 nbdkit_error ("stat: %m");
172 return -1;
175 /* Use the debug flags for extra debugging which would only be
176 * useful for the original developers of the plugin. For ordinary
177 * debugging, just use nbdkit_debug and enable messages with the -v
178 * flag on the command line. This is a contrived example of how to
179 * use debug flags.
181 if (example2_debug_extra)
182 nbdkit_debug ("extra debugging: statbuf.st_size = %jd",
183 (intmax_t)statbuf.st_size);
185 return statbuf.st_size;
188 /* Read data from the file. */
189 static int
190 example2_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
191 uint32_t flags)
193 struct example2_handle *h = handle;
195 while (count > 0) {
196 ssize_t r = pread (h->fd, buf, count, offset);
197 if (r == -1) {
198 nbdkit_error ("pread: %m");
199 return -1;
201 if (r == 0) {
202 nbdkit_error ("pread: unexpected end of file");
203 return -1;
205 buf += r;
206 count -= r;
207 offset += r;
210 return 0;
213 static struct nbdkit_plugin plugin = {
214 .name = "example2",
215 .version = PACKAGE_VERSION,
216 .unload = example2_unload,
217 .dump_plugin = example2_dump_plugin,
218 .config = example2_config,
219 .config_complete = example2_config_complete,
220 .config_help = example2_config_help,
221 .open = example2_open,
222 .close = example2_close,
223 .get_size = example2_get_size,
224 .pread = example2_pread,
225 /* In this plugin, errno is preserved properly along error return
226 * paths from failed system calls.
228 .errno_is_preserved = 1,
231 NBDKIT_REGISTER_PLUGIN (plugin)