Commit 8979b2277d92d0acd0fd3be523a7515f86f79bec

Authored by bellard
1 parent 97ccc689

VMDK disk image creation (Filip Navara)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1461 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 105 additions and 1 deletions
Changelog
... ... @@ -3,6 +3,7 @@ version 0.7.1:
3 3 - read-only Virtual FAT support (Johannes Schindelin)
4 4 - Windows 2000 install disk full hack (original idea from Vladimir
5 5 N. Oleynik)
  6 + - VMDK disk image creation (Filip Navara)
6 7  
7 8 version 0.7.0:
8 9  
... ...
block-vmdk.c
... ... @@ -315,6 +315,109 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
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,6 +434,6 @@ BlockDriver bdrv_vmdk = {
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 };
... ...