Update Red Hat Copyright Notices
[nbdkit.git] / filters / offset / offset.c
blobf00618fb37d0b9d8c4682727b4cd34cf60f27074
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 <stdint.h>
38 #include <inttypes.h>
39 #include <string.h>
41 #include <nbdkit-filter.h>
43 #include "cleanup.h"
45 static int64_t offset = 0, range = -1;
47 /* Called for each key=value passed on the command line. */
48 static int
49 offset_config (nbdkit_next_config *next, nbdkit_backend *nxdata,
50 const char *key, const char *value)
52 if (strcmp (key, "offset") == 0) {
53 offset = nbdkit_parse_size (value);
54 if (offset == -1)
55 return -1;
56 return 0;
58 else if (strcmp (key, "range") == 0) {
59 range = nbdkit_parse_size (value);
60 if (range == -1)
61 return -1;
62 return 0;
64 else
65 return next (nxdata, key, value);
68 #define offset_config_help \
69 "offset=<OFFSET> The start offset to serve (default 0).\n" \
70 "range=<LENGTH> The total size to serve (default rest of file)."
72 /* Get the file size. */
73 static int64_t
74 offset_get_size (nbdkit_next *next,
75 void *handle)
77 int64_t real_size = next->get_size (next);
79 if (real_size == -1)
80 return -1;
82 if (range >= 0) {
83 if (offset > real_size - range) {
84 nbdkit_error ("offset+range (%" PRIi64 "+%" PRIi64 ") "
85 "is larger than the real size (%" PRIi64 ") "
86 "of the underlying file or device",
87 offset, range, real_size);
88 return -1;
90 return range;
92 else if (offset > real_size) {
93 nbdkit_error ("offset (%" PRIi64 ") "
94 "is larger than the real size (%" PRIi64 ") "
95 "of the underlying file or device",
96 offset, real_size);
97 return -1;
99 else
100 return real_size - offset;
103 /* Read data. */
104 static int
105 offset_pread (nbdkit_next *next,
106 void *handle, void *buf, uint32_t count, uint64_t offs,
107 uint32_t flags, int *err)
109 return next->pread (next, buf, count, offs + offset, flags, err);
112 /* Write data. */
113 static int
114 offset_pwrite (nbdkit_next *next,
115 void *handle,
116 const void *buf, uint32_t count, uint64_t offs, uint32_t flags,
117 int *err)
119 return next->pwrite (next, buf, count, offs + offset, flags, err);
122 /* Trim data. */
123 static int
124 offset_trim (nbdkit_next *next,
125 void *handle, uint32_t count, uint64_t offs, uint32_t flags,
126 int *err)
128 return next->trim (next, count, offs + offset, flags, err);
131 /* Zero data. */
132 static int
133 offset_zero (nbdkit_next *next,
134 void *handle, uint32_t count, uint64_t offs, uint32_t flags,
135 int *err)
137 return next->zero (next, count, offs + offset, flags, err);
140 /* Extents. */
141 static int
142 offset_extents (nbdkit_next *next,
143 void *handle, uint32_t count, uint64_t offs, uint32_t flags,
144 struct nbdkit_extents *extents, int *err)
146 size_t i;
147 CLEANUP_EXTENTS_FREE struct nbdkit_extents *extents2 = NULL;
148 struct nbdkit_extent e;
149 int64_t end = range >= 0 ? offset + range : next->get_size (next);
151 extents2 = nbdkit_extents_new (offs + offset, end);
152 if (extents2 == NULL) {
153 *err = errno;
154 return -1;
156 if (next->extents (next, count, offs + offset, flags, extents2, err) == -1)
157 return -1;
159 for (i = 0; i < nbdkit_extents_count (extents2); ++i) {
160 e = nbdkit_get_extent (extents2, i);
161 e.offset -= offset;
162 if (nbdkit_add_extent (extents, e.offset, e.length, e.type) == -1) {
163 *err = errno;
164 return -1;
167 return 0;
170 /* Cache data. */
171 static int
172 offset_cache (nbdkit_next *next,
173 void *handle, uint32_t count, uint64_t offs, uint32_t flags,
174 int *err)
176 return next->cache (next, count, offs + offset, flags, err);
179 static struct nbdkit_filter filter = {
180 .name = "offset",
181 .longname = "nbdkit offset filter",
182 .config = offset_config,
183 .config_help = offset_config_help,
184 .get_size = offset_get_size,
185 .pread = offset_pread,
186 .pwrite = offset_pwrite,
187 .trim = offset_trim,
188 .zero = offset_zero,
189 .extents = offset_extents,
190 .cache = offset_cache,
193 NBDKIT_REGISTER_FILTER (filter)