Update Red Hat Copyright Notices
[nbdkit.git] / plugins / example2 / winexample2.c
blob1e8ae43fec70a93913aa8dd2238f75bf64a80b2a
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 #ifndef WIN32
39 #error "build error: winexample2.c should only be used on Windows"
40 #endif
42 #include <config.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <stdint.h>
47 #include <string.h>
48 #include <fcntl.h>
49 #include <sys/types.h>
51 #include <ws2tcpip.h>
52 #include <windows.h>
54 #define NBDKIT_API_VERSION 2
55 #include <nbdkit-plugin.h>
57 static char *filename = NULL;
59 /* A debug flag which can be set on the command line using
60 * '-D example2.extra=1' to enable very verbose debugging to help
61 * developers. Use the debug flags for extra debugging which would
62 * only be useful for the original developers of the plugin. For
63 * ordinary debugging, just use nbdkit_debug and enable messages with
64 * the -v flag on the command line.
66 NBDKIT_DLL_PUBLIC int example2_debug_extra = 0;
68 static void
69 example2_unload (void)
71 free (filename);
74 /* If you want to display extra information about the plugin when
75 * the user does ‘nbdkit example2 --dump-plugin’ then you can print
76 * ‘key=value’ lines here.
78 static void
79 example2_dump_plugin (void)
81 printf ("example2_extra=hello\n");
84 /* Called for each key=value passed on the command line. This plugin
85 * only accepts file=<filename>, which is required.
87 static int
88 example2_config (const char *key, const char *value)
90 if (strcmp (key, "file") == 0) {
91 /* See FILENAMES AND PATHS in nbdkit-plugin(3). */
92 filename = nbdkit_realpath (value);
93 if (!filename)
94 return -1;
96 else {
97 nbdkit_error ("unknown parameter '%s'", key);
98 return -1;
101 return 0;
104 /* Check the user did pass a file=<FILENAME> parameter. */
105 static int
106 example2_config_complete (void)
108 if (filename == NULL) {
109 nbdkit_error ("you must supply the file=<FILENAME> parameter "
110 "after the plugin name on the command line");
111 return -1;
114 return 0;
117 #define example2_config_help \
118 "file=<FILENAME> (required) The filename to serve."
120 /* The per-connection handle. */
121 struct example2_handle {
122 HANDLE fh;
125 /* Create the per-connection handle.
127 * Because this plugin can only serve readonly, we can ignore the
128 * 'readonly' parameter.
130 static void *
131 example2_open (int readonly)
133 struct example2_handle *h;
135 h = malloc (sizeof *h);
136 if (h == NULL) {
137 nbdkit_error ("malloc: error %lu", GetLastError ());
138 return NULL;
141 h->fh = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
142 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
143 if (h->fh == INVALID_HANDLE_VALUE) {
144 nbdkit_error ("CreateFile: %s: error %lu", filename, GetLastError ());
145 free (h);
146 return NULL;
149 return h;
152 /* Free up the per-connection handle. */
153 static void
154 example2_close (void *handle)
156 struct example2_handle *h = handle;
158 CloseHandle (h->fh);
159 free (h);
162 /* In fact NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS would work here.
163 * However for the benefit of people who blindly cut and paste code
164 * without bothering to read any documentation, leave this at a safe
165 * default.
167 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
169 /* Get the file size. */
170 static int64_t
171 example2_get_size (void *handle)
173 struct example2_handle *h = handle;
174 LARGE_INTEGER size = { 0 };
176 if (!GetFileSizeEx (h->fh, &size)) {
177 nbdkit_error ("%s: GetFileSizeEx: error %lu", filename, GetLastError ());
178 return -1;
181 /* Use the debug flags for extra debugging which would only be
182 * useful for the original developers of the plugin. For ordinary
183 * debugging, just use nbdkit_debug and enable messages with the -v
184 * flag on the command line. This is a contrived example of how to
185 * use debug flags.
187 if (example2_debug_extra)
188 nbdkit_debug ("extra debugging: size = %I64d", (long long)size.QuadPart);
190 return size.QuadPart;
193 /* Read data from the file. */
194 static int
195 example2_pread (void *handle, void *buf, uint32_t count, uint64_t offset,
196 uint32_t flags)
198 struct example2_handle *h = handle;
199 DWORD r;
200 OVERLAPPED ovl;
202 memset (&ovl, 0, sizeof ovl);
203 ovl.Offset = offset & 0xffffffff;
204 ovl.OffsetHigh = offset >> 32;
206 /* XXX Will fail weirdly if count is larger than 32 bits. */
207 if (!ReadFile (h->fh, buf, count, &r, &ovl)) {
208 nbdkit_error ("%s: ReadFile: error %lu", filename, GetLastError ());
209 return -1;
212 return 0;
215 static struct nbdkit_plugin plugin = {
216 .name = "example2",
217 .version = PACKAGE_VERSION,
218 .unload = example2_unload,
219 .dump_plugin = example2_dump_plugin,
220 .config = example2_config,
221 .config_complete = example2_config_complete,
222 .config_help = example2_config_help,
223 .open = example2_open,
224 .close = example2_close,
225 .get_size = example2_get_size,
226 .pread = example2_pread,
229 NBDKIT_REGISTER_PLUGIN (plugin)