vhddtool.cpp revision 9250c46f9b6077b7b40f1d2af868329031d39390
3802a3d3d7af51ddff31943d5514382f01265770Lennart Poettering/** @file
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek *
12b42c76672a66c2d4ea7212c14f8f1b5a62b78dTom Gundersen * VBox HDD container maintenance/conversion utility
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek */
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek/*
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * Copyright (C) 2006 InnoTek Systemberatung GmbH
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek *
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 *
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.
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek */
b975b0d514321f169b3c4599a8ea92e13741b4e4Zbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek/*******************************************************************************
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek* Header Files *
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek*******************************************************************************/
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek#include <VBox/VBoxHDD.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <iprt/alloc.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <iprt/file.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <iprt/stream.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <iprt/string.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <iprt/runtime.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <VBox/err.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek#include <stdlib.h>
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic void ascii2upper(char *psz)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek{
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek for (;*psz; psz++)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (*psz >= 'a' && *psz <= 'z')
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek *psz += 'A' - 'z';
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek}
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int UsageExit()
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek{
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-Szmek return 1;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek}
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int SyntaxError(const char *pszMsg)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek{
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Syntax error: %s\n\n", pszMsg);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek UsageExit();
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return 1;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek}
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek/**
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * Prints a done message indicating success or failure.
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * @returns rc
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * @param rc Status code.
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek */
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int PrintDone(int rc)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek{
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (rc == VINF_SUCCESS)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("The operation completed successfully!\n");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek else if (VBOX_SUCCESS(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("The operation completed successfully! (rc=%Rrc)\n", rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek else
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("FAILURE: %Rrf (%Rrc)\n", rc, rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return rc;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek}
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int NewImage(const char *pszFilename, uint32_t cMBs)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek{
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Creating VDI: file=\"%s\" size=%u MB...\n",
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek pszFilename, cMBs);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering int rc = VDICreateBaseImage(pszFilename,
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek VDI_IMAGE_TYPE_NORMAL,
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek (uint64_t)cMBs * (uint64_t)(1024 * 1024),
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek "Newly created test image", NULL, NULL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return PrintDone(rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek}
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekstatic int ConvertDDImage(const char *pszFilename, const char *pszDDFilename)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek{
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering pszDDFilename, pszFilename);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek /* open raw image file. */
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTFILE File;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek int rc = RTFileOpen(&File, pszDDFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (VBOX_FAILURE(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("File=\"%s\" open error: %Rrf\n", pszDDFilename, rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return rc;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek }
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek /* get image size. */
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek uint64_t cbFile;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = RTFileGetSize(File, &cbFile);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (VBOX_SUCCESS(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering RTPrintf("Creating fixed image with size %u Bytes...\n", (unsigned)cbFile);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering rc = VDICreateBaseImage(pszFilename,
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering VDI_IMAGE_TYPE_FIXED,
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek cbFile,
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek "Converted from DD test image", NULL, NULL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek PrintDone(rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (VBOX_SUCCESS(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTPrintf("Writing data...\n");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek PVDIDISK pVdi = VDIDiskCreate();
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_NORMAL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (VBOX_SUCCESS(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek /* alloc work buffer. */
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering void *pvBuf = RTMemAlloc(VDIDiskGetBufferSize(pVdi));
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering if (pvBuf)
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering {
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering uint64_t off = 0;
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt while (off < cbFile)
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering {
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering unsigned cbRead = 0;
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering rc = RTFileRead(File, pvBuf, VDIDiskGetBufferSize(pVdi), &cbRead);
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering if (VBOX_FAILURE(rc) || !cbRead)
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering break;
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering rc = VDIDiskWrite(pVdi, off, pvBuf, cbRead);
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering if (VBOX_FAILURE(rc))
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering break;
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering off += cbRead;
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt }
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering RTMemFree(pvBuf);
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering }
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering else
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering rc = VERR_NO_MEMORY;
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering VDIDiskCloseImage(pVdi);
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering }
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering if (VBOX_FAILURE(rc))
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt {
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering /* delete image on error */
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering VDIDeleteImage(pszFilename);
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering }
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering PrintDone(rc);
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering }
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering }
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering RTFileClose(File);
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return rc;
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering}
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poetteringstatic DECLCALLBACK(int) ProcessCallback(PVM pVM, unsigned uPercent, void *pvUser)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering{
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering unsigned *pPercent = (unsigned *)pvUser;
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering if (*pPercent != uPercent)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering {
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering *pPercent = uPercent;
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf(".");
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt if ((uPercent % 10) == 0 && uPercent)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("%d%%", uPercent);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTStrmFlush(g_pStdOut);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering }
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering return VINF_SUCCESS;
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering}
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardtstatic int ConvertOldImage(const char *pszFilename)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering{
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("Converting VDI image file=\"%s\" to a new format...\n"
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering "progress: 0%%",
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering pszFilename);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering unsigned uPercent = 0;
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering int rc = VDIConvertImage(pszFilename, ProcessCallback, &uPercent);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("\n");
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering return PrintDone(rc);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering}
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt
38051578360c211e88ef4082ce5746adb52a500eLennart Poetteringstatic int DumpImage(const char *pszFilename)
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt{
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("Dumping VDI image file=\"%s\" into the log file...\n", pszFilename);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering PVDIDISK pVdi = VDIDiskCreate();
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering int rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_READONLY);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering if (VBOX_SUCCESS(rc))
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering {
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering VDIDiskDumpImages(pVdi);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering VDIDiskCloseAllImages(pVdi);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering }
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering return PrintDone(rc);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt}
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering
38051578360c211e88ef4082ce5746adb52a500eLennart Poetteringstatic int ResetImageGeometry(const char *pszFilename)
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering{
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering RTPrintf("Resetting geometry info of VDI image file=\"%s\"\n", pszFilename);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering PVDIDISK pVdi = VDIDiskCreate();
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering int rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_NORMAL);
38051578360c211e88ef4082ce5746adb52a500eLennart Poettering if (VBOX_SUCCESS(rc))
a44b10818a531787c359f6446d218a975503f032Lennart Poettering {
a44b10818a531787c359f6446d218a975503f032Lennart Poettering rc = VDIDiskSetGeometry(pVdi, 0, 0, 0);
a44b10818a531787c359f6446d218a975503f032Lennart Poettering if (VBOX_SUCCESS(rc))
a44b10818a531787c359f6446d218a975503f032Lennart Poettering rc = VDIDiskSetTranslation(pVdi, PDMBIOSTRANSLATION_AUTO);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt }
a44b10818a531787c359f6446d218a975503f032Lennart Poettering VDIDiskCloseImage(pVdi);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt return PrintDone(rc);
a44b10818a531787c359f6446d218a975503f032Lennart Poettering}
a44b10818a531787c359f6446d218a975503f032Lennart Poettering
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardtstatic int CopyImage(const char *pszDstFile, const char *pszSrcFile)
a44b10818a531787c359f6446d218a975503f032Lennart Poettering{
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt RTPrintf("Copying VDI image file=\"%s\" to image file=\"%s\"...\n"
a44b10818a531787c359f6446d218a975503f032Lennart Poettering "progress: 0%%",
a44b10818a531787c359f6446d218a975503f032Lennart Poettering pszSrcFile, pszDstFile);
a44b10818a531787c359f6446d218a975503f032Lennart Poettering unsigned uPrecent = 0;
a44b10818a531787c359f6446d218a975503f032Lennart Poettering int rc = VDICopyImage(pszDstFile, pszSrcFile, NULL, ProcessCallback, &uPrecent);
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering RTPrintf("\n");
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering return PrintDone(rc);
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering}
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poetteringstatic int CopyToDD(const char *pszDstFile, const char *pszSrcFile)
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering{
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering RTPrintf("Copying VDI image file=\"%s\" to DD file=\"%s\"...\n",
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt pszSrcFile, pszDstFile);
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering PVDIDISK pVdi = VDIDiskCreate();
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt int rc = VDIDiskOpenImage(pVdi, pszSrcFile, VDI_OPEN_FLAGS_NORMAL);
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering if (VBOX_SUCCESS(rc))
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering {
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering RTFILE FileDst;
40ed1a4574152337479f7f9c01763b84847ff09fLennart Poettering rc = RTFileOpen(&FileDst, pszDstFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE);
88ae7333ee052e64607ae6678fe0e84991fe3482Zbigniew Jędrzejewski-Szmek if (VBOX_SUCCESS(rc))
88ae7333ee052e64607ae6678fe0e84991fe3482Zbigniew Jędrzejewski-Szmek {
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);
12f15e596a3040f32bb8c9aa9d0bf9b43fc96567Zbigniew Jędrzejewski-Szmek if (pvBuf)
12f15e596a3040f32bb8c9aa9d0bf9b43fc96567Zbigniew Jędrzejewski-Szmek {
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek uint64_t off = 0;
dfdebb1b925332352966804303b2516a6506a429Zbigniew Jędrzejewski-Szmek while (off < cbSrc)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = VDIDiskRead(pVdi, off, pvBuf, cbBuf);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (VBOX_FAILURE(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek break;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = RTFileWrite(FileDst, pvBuf, cbBuf, NULL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (VBOX_FAILURE(rc))
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek break;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek off += cbBuf;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek }
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTMemFree(pvBuf);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek }
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTFileClose(FileDst);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering }
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt }
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering VDIDiskCloseImage(pVdi);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering return PrintDone(rc);
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering}
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering
d9130355ee0530117518ff24354bdd552d030238Lennart Poetteringstatic int ShrinkImage(const char *pszFilename)
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering{
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering RTPrintf("Shrinking VDI image file=\"%s\"...\n"
d9130355ee0530117518ff24354bdd552d030238Lennart Poettering "progress: 0%%",
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering pszFilename);
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering unsigned uPrecent;
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering int rc = VDIShrinkImage(pszFilename, ProcessCallback, &uPrecent);
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering RTPrintf("\n");
2e9efd22ce0099c3b4d35898d70f8fc706c8a66cLennart Poettering return PrintDone(rc);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek}
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmekint main(int argc, char **argv)
86349ffe49092345269762e3274121133604c3d4Lennart Poettering{
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek putenv("VBOX_LOG_DEST=stdout");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek putenv("VBOX_LOG_FLAGS=");
86349ffe49092345269762e3274121133604c3d4Lennart Poettering
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering RTR3Init();
3ed18ce28c2a8058fa740ad27436a2d73f096488Lennart Poettering RTPrintf("vditool Copyright (c) 2004-2005 InnoTek Systemberatung GmbH.\n\n");
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek /*
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek * Do cmd line parsing.
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering */
86349ffe49092345269762e3274121133604c3d4Lennart Poettering if (argc < 2)
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering return UsageExit();
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt char szCmd[16];
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering if (strlen(argv[1]) >= sizeof(szCmd))
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering return SyntaxError("Invalid command!");
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering strcpy(szCmd, argv[1]);
3ba3a79df4ae094d1008c04a9af8d1ff970124c4Zbigniew Jędrzejewski-Szmek ascii2upper(szCmd);
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering PRTLOGGER pLogger;
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
1f70b0876a9388f38422c12fa0c73761559d9425Lennart Poettering int rc = RTLogCreate(&pLogger, 0, "all",
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek NULL, ELEMENTS(s_apszGroups), s_apszGroups,
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering RTLOGDEST_STDOUT, NULL);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek RTLogRelSetDefaultInstance(pLogger);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (strcmp(szCmd, "NEW") == 0)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (argc != 4)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return SyntaxError("Invalid argument count!");
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering uint32_t cMBs;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering rc = RTStrToUInt32Ex(argv[3], NULL, 10, &cMBs);
4f44c03eaa7bc05240ef619d07766f61eda3d5b7Lennart Poettering if (VBOX_FAILURE(rc))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return SyntaxError("Invalid number!");
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if ( cMBs < 2
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering || cMBs > 1024*1024)
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt {
4f44c03eaa7bc05240ef619d07766f61eda3d5b7Lennart Poettering RTPrintf("error: Disk size %RU32 (MB) is not within the range %u-%u!\n",
4f44c03eaa7bc05240ef619d07766f61eda3d5b7Lennart Poettering cMBs, 2, 1024*1024);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return 1;
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek }
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering rc = NewImage(argv[2], cMBs);
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering }
d55192add75584f55932ad463ee6b4cc30370c63Lennart Poettering else if (strcmp(szCmd, "DD") == 0)
d55192add75584f55932ad463ee6b4cc30370c63Lennart Poettering {
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt if (argc != 4)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return SyntaxError("Invalid argument count!");
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering rc = ConvertDDImage(argv[2], argv[3]);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt }
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering else if (strcmp(szCmd, "CONVERT") == 0)
d55192add75584f55932ad463ee6b4cc30370c63Lennart Poettering {
d55192add75584f55932ad463ee6b4cc30370c63Lennart Poettering if (argc != 3)
d55192add75584f55932ad463ee6b4cc30370c63Lennart Poettering return SyntaxError("Invalid argument count!");
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering rc = ConvertOldImage(argv[2]);
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering }
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering else if (strcmp(szCmd, "DUMP") == 0)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering {
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering if (argc != 3)
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt return SyntaxError("Invalid argument count!");
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt rc = DumpImage(argv[2]);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt }
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering else if (strcmp(szCmd, "RESETGEO") == 0)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering {
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering if (argc != 3)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return SyntaxError("Invalid argument count!");
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering rc = ResetImageGeometry(argv[2]);
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering }
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt else if (strcmp(szCmd, "COPY") == 0)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering {
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering if (argc != 4)
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering return SyntaxError("Invalid argument count!");
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering rc = CopyImage(argv[3], argv[2]);
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering }
781fa93815fafd02b5287ef5781b92ef7b99973bLennart Poettering else if (strcmp(szCmd, "COPYDD") == 0)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek if (argc != 4)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek return SyntaxError("Invalid argument count!");
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek rc = CopyToDD(argv[3], argv[2]);
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek }
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek else if (strcmp(szCmd, "SHRINK") == 0)
708c143c7cd2bbd748ac0fa993496ff44e72701cZbigniew Jędrzejewski-Szmek {
1fc5560911a7e9e8cf2993e17e1f0a001e148809Lennart Poettering if (argc != 3)
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering return SyntaxError("Invalid argument count!");
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering rc = ShrinkImage(argv[2]);
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering }
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering else
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering return SyntaxError("Invalid command!");
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering RTLogFlush(NULL);
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering return !VBOX_SUCCESS(rc);
b938cb902c3b5bca807a94b277672c64d6767886Jan Engelhardt}
43dbecd5a31f6b247b261a5a281afecafdf1c841Lennart Poettering