Revision 8979b227 block-vmdk.c
b/block-vmdk.c | ||
---|---|---|
315 | 315 |
return 0; |
316 | 316 |
} |
317 | 317 |
|
318 |
static int vmdk_create(const char *filename, int64_t total_size, |
|
319 |
const char *backing_file, int flags) |
|
320 |
{ |
|
321 |
int fd, i; |
|
322 |
VMDK4Header header; |
|
323 |
uint32_t tmp, magic, grains, gd_size, gt_size, gt_count; |
|
324 |
char *desc_template = |
|
325 |
"# Disk DescriptorFile\n" |
|
326 |
"version=1\n" |
|
327 |
"CID=%x\n" |
|
328 |
"parentCID=ffffffff\n" |
|
329 |
"createType=\"monolithicSparse\"\n" |
|
330 |
"\n" |
|
331 |
"# Extent description\n" |
|
332 |
"RW %lu SPARSE \"%s\"\n" |
|
333 |
"\n" |
|
334 |
"# The Disk Data Base \n" |
|
335 |
"#DDB\n" |
|
336 |
"\n" |
|
337 |
"ddb.virtualHWVersion = \"3\"\n" |
|
338 |
"ddb.geometry.cylinders = \"%lu\"\n" |
|
339 |
"ddb.geometry.heads = \"16\"\n" |
|
340 |
"ddb.geometry.sectors = \"63\"\n" |
|
341 |
"ddb.adapterType = \"ide\"\n"; |
|
342 |
char desc[1024]; |
|
343 |
const char *real_filename, *temp_str; |
|
344 |
|
|
345 |
/* XXX: add support for backing file */ |
|
346 |
|
|
347 |
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, |
|
348 |
0644); |
|
349 |
if (fd < 0) |
|
350 |
return -1; |
|
351 |
magic = cpu_to_be32(VMDK4_MAGIC); |
|
352 |
memset(&header, 0, sizeof(header)); |
|
353 |
header.version = cpu_to_le32(1); |
|
354 |
header.flags = cpu_to_le32(3); /* ?? */ |
|
355 |
header.capacity = cpu_to_le64(total_size); |
|
356 |
header.granularity = cpu_to_le64(128); |
|
357 |
header.num_gtes_per_gte = cpu_to_le32(512); |
|
358 |
|
|
359 |
grains = (total_size + header.granularity - 1) / header.granularity; |
|
360 |
gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9; |
|
361 |
gt_count = (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte; |
|
362 |
gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9; |
|
363 |
|
|
364 |
header.desc_offset = 1; |
|
365 |
header.desc_size = 20; |
|
366 |
header.rgd_offset = header.desc_offset + header.desc_size; |
|
367 |
header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count); |
|
368 |
header.grain_offset = |
|
369 |
((header.gd_offset + gd_size + (gt_size * gt_count) + |
|
370 |
header.granularity - 1) / header.granularity) * |
|
371 |
header.granularity; |
|
372 |
|
|
373 |
header.desc_offset = cpu_to_le64(header.desc_offset); |
|
374 |
header.desc_size = cpu_to_le64(header.desc_size); |
|
375 |
header.rgd_offset = cpu_to_le64(header.rgd_offset); |
|
376 |
header.gd_offset = cpu_to_le64(header.gd_offset); |
|
377 |
header.grain_offset = cpu_to_le64(header.grain_offset); |
|
378 |
|
|
379 |
header.check_bytes[0] = 0xa; |
|
380 |
header.check_bytes[1] = 0x20; |
|
381 |
header.check_bytes[2] = 0xd; |
|
382 |
header.check_bytes[3] = 0xa; |
|
383 |
|
|
384 |
/* write all the data */ |
|
385 |
write(fd, &magic, sizeof(magic)); |
|
386 |
write(fd, &header, sizeof(header)); |
|
387 |
|
|
388 |
ftruncate(fd, header.grain_offset << 9); |
|
389 |
|
|
390 |
/* write grain directory */ |
|
391 |
lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET); |
|
392 |
for (i = 0, tmp = header.rgd_offset + gd_size; |
|
393 |
i < gt_count; i++, tmp += gt_size) |
|
394 |
write(fd, &tmp, sizeof(tmp)); |
|
395 |
|
|
396 |
/* write backup grain directory */ |
|
397 |
lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET); |
|
398 |
for (i = 0, tmp = header.gd_offset + gd_size; |
|
399 |
i < gt_count; i++, tmp += gt_size) |
|
400 |
write(fd, &tmp, sizeof(tmp)); |
|
401 |
|
|
402 |
/* compose the descriptor */ |
|
403 |
real_filename = filename; |
|
404 |
if ((temp_str = strrchr(real_filename, '\\')) != NULL) |
|
405 |
real_filename = temp_str + 1; |
|
406 |
if ((temp_str = strrchr(real_filename, '/')) != NULL) |
|
407 |
real_filename = temp_str + 1; |
|
408 |
if ((temp_str = strrchr(real_filename, ':')) != NULL) |
|
409 |
real_filename = temp_str + 1; |
|
410 |
sprintf(desc, desc_template, time(NULL), (unsigned long)total_size, |
|
411 |
real_filename, total_size / (63 * 16)); |
|
412 |
|
|
413 |
/* write the descriptor */ |
|
414 |
lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET); |
|
415 |
write(fd, desc, strlen(desc)); |
|
416 |
|
|
417 |
close(fd); |
|
418 |
return 0; |
|
419 |
} |
|
420 |
|
|
318 | 421 |
static void vmdk_close(BlockDriverState *bs) |
319 | 422 |
{ |
320 | 423 |
BDRVVmdkState *s = bs->opaque; |
... | ... | |
331 | 434 |
vmdk_read, |
332 | 435 |
vmdk_write, |
333 | 436 |
vmdk_close, |
334 |
NULL, /* no create yet */
|
|
437 |
vmdk_create,
|
|
335 | 438 |
vmdk_is_allocated, |
336 | 439 |
}; |
Also available in: Unified diff