Update Red Hat Copyright Notices
[nbdkit.git] / plugins / floppy / floppy.c
blob95c82473a83bd84f7aea6fb42e55478da8bea67e
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 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <fcntl.h>
41 #include <nbdkit-plugin.h>
43 #include "regions.h"
45 #include "virtual-floppy.h"
47 /* Directory. */
48 static char *dir = NULL;
50 /* Volume label. */
51 static const char *label = "NBDKITFLOPY";
53 /* Filesystem size. */
54 static uint64_t size = 0;
56 /* Virtual floppy. */
57 static struct virtual_floppy floppy;
59 static void
60 floppy_load (void)
62 init_virtual_floppy (&floppy);
65 static void
66 floppy_unload (void)
68 free (dir);
69 free_virtual_floppy (&floppy);
72 static int
73 floppy_config (const char *key, const char *value)
75 int64_t r;
77 if (strcmp (key, "dir") == 0) {
78 if (dir != NULL) {
79 /* TODO: Support merging of multiple directories, like iso plugin. */
80 nbdkit_error ("dir=<DIRECTORY> must only be set once");
81 return -1;
83 dir = nbdkit_realpath (value);
84 if (dir == NULL)
85 return -1;
87 else if (strcmp (key, "label") == 0) {
88 label = value;
90 else if (strcmp (key, "size") == 0) {
91 r = nbdkit_parse_size (value);
92 if (r == -1)
93 return -1;
94 size = r;
96 else {
97 nbdkit_error ("unknown parameter '%s'", key);
98 return -1;
101 return 0;
104 static int
105 floppy_config_complete (void)
107 if (dir == NULL) {
108 nbdkit_error ("you must supply the dir=<DIRECTORY> parameter "
109 "after the plugin name on the command line");
110 return -1;
113 return 0;
116 #define floppy_config_help \
117 "dir=<DIRECTORY> (required) The directory to serve\n" \
118 "label=<LABEL> The volume label\n" \
119 "size=<SIZE> Optional total disk size"
121 static int
122 floppy_get_ready (void)
124 return create_virtual_floppy (dir, label, size, &floppy);
127 static void *
128 floppy_open (int readonly)
130 return NBDKIT_HANDLE_NOT_NEEDED;
133 #define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL
135 /* Get the file size. */
136 static int64_t
137 floppy_get_size (void *handle)
139 return virtual_size (&floppy.regions);
142 /* Serves the same data over multiple connections. */
143 static int
144 floppy_can_multi_conn (void *handle)
146 return 1;
149 /* Cache. */
150 static int
151 floppy_can_cache (void *handle)
153 /* Let nbdkit call pread to populate the file system cache. */
154 return NBDKIT_CACHE_EMULATE;
157 /* Read data from the file. */
158 static int
159 floppy_pread (void *handle, void *buf, uint32_t count, uint64_t offset)
161 while (count > 0) {
162 const struct region *region = find_region (&floppy.regions, offset);
163 size_t i, len;
164 const char *host_path;
165 int fd;
166 ssize_t r;
168 /* Length to end of region. */
169 len = region->end - offset + 1;
170 if (len > count)
171 len = count;
173 switch (region->type) {
174 case region_file:
175 i = region->u.i;
176 assert (i < floppy.files.len);
177 host_path = floppy.files.ptr[i].host_path;
178 fd = open (host_path, O_RDONLY|O_CLOEXEC);
179 if (fd == -1) {
180 nbdkit_error ("open: %s: %m", host_path);
181 return -1;
183 r = pread (fd, buf, len, offset - region->start);
184 if (r == -1) {
185 nbdkit_error ("pread: %s: %m", host_path);
186 close (fd);
187 return -1;
189 if (r == 0) {
190 nbdkit_error ("pread: %s: unexpected end of file", host_path);
191 close (fd);
192 return -1;
194 close (fd);
195 len = r;
196 break;
198 case region_data:
199 memcpy (buf, &region->u.data[offset - region->start], len);
200 break;
202 case region_zero:
203 memset (buf, 0, len);
204 break;
207 count -= len;
208 buf += len;
209 offset += len;
212 return 0;
215 static struct nbdkit_plugin plugin = {
216 .name = "floppy",
217 .longname = "nbdkit floppy plugin",
218 .version = PACKAGE_VERSION,
219 .load = floppy_load,
220 .unload = floppy_unload,
221 .config = floppy_config,
222 .config_complete = floppy_config_complete,
223 .config_help = floppy_config_help,
224 .magic_config_key = "dir",
225 .get_ready = floppy_get_ready,
226 .open = floppy_open,
227 .get_size = floppy_get_size,
228 .can_multi_conn = floppy_can_multi_conn,
229 .can_cache = floppy_can_cache,
230 .pread = floppy_pread,
231 .errno_is_preserved = 1,
234 NBDKIT_REGISTER_PLUGIN (plugin)