vhddtool.cpp revision 9250c46f9b6077b7b40f1d2af868329031d39390
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen * VBox HDD container maintenance/conversion utility
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * Copyright (C) 2006 InnoTek Systemberatung GmbH
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * This file is part of VirtualBox Open Source Edition (OSE), as
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * available from http://www.virtualbox.org. This file is free software;
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * you can redistribute it and/or modify it under the terms of the GNU
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * General Public License as published by the Free Software Foundation,
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * distribution. VirtualBox OSE is distributed in the hope that it will
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * be useful, but WITHOUT ANY WARRANTY of any kind.
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * If you received this file as part of a commercial VirtualBox
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek * distribution, then only the terms of your commercial VirtualBox
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * license agreement apply instead of the previous paragraph.
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek/*******************************************************************************
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek*******************************************************************************/
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic void ascii2upper(char *psz)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Usage: vditool <Command> [Params]\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek "Commands and params:\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " NEW Filename Mbytes - create new image;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " DD Filename DDFilename - create new image from DD format image;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " CONVERT Filename - convert VDI image from old format;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " DUMP Filename - debug dump;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " RESETGEO Filename - reset geometry information;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " COPY FromImage ToImage - make image copy;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " COPYDD FromImage DDFilename - make a DD copy of the image;\n" \
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek " SHRINK Filename - optimize (reduce) VDI image size.\n");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int SyntaxError(const char *pszMsg)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Syntax error: %s\n\n", pszMsg);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * Prints a done message indicating success or failure.
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * @param rc Status code.
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("The operation completed successfully!\n");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("The operation completed successfully! (rc=%Rrc)\n", rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("FAILURE: %Rrf (%Rrc)\n", rc, rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int NewImage(const char *pszFilename, uint32_t cMBs)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Creating VDI: file=\"%s\" size=%u MB...\n",
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek (uint64_t)cMBs * (uint64_t)(1024 * 1024),
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek "Newly created test image", NULL, NULL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int ConvertDDImage(const char *pszFilename, const char *pszDDFilename)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek /* open raw image file. */
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek int rc = RTFileOpen(&File, pszDDFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("File=\"%s\" open error: %Rrf\n", pszDDFilename, rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek /* get image size. */
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = RTFileGetSize(File, &cbFile);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering RTPrintf("Creating fixed image with size %u Bytes...\n", (unsigned)cbFile);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek "Converted from DD test image", NULL, NULL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek PVDIDISK pVdi = VDIDiskCreate();
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_NORMAL);
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek /* alloc work buffer. */
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering void *pvBuf = RTMemAlloc(VDIDiskGetBufferSize(pVdi));
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering rc = RTFileRead(File, pvBuf, VDIDiskGetBufferSize(pVdi), &cbRead);
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering rc = VDIDiskWrite(pVdi, off, pvBuf, cbRead);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering /* delete image on error */
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poetteringstatic DECLCALLBACK(int) ProcessCallback(PVM pVM, unsigned uPercent, void *pvUser)
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardtstatic int ConvertOldImage(const char *pszFilename)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("Converting VDI image file=\"%s\" to a new format...\n"
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering "progress: 0%%",
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering int rc = VDIConvertImage(pszFilename, ProcessCallback, &uPercent);
38051578360c211e88ef4082ce5746adb52a500eLennart Poetteringstatic int DumpImage(const char *pszFilename)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("Dumping VDI image file=\"%s\" into the log file...\n", pszFilename);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering int rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_READONLY);
38051578360c211e88ef4082ce5746adb52a500eLennart Poetteringstatic int ResetImageGeometry(const char *pszFilename)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("Resetting geometry info of VDI image file=\"%s\"\n", pszFilename);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering int rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_NORMAL);
a44b10818a531787c359f6446d218a975503f032Lennart Poettering rc = VDIDiskSetTranslation(pVdi, PDMBIOSTRANSLATION_AUTO);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardtstatic int CopyImage(const char *pszDstFile, const char *pszSrcFile)
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt RTPrintf("Copying VDI image file=\"%s\" to image file=\"%s\"...\n"
a44b10818a531787c359f6446d218a975503f032Lennart Poettering "progress: 0%%",
a44b10818a531787c359f6446d218a975503f032Lennart Poettering int rc = VDICopyImage(pszDstFile, pszSrcFile, NULL, ProcessCallback, &uPrecent);
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poetteringstatic int CopyToDD(const char *pszDstFile, const char *pszSrcFile)
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering RTPrintf("Copying VDI image file=\"%s\" to DD file=\"%s\"...\n",
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt int rc = VDIDiskOpenImage(pVdi, pszSrcFile, VDI_OPEN_FLAGS_NORMAL);
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering rc = RTFileOpen(&FileDst, pszDstFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE);
4f50d2efbac87aba0505b9f998bf3e4bde64c214Zbigniew Jędrzejewski-Szmek uint64_t cbSrc = VDIDiskGetSize(pVdi);
4f50d2efbac87aba0505b9f998bf3e4bde64c214Zbigniew Jędrzejewski-Szmek const unsigned cbBuf = VDIDiskGetBlockSize(pVdi); /* or perhaps VDIDiskGetBufferSize(pVdi)? */
88ae7333ee052e64607ae6678fe0e84991fe3482Zbigniew Jędrzejewski-Szmek void *pvBuf = RTMemAlloc(cbBuf);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = VDIDiskRead(pVdi, off, pvBuf, cbBuf);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = RTFileWrite(FileDst, pvBuf, cbBuf, NULL);
d9130355ee0530117518ff24354bdd552d030238Lennart Poetteringstatic int ShrinkImage(const char *pszFilename)
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering RTPrintf("Shrinking VDI image file=\"%s\"...\n"
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering "progress: 0%%",
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering int rc = VDIShrinkImage(pszFilename, ProcessCallback, &uPrecent);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering RTPrintf("vditool Copyright (c) 2004-2005 InnoTek Systemberatung GmbH.\n\n");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * Do cmd line parsing.
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek NULL, ELEMENTS(s_apszGroups), s_apszGroups,
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTLogRelSetDefaultInstance(pLogger);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return SyntaxError("Invalid argument count!");
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering rc = RTStrToUInt32Ex(argv[3], NULL, 10, &cMBs);
4f44c03eaa7bc05240ef619d07766f61eda3d5b7Lennart Poettering RTPrintf("error: Disk size %RU32 (MB) is not within the range %u-%u!\n",
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return SyntaxError("Invalid argument count!");
d55192add75584f55932ad463ee6b4cc30370c63Lennart Poettering return SyntaxError("Invalid argument count!");
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt return SyntaxError("Invalid argument count!");
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return SyntaxError("Invalid argument count!");
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return SyntaxError("Invalid argument count!");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return SyntaxError("Invalid argument count!");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = CopyToDD(argv[3], argv[2]);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek else if (strcmp(szCmd, "SHRINK") == 0)
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering return SyntaxError("Invalid argument count!");