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 |
};
|