]> git.proxmox.com Git - qemu.git/blame - block/vmdk.c
vmdk: Improve error handling
[qemu.git] / block / vmdk.c
CommitLineData
ea2384d3
FB
1/*
2 * Block driver for the VMDK format
5fafdf24 3 *
ea2384d3 4 * Copyright (c) 2004 Fabrice Bellard
ff1afc72 5 * Copyright (c) 2005 Filip Navara
5fafdf24 6 *
ea2384d3
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
5f4da8c0 25
faf07963 26#include "qemu-common.h"
ea2384d3 27#include "block_int.h"
5efa9d5a 28#include "module.h"
432bb170 29#include "zlib.h"
ea2384d3 30
ea2384d3
FB
31#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
32#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
432bb170 33#define VMDK4_COMPRESSION_DEFLATE 1
bb45ded9 34#define VMDK4_FLAG_RGD (1 << 1)
432bb170
FZ
35#define VMDK4_FLAG_COMPRESS (1 << 16)
36#define VMDK4_FLAG_MARKER (1 << 17)
ea2384d3
FB
37
38typedef struct {
39 uint32_t version;
40 uint32_t flags;
41 uint32_t disk_sectors;
42 uint32_t granularity;
43 uint32_t l1dir_offset;
44 uint32_t l1dir_size;
45 uint32_t file_sectors;
46 uint32_t cylinders;
47 uint32_t heads;
48 uint32_t sectors_per_track;
49} VMDK3Header;
50
51typedef struct {
52 uint32_t version;
53 uint32_t flags;
54 int64_t capacity;
55 int64_t granularity;
56 int64_t desc_offset;
57 int64_t desc_size;
58 int32_t num_gtes_per_gte;
ea2384d3 59 int64_t gd_offset;
bb45ded9 60 int64_t rgd_offset;
ea2384d3
FB
61 int64_t grain_offset;
62 char filler[1];
63 char check_bytes[4];
432bb170 64 uint16_t compressAlgorithm;
541dc0d4 65} QEMU_PACKED VMDK4Header;
ea2384d3
FB
66
67#define L2_CACHE_SIZE 16
68
b3976d3c
FZ
69typedef struct VmdkExtent {
70 BlockDriverState *file;
71 bool flat;
432bb170
FZ
72 bool compressed;
73 bool has_marker;
b3976d3c
FZ
74 int64_t sectors;
75 int64_t end_sector;
7fa60fa3 76 int64_t flat_start_offset;
ea2384d3 77 int64_t l1_table_offset;
ff1afc72 78 int64_t l1_backup_table_offset;
ea2384d3 79 uint32_t *l1_table;
ff1afc72 80 uint32_t *l1_backup_table;
ea2384d3
FB
81 unsigned int l1_size;
82 uint32_t l1_entry_sectors;
83
84 unsigned int l2_size;
85 uint32_t *l2_cache;
86 uint32_t l2_cache_offsets[L2_CACHE_SIZE];
87 uint32_t l2_cache_counts[L2_CACHE_SIZE];
88
89 unsigned int cluster_sectors;
b3976d3c
FZ
90} VmdkExtent;
91
92typedef struct BDRVVmdkState {
848c66e8 93 CoMutex lock;
e1da9b24 94 int desc_offset;
69b4d86d 95 bool cid_updated;
5f4da8c0 96 uint32_t parent_cid;
b3976d3c
FZ
97 int num_extents;
98 /* Extent array with num_extents entries, ascend ordered by address */
99 VmdkExtent *extents;
ea2384d3
FB
100} BDRVVmdkState;
101
630530a6
TS
102typedef struct VmdkMetaData {
103 uint32_t offset;
104 unsigned int l1_index;
105 unsigned int l2_index;
106 unsigned int l2_offset;
107 int valid;
108} VmdkMetaData;
109
432bb170
FZ
110typedef struct VmdkGrainMarker {
111 uint64_t lba;
112 uint32_t size;
113 uint8_t data[0];
114} VmdkGrainMarker;
115
ea2384d3
FB
116static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
117{
118 uint32_t magic;
119
ae261c86 120 if (buf_size < 4) {
ea2384d3 121 return 0;
ae261c86 122 }
ea2384d3
FB
123 magic = be32_to_cpu(*(uint32_t *)buf);
124 if (magic == VMDK3_MAGIC ||
01fc99d6 125 magic == VMDK4_MAGIC) {
ea2384d3 126 return 100;
01fc99d6
FZ
127 } else {
128 const char *p = (const char *)buf;
129 const char *end = p + buf_size;
130 while (p < end) {
131 if (*p == '#') {
132 /* skip comment line */
133 while (p < end && *p != '\n') {
134 p++;
135 }
136 p++;
137 continue;
138 }
139 if (*p == ' ') {
140 while (p < end && *p == ' ') {
141 p++;
142 }
143 /* skip '\r' if windows line endings used. */
144 if (p < end && *p == '\r') {
145 p++;
146 }
147 /* only accept blank lines before 'version=' line */
148 if (p == end || *p != '\n') {
149 return 0;
150 }
151 p++;
152 continue;
153 }
154 if (end - p >= strlen("version=X\n")) {
155 if (strncmp("version=1\n", p, strlen("version=1\n")) == 0 ||
156 strncmp("version=2\n", p, strlen("version=2\n")) == 0) {
157 return 100;
158 }
159 }
160 if (end - p >= strlen("version=X\r\n")) {
161 if (strncmp("version=1\r\n", p, strlen("version=1\r\n")) == 0 ||
162 strncmp("version=2\r\n", p, strlen("version=2\r\n")) == 0) {
163 return 100;
164 }
165 }
166 return 0;
167 }
ea2384d3 168 return 0;
01fc99d6 169 }
ea2384d3
FB
170}
171
5f4da8c0
TS
172#define CHECK_CID 1
173
3b46e624 174#define SECTOR_SIZE 512
f66fd6c3
FZ
175#define DESC_SIZE (20 * SECTOR_SIZE) /* 20 sectors of 512 bytes each */
176#define BUF_SIZE 4096
177#define HEADER_SIZE 512 /* first sector of 512 bytes */
5f4da8c0 178
b3976d3c
FZ
179static void vmdk_free_extents(BlockDriverState *bs)
180{
181 int i;
182 BDRVVmdkState *s = bs->opaque;
b3c0bfb6 183 VmdkExtent *e;
b3976d3c
FZ
184
185 for (i = 0; i < s->num_extents; i++) {
b3c0bfb6
FZ
186 e = &s->extents[i];
187 g_free(e->l1_table);
188 g_free(e->l2_cache);
189 g_free(e->l1_backup_table);
190 if (e->file != bs->file) {
191 bdrv_delete(e->file);
192 }
b3976d3c 193 }
7267c094 194 g_free(s->extents);
b3976d3c
FZ
195}
196
86c6b429
FZ
197static void vmdk_free_last_extent(BlockDriverState *bs)
198{
199 BDRVVmdkState *s = bs->opaque;
200
201 if (s->num_extents == 0) {
202 return;
203 }
204 s->num_extents--;
205 s->extents = g_realloc(s->extents, s->num_extents * sizeof(VmdkExtent));
206}
207
5f4da8c0 208static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
ea2384d3 209{
5f4da8c0 210 char desc[DESC_SIZE];
bac8d7b4 211 uint32_t cid = 0;
7ccfb2eb 212 const char *p_name, *cid_str;
5f4da8c0 213 size_t cid_str_size;
e1da9b24 214 BDRVVmdkState *s = bs->opaque;
99f1835d 215 int ret;
5f4da8c0 216
99f1835d
KW
217 ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
218 if (ret < 0) {
5f4da8c0 219 return 0;
e1da9b24 220 }
5f4da8c0
TS
221
222 if (parent) {
223 cid_str = "parentCID";
224 cid_str_size = sizeof("parentCID");
225 } else {
226 cid_str = "CID";
227 cid_str_size = sizeof("CID");
228 }
229
ae261c86
FZ
230 p_name = strstr(desc, cid_str);
231 if (p_name != NULL) {
5f4da8c0 232 p_name += cid_str_size;
ae261c86 233 sscanf(p_name, "%x", &cid);
5f4da8c0
TS
234 }
235
236 return cid;
237}
238
239static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
240{
5f4da8c0
TS
241 char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
242 char *p_name, *tmp_str;
e1da9b24 243 BDRVVmdkState *s = bs->opaque;
99f1835d 244 int ret;
5f4da8c0 245
e1da9b24 246 memset(desc, 0, sizeof(desc));
99f1835d
KW
247 ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
248 if (ret < 0) {
249 return ret;
e1da9b24 250 }
5f4da8c0 251
ae261c86 252 tmp_str = strstr(desc, "parentCID");
363a37d5 253 pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str);
ae261c86
FZ
254 p_name = strstr(desc, "CID");
255 if (p_name != NULL) {
5f4da8c0 256 p_name += sizeof("CID");
363a37d5
BS
257 snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid);
258 pstrcat(desc, sizeof(desc), tmp_desc);
5f4da8c0
TS
259 }
260
99f1835d
KW
261 ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE);
262 if (ret < 0) {
263 return ret;
e1da9b24 264 }
99f1835d 265
5f4da8c0
TS
266 return 0;
267}
268
269static int vmdk_is_cid_valid(BlockDriverState *bs)
270{
271#ifdef CHECK_CID
272 BDRVVmdkState *s = bs->opaque;
b171271a 273 BlockDriverState *p_bs = bs->backing_hd;
5f4da8c0
TS
274 uint32_t cur_pcid;
275
276 if (p_bs) {
ae261c86
FZ
277 cur_pcid = vmdk_read_cid(p_bs, 0);
278 if (s->parent_cid != cur_pcid) {
279 /* CID not valid */
5f4da8c0 280 return 0;
ae261c86 281 }
5f4da8c0
TS
282 }
283#endif
ae261c86 284 /* CID valid */
5f4da8c0
TS
285 return 1;
286}
287
9949f97e 288static int vmdk_parent_open(BlockDriverState *bs)
5f4da8c0 289{
5fafdf24 290 char *p_name;
7fa60fa3 291 char desc[DESC_SIZE + 1];
e1da9b24 292 BDRVVmdkState *s = bs->opaque;
588b65a3 293 int ret;
5f4da8c0 294
7fa60fa3 295 desc[DESC_SIZE] = '\0';
588b65a3
PB
296 ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
297 if (ret < 0) {
298 return ret;
e1da9b24 299 }
5f4da8c0 300
ae261c86
FZ
301 p_name = strstr(desc, "parentFileNameHint");
302 if (p_name != NULL) {
5f4da8c0 303 char *end_name;
5f4da8c0
TS
304
305 p_name += sizeof("parentFileNameHint") + 1;
ae261c86
FZ
306 end_name = strchr(p_name, '\"');
307 if (end_name == NULL) {
588b65a3 308 return -EINVAL;
ae261c86
FZ
309 }
310 if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
588b65a3 311 return -EINVAL;
ae261c86 312 }
3b46e624 313
b171271a 314 pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
ff1afc72 315 }
5f4da8c0
TS
316
317 return 0;
318}
319
b3976d3c
FZ
320/* Create and append extent to the extent array. Return the added VmdkExtent
321 * address. return NULL if allocation failed. */
322static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
323 BlockDriverState *file, bool flat, int64_t sectors,
324 int64_t l1_offset, int64_t l1_backup_offset,
325 uint32_t l1_size,
326 int l2_size, unsigned int cluster_sectors)
327{
328 VmdkExtent *extent;
329 BDRVVmdkState *s = bs->opaque;
330
7267c094 331 s->extents = g_realloc(s->extents,
b3976d3c
FZ
332 (s->num_extents + 1) * sizeof(VmdkExtent));
333 extent = &s->extents[s->num_extents];
334 s->num_extents++;
335
336 memset(extent, 0, sizeof(VmdkExtent));
337 extent->file = file;
338 extent->flat = flat;
339 extent->sectors = sectors;
340 extent->l1_table_offset = l1_offset;
341 extent->l1_backup_table_offset = l1_backup_offset;
342 extent->l1_size = l1_size;
343 extent->l1_entry_sectors = l2_size * cluster_sectors;
344 extent->l2_size = l2_size;
345 extent->cluster_sectors = cluster_sectors;
346
347 if (s->num_extents > 1) {
348 extent->end_sector = (*(extent - 1)).end_sector + extent->sectors;
349 } else {
350 extent->end_sector = extent->sectors;
351 }
352 bs->total_sectors = extent->end_sector;
353 return extent;
354}
355
b4b3ab14 356static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
5f4da8c0 357{
b4b3ab14
FZ
358 int ret;
359 int l1_size, i;
5f4da8c0 360
ea2384d3 361 /* read the L1 table */
b3976d3c 362 l1_size = extent->l1_size * sizeof(uint32_t);
7267c094 363 extent->l1_table = g_malloc(l1_size);
b4b3ab14
FZ
364 ret = bdrv_pread(extent->file,
365 extent->l1_table_offset,
366 extent->l1_table,
367 l1_size);
368 if (ret < 0) {
369 goto fail_l1;
b3976d3c
FZ
370 }
371 for (i = 0; i < extent->l1_size; i++) {
372 le32_to_cpus(&extent->l1_table[i]);
ea2384d3
FB
373 }
374
b3976d3c 375 if (extent->l1_backup_table_offset) {
7267c094 376 extent->l1_backup_table = g_malloc(l1_size);
b4b3ab14
FZ
377 ret = bdrv_pread(extent->file,
378 extent->l1_backup_table_offset,
379 extent->l1_backup_table,
380 l1_size);
381 if (ret < 0) {
382 goto fail_l1b;
b3976d3c
FZ
383 }
384 for (i = 0; i < extent->l1_size; i++) {
385 le32_to_cpus(&extent->l1_backup_table[i]);
ff1afc72
FB
386 }
387 }
388
b3976d3c 389 extent->l2_cache =
7267c094 390 g_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
ea2384d3 391 return 0;
b4b3ab14 392 fail_l1b:
7267c094 393 g_free(extent->l1_backup_table);
b4b3ab14 394 fail_l1:
7267c094 395 g_free(extent->l1_table);
b4b3ab14
FZ
396 return ret;
397}
398
86c6b429
FZ
399static int vmdk_open_vmdk3(BlockDriverState *bs,
400 BlockDriverState *file,
401 int flags)
b4b3ab14
FZ
402{
403 int ret;
404 uint32_t magic;
405 VMDK3Header header;
406 VmdkExtent *extent;
407
86c6b429 408 ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
b4b3ab14 409 if (ret < 0) {
86c6b429 410 return ret;
b4b3ab14
FZ
411 }
412 extent = vmdk_add_extent(bs,
413 bs->file, false,
414 le32_to_cpu(header.disk_sectors),
415 le32_to_cpu(header.l1dir_offset) << 9,
416 0, 1 << 6, 1 << 9,
417 le32_to_cpu(header.granularity));
418 ret = vmdk_init_tables(bs, extent);
419 if (ret) {
86c6b429
FZ
420 /* free extent allocated by vmdk_add_extent */
421 vmdk_free_last_extent(bs);
b4b3ab14 422 }
b4b3ab14
FZ
423 return ret;
424}
425
f16f509d
FZ
426static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
427 int64_t desc_offset);
428
86c6b429
FZ
429static int vmdk_open_vmdk4(BlockDriverState *bs,
430 BlockDriverState *file,
431 int flags)
b4b3ab14
FZ
432{
433 int ret;
434 uint32_t magic;
435 uint32_t l1_size, l1_entry_sectors;
436 VMDK4Header header;
b4b3ab14 437 VmdkExtent *extent;
bb45ded9 438 int64_t l1_backup_offset = 0;
b4b3ab14 439
86c6b429 440 ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
b4b3ab14 441 if (ret < 0) {
86c6b429 442 return ret;
b4b3ab14 443 }
f16f509d
FZ
444 if (header.capacity == 0 && header.desc_offset) {
445 return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
446 }
b4b3ab14
FZ
447 l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
448 * le64_to_cpu(header.granularity);
86c6b429
FZ
449 if (l1_entry_sectors <= 0) {
450 return -EINVAL;
451 }
b4b3ab14
FZ
452 l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1)
453 / l1_entry_sectors;
bb45ded9
FZ
454 if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
455 l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
456 }
86c6b429 457 extent = vmdk_add_extent(bs, file, false,
b4b3ab14
FZ
458 le64_to_cpu(header.capacity),
459 le64_to_cpu(header.gd_offset) << 9,
bb45ded9 460 l1_backup_offset,
b4b3ab14
FZ
461 l1_size,
462 le32_to_cpu(header.num_gtes_per_gte),
463 le64_to_cpu(header.granularity));
432bb170
FZ
464 extent->compressed =
465 le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
466 extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
b4b3ab14
FZ
467 ret = vmdk_init_tables(bs, extent);
468 if (ret) {
86c6b429
FZ
469 /* free extent allocated by vmdk_add_extent */
470 vmdk_free_last_extent(bs);
b4b3ab14 471 }
b4b3ab14
FZ
472 return ret;
473}
474
7fa60fa3
FZ
475/* find an option value out of descriptor file */
476static int vmdk_parse_description(const char *desc, const char *opt_name,
477 char *buf, int buf_size)
478{
479 char *opt_pos, *opt_end;
480 const char *end = desc + strlen(desc);
481
482 opt_pos = strstr(desc, opt_name);
483 if (!opt_pos) {
484 return -1;
485 }
486 /* Skip "=\"" following opt_name */
487 opt_pos += strlen(opt_name) + 2;
488 if (opt_pos >= end) {
489 return -1;
490 }
491 opt_end = opt_pos;
492 while (opt_end < end && *opt_end != '"') {
493 opt_end++;
494 }
495 if (opt_end == end || buf_size < opt_end - opt_pos + 1) {
496 return -1;
497 }
498 pstrcpy(buf, opt_end - opt_pos + 1, opt_pos);
499 return 0;
500}
501
86c6b429
FZ
502/* Open an extent file and append to bs array */
503static int vmdk_open_sparse(BlockDriverState *bs,
504 BlockDriverState *file,
505 int flags)
506{
507 uint32_t magic;
508
509 if (bdrv_pread(file, 0, &magic, sizeof(magic)) != sizeof(magic)) {
510 return -EIO;
511 }
512
513 magic = be32_to_cpu(magic);
514 switch (magic) {
515 case VMDK3_MAGIC:
516 return vmdk_open_vmdk3(bs, file, flags);
517 break;
518 case VMDK4_MAGIC:
519 return vmdk_open_vmdk4(bs, file, flags);
520 break;
521 default:
522 return -EINVAL;
523 break;
524 }
525}
526
7fa60fa3
FZ
527static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
528 const char *desc_file_path)
529{
530 int ret;
531 char access[11];
532 char type[11];
533 char fname[512];
534 const char *p = desc;
535 int64_t sectors = 0;
536 int64_t flat_offset;
86c6b429
FZ
537 char extent_path[PATH_MAX];
538 BlockDriverState *extent_file;
7fa60fa3
FZ
539
540 while (*p) {
541 /* parse extent line:
542 * RW [size in sectors] FLAT "file-name.vmdk" OFFSET
543 * or
544 * RW [size in sectors] SPARSE "file-name.vmdk"
545 */
546 flat_offset = -1;
547 ret = sscanf(p, "%10s %" SCNd64 " %10s %511s %" SCNd64,
548 access, &sectors, type, fname, &flat_offset);
549 if (ret < 4 || strcmp(access, "RW")) {
550 goto next_line;
551 } else if (!strcmp(type, "FLAT")) {
552 if (ret != 5 || flat_offset < 0) {
553 return -EINVAL;
554 }
555 } else if (ret != 4) {
556 return -EINVAL;
557 }
558
559 /* trim the quotation marks around */
560 if (fname[0] == '"') {
561 memmove(fname, fname + 1, strlen(fname));
562 if (strlen(fname) <= 1 || fname[strlen(fname) - 1] != '"') {
563 return -EINVAL;
564 }
565 fname[strlen(fname) - 1] = '\0';
566 }
567 if (sectors <= 0 ||
568 (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) ||
569 (strcmp(access, "RW"))) {
570 goto next_line;
571 }
572
86c6b429
FZ
573 path_combine(extent_path, sizeof(extent_path),
574 desc_file_path, fname);
575 ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
576 if (ret) {
577 return ret;
578 }
579
7fa60fa3
FZ
580 /* save to extents array */
581 if (!strcmp(type, "FLAT")) {
582 /* FLAT extent */
7fa60fa3
FZ
583 VmdkExtent *extent;
584
7fa60fa3
FZ
585 extent = vmdk_add_extent(bs, extent_file, true, sectors,
586 0, 0, 0, 0, sectors);
f16f509d 587 extent->flat_start_offset = flat_offset << 9;
86c6b429
FZ
588 } else if (!strcmp(type, "SPARSE")) {
589 /* SPARSE extent */
590 ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
591 if (ret) {
592 bdrv_delete(extent_file);
593 return ret;
594 }
7fa60fa3 595 } else {
7fa60fa3
FZ
596 fprintf(stderr,
597 "VMDK: Not supported extent type \"%s\""".\n", type);
598 return -ENOTSUP;
599 }
600next_line:
601 /* move to next line */
602 while (*p && *p != '\n') {
603 p++;
604 }
605 p++;
606 }
607 return 0;
608}
609
f16f509d
FZ
610static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
611 int64_t desc_offset)
7fa60fa3
FZ
612{
613 int ret;
614 char buf[2048];
615 char ct[128];
616 BDRVVmdkState *s = bs->opaque;
617
f16f509d 618 ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf));
7fa60fa3
FZ
619 if (ret < 0) {
620 return ret;
621 }
622 buf[2047] = '\0';
623 if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) {
624 return -EINVAL;
625 }
6398de51 626 if (strcmp(ct, "monolithicFlat") &&
86c6b429 627 strcmp(ct, "twoGbMaxExtentSparse") &&
6398de51 628 strcmp(ct, "twoGbMaxExtentFlat")) {
7fa60fa3
FZ
629 fprintf(stderr,
630 "VMDK: Not supported image type \"%s\""".\n", ct);
631 return -ENOTSUP;
632 }
633 s->desc_offset = 0;
bae0a0cc 634 return vmdk_parse_extents(buf, bs, bs->file->filename);
7fa60fa3
FZ
635}
636
b4b3ab14
FZ
637static int vmdk_open(BlockDriverState *bs, int flags)
638{
86c6b429
FZ
639 int ret;
640 BDRVVmdkState *s = bs->opaque;
b4b3ab14 641
86c6b429
FZ
642 if (vmdk_open_sparse(bs, bs->file, flags) == 0) {
643 s->desc_offset = 0x200;
bae0a0cc
PB
644 } else {
645 ret = vmdk_open_desc_file(bs, flags, 0);
86c6b429 646 if (ret) {
bae0a0cc 647 goto fail;
86c6b429 648 }
b4b3ab14 649 }
bae0a0cc
PB
650 /* try to open parent images, if exist */
651 ret = vmdk_parent_open(bs);
652 if (ret) {
653 goto fail;
654 }
655 s->parent_cid = vmdk_read_cid(bs, 1);
848c66e8 656 qemu_co_mutex_init(&s->lock);
bae0a0cc
PB
657 return ret;
658
659fail:
660 vmdk_free_extents(bs);
661 return ret;
ea2384d3
FB
662}
663
b3976d3c
FZ
664static int get_whole_cluster(BlockDriverState *bs,
665 VmdkExtent *extent,
666 uint64_t cluster_offset,
667 uint64_t offset,
668 bool allocate)
5f4da8c0 669{
b3976d3c
FZ
670 /* 128 sectors * 512 bytes each = grain size 64KB */
671 uint8_t whole_grain[extent->cluster_sectors * 512];
5f4da8c0 672
0e69c543
FZ
673 /* we will be here if it's first write on non-exist grain(cluster).
674 * try to read from parent image, if exist */
b171271a 675 if (bs->backing_hd) {
c336500d 676 int ret;
5f4da8c0 677
ae261c86 678 if (!vmdk_is_cid_valid(bs)) {
5f4da8c0 679 return -1;
ae261c86 680 }
5f4da8c0 681
0e69c543
FZ
682 /* floor offset to cluster */
683 offset -= offset % (extent->cluster_sectors * 512);
c336500d 684 ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
b3976d3c 685 extent->cluster_sectors);
c336500d
KW
686 if (ret < 0) {
687 return -1;
688 }
630530a6 689
0e69c543 690 /* Write grain only into the active image */
b3976d3c
FZ
691 ret = bdrv_write(extent->file, cluster_offset, whole_grain,
692 extent->cluster_sectors);
c336500d
KW
693 if (ret < 0) {
694 return -1;
630530a6
TS
695 }
696 }
697 return 0;
698}
699
b3976d3c 700static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
630530a6 701{
630530a6 702 /* update L2 table */
b3976d3c
FZ
703 if (bdrv_pwrite_sync(
704 extent->file,
705 ((int64_t)m_data->l2_offset * 512)
706 + (m_data->l2_index * sizeof(m_data->offset)),
707 &(m_data->offset),
708 sizeof(m_data->offset)
709 ) < 0) {
630530a6 710 return -1;
b3976d3c 711 }
630530a6 712 /* update backup L2 table */
b3976d3c
FZ
713 if (extent->l1_backup_table_offset != 0) {
714 m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
715 if (bdrv_pwrite_sync(
716 extent->file,
717 ((int64_t)m_data->l2_offset * 512)
718 + (m_data->l2_index * sizeof(m_data->offset)),
719 &(m_data->offset), sizeof(m_data->offset)
720 ) < 0) {
5f4da8c0 721 return -1;
b3976d3c 722 }
5f4da8c0 723 }
630530a6 724
5f4da8c0
TS
725 return 0;
726}
727
91b85bd3 728static int get_cluster_offset(BlockDriverState *bs,
b3976d3c
FZ
729 VmdkExtent *extent,
730 VmdkMetaData *m_data,
91b85bd3
FZ
731 uint64_t offset,
732 int allocate,
733 uint64_t *cluster_offset)
ea2384d3 734{
ea2384d3
FB
735 unsigned int l1_index, l2_offset, l2_index;
736 int min_index, i, j;
630530a6 737 uint32_t min_count, *l2_table, tmp = 0;
630530a6 738
ae261c86 739 if (m_data) {
630530a6 740 m_data->valid = 0;
ae261c86 741 }
91b85bd3 742 if (extent->flat) {
7fa60fa3 743 *cluster_offset = extent->flat_start_offset;
91b85bd3
FZ
744 return 0;
745 }
630530a6 746
6398de51 747 offset -= (extent->end_sector - extent->sectors) * SECTOR_SIZE;
b3976d3c
FZ
748 l1_index = (offset >> 9) / extent->l1_entry_sectors;
749 if (l1_index >= extent->l1_size) {
91b85bd3 750 return -1;
b3976d3c
FZ
751 }
752 l2_offset = extent->l1_table[l1_index];
753 if (!l2_offset) {
91b85bd3 754 return -1;
b3976d3c 755 }
b4b3ab14 756 for (i = 0; i < L2_CACHE_SIZE; i++) {
b3976d3c 757 if (l2_offset == extent->l2_cache_offsets[i]) {
ea2384d3 758 /* increment the hit count */
b3976d3c 759 if (++extent->l2_cache_counts[i] == 0xffffffff) {
b4b3ab14 760 for (j = 0; j < L2_CACHE_SIZE; j++) {
b3976d3c 761 extent->l2_cache_counts[j] >>= 1;
ea2384d3
FB
762 }
763 }
b3976d3c 764 l2_table = extent->l2_cache + (i * extent->l2_size);
ea2384d3
FB
765 goto found;
766 }
767 }
768 /* not found: load a new entry in the least used one */
769 min_index = 0;
770 min_count = 0xffffffff;
b4b3ab14 771 for (i = 0; i < L2_CACHE_SIZE; i++) {
b3976d3c
FZ
772 if (extent->l2_cache_counts[i] < min_count) {
773 min_count = extent->l2_cache_counts[i];
ea2384d3
FB
774 min_index = i;
775 }
776 }
b3976d3c
FZ
777 l2_table = extent->l2_cache + (min_index * extent->l2_size);
778 if (bdrv_pread(
779 extent->file,
780 (int64_t)l2_offset * 512,
781 l2_table,
782 extent->l2_size * sizeof(uint32_t)
783 ) != extent->l2_size * sizeof(uint32_t)) {
91b85bd3 784 return -1;
b3976d3c 785 }
5f4da8c0 786
b3976d3c
FZ
787 extent->l2_cache_offsets[min_index] = l2_offset;
788 extent->l2_cache_counts[min_index] = 1;
ea2384d3 789 found:
b3976d3c 790 l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
91b85bd3 791 *cluster_offset = le32_to_cpu(l2_table[l2_index]);
630530a6 792
91b85bd3
FZ
793 if (!*cluster_offset) {
794 if (!allocate) {
795 return -1;
796 }
9949f97e 797
ae261c86 798 /* Avoid the L2 tables update for the images that have snapshots. */
91b85bd3 799 *cluster_offset = bdrv_getlength(extent->file);
2b2c8c5d
FZ
800 if (!extent->compressed) {
801 bdrv_truncate(
802 extent->file,
803 *cluster_offset + (extent->cluster_sectors << 9)
804 );
805 }
9949f97e 806
91b85bd3
FZ
807 *cluster_offset >>= 9;
808 tmp = cpu_to_le32(*cluster_offset);
9949f97e 809 l2_table[l2_index] = tmp;
630530a6 810
630530a6
TS
811 /* First of all we write grain itself, to avoid race condition
812 * that may to corrupt the image.
813 * This problem may occur because of insufficient space on host disk
814 * or inappropriate VM shutdown.
815 */
b3976d3c 816 if (get_whole_cluster(
ae261c86 817 bs, extent, *cluster_offset, offset, allocate) == -1) {
91b85bd3 818 return -1;
ae261c86 819 }
630530a6
TS
820
821 if (m_data) {
822 m_data->offset = tmp;
823 m_data->l1_index = l1_index;
824 m_data->l2_index = l2_index;
825 m_data->l2_offset = l2_offset;
826 m_data->valid = 1;
827 }
ff1afc72 828 }
91b85bd3
FZ
829 *cluster_offset <<= 9;
830 return 0;
ea2384d3
FB
831}
832
b3976d3c
FZ
833static VmdkExtent *find_extent(BDRVVmdkState *s,
834 int64_t sector_num, VmdkExtent *start_hint)
835{
836 VmdkExtent *extent = start_hint;
837
838 if (!extent) {
839 extent = &s->extents[0];
840 }
841 while (extent < &s->extents[s->num_extents]) {
842 if (sector_num < extent->end_sector) {
843 return extent;
844 }
845 extent++;
846 }
847 return NULL;
848}
849
5fafdf24 850static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
ea2384d3
FB
851 int nb_sectors, int *pnum)
852{
853 BDRVVmdkState *s = bs->opaque;
b3976d3c
FZ
854 int64_t index_in_cluster, n, ret;
855 uint64_t offset;
856 VmdkExtent *extent;
857
858 extent = find_extent(s, sector_num, NULL);
859 if (!extent) {
860 return 0;
861 }
91b85bd3
FZ
862 ret = get_cluster_offset(bs, extent, NULL,
863 sector_num * 512, 0, &offset);
864 /* get_cluster_offset returning 0 means success */
865 ret = !ret;
866
867 index_in_cluster = sector_num % extent->cluster_sectors;
868 n = extent->cluster_sectors - index_in_cluster;
ae261c86 869 if (n > nb_sectors) {
ea2384d3 870 n = nb_sectors;
ae261c86 871 }
ea2384d3 872 *pnum = n;
b3976d3c 873 return ret;
ea2384d3
FB
874}
875
dd3f6ee2
FZ
876static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
877 int64_t offset_in_cluster, const uint8_t *buf,
878 int nb_sectors, int64_t sector_num)
879{
880 int ret;
2b2c8c5d
FZ
881 VmdkGrainMarker *data = NULL;
882 uLongf buf_len;
dd3f6ee2
FZ
883 const uint8_t *write_buf = buf;
884 int write_len = nb_sectors * 512;
885
2b2c8c5d
FZ
886 if (extent->compressed) {
887 if (!extent->has_marker) {
888 ret = -EINVAL;
889 goto out;
890 }
891 buf_len = (extent->cluster_sectors << 9) * 2;
892 data = g_malloc(buf_len + sizeof(VmdkGrainMarker));
893 if (compress(data->data, &buf_len, buf, nb_sectors << 9) != Z_OK ||
894 buf_len == 0) {
895 ret = -EINVAL;
896 goto out;
897 }
898 data->lba = sector_num;
899 data->size = buf_len;
900 write_buf = (uint8_t *)data;
901 write_len = buf_len + sizeof(VmdkGrainMarker);
902 }
dd3f6ee2
FZ
903 ret = bdrv_pwrite(extent->file,
904 cluster_offset + offset_in_cluster,
905 write_buf,
906 write_len);
907 if (ret != write_len) {
908 ret = ret < 0 ? ret : -EIO;
909 goto out;
910 }
911 ret = 0;
912 out:
2b2c8c5d 913 g_free(data);
dd3f6ee2
FZ
914 return ret;
915}
916
917static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
918 int64_t offset_in_cluster, uint8_t *buf,
919 int nb_sectors)
920{
921 int ret;
2b2c8c5d
FZ
922 int cluster_bytes, buf_bytes;
923 uint8_t *cluster_buf, *compressed_data;
924 uint8_t *uncomp_buf;
925 uint32_t data_len;
926 VmdkGrainMarker *marker;
927 uLongf buf_len;
928
dd3f6ee2 929
2b2c8c5d
FZ
930 if (!extent->compressed) {
931 ret = bdrv_pread(extent->file,
932 cluster_offset + offset_in_cluster,
933 buf, nb_sectors * 512);
934 if (ret == nb_sectors * 512) {
935 return 0;
936 } else {
937 return -EIO;
938 }
939 }
940 cluster_bytes = extent->cluster_sectors * 512;
941 /* Read two clusters in case GrainMarker + compressed data > one cluster */
942 buf_bytes = cluster_bytes * 2;
943 cluster_buf = g_malloc(buf_bytes);
944 uncomp_buf = g_malloc(cluster_bytes);
dd3f6ee2 945 ret = bdrv_pread(extent->file,
2b2c8c5d
FZ
946 cluster_offset,
947 cluster_buf, buf_bytes);
948 if (ret < 0) {
949 goto out;
950 }
951 compressed_data = cluster_buf;
952 buf_len = cluster_bytes;
953 data_len = cluster_bytes;
954 if (extent->has_marker) {
955 marker = (VmdkGrainMarker *)cluster_buf;
956 compressed_data = marker->data;
957 data_len = le32_to_cpu(marker->size);
958 }
959 if (!data_len || data_len > buf_bytes) {
960 ret = -EINVAL;
961 goto out;
962 }
963 ret = uncompress(uncomp_buf, &buf_len, compressed_data, data_len);
964 if (ret != Z_OK) {
965 ret = -EINVAL;
966 goto out;
967
968 }
969 if (offset_in_cluster < 0 ||
970 offset_in_cluster + nb_sectors * 512 > buf_len) {
971 ret = -EINVAL;
972 goto out;
dd3f6ee2 973 }
2b2c8c5d
FZ
974 memcpy(buf, uncomp_buf + offset_in_cluster, nb_sectors * 512);
975 ret = 0;
976
977 out:
978 g_free(uncomp_buf);
979 g_free(cluster_buf);
980 return ret;
dd3f6ee2
FZ
981}
982
5fafdf24 983static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
ea2384d3
FB
984 uint8_t *buf, int nb_sectors)
985{
986 BDRVVmdkState *s = bs->opaque;
b3976d3c
FZ
987 int ret;
988 uint64_t n, index_in_cluster;
989 VmdkExtent *extent = NULL;
ea2384d3 990 uint64_t cluster_offset;
5f4da8c0 991
ea2384d3 992 while (nb_sectors > 0) {
b3976d3c
FZ
993 extent = find_extent(s, sector_num, extent);
994 if (!extent) {
995 return -EIO;
996 }
91b85bd3
FZ
997 ret = get_cluster_offset(
998 bs, extent, NULL,
999 sector_num << 9, 0, &cluster_offset);
b3976d3c
FZ
1000 index_in_cluster = sector_num % extent->cluster_sectors;
1001 n = extent->cluster_sectors - index_in_cluster;
ae261c86 1002 if (n > nb_sectors) {
ea2384d3 1003 n = nb_sectors;
ae261c86 1004 }
91b85bd3
FZ
1005 if (ret) {
1006 /* if not allocated, try to read from parent image, if exist */
b171271a 1007 if (bs->backing_hd) {
ae261c86 1008 if (!vmdk_is_cid_valid(bs)) {
7fa60fa3 1009 return -EINVAL;
ae261c86 1010 }
b171271a 1011 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
ae261c86 1012 if (ret < 0) {
7fa60fa3 1013 return ret;
ae261c86 1014 }
5f4da8c0
TS
1015 } else {
1016 memset(buf, 0, 512 * n);
1017 }
ea2384d3 1018 } else {
dd3f6ee2
FZ
1019 ret = vmdk_read_extent(extent,
1020 cluster_offset, index_in_cluster * 512,
1021 buf, n);
1022 if (ret) {
7fa60fa3
FZ
1023 return ret;
1024 }
ea2384d3
FB
1025 }
1026 nb_sectors -= n;
1027 sector_num += n;
1028 buf += n * 512;
1029 }
1030 return 0;
1031}
1032
2914caa0
PB
1033static coroutine_fn int vmdk_co_read(BlockDriverState *bs, int64_t sector_num,
1034 uint8_t *buf, int nb_sectors)
1035{
1036 int ret;
1037 BDRVVmdkState *s = bs->opaque;
1038 qemu_co_mutex_lock(&s->lock);
1039 ret = vmdk_read(bs, sector_num, buf, nb_sectors);
1040 qemu_co_mutex_unlock(&s->lock);
1041 return ret;
1042}
1043
5fafdf24 1044static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
ea2384d3
FB
1045 const uint8_t *buf, int nb_sectors)
1046{
ff1afc72 1047 BDRVVmdkState *s = bs->opaque;
b3976d3c 1048 VmdkExtent *extent = NULL;
91b85bd3 1049 int n, ret;
b3976d3c 1050 int64_t index_in_cluster;
ff1afc72 1051 uint64_t cluster_offset;
b3976d3c 1052 VmdkMetaData m_data;
ff1afc72 1053
630530a6
TS
1054 if (sector_num > bs->total_sectors) {
1055 fprintf(stderr,
92868412
JM
1056 "(VMDK) Wrong offset: sector_num=0x%" PRIx64
1057 " total_sectors=0x%" PRIx64 "\n",
630530a6 1058 sector_num, bs->total_sectors);
7fa60fa3 1059 return -EIO;
630530a6
TS
1060 }
1061
ff1afc72 1062 while (nb_sectors > 0) {
b3976d3c
FZ
1063 extent = find_extent(s, sector_num, extent);
1064 if (!extent) {
1065 return -EIO;
1066 }
91b85bd3 1067 ret = get_cluster_offset(
b3976d3c
FZ
1068 bs,
1069 extent,
1070 &m_data,
2b2c8c5d 1071 sector_num << 9, !extent->compressed,
91b85bd3 1072 &cluster_offset);
2b2c8c5d
FZ
1073 if (extent->compressed) {
1074 if (ret == 0) {
1075 /* Refuse write to allocated cluster for streamOptimized */
1076 fprintf(stderr,
1077 "VMDK: can't write to allocated cluster"
1078 " for streamOptimized\n");
1079 return -EIO;
1080 } else {
1081 /* allocate */
1082 ret = get_cluster_offset(
1083 bs,
1084 extent,
1085 &m_data,
1086 sector_num << 9, 1,
1087 &cluster_offset);
1088 }
1089 }
91b85bd3
FZ
1090 if (ret) {
1091 return -EINVAL;
b3976d3c
FZ
1092 }
1093 index_in_cluster = sector_num % extent->cluster_sectors;
1094 n = extent->cluster_sectors - index_in_cluster;
1095 if (n > nb_sectors) {
1096 n = nb_sectors;
1097 }
630530a6 1098
dd3f6ee2
FZ
1099 ret = vmdk_write_extent(extent,
1100 cluster_offset, index_in_cluster * 512,
1101 buf, n, sector_num);
1102 if (ret) {
7fa60fa3 1103 return ret;
b3976d3c 1104 }
630530a6
TS
1105 if (m_data.valid) {
1106 /* update L2 tables */
b3976d3c 1107 if (vmdk_L2update(extent, &m_data) == -1) {
7fa60fa3 1108 return -EIO;
b3976d3c 1109 }
630530a6 1110 }
ff1afc72
FB
1111 nb_sectors -= n;
1112 sector_num += n;
1113 buf += n * 512;
5f4da8c0 1114
ae261c86
FZ
1115 /* update CID on the first write every time the virtual disk is
1116 * opened */
69b4d86d 1117 if (!s->cid_updated) {
99f1835d
KW
1118 ret = vmdk_write_cid(bs, time(NULL));
1119 if (ret < 0) {
1120 return ret;
1121 }
69b4d86d 1122 s->cid_updated = true;
5f4da8c0 1123 }
ff1afc72
FB
1124 }
1125 return 0;
ea2384d3
FB
1126}
1127
e183ef75
PB
1128static coroutine_fn int vmdk_co_write(BlockDriverState *bs, int64_t sector_num,
1129 const uint8_t *buf, int nb_sectors)
1130{
1131 int ret;
1132 BDRVVmdkState *s = bs->opaque;
1133 qemu_co_mutex_lock(&s->lock);
1134 ret = vmdk_write(bs, sector_num, buf, nb_sectors);
1135 qemu_co_mutex_unlock(&s->lock);
1136 return ret;
1137}
1138
f66fd6c3 1139
6c031aac
FZ
1140static int vmdk_create_extent(const char *filename, int64_t filesize,
1141 bool flat, bool compress)
8979b227 1142{
f66fd6c3
FZ
1143 int ret, i;
1144 int fd = 0;
8979b227
FB
1145 VMDK4Header header;
1146 uint32_t tmp, magic, grains, gd_size, gt_size, gt_count;
0e7e1989 1147
f66fd6c3
FZ
1148 fd = open(
1149 filename,
1150 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
1151 0644);
1152 if (fd < 0) {
1153 return -errno;
0e7e1989 1154 }
f66fd6c3
FZ
1155 if (flat) {
1156 ret = ftruncate(fd, filesize);
1157 if (ret < 0) {
1158 ret = -errno;
1159 }
1160 goto exit;
5f4da8c0 1161 }
8979b227
FB
1162 magic = cpu_to_be32(VMDK4_MAGIC);
1163 memset(&header, 0, sizeof(header));
16372ff0 1164 header.version = 1;
6c031aac
FZ
1165 header.flags =
1166 3 | (compress ? VMDK4_FLAG_COMPRESS | VMDK4_FLAG_MARKER : 0);
1167 header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
f66fd6c3 1168 header.capacity = filesize / 512;
16372ff0
AG
1169 header.granularity = 128;
1170 header.num_gtes_per_gte = 512;
8979b227 1171
f66fd6c3 1172 grains = (filesize / 512 + header.granularity - 1) / header.granularity;
8979b227 1173 gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
f66fd6c3
FZ
1174 gt_count =
1175 (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
8979b227
FB
1176 gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
1177
1178 header.desc_offset = 1;
1179 header.desc_size = 20;
1180 header.rgd_offset = header.desc_offset + header.desc_size;
1181 header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
1182 header.grain_offset =
1183 ((header.gd_offset + gd_size + (gt_size * gt_count) +
1184 header.granularity - 1) / header.granularity) *
1185 header.granularity;
16372ff0
AG
1186 /* swap endianness for all header fields */
1187 header.version = cpu_to_le32(header.version);
1188 header.flags = cpu_to_le32(header.flags);
1189 header.capacity = cpu_to_le64(header.capacity);
1190 header.granularity = cpu_to_le64(header.granularity);
1191 header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte);
8979b227
FB
1192 header.desc_offset = cpu_to_le64(header.desc_offset);
1193 header.desc_size = cpu_to_le64(header.desc_size);
1194 header.rgd_offset = cpu_to_le64(header.rgd_offset);
1195 header.gd_offset = cpu_to_le64(header.gd_offset);
1196 header.grain_offset = cpu_to_le64(header.grain_offset);
6c031aac 1197 header.compressAlgorithm = cpu_to_le16(header.compressAlgorithm);
8979b227
FB
1198
1199 header.check_bytes[0] = 0xa;
1200 header.check_bytes[1] = 0x20;
1201 header.check_bytes[2] = 0xd;
1202 header.check_bytes[3] = 0xa;
3b46e624
TS
1203
1204 /* write all the data */
1640366c
KS
1205 ret = qemu_write_full(fd, &magic, sizeof(magic));
1206 if (ret != sizeof(magic)) {
b781cce5 1207 ret = -errno;
1640366c
KS
1208 goto exit;
1209 }
1210 ret = qemu_write_full(fd, &header, sizeof(header));
1211 if (ret != sizeof(header)) {
b781cce5 1212 ret = -errno;
1640366c
KS
1213 goto exit;
1214 }
8979b227 1215
16372ff0 1216 ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9);
1640366c 1217 if (ret < 0) {
b781cce5 1218 ret = -errno;
1640366c
KS
1219 goto exit;
1220 }
8979b227
FB
1221
1222 /* write grain directory */
1223 lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
16372ff0 1224 for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size;
1640366c
KS
1225 i < gt_count; i++, tmp += gt_size) {
1226 ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1227 if (ret != sizeof(tmp)) {
b781cce5 1228 ret = -errno;
1640366c
KS
1229 goto exit;
1230 }
1231 }
3b46e624 1232
8979b227
FB
1233 /* write backup grain directory */
1234 lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
16372ff0 1235 for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size;
1640366c
KS
1236 i < gt_count; i++, tmp += gt_size) {
1237 ret = qemu_write_full(fd, &tmp, sizeof(tmp));
1238 if (ret != sizeof(tmp)) {
b781cce5 1239 ret = -errno;
1640366c
KS
1240 goto exit;
1241 }
1242 }
8979b227 1243
f66fd6c3
FZ
1244 ret = 0;
1245 exit:
1246 close(fd);
1247 return ret;
1248}
1249
1250static int filename_decompose(const char *filename, char *path, char *prefix,
1251 char *postfix, size_t buf_len)
1252{
1253 const char *p, *q;
1254
1255 if (filename == NULL || !strlen(filename)) {
1256 fprintf(stderr, "Vmdk: no filename provided.\n");
1257 return -1;
1258 }
1259 p = strrchr(filename, '/');
1260 if (p == NULL) {
1261 p = strrchr(filename, '\\');
1262 }
1263 if (p == NULL) {
1264 p = strrchr(filename, ':');
1265 }
1266 if (p != NULL) {
1267 p++;
1268 if (p - filename >= buf_len) {
1269 return -1;
1270 }
1271 pstrcpy(path, p - filename + 1, filename);
1272 } else {
1273 p = filename;
1274 path[0] = '\0';
1275 }
1276 q = strrchr(p, '.');
1277 if (q == NULL) {
1278 pstrcpy(prefix, buf_len, p);
1279 postfix[0] = '\0';
1280 } else {
1281 if (q - p >= buf_len) {
1282 return -1;
1283 }
1284 pstrcpy(prefix, q - p + 1, p);
1285 pstrcpy(postfix, buf_len, q);
1286 }
1287 return 0;
1288}
1289
1290static int relative_path(char *dest, int dest_size,
1291 const char *base, const char *target)
1292{
1293 int i = 0;
1294 int n = 0;
1295 const char *p, *q;
1296#ifdef _WIN32
1297 const char *sep = "\\";
1298#else
1299 const char *sep = "/";
1300#endif
1301
1302 if (!(dest && base && target)) {
1303 return -1;
1304 }
1305 if (path_is_absolute(target)) {
1306 dest[dest_size - 1] = '\0';
1307 strncpy(dest, target, dest_size - 1);
1308 return 0;
1309 }
1310 while (base[i] == target[i]) {
1311 i++;
1312 }
1313 p = &base[i];
1314 q = &target[i];
1315 while (*p) {
1316 if (*p == *sep) {
1317 n++;
1318 }
1319 p++;
1320 }
1321 dest[0] = '\0';
1322 for (; n; n--) {
1323 pstrcat(dest, dest_size, "..");
1324 pstrcat(dest, dest_size, sep);
1325 }
1326 pstrcat(dest, dest_size, q);
1327 return 0;
1328}
1329
1330static int vmdk_create(const char *filename, QEMUOptionParameter *options)
1331{
1332 int fd, idx = 0;
1333 char desc[BUF_SIZE];
1334 int64_t total_size = 0, filesize;
1335 const char *backing_file = NULL;
1336 const char *fmt = NULL;
1337 int flags = 0;
1338 int ret = 0;
6c031aac 1339 bool flat, split, compress;
f66fd6c3
FZ
1340 char ext_desc_lines[BUF_SIZE] = "";
1341 char path[PATH_MAX], prefix[PATH_MAX], postfix[PATH_MAX];
1342 const int64_t split_size = 0x80000000; /* VMDK has constant split size */
1343 const char *desc_extent_line;
1344 char parent_desc_line[BUF_SIZE] = "";
1345 uint32_t parent_cid = 0xffffffff;
1346 const char desc_template[] =
1347 "# Disk DescriptorFile\n"
1348 "version=1\n"
1349 "CID=%x\n"
1350 "parentCID=%x\n"
1351 "createType=\"%s\"\n"
1352 "%s"
1353 "\n"
1354 "# Extent description\n"
1355 "%s"
1356 "\n"
1357 "# The Disk Data Base\n"
1358 "#DDB\n"
1359 "\n"
1360 "ddb.virtualHWVersion = \"%d\"\n"
1361 "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
1362 "ddb.geometry.heads = \"16\"\n"
1363 "ddb.geometry.sectors = \"63\"\n"
1364 "ddb.adapterType = \"ide\"\n";
1365
1366 if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) {
1367 return -EINVAL;
1368 }
1369 /* Read out options */
1370 while (options && options->name) {
1371 if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
1372 total_size = options->value.n;
1373 } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
1374 backing_file = options->value.s;
1375 } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
1376 flags |= options->value.n ? BLOCK_FLAG_COMPAT6 : 0;
1377 } else if (!strcmp(options->name, BLOCK_OPT_SUBFMT)) {
1378 fmt = options->value.s;
1379 }
1380 options++;
1381 }
1382 if (!fmt) {
1383 /* Default format to monolithicSparse */
1384 fmt = "monolithicSparse";
1385 } else if (strcmp(fmt, "monolithicFlat") &&
1386 strcmp(fmt, "monolithicSparse") &&
1387 strcmp(fmt, "twoGbMaxExtentSparse") &&
6c031aac
FZ
1388 strcmp(fmt, "twoGbMaxExtentFlat") &&
1389 strcmp(fmt, "streamOptimized")) {
f66fd6c3
FZ
1390 fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt);
1391 return -EINVAL;
1392 }
1393 split = !(strcmp(fmt, "twoGbMaxExtentFlat") &&
1394 strcmp(fmt, "twoGbMaxExtentSparse"));
1395 flat = !(strcmp(fmt, "monolithicFlat") &&
1396 strcmp(fmt, "twoGbMaxExtentFlat"));
6c031aac 1397 compress = !strcmp(fmt, "streamOptimized");
f66fd6c3
FZ
1398 if (flat) {
1399 desc_extent_line = "RW %lld FLAT \"%s\" 0\n";
1400 } else {
1401 desc_extent_line = "RW %lld SPARSE \"%s\"\n";
1402 }
1403 if (flat && backing_file) {
1404 /* not supporting backing file for flat image */
1405 return -ENOTSUP;
1406 }
1407 if (backing_file) {
1408 char parent_filename[PATH_MAX];
1409 BlockDriverState *bs = bdrv_new("");
1410 ret = bdrv_open(bs, backing_file, 0, NULL);
1411 if (ret != 0) {
1412 bdrv_delete(bs);
1413 return ret;
1414 }
1415 if (strcmp(bs->drv->format_name, "vmdk")) {
1416 bdrv_delete(bs);
1417 return -EINVAL;
1418 }
1419 filesize = bdrv_getlength(bs);
1420 parent_cid = vmdk_read_cid(bs, 0);
1421 bdrv_delete(bs);
1422 relative_path(parent_filename, sizeof(parent_filename),
1423 filename, backing_file);
1424 snprintf(parent_desc_line, sizeof(parent_desc_line),
1425 "parentFileNameHint=\"%s\"", parent_filename);
1426 }
1427
1428 /* Create extents */
1429 filesize = total_size;
1430 while (filesize > 0) {
1431 char desc_line[BUF_SIZE];
1432 char ext_filename[PATH_MAX];
1433 char desc_filename[PATH_MAX];
1434 int64_t size = filesize;
1435
1436 if (split && size > split_size) {
1437 size = split_size;
1438 }
1439 if (split) {
1440 snprintf(desc_filename, sizeof(desc_filename), "%s-%c%03d%s",
1441 prefix, flat ? 'f' : 's', ++idx, postfix);
1442 } else if (flat) {
1443 snprintf(desc_filename, sizeof(desc_filename), "%s-flat%s",
1444 prefix, postfix);
1445 } else {
1446 snprintf(desc_filename, sizeof(desc_filename), "%s%s",
1447 prefix, postfix);
1448 }
1449 snprintf(ext_filename, sizeof(ext_filename), "%s%s",
1450 path, desc_filename);
1451
6c031aac 1452 if (vmdk_create_extent(ext_filename, size, flat, compress)) {
f66fd6c3
FZ
1453 return -EINVAL;
1454 }
1455 filesize -= size;
1456
1457 /* Format description line */
1458 snprintf(desc_line, sizeof(desc_line),
1459 desc_extent_line, size / 512, desc_filename);
1460 pstrcat(ext_desc_lines, sizeof(ext_desc_lines), desc_line);
1461 }
1462 /* generate descriptor file */
1463 snprintf(desc, sizeof(desc), desc_template,
1464 (unsigned int)time(NULL),
1465 parent_cid,
1466 fmt,
1467 parent_desc_line,
1468 ext_desc_lines,
1469 (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
1470 total_size / (int64_t)(63 * 16 * 512));
1471 if (split || flat) {
1472 fd = open(
1473 filename,
1474 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
1475 0644);
1476 } else {
1477 fd = open(
1478 filename,
1479 O_WRONLY | O_BINARY | O_LARGEFILE,
1480 0644);
1481 }
1482 if (fd < 0) {
1483 return -errno;
1484 }
1485 /* the descriptor offset = 0x200 */
1486 if (!split && !flat && 0x200 != lseek(fd, 0x200, SEEK_SET)) {
1487 ret = -errno;
1488 goto exit;
1489 }
1640366c
KS
1490 ret = qemu_write_full(fd, desc, strlen(desc));
1491 if (ret != strlen(desc)) {
b781cce5 1492 ret = -errno;
1640366c
KS
1493 goto exit;
1494 }
1640366c
KS
1495 ret = 0;
1496exit:
8979b227 1497 close(fd);
1640366c 1498 return ret;
8979b227
FB
1499}
1500
e2731add 1501static void vmdk_close(BlockDriverState *bs)
ea2384d3 1502{
b3976d3c 1503 vmdk_free_extents(bs);
ea2384d3
FB
1504}
1505
8b94ff85 1506static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
7a6cba61 1507{
333c574d
FZ
1508 int i, ret, err;
1509 BDRVVmdkState *s = bs->opaque;
1510
8b94ff85 1511 ret = bdrv_co_flush(bs->file);
333c574d 1512 for (i = 0; i < s->num_extents; i++) {
8b94ff85 1513 err = bdrv_co_flush(s->extents[i].file);
333c574d
FZ
1514 if (err < 0) {
1515 ret = err;
1516 }
1517 }
1518 return ret;
7a6cba61
PB
1519}
1520
4a1d5e1f
FZ
1521static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
1522{
1523 int i;
1524 int64_t ret = 0;
1525 int64_t r;
1526 BDRVVmdkState *s = bs->opaque;
1527
1528 ret = bdrv_get_allocated_file_size(bs->file);
1529 if (ret < 0) {
1530 return ret;
1531 }
1532 for (i = 0; i < s->num_extents; i++) {
1533 if (s->extents[i].file == bs->file) {
1534 continue;
1535 }
1536 r = bdrv_get_allocated_file_size(s->extents[i].file);
1537 if (r < 0) {
1538 return r;
1539 }
1540 ret += r;
1541 }
1542 return ret;
1543}
0e7e1989
KW
1544
1545static QEMUOptionParameter vmdk_create_options[] = {
db08adf5
KW
1546 {
1547 .name = BLOCK_OPT_SIZE,
1548 .type = OPT_SIZE,
1549 .help = "Virtual disk size"
1550 },
1551 {
1552 .name = BLOCK_OPT_BACKING_FILE,
1553 .type = OPT_STRING,
1554 .help = "File name of a base image"
1555 },
1556 {
1557 .name = BLOCK_OPT_COMPAT6,
1558 .type = OPT_FLAG,
1559 .help = "VMDK version 6 image"
1560 },
f66fd6c3
FZ
1561 {
1562 .name = BLOCK_OPT_SUBFMT,
1563 .type = OPT_STRING,
1564 .help =
1565 "VMDK flat extent format, can be one of "
6c031aac 1566 "{monolithicSparse (default) | monolithicFlat | twoGbMaxExtentSparse | twoGbMaxExtentFlat | streamOptimized} "
f66fd6c3 1567 },
0e7e1989
KW
1568 { NULL }
1569};
1570
5efa9d5a 1571static BlockDriver bdrv_vmdk = {
ae261c86
FZ
1572 .format_name = "vmdk",
1573 .instance_size = sizeof(BDRVVmdkState),
1574 .bdrv_probe = vmdk_probe,
6511ef77 1575 .bdrv_open = vmdk_open,
2914caa0 1576 .bdrv_read = vmdk_co_read,
e183ef75 1577 .bdrv_write = vmdk_co_write,
ae261c86
FZ
1578 .bdrv_close = vmdk_close,
1579 .bdrv_create = vmdk_create,
8b94ff85 1580 .bdrv_co_flush = vmdk_co_flush,
ae261c86 1581 .bdrv_is_allocated = vmdk_is_allocated,
4a1d5e1f 1582 .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
0e7e1989
KW
1583
1584 .create_options = vmdk_create_options,
ea2384d3 1585};
5efa9d5a
AL
1586
1587static void bdrv_vmdk_init(void)
1588{
1589 bdrv_register(&bdrv_vmdk);
1590}
1591
1592block_init(bdrv_vmdk_init);