Commandline tool to write a vmware vmdk header to a haiku image file (space for the header has to be reserved)
Tested with VMware Player 1.0.3 on linux and works. Can also be used to create a haiku.vmdk file from an existing haiku.image file: rm haiku.vmdk generated/objects/linux/x86/release/tools/vmdkheader/vmdkheader -h 64k -i100M haiku.vmdk cat generated/haiku.image >>haiku.vmdk git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19980 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -68,5 +68,6 @@ SubInclude HAIKU_TOP src tools remote_disk_server ;
|
|||||||
SubInclude HAIKU_TOP src tools resattr ;
|
SubInclude HAIKU_TOP src tools resattr ;
|
||||||
SubInclude HAIKU_TOP src tools rman ;
|
SubInclude HAIKU_TOP src tools rman ;
|
||||||
SubInclude HAIKU_TOP src tools translation ;
|
SubInclude HAIKU_TOP src tools translation ;
|
||||||
|
SubInclude HAIKU_TOP src tools vmdkheader ;
|
||||||
SubInclude HAIKU_TOP src tools unflatten ;
|
SubInclude HAIKU_TOP src tools unflatten ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
SubDir HAIKU_TOP src tools vmdkheader ;
|
||||||
|
|
||||||
|
UsePrivateHeaders kernel ;
|
||||||
|
|
||||||
|
BuildPlatformMain <build>vmdkheader
|
||||||
|
: vmdkheader.cpp
|
||||||
|
: $(HOST_LIBSUPC++)
|
||||||
|
;
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Marcus Overhagen. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "vmdkheader.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage()
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("vmdkheader\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("usage: vmdkheader -i <imagesize> -h <headersize> [-f] <file>\n");
|
||||||
|
printf(" -i, --imagesize size of raw partition image file\n");
|
||||||
|
printf(" -h, --headersize size of the vmdk header to write\n");
|
||||||
|
printf(" -f, --file the raw partition image file\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
uint64 headersize = 0;
|
||||||
|
uint64 imagesize = 0;
|
||||||
|
const char *file = NULL;
|
||||||
|
|
||||||
|
if (sizeof(SparseExtentHeader) != 512) {
|
||||||
|
fprintf(stderr, "compilation error: struct size is %u byte\n", sizeof(SparseExtentHeader));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int c;
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{"headersize", required_argument, 0, 'h'},
|
||||||
|
{"imagesize", required_argument, 0, 'i'},
|
||||||
|
{"file", required_argument, 0, 'f'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
opterr = 0; /* don't print errors */
|
||||||
|
c = getopt_long(argc, argv, "h:i:f:", long_options, NULL);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
headersize = strtoull(optarg, NULL, 10);
|
||||||
|
if (strchr(optarg, 'G') || strchr(optarg, 'g'))
|
||||||
|
headersize *= 1024 * 1024 * 1024;
|
||||||
|
else if (strchr(optarg, 'M') || strchr(optarg, 'm'))
|
||||||
|
headersize *= 1024 * 1024;
|
||||||
|
else if (strchr(optarg, 'K') || strchr(optarg, 'k'))
|
||||||
|
headersize *= 1024;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
imagesize = strtoull(optarg, NULL, 10);
|
||||||
|
if (strchr(optarg, 'G') || strchr(optarg, 'g'))
|
||||||
|
imagesize *= 1024 * 1024 * 1024;
|
||||||
|
else if (strchr(optarg, 'M') || strchr(optarg, 'm'))
|
||||||
|
imagesize *= 1024 * 1024;
|
||||||
|
else if (strchr(optarg, 'K') || strchr(optarg, 'k'))
|
||||||
|
imagesize *= 1024;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
file = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file == NULL && optind == argc - 1)
|
||||||
|
file = argv[optind];
|
||||||
|
|
||||||
|
if (!headersize || !imagesize || !file)
|
||||||
|
print_usage();
|
||||||
|
|
||||||
|
char desc[512];
|
||||||
|
SparseExtentHeader header;
|
||||||
|
|
||||||
|
if (headersize < sizeof(desc) + sizeof(header)) {
|
||||||
|
fprintf(stderr, "Error: header size must be at least %u byte\n", sizeof(desc) + sizeof(header));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arbitrary 1 GB limitation
|
||||||
|
if (headersize > 0x40000000u) {
|
||||||
|
fprintf(stderr, "Error: header size too large\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arbitrary 2 GB limitation
|
||||||
|
if (imagesize > 0x80000000u) {
|
||||||
|
fprintf(stderr, "Error: image size too large\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = strrchr(file, '/');
|
||||||
|
name = name ? (name + 1) : file;
|
||||||
|
|
||||||
|
// printf("headersize %llu\n", headersize);
|
||||||
|
// printf("imagesize %llu\n", imagesize);
|
||||||
|
// printf("file %s\n", file);
|
||||||
|
|
||||||
|
uint64 sectors;
|
||||||
|
uint64 heads;
|
||||||
|
uint64 cylinders;
|
||||||
|
|
||||||
|
// TODO: fixme!
|
||||||
|
sectors = 63;
|
||||||
|
heads = 16;
|
||||||
|
cylinders = imagesize / (sectors * heads * 512);
|
||||||
|
while (cylinders > 1024) {
|
||||||
|
cylinders /= 2;
|
||||||
|
heads *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(desc, 0, sizeof(desc));
|
||||||
|
memset(&header, 0, sizeof(header));
|
||||||
|
|
||||||
|
header.magicNumber = SPARSE_MAGICNUMBER;
|
||||||
|
header.version = 1;
|
||||||
|
header.flags = 1;
|
||||||
|
header.capacity = 0;
|
||||||
|
header.grainSize = 16;
|
||||||
|
header.descriptorOffset = 1;
|
||||||
|
header.descriptorSize = sizeof(desc) / 512;
|
||||||
|
header.numGTEsPerGT = 512;
|
||||||
|
header.rgdOffset = 0;
|
||||||
|
header.gdOffset = 0;
|
||||||
|
header.overHead = headersize / 512;
|
||||||
|
header.uncleanShutdown = 0;
|
||||||
|
header.singleEndLineChar = '\n';
|
||||||
|
header.nonEndLineChar = ' ';
|
||||||
|
header.doubleEndLineChar1 = '\r';
|
||||||
|
header.doubleEndLineChar2 = '\n';
|
||||||
|
|
||||||
|
strcat(desc,
|
||||||
|
"# Disk Descriptor File\n"
|
||||||
|
"version=1\n"
|
||||||
|
"CID=fffffffe\n"
|
||||||
|
"parentCID=ffffffff\n"
|
||||||
|
"createType=\"monolithicFlat\"\n");
|
||||||
|
sprintf(desc + strlen(desc),
|
||||||
|
"# Extent Description\n"
|
||||||
|
"RW %llu FLAT \"%s\" %llu\n",
|
||||||
|
imagesize / 512, name, headersize / 512);
|
||||||
|
sprintf(desc + strlen(desc),
|
||||||
|
"# Disk Data Base\n"
|
||||||
|
"ddb.toolsVersion = \"0\"\n"
|
||||||
|
"ddb.virtualHWVersion = \"3\"\n"
|
||||||
|
"ddb.geometry.sectors = \"%llu\"\n"
|
||||||
|
"ddb.adapterType = \"ide\"\n"
|
||||||
|
"ddb.geometry.heads = \"%llu\"\n"
|
||||||
|
"ddb.geometry.cylinders = \"%llu\"\n",
|
||||||
|
sectors, heads, cylinders);
|
||||||
|
|
||||||
|
int fd = open(file, O_RDWR | O_CREAT, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "Error: couldn't open file %s (%s)\n", file, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (sizeof(header) != write(fd, &header, sizeof(header)))
|
||||||
|
goto write_err;
|
||||||
|
|
||||||
|
if (sizeof(desc) != write(fd, desc, sizeof(desc)))
|
||||||
|
goto write_err;
|
||||||
|
|
||||||
|
headersize--;
|
||||||
|
if (headersize != (uint64)lseek(fd, headersize, SEEK_SET))
|
||||||
|
goto write_err;
|
||||||
|
|
||||||
|
if (1 != write(fd, "", 1))
|
||||||
|
goto write_err;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
write_err:
|
||||||
|
fprintf(stderr, "Error: writing file %s failed (%s)\n", file, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Marcus Overhagen. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _VMDKHEADER_H
|
||||||
|
#define _VMDKHEADER_H
|
||||||
|
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint64 SectorType;
|
||||||
|
typedef uint8 Bool;
|
||||||
|
|
||||||
|
struct SparseExtentHeader
|
||||||
|
{
|
||||||
|
uint32 magicNumber;
|
||||||
|
uint32 version;
|
||||||
|
uint32 flags;
|
||||||
|
SectorType capacity;
|
||||||
|
SectorType grainSize;
|
||||||
|
SectorType descriptorOffset;
|
||||||
|
SectorType descriptorSize;
|
||||||
|
uint32 numGTEsPerGT;
|
||||||
|
SectorType rgdOffset;
|
||||||
|
SectorType gdOffset;
|
||||||
|
SectorType overHead;
|
||||||
|
Bool uncleanShutdown;
|
||||||
|
char singleEndLineChar;
|
||||||
|
char nonEndLineChar;
|
||||||
|
char doubleEndLineChar1;
|
||||||
|
char doubleEndLineChar2;
|
||||||
|
uint8 pad[435];
|
||||||
|
} __attribute__((__packed__)) ;
|
||||||
|
|
||||||
|
#define SPARSE_MAGICNUMBER 0x564d444b /* 'V' 'M' 'D' 'K' */
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user