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