Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. 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.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #ifndef _VHD_LIB_H_
32 : : #define _VHD_LIB_H_
33 : :
34 : : /** \defgroup LibVHD LibVHD Module
35 : : * Core VHD handling
36 : : * @{
37 : : */
38 : :
39 : : #include <string.h>
40 : : #include <endian.h>
41 : : #include <byteswap.h>
42 : : #include <uuid/uuid.h>
43 : : #include <stdbool.h>
44 : :
45 : : #include "vhd.h"
46 : : #include "list.h"
47 : :
48 : : #if BYTE_ORDER == LITTLE_ENDIAN
49 : : #define BE16_IN(foo) (*(foo)) = bswap_16(*(foo))
50 : : #define BE32_IN(foo) (*(foo)) = bswap_32(*(foo))
51 : : #define BE64_IN(foo) (*(foo)) = bswap_64(*(foo))
52 : : #define BE16_OUT(foo) (*(foo)) = bswap_16(*(foo))
53 : : #define BE32_OUT(foo) (*(foo)) = bswap_32(*(foo))
54 : : #define BE64_OUT(foo) (*(foo)) = bswap_64(*(foo))
55 : : #else
56 : : #define BE16_IN(foo)
57 : : #define BE32_IN(foo)
58 : : #define BE64_IN(foo)
59 : : #define BE32_OUT(foo)
60 : : #define BE32_OUT(foo)
61 : : #define BE64_OUT(foo)
62 : : #endif
63 : :
64 : : #define BIT_MASK 0x80
65 : :
66 : : #define MIN(a, b) (((a) < (b)) ? (a) : (b))
67 : : #define MAX(a, b) (((a) > (b)) ? (a) : (b))
68 : :
69 : : #define VHD_MAX_NAME_LEN 1024
70 : :
71 : : #define VHD_BLOCK_SHIFT 21
72 : : #define VHD_BLOCK_SIZE (1ULL << VHD_BLOCK_SHIFT)
73 : :
74 : : #define UTF_16 "UTF-16"
75 : : #define UTF_16LE "UTF-16LE"
76 : : #define UTF_16BE "UTF-16BE"
77 : :
78 : : #define VHD_OPEN_RDONLY 0x00001
79 : : #define VHD_OPEN_RDWR 0x00002
80 : : #define VHD_OPEN_FAST 0x00004
81 : : #define VHD_OPEN_STRICT 0x00008
82 : : #define VHD_OPEN_IGNORE_DISABLED 0x00010
83 : : #define VHD_OPEN_CACHED 0x00020
84 : : #define VHD_OPEN_IO_WRITE_SPARSE 0x00040
85 : : #define VHD_OPEN_USE_BKP_FOOTER 0x00080
86 : :
87 : : #define VHD_FLAG_CREAT_FILE_SIZE_FIXED 0x00001
88 : : #define VHD_FLAG_CREAT_PARENT_RAW 0x00002
89 : :
90 : : #define vhd_flag_set(word, flag) ((word) |= (flag))
91 : : #define vhd_flag_clear(word, flag) ((word) &= ~(flag))
92 : : #define vhd_flag_test(word, flag) ((word) & (flag))
93 : :
94 : : #define LIBBLOCKCRYPTO_NAME "libblockcrypto.so.0"
95 : :
96 : : #define CRYPTO_DEFAULT_KEYDIR "/var/xen/blktap/keys"
97 : : extern int CRYPTO_SUPPORTED_KEYSIZE[];
98 : :
99 : : #define ENABLE_FAILURE_TESTING
100 : : #define FAIL_REPARENT_BEGIN 0
101 : : #define FAIL_REPARENT_LOCATOR 1
102 : : #define FAIL_REPARENT_END 2
103 : : #define FAIL_RESIZE_BEGIN 3
104 : : #define FAIL_RESIZE_DATA_MOVED 4
105 : : #define FAIL_RESIZE_METADATA_MOVED 5
106 : : #define FAIL_RESIZE_END 6
107 : : #define NUM_FAIL_TESTS 7
108 : :
109 : : #ifdef ENABLE_FAILURE_TESTING
110 : : #define TEST_FAIL_AT(point) \
111 : : if (TEST_FAIL[point]) { \
112 : : printf("Failing at %s\n", ENV_VAR_FAIL[point]); exit(EINVAL); }
113 : : #define TEST_FAIL_EXTERN_VARS \
114 : : extern const char* ENV_VAR_FAIL[]; \
115 : : extern int TEST_FAIL[];
116 : : #else
117 : : #define TEST_FAIL_AT(point)
118 : : #define TEST_FAIL_EXTERN_VARS
119 : : #endif // ENABLE_FAILURE_TESTING
120 : :
121 : :
122 : : static const char VHD_POISON_COOKIE[] = "v_poison";
123 : :
124 : : typedef struct hd_ftr vhd_footer_t;
125 : : typedef struct dd_hdr vhd_header_t;
126 : : typedef struct vhd_bat vhd_bat_t;
127 : : typedef struct vhd_batmap vhd_batmap_t;
128 : : typedef struct dd_batmap_hdr vhd_batmap_header_t;
129 : : typedef struct prt_loc vhd_parent_locator_t;
130 : : typedef struct vhd_context vhd_context_t;
131 : : typedef uint32_t vhd_flag_creat_t;
132 : :
133 : : struct vhd_bat {
134 : : uint32_t spb;
135 : : uint32_t entries;
136 : : uint32_t *bat;
137 : : };
138 : :
139 : : struct vhd_batmap {
140 : : vhd_batmap_header_t header;
141 : : char *map;
142 : : };
143 : :
144 : : struct crypto_blkcipher;
145 : :
146 : : struct vhd_context {
147 : : int fd;
148 : : char *file;
149 : : int oflags;
150 : : int is_block;
151 : :
152 : : off64_t offset;
153 : : uint32_t spb;
154 : : uint32_t bm_secs;
155 : :
156 : : vhd_header_t header;
157 : : vhd_footer_t footer;
158 : : vhd_bat_t bat;
159 : : vhd_batmap_t batmap;
160 : :
161 : : struct crypto_blkcipher *xts_tfm;
162 : : struct list_head next;
163 : :
164 : : char *custom_parent;
165 : : };
166 : :
167 : : /* Helpers for manipulating bitmaps *
168 : : *
169 : : * The bitmap is stored on a per-byte basis with the MSB representing
170 : : * the first bit in the bitmap.
171 : : */
172 : :
173 : : static inline bool
174 : : test_bit (const void *addr, uint32_t nr)
175 : : {
176 : 12288 : return (((const uint8_t *)addr)[nr >> 3] << (nr & 7)) & BIT_MASK;
177 : : }
178 : :
179 : : static inline void
180 : : set_bit (void *addr, uint32_t nr)
181 : : {
182 : 4097 : ((uint8_t *)addr)[nr >> 3] |= (BIT_MASK >> (nr & 7));
183 : : }
184 : :
185 : : static inline void
186 : : clear_bit (void *addr, uint32_t nr)
187 : : {
188 : 4097 : ((uint8_t *)addr)[nr >> 3] &= ~(BIT_MASK >> (nr & 7));
189 : : }
190 : :
191 : : static inline uint32_t
192 : : secs_round_up(uint64_t bytes)
193 : : {
194 : 0 : return ((bytes + (VHD_SECTOR_SIZE - 1)) >> VHD_SECTOR_SHIFT);
195 : : }
196 : :
197 : : static inline uint32_t
198 : : secs_round_up_no_zero(uint64_t bytes)
199 : : {
200 [ # # ][ # # ]: 0 : return (secs_round_up(bytes) ? : 1);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
201 : : }
202 : :
203 : : static inline uint64_t
204 : : vhd_sectors_to_bytes(uint64_t sectors)
205 : : {
206 : 0 : return sectors << VHD_SECTOR_SHIFT;
207 : : }
208 : :
209 : : static inline uint64_t
210 : : vhd_bytes_padded(uint64_t bytes)
211 : : {
212 : 0 : return vhd_sectors_to_bytes(secs_round_up_no_zero(bytes));
213 : : }
214 : :
215 : : static inline int
216 : 0 : vhd_type_dynamic(vhd_context_t *ctx)
217 : : {
218 : 0 : return (ctx->footer.type == HD_TYPE_DYNAMIC ||
219 : : ctx->footer.type == HD_TYPE_DIFF);
220 : : }
221 : :
222 : : static inline int
223 : : vhd_creator_tapdisk(vhd_context_t *ctx)
224 : : {
225 : 0 : return !strncmp(ctx->footer.crtr_app, "tap", 3);
226 : : }
227 : :
228 : : static inline int
229 : : vhd_disabled(vhd_context_t *ctx)
230 : : {
231 : 0 : return (!memcmp(ctx->footer.cookie,
232 : : VHD_POISON_COOKIE, sizeof(ctx->footer.cookie)));
233 : : }
234 : :
235 : : static inline size_t
236 : 0 : vhd_parent_locator_size(vhd_parent_locator_t *loc)
237 : : {
238 : : /*
239 : : * MICROSOFT_COMPAT
240 : : * data_space *should* be in sectors,
241 : : * but sometimes we find it in bytes
242 : : */
243 [ # # ][ # # ]: 0 : if (loc->data_space < 512)
[ # # ][ # # ]
244 : 0 : return vhd_sectors_to_bytes(loc->data_space);
245 [ # # ][ # # ]: 0 : else if (loc->data_space % 512 == 0)
[ # # ][ # # ]
246 : 0 : return loc->data_space;
247 : : else
248 : : return 0;
249 : : }
250 : :
251 : : static inline int
252 : : vhd_parent_raw(vhd_context_t *ctx)
253 : : {
254 : 0 : return uuid_is_null(ctx->header.prt_uuid);
255 : : }
256 : :
257 : : int open_optional_odirect(const char *pathname, int flags, ...);
258 : :
259 : : void libvhd_set_log_level(int);
260 : :
261 : : int vhd_test_file_fixed(const char *, int *);
262 : :
263 : : uint32_t vhd_time(time_t time);
264 : : size_t vhd_time_to_string(uint32_t timestamp, char *target);
265 : : uint32_t vhd_chs(uint64_t size);
266 : :
267 : : uint32_t vhd_checksum_footer(vhd_footer_t *);
268 : : uint32_t vhd_checksum_header(vhd_header_t *);
269 : : uint32_t vhd_checksum_batmap(vhd_context_t *, vhd_batmap_t *);
270 : :
271 : : void vhd_footer_in(vhd_footer_t *);
272 : : void vhd_footer_out(vhd_footer_t *);
273 : : void vhd_header_in(vhd_header_t *);
274 : : void vhd_header_out(vhd_header_t *);
275 : : void vhd_bat_in(vhd_bat_t *);
276 : : void vhd_bat_out(vhd_bat_t *);
277 : : void vhd_batmap_header_in(vhd_batmap_t *);
278 : : void vhd_batmap_header_out(vhd_batmap_t *);
279 : :
280 : : int vhd_validate_footer(vhd_footer_t *footer);
281 : : int vhd_validate_header(vhd_header_t *header);
282 : : int vhd_validate_batmap_header(vhd_batmap_t *batmap);
283 : : int vhd_validate_batmap(vhd_context_t *, vhd_batmap_t *batmap);
284 : : int vhd_validate_platform_code(uint32_t code);
285 : :
286 : : int vhd_open(vhd_context_t *, const char *file, int flags);
287 : : void vhd_close(vhd_context_t *);
288 : : /* vhd_create: mbytes is the virtual size for BAT/batmap preallocation - see
289 : : * vhd-util-resize.c
290 : : */
291 : : int vhd_create(const char *name, uint64_t bytes, int type, uint64_t mbytes,
292 : : vhd_flag_creat_t);
293 : : /* vhd_snapshot: the bytes parameter is optional and can be 0 if the snapshot
294 : : * is to have the same size as the (first non-empty) parent */
295 : : int vhd_snapshot(const char *snapshot, uint64_t bytes, const char *parent,
296 : : uint64_t mbytes, vhd_flag_creat_t);
297 : :
298 : : int vhd_hidden(vhd_context_t *, int *);
299 : : int vhd_chain_depth(vhd_context_t *, int *);
300 : : int vhd_marker(vhd_context_t *, char *);
301 : : int vhd_set_marker(vhd_context_t *, char);
302 : : int vhd_get_keyhash(vhd_context_t *, struct vhd_keyhash *);
303 : : int vhd_set_keyhash(vhd_context_t *, const struct vhd_keyhash *);
304 : :
305 : : off64_t vhd_position(vhd_context_t *);
306 : : int vhd_seek(vhd_context_t *, off64_t, int);
307 : : int vhd_read(vhd_context_t *, void *, size_t);
308 : : int vhd_write(vhd_context_t *, void *, size_t);
309 : :
310 : : int vhd_offset(vhd_context_t *, uint32_t, uint32_t *);
311 : :
312 : : int vhd_end_of_headers(vhd_context_t *ctx, off64_t *off);
313 : : int vhd_end_of_data(vhd_context_t *ctx, off64_t *off);
314 : : int vhd_batmap_header_offset(vhd_context_t *ctx, off64_t *off);
315 : :
316 : : int vhd_get_header(vhd_context_t *);
317 : : int vhd_get_footer(vhd_context_t *);
318 : : int vhd_get_bat(vhd_context_t *);
319 : : int vhd_get_batmap(vhd_context_t *);
320 : :
321 : : void vhd_put_header(vhd_context_t *);
322 : : void vhd_put_footer(vhd_context_t *);
323 : : void vhd_put_bat(vhd_context_t *);
324 : : void vhd_put_batmap(vhd_context_t *);
325 : :
326 : : int vhd_has_batmap(vhd_context_t *);
327 : : int vhd_batmap_test(vhd_context_t *, vhd_batmap_t *, uint32_t);
328 : : void vhd_batmap_set(vhd_context_t *, vhd_batmap_t *, uint32_t);
329 : : void vhd_batmap_clear(vhd_context_t *, vhd_batmap_t *, uint32_t);
330 : :
331 : : int vhd_file_size_fixed(vhd_context_t *);
332 : : int vhd_get_phys_size(vhd_context_t *, off64_t *);
333 : : int vhd_set_phys_size(vhd_context_t *, off64_t);
334 : : int vhd_set_virt_size(vhd_context_t *, uint64_t);
335 : :
336 : : int vhd_bitmap_test(vhd_context_t *, char *, uint32_t);
337 : : void vhd_bitmap_set(vhd_context_t *, char *, uint32_t);
338 : : void vhd_bitmap_clear(vhd_context_t *, char *, uint32_t);
339 : :
340 : : int vhd_initialize_header_parent_name(vhd_context_t *, const char *);
341 : : int vhd_write_parent_locators(vhd_context_t *, const char *);
342 : : int vhd_parent_locator_count(vhd_context_t *);
343 : : int vhd_parent_locator_get(vhd_context_t *, char **);
344 : : int vhd_parent_locator_unresolved_get(vhd_context_t *, char **);
345 : : int vhd_custom_parent_set(vhd_context_t *vhd, const char *parent);
346 : :
347 : : int vhd_parent_locator_read(vhd_context_t *, vhd_parent_locator_t *, char **);
348 : : int vhd_find_parent(vhd_context_t *, const char *, char **);
349 : : int vhd_parent_locator_write_at(vhd_context_t *, const char *,
350 : : off64_t, uint32_t, size_t,
351 : : vhd_parent_locator_t *);
352 : :
353 : : int vhd_header_decode_parent(vhd_context_t *, vhd_header_t *, char **);
354 : : int vhd_change_parent(vhd_context_t *, char *parent_path, int raw);
355 : : int vhd_macx_encode_location(char *name, char **out, int *outlen);
356 : : int vhd_w2u_encode_location(char *name, char **out, int *outlen);
357 : :
358 : : int vhd_read_footer(vhd_context_t *, vhd_footer_t *, bool use_bkp_footer);
359 : : int vhd_read_footer_at(vhd_context_t *, vhd_footer_t *, off64_t);
360 : : int vhd_read_footer_strict(vhd_context_t *, vhd_footer_t *);
361 : : int vhd_read_header(vhd_context_t *, vhd_header_t *);
362 : : int vhd_read_header_at(vhd_context_t *, vhd_header_t *, off64_t);
363 : : int vhd_read_bat(vhd_context_t *, vhd_bat_t *);
364 : : int vhd_read_batmap(vhd_context_t *, vhd_batmap_t *);
365 : : int vhd_read_bitmap(vhd_context_t *, uint32_t block, char **bufp);
366 : : int vhd_read_at(vhd_context_t *ctx, uint64_t block, uint32_t from, size_t size, char *buf);
367 : : int vhd_read_block(vhd_context_t *, uint32_t block, char **bufp);
368 : :
369 : : int vhd_write_footer(vhd_context_t *, vhd_footer_t *);
370 : : int vhd_write_footer_at(vhd_context_t *, vhd_footer_t *, off64_t);
371 : : int vhd_write_header(vhd_context_t *, vhd_header_t *);
372 : : int vhd_write_header_at(vhd_context_t *, vhd_header_t *, off64_t);
373 : : int vhd_write_bat(vhd_context_t *, vhd_bat_t *);
374 : : int vhd_write_batmap(vhd_context_t *, vhd_batmap_t *);
375 : : int vhd_write_bitmap(vhd_context_t *, uint32_t block, char *bitmap);
376 : : int vhd_write_block(vhd_context_t *, uint32_t block, char *data);
377 : :
378 : : int vhd_io_read(vhd_context_t *, char *, uint64_t, uint32_t);
379 : : int vhd_io_write(vhd_context_t *, char *, uint64_t, uint32_t);
380 : : int vhd_io_read_bytes(vhd_context_t *, void *, size_t, uint64_t);
381 : : int vhd_io_write_bytes(vhd_context_t *, void *, size_t, uint64_t);
382 : :
383 : : /** @} */ // End of LibVHD Doxygen group
384 : :
385 : : #endif
|