4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
41 #include <nbdkit-filter.h>
45 static int64_t offset
= 0, range
= -1;
47 /* Called for each key=value passed on the command line. */
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
);
58 else if (strcmp (key
, "range") == 0) {
59 range
= nbdkit_parse_size (value
);
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. */
74 offset_get_size (nbdkit_next
*next
,
77 int64_t real_size
= next
->get_size (next
);
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
);
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",
100 return real_size
- offset
;
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
);
114 offset_pwrite (nbdkit_next
*next
,
116 const void *buf
, uint32_t count
, uint64_t offs
, uint32_t flags
,
119 return next
->pwrite (next
, buf
, count
, offs
+ offset
, flags
, err
);
124 offset_trim (nbdkit_next
*next
,
125 void *handle
, uint32_t count
, uint64_t offs
, uint32_t flags
,
128 return next
->trim (next
, count
, offs
+ offset
, flags
, err
);
133 offset_zero (nbdkit_next
*next
,
134 void *handle
, uint32_t count
, uint64_t offs
, uint32_t flags
,
137 return next
->zero (next
, count
, offs
+ offset
, flags
, err
);
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
)
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
) {
156 if (next
->extents (next
, count
, offs
+ offset
, flags
, extents2
, err
) == -1)
159 for (i
= 0; i
< nbdkit_extents_count (extents2
); ++i
) {
160 e
= nbdkit_get_extent (extents2
, i
);
162 if (nbdkit_add_extent (extents
, e
.offset
, e
.length
, e
.type
) == -1) {
172 offset_cache (nbdkit_next
*next
,
173 void *handle
, uint32_t count
, uint64_t offs
, uint32_t flags
,
176 return next
->cache (next
, count
, offs
+ offset
, flags
, err
);
179 static struct nbdkit_filter filter
= {
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
,
189 .extents
= offset_extents
,
190 .cache
= offset_cache
,
193 NBDKIT_REGISTER_FILTER (filter
)