VBoxManageDisk.cpp revision 0bbcd928b2a3d73607f224687249c3cec733aee3
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/* $Id$ */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** @file
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * VBoxManage - The disk delated commands.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * available from http://www.virtualbox.org. This file is free software;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * you can redistribute it and/or modify it under the terms of the GNU
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * General Public License (GPL) as published by the Free Software
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * additional information or have any questions.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#ifndef VBOX_ONLY_DOCS
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/*******************************************************************************
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync* Header Files *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync*******************************************************************************/
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/com/com.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/com/array.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/com/ErrorInfo.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/com/errorprint2.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/com/VirtualBox.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/asm.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/file.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/path.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/param.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/stream.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/string.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/ctype.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/getopt.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/log.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <VBox/VBoxHDD.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include "VBoxManage.h"
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncusing namespace com;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync// funcs
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync///////////////////////////////////////////////////////////////////////////////
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("ERROR: ");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintfV(pszFormat, va);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("\n");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("Error code %Rrc at %s(%u) in function %s\n", rc, RT_SRC_POS_ARGS);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic int parseDiskVariant(const char *psz, HardDiskVariant_T *pDiskVariant)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync unsigned DiskVariant = (unsigned)(*pDiskVariant);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync while (psz && *psz && RT_SUCCESS(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync size_t len;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync const char *pszComma = strchr(psz, ',');
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (pszComma)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync len = pszComma - psz;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync len = strlen(psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (len > 0)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
10d739d22a5d5a13803f7e34de34de010099270cvboxsync // Parsing is intentionally inconsistent: "standard" resets the
10d739d22a5d5a13803f7e34de34de010099270cvboxsync // variant, whereas the other flags are cumulative.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!RTStrNICmp(psz, "standard", len))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskVariant = HardDiskVariant_Standard;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if ( !RTStrNICmp(psz, "fixed", len)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrNICmp(psz, "static", len))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskVariant |= HardDiskVariant_Fixed;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (!RTStrNICmp(psz, "Diff", len))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskVariant |= HardDiskVariant_Diff;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (!RTStrNICmp(psz, "split2g", len))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskVariant |= HardDiskVariant_VmdkSplit2G;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if ( !RTStrNICmp(psz, "stream", len)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrNICmp(psz, "streamoptimized", len))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskVariant |= HardDiskVariant_VmdkStreamOptimized;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (!RTStrNICmp(psz, "esx", len))
be196d173cf52fa33016912e4745dbe1170ac53avboxsync DiskVariant |= HardDiskVariant_VmdkESX;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = VERR_PARSE_ERROR;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (pszComma)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync psz += len + 1;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync psz += len;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_SUCCESS(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *pDiskVariant = (HardDiskVariant_T)DiskVariant;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic int parseDiskType(const char *psz, HardDiskType_T *pDiskType)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskType_T DiskType = HardDiskType_Normal;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!RTStrICmp(psz, "normal"))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskType = HardDiskType_Normal;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (!RTStrICmp(psz, "immutable"))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskType = HardDiskType_Immutable;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (!RTStrICmp(psz, "writethrough"))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskType = HardDiskType_Writethrough;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = VERR_PARSE_ERROR;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_SUCCESS(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *pDiskType = DiskType;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** @todo move this into getopt, as getting bool values is generic */
be196d173cf52fa33016912e4745dbe1170ac53avboxsyncstatic int parseBool(const char *psz, bool *pb)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync{
be196d173cf52fa33016912e4745dbe1170ac53avboxsync int rc = VINF_SUCCESS;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync if ( !RTStrICmp(psz, "on")
be196d173cf52fa33016912e4745dbe1170ac53avboxsync || !RTStrICmp(psz, "yes")
be196d173cf52fa33016912e4745dbe1170ac53avboxsync || !RTStrICmp(psz, "true")
be196d173cf52fa33016912e4745dbe1170ac53avboxsync || !RTStrICmp(psz, "1")
be196d173cf52fa33016912e4745dbe1170ac53avboxsync || !RTStrICmp(psz, "enable")
be196d173cf52fa33016912e4745dbe1170ac53avboxsync || !RTStrICmp(psz, "enabled"))
be196d173cf52fa33016912e4745dbe1170ac53avboxsync {
be196d173cf52fa33016912e4745dbe1170ac53avboxsync *pb = true;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if ( !RTStrICmp(psz, "off")
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrICmp(psz, "no")
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrICmp(psz, "false")
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrICmp(psz, "0")
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrICmp(psz, "disable")
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || !RTStrICmp(psz, "disabled"))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *pb = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = VERR_PARSE_ERROR;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic const RTGETOPTDEF g_aCreateHardDiskOptions[] =
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--filename", 'f', RTGETOPT_REQ_STRING },
be196d173cf52fa33016912e4745dbe1170ac53avboxsync { "-filename", 'f', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--size", 's', RTGETOPT_REQ_UINT64 },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-size", 's', RTGETOPT_REQ_UINT64 }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--format", 'o', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-format", 'o', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--static", 'F', RTGETOPT_REQ_NOTHING },
be196d173cf52fa33016912e4745dbe1170ac53avboxsync { "-static", 'F', RTGETOPT_REQ_NOTHING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--variant", 'm', RTGETOPT_REQ_STRING },
be196d173cf52fa33016912e4745dbe1170ac53avboxsync { "-variant", 'm', RTGETOPT_REQ_STRING }, // deprecated
be196d173cf52fa33016912e4745dbe1170ac53avboxsync { "--type", 't', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--comment", 'c', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-comment", 'c', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--remember", 'r', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-remember", 'r', RTGETOPT_REQ_NOTHING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--register", 'r', RTGETOPT_REQ_NOTHING }, // deprecated (inofficial)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync { "-register", 'r', RTGETOPT_REQ_NOTHING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync};
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncint handleCreateHardDisk(HandlerArg *a)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HRESULT rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int vrc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Bstr filename;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync uint64_t sizeMB = 0;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Bstr format = "VDI";
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskVariant_T DiskVariant = HardDiskVariant_Standard;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Bstr comment;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool fRemember = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskType_T DiskType = HardDiskType_Normal;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int c;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTGETOPTUNION ValueUnion;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGETOPTSTATE GetState;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync // start at 0 because main() has hacked both the argc and argv given to us
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGetOptInit(&GetState, a->argc, a->argv, g_aCreateHardDiskOptions, RT_ELEMENTS(g_aCreateHardDiskOptions), 0, 0 /* fFlags */);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync while ((c = RTGetOpt(&GetState, &ValueUnion)))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync switch (c)
cecfddc5f644039b889734369f7087dcdeb42e85vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'f': // --filename
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync filename = ValueUnion.psz;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 's': // --size
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync sizeMB = ValueUnion.u64;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'o': // --format
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync format = ValueUnion.psz;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'F': // --static ("fixed"/"flat")
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync unsigned uDiskVariant = (unsigned)DiskVariant;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync uDiskVariant |= HardDiskVariant_Fixed;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DiskVariant = (HardDiskVariant_T)uDiskVariant;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'm': // --variant
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync vrc = parseDiskVariant(ValueUnion.psz, &DiskVariant);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_FAILURE(vrc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorArgument("Invalid hard disk variant '%s'", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'c': // --comment
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync comment = ValueUnion.psz;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'r': // --remember
eab872ee272cc9e799e0b68735b660deb84b8629vboxsync fRemember = true;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 't': // --type
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync vrc = parseDiskType(ValueUnion.psz, &DiskType);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if ( RT_FAILURE(vrc)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync || (DiskType != HardDiskType_Normal && DiskType != HardDiskType_Writethrough))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case VINF_GETOPT_NOT_OPTION:
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "Invalid parameter '%s'", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync default:
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (c > 0)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_C_IS_PRINT(c))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "Invalid option -%c", c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "Invalid option case %i", c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (c == VERR_GETOPT_UNKNOWN_OPTION)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "unknown option: %s\n", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (ValueUnion.pDef)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync return errorSyntax(USAGE_CREATEHD, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "error: %Rrs", c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
be196d173cf52fa33016912e4745dbe1170ac53avboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* check the outcome */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!filename || (sizeMB == 0))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "Parameters --filename and --size are required");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ComPtr<IHardDisk> hardDisk;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(a->virtualBox, CreateHardDisk(format, filename, hardDisk.asOutParam()));
be196d173cf52fa33016912e4745dbe1170ac53avboxsync if (SUCCEEDED(rc) && hardDisk)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* we will close the hard disk after the storage has been successfully
be196d173cf52fa33016912e4745dbe1170ac53avboxsync * created unless fRemember is set */
be196d173cf52fa33016912e4745dbe1170ac53avboxsync bool doClose = false;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!comment.isNull())
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk,COMSETTER(Description)(comment));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
10d739d22a5d5a13803f7e34de34de010099270cvboxsync ComPtr<IProgress> progress;
10d739d22a5d5a13803f7e34de34de010099270cvboxsync CHECK_ERROR(hardDisk, CreateBaseStorage(sizeMB, DiskVariant, progress.asOutParam()));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (SUCCEEDED(rc) && progress)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync showProgress(progress);
10d739d22a5d5a13803f7e34de34de010099270cvboxsync if (SUCCEEDED(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync LONG iRc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync progress->COMGETTER(ResultCode)(&iRc);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = iRc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (FAILED(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync com::ProgressErrorInfo info(progress);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (info.isBasicAvailable())
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("Error: failed to create hard disk. Error message: %lS\n", info.getText().raw());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("Error: failed to create hard disk. No error message available!\n");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync doClose = !fRemember;
10d739d22a5d5a13803f7e34de34de010099270cvboxsync
10d739d22a5d5a13803f7e34de34de010099270cvboxsync Bstr uuid;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk, COMGETTER(Id)(uuid.asOutParam()));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (DiskType == HardDiskType_Writethrough)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("Disk image created. UUID: %s\n", Utf8Str(uuid).raw());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (doClose)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk, Close());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return SUCCEEDED(rc) ? 0 : 1;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#if 0 /* disabled until disk shrinking is implemented based on VBoxHDD */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic DECLCALLBACK(int) hardDiskProgressCallback(PVM pVM, unsigned uPercent, void *pvUser)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync unsigned *pPercent = (unsigned *)pvUser;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (*pPercent != uPercent)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *pPercent = uPercent;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf(".");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if ((uPercent % 10) == 0 && uPercent)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTPrintf("%d%%", uPercent);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTStrmFlush(g_pStdOut);
cecfddc5f644039b889734369f7087dcdeb42e85vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#endif
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic const RTGETOPTDEF g_aModifyHardDiskOptions[] =
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--type", 't', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "settype", 't', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--autoreset", 'z', RTGETOPT_REQ_STRING },
be196d173cf52fa33016912e4745dbe1170ac53avboxsync { "-autoreset", 'z', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "autoreset", 'z', RTGETOPT_REQ_STRING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--compact", 'c', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync};
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncint handleModifyHardDisk(HandlerArg *a)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
27de6b7fcf72c0add242c8dbefff24fbdc7869ebvboxsync HRESULT rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int vrc;
78817f40cd3fec6cba19ad8a2df2a690970c5895vboxsync ComPtr<IHardDisk> hardDisk;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskType_T DiskType;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool AutoReset = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool fModifyDiskType = false, fModifyAutoReset = false, fModifyCompact = false;;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync const char *FilenameOrUuid = NULL;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int c;
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync RTGETOPTUNION ValueUnion;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGETOPTSTATE GetState;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync // start at 0 because main() has hacked both the argc and argv given to us
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGetOptInit(&GetState, a->argc, a->argv, g_aModifyHardDiskOptions, RT_ELEMENTS(g_aModifyHardDiskOptions), 0, 0 /* fFlags */);
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync while ((c = RTGetOpt(&GetState, &ValueUnion)))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync switch (c)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 't': // --type
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync vrc = parseDiskType(ValueUnion.psz, &DiskType);
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync if (RT_FAILURE(vrc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync fModifyDiskType = true;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
b64d5de6949f62d8b70658f77d9f28f58b0d4668vboxsync
b64d5de6949f62d8b70658f77d9f28f58b0d4668vboxsync case 'z': // --autoreset
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync vrc = parseBool(ValueUnion.psz, &AutoReset);
b64d5de6949f62d8b70658f77d9f28f58b0d4668vboxsync if (RT_FAILURE(vrc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorArgument("Invalid autoreset parameter '%s'", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync fModifyAutoReset = true;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync case 'c': // --compact
be196d173cf52fa33016912e4745dbe1170ac53avboxsync fModifyCompact = true;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsync case VINF_GETOPT_NOT_OPTION:
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!FilenameOrUuid)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync FilenameOrUuid = ValueUnion.psz;
27de6b7fcf72c0add242c8dbefff24fbdc7869ebvboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_CREATEHD, "Invalid parameter '%s'", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync default:
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (c > 0)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_C_IS_PRINT(c))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_MODIFYHD, "Invalid option -%c", c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_MODIFYHD, "Invalid option case %i", c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (c == VERR_GETOPT_UNKNOWN_OPTION)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_MODIFYHD, "unknown option: %s\n", ValueUnion.psz);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (ValueUnion.pDef)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_MODIFYHD, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_MODIFYHD, "error: %Rrs", c);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!FilenameOrUuid)
10d739d22a5d5a13803f7e34de34de010099270cvboxsync return errorSyntax(USAGE_MODIFYHD, "Disk name or UUID required");
10d739d22a5d5a13803f7e34de34de010099270cvboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!fModifyDiskType && !fModifyAutoReset && !fModifyCompact)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorSyntax(USAGE_MODIFYHD, "No operation specified");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* first guess is that it's a UUID */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Guid uuid(FilenameOrUuid);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = a->virtualBox->GetHardDisk(uuid.toUtf16(), hardDisk.asOutParam());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* no? then it must be a filename */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!hardDisk)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(a->virtualBox, FindHardDisk(Bstr(FilenameOrUuid), hardDisk.asOutParam()));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (FAILED(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return 1;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (fModifyDiskType)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync /* hard disk must be registered */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (SUCCEEDED(rc) && hardDisk)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskType_T hddType;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (hddType != DiskType)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return errorArgument("Hard disk image not registered");
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (fModifyAutoReset)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(hardDisk, COMSETTER(AutoReset)(AutoReset));
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync }
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (fModifyCompact)
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool unknown = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* the hard disk image might not be registered */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!hardDisk)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync unknown = true;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = a->virtualBox->OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, hardDisk.asOutParam());
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync if (rc == VBOX_E_FILE_ERROR)
e41b10cedab46ca3ff69b2db87291a74ec1ddd61vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync char szFilenameAbs[RTPATH_MAX] = "";
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync int vrc = RTPathAbs(FilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_FAILURE(vrc))
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync {
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync RTPrintf("Cannot convert filename \"%s\" to absolute path\n", FilenameOrUuid);
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync return 1;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, hardDisk.asOutParam()));
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync else if (FAILED(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, hardDisk.asOutParam()));
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync }
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync if (SUCCEEDED(rc) && hardDisk)
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync {
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync ComPtr<IProgress> progress;
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync CHECK_ERROR(hardDisk, Compact(progress.asOutParam()));
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync if (SUCCEEDED(rc))
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync {
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync showProgress(progress);
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync LONG iRc;
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync progress->COMGETTER(ResultCode)(&iRc);
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync rc = iRc;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (FAILED(rc))
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync {
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (rc == E_NOTIMPL)
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync {
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync RTPrintf("Error: Compact hard disk operation is not implemented!\n");
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync RTPrintf("The functionality will be restored later.\n");
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync else if (rc == VBOX_E_NOT_SUPPORTED)
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync {
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync RTPrintf("Error: Compact hard disk operation for this format is not implemented yet!\n");
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync else
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync com::GluePrintRCMessage(rc);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (unknown)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync hardDisk->Close();
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return SUCCEEDED(rc) ? 0 : 1;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncstatic const RTGETOPTDEF g_aCloneHardDiskOptions[] =
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--format", 'o', RTGETOPT_REQ_STRING },
6757b795f7bfac39777e1e86a49fa120f86def25vboxsync { "-format", 'o', RTGETOPT_REQ_STRING },
6757b795f7bfac39777e1e86a49fa120f86def25vboxsync { "--static", 'F', RTGETOPT_REQ_NOTHING },
6757b795f7bfac39777e1e86a49fa120f86def25vboxsync { "-static", 'F', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--variant", 'm', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-variant", 'm', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--type", 't', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-type", 't', RTGETOPT_REQ_STRING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--remember", 'r', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-remember", 'r', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "--register", 'r', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync { "-register", 'r', RTGETOPT_REQ_NOTHING },
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync};
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncint handleCloneHardDisk(HandlerArg *a)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HRESULT rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int vrc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Bstr src, dst;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Bstr format;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskVariant_T DiskVariant = HardDiskVariant_Standard;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool fRemember = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HardDiskType_T DiskType = HardDiskType_Normal;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int c;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGETOPTUNION ValueUnion;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGETOPTSTATE GetState;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync // start at 0 because main() has hacked both the argc and argv given to us
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneHardDiskOptions, RT_ELEMENTS(g_aCloneHardDiskOptions), 0, 0 /* fFlags */);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync while ((c = RTGetOpt(&GetState, &ValueUnion)))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync switch (c)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
case 'o': // --format
format = ValueUnion.psz;
break;
case 'm': // --variant
vrc = parseDiskVariant(ValueUnion.psz, &DiskVariant);
if (RT_FAILURE(vrc))
return errorArgument("Invalid hard disk variant '%s'", ValueUnion.psz);
break;
case 'r': // --remember
fRemember = true;
break;
case 't': // --type
vrc = parseDiskType(ValueUnion.psz, &DiskType);
if (RT_FAILURE(vrc))
return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
break;
case VINF_GETOPT_NOT_OPTION:
if (src.isEmpty())
src = ValueUnion.psz;
else if (dst.isEmpty())
dst = ValueUnion.psz;
else
return errorSyntax(USAGE_CLONEHD, "Invalid parameter '%s'", ValueUnion.psz);
break;
default:
if (c > 0)
{
if (RT_C_IS_GRAPH(c))
return errorSyntax(USAGE_CLONEHD, "unhandled option: -%c", c);
else
return errorSyntax(USAGE_CLONEHD, "unhandled option: %i", c);
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
return errorSyntax(USAGE_CLONEHD, "unknown option: %s", ValueUnion.psz);
else if (ValueUnion.pDef)
return errorSyntax(USAGE_CLONEHD, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
else
return errorSyntax(USAGE_CLONEHD, "error: %Rrs", c);
}
}
if (src.isEmpty())
return errorSyntax(USAGE_CLONEHD, "Mandatory UUID or input file parameter missing");
if (dst.isEmpty())
return errorSyntax(USAGE_CLONEHD, "Mandatory output file parameter missing");
ComPtr<IHardDisk> srcDisk;
ComPtr<IHardDisk> dstDisk;
bool unknown = false;
/* first guess is that it's a UUID */
rc = a->virtualBox->GetHardDisk(src, srcDisk.asOutParam());
/* no? then it must be a filename */
if (FAILED (rc))
{
rc = a->virtualBox->FindHardDisk(src, srcDisk.asOutParam());
/* no? well, then it's an unknown image */
if (FAILED (rc))
{
rc = a->virtualBox->OpenHardDisk(src, AccessMode_ReadWrite, srcDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
char szFilenameAbs[RTPATH_MAX] = "";
int vrc = RTPathAbs(Utf8Str(src), szFilenameAbs, sizeof(szFilenameAbs));
if (RT_FAILURE(vrc))
{
RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Utf8Str(src).raw());
return 1;
}
CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, srcDisk.asOutParam()));
}
else if (FAILED(rc))
CHECK_ERROR(a->virtualBox, OpenHardDisk(src, AccessMode_ReadWrite, srcDisk.asOutParam()));
if (SUCCEEDED (rc))
{
unknown = true;
}
}
}
do
{
if (!SUCCEEDED(rc))
break;
if (format.isEmpty())
{
/* get the format of the source hard disk */
CHECK_ERROR_BREAK(srcDisk, COMGETTER(Format) (format.asOutParam()));
}
CHECK_ERROR_BREAK(a->virtualBox, CreateHardDisk(format, dst, dstDisk.asOutParam()));
ComPtr<IProgress> progress;
CHECK_ERROR_BREAK(srcDisk, CloneTo(dstDisk, DiskVariant, NULL, progress.asOutParam()));
showProgress(progress);
LONG iRc;
progress->COMGETTER(ResultCode)(&iRc);
rc = iRc;
if (FAILED(rc))
{
com::ProgressErrorInfo info(progress);
if (info.isBasicAvailable())
RTPrintf("Error: failed to clone hard disk. Error message: %lS\n", info.getText().raw());
else
RTPrintf("Error: failed to clone hard disk. No error message available!\n");
break;
}
Bstr uuid;
CHECK_ERROR_BREAK(dstDisk, COMGETTER(Id)(uuid.asOutParam()));
RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n",
format.raw(), Utf8Str(uuid).raw());
}
while (0);
if (!fRemember && !dstDisk.isNull())
{
/* forget the created clone */
dstDisk->Close();
}
if (unknown)
{
/* close the unknown hard disk to forget it again */
srcDisk->Close();
}
return SUCCEEDED(rc) ? 0 : 1;
}
static const RTGETOPTDEF g_aConvertFromRawHardDiskOptions[] =
{
{ "--format", 'o', RTGETOPT_REQ_STRING },
{ "-format", 'o', RTGETOPT_REQ_STRING },
{ "--static", 'F', RTGETOPT_REQ_NOTHING },
{ "-static", 'F', RTGETOPT_REQ_NOTHING },
{ "--variant", 'm', RTGETOPT_REQ_STRING },
{ "-variant", 'm', RTGETOPT_REQ_STRING },
};
int handleConvertFromRaw(int argc, char *argv[])
{
int rc = VINF_SUCCESS;
bool fReadFromStdIn = false;
const char *format = "VDI";
const char *srcfilename = NULL;
const char *dstfilename = NULL;
const char *filesize = NULL;
unsigned uImageFlags = VD_IMAGE_FLAGS_NONE;
void *pvBuf = NULL;
int c;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, argc, argv, g_aConvertFromRawHardDiskOptions, RT_ELEMENTS(g_aConvertFromRawHardDiskOptions), 0, 0 /* fFlags */);
while ((c = RTGetOpt(&GetState, &ValueUnion)))
{
switch (c)
{
case 'o': // --format
format = ValueUnion.psz;
break;
case 'm': // --variant
HardDiskVariant_T DiskVariant;
rc = parseDiskVariant(ValueUnion.psz, &DiskVariant);
if (RT_FAILURE(rc))
return errorArgument("Invalid hard disk variant '%s'", ValueUnion.psz);
/// @todo cleaner solution than assuming 1:1 mapping?
uImageFlags = (unsigned)DiskVariant;
break;
case VINF_GETOPT_NOT_OPTION:
if (!srcfilename)
{
srcfilename = ValueUnion.psz;
#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
fReadFromStdIn = !strcmp(srcfilename, "stdin");
#endif
}
else if (!dstfilename)
dstfilename = ValueUnion.psz;
else if (fReadFromStdIn && !filesize)
filesize = ValueUnion.psz;
else
return errorSyntax(USAGE_CONVERTFROMRAW, "Invalid parameter '%s'", ValueUnion.psz);
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
return errorSyntax(USAGE_CONVERTFROMRAW, "Invalid option -%c", c);
else
return errorSyntax(USAGE_CONVERTFROMRAW, "Invalid option case %i", c);
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
return errorSyntax(USAGE_CREATEHD, "unknown option: %s\n", ValueUnion.psz);
else if (ValueUnion.pDef)
return errorSyntax(USAGE_CONVERTFROMRAW, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
else
return errorSyntax(USAGE_CONVERTFROMRAW, "error: %Rrs", c);
}
}
if (!srcfilename || !dstfilename || (fReadFromStdIn && !filesize))
return errorSyntax(USAGE_CONVERTFROMRAW, "Incorrect number of parameters");
RTPrintf("Converting from raw image file=\"%s\" to file=\"%s\"...\n",
srcfilename, dstfilename);
PVBOXHDD pDisk = NULL;
PVDINTERFACE pVDIfs = NULL;
VDINTERFACE vdInterfaceError;
VDINTERFACEERROR vdInterfaceErrorCallbacks;
vdInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
vdInterfaceErrorCallbacks.pfnError = handleVDError;
rc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
&vdInterfaceErrorCallbacks, NULL, &pVDIfs);
AssertRC(rc);
/* open raw image file. */
RTFILE File;
if (fReadFromStdIn)
File = 0;
else
rc = RTFileOpen(&File, srcfilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
if (RT_FAILURE(rc))
{
RTPrintf("File=\"%s\" open error: %Rrf\n", srcfilename, rc);
goto out;
}
uint64_t cbFile;
/* get image size. */
if (fReadFromStdIn)
cbFile = RTStrToUInt64(filesize);
else
rc = RTFileGetSize(File, &cbFile);
if (RT_FAILURE(rc))
{
RTPrintf("Error getting image size for file \"%s\": %Rrc\n", srcfilename, rc);
goto out;
}
RTPrintf("Creating %s image with size %RU64 bytes (%RU64MB)...\n", (uImageFlags & VD_IMAGE_FLAGS_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);
char pszComment[256];
RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", srcfilename);
rc = VDCreate(pVDIfs, &pDisk);
if (RT_FAILURE(rc))
{
RTPrintf("Error while creating the virtual disk container: %Rrc\n", rc);
goto out;
}
Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) -
(unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0);
PDMMEDIAGEOMETRY PCHS, LCHS;
PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383);
PCHS.cHeads = 16;
PCHS.cSectors = 63;
LCHS.cCylinders = 0;
LCHS.cHeads = 0;
LCHS.cSectors = 0;
rc = VDCreateBase(pDisk, format, dstfilename, cbFile,
uImageFlags, pszComment, &PCHS, &LCHS, NULL,
VD_OPEN_FLAGS_NORMAL, NULL, NULL);
if (RT_FAILURE(rc))
{
RTPrintf("Error while creating the disk image \"%s\": %Rrc\n", dstfilename, rc);
goto out;
}
size_t cbBuffer;
cbBuffer = _1M;
pvBuf = RTMemAlloc(cbBuffer);
if (!pvBuf)
{
rc = VERR_NO_MEMORY;
RTPrintf("Not enough memory allocating buffers for image \"%s\": %Rrc\n", dstfilename, rc);
goto out;
}
uint64_t offFile;
offFile = 0;
while (offFile < cbFile)
{
size_t cbRead;
size_t cbToRead;
cbRead = 0;
cbToRead = cbFile - offFile >= (uint64_t)cbBuffer ?
cbBuffer : (size_t) (cbFile - offFile);
rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);
if (RT_FAILURE(rc) || !cbRead)
break;
rc = VDWrite(pDisk, offFile, pvBuf, cbRead);
if (RT_FAILURE(rc))
{
RTPrintf("Failed to write to disk image \"%s\": %Rrc\n", dstfilename, rc);
goto out;
}
offFile += cbRead;
}
out:
if (pvBuf)
RTMemFree(pvBuf);
if (pDisk)
VDClose(pDisk, RT_FAILURE(rc));
if (File != NIL_RTFILE)
RTFileClose(File);
return RT_FAILURE(rc);
}
static const RTGETOPTDEF g_aAddiSCSIDiskOptions[] =
{
{ "--server", 's', RTGETOPT_REQ_STRING },
{ "-server", 's', RTGETOPT_REQ_STRING }, // deprecated
{ "--target", 'T', RTGETOPT_REQ_STRING },
{ "-target", 'T', RTGETOPT_REQ_STRING }, // deprecated
{ "--port", 'p', RTGETOPT_REQ_STRING },
{ "-port", 'p', RTGETOPT_REQ_STRING }, // deprecated
{ "--lun", 'l', RTGETOPT_REQ_STRING },
{ "-lun", 'l', RTGETOPT_REQ_STRING }, // deprecated
{ "--encodedlun", 'L', RTGETOPT_REQ_STRING },
{ "-encodedlun", 'L', RTGETOPT_REQ_STRING }, // deprecated
{ "--username", 'u', RTGETOPT_REQ_STRING },
{ "-username", 'u', RTGETOPT_REQ_STRING }, // deprecated
{ "--password", 'P', RTGETOPT_REQ_STRING },
{ "-password", 'P', RTGETOPT_REQ_STRING }, // deprecated
{ "--type", 't', RTGETOPT_REQ_STRING },
{ "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
{ "--comment", 'c', RTGETOPT_REQ_STRING },
{ "-comment", 'c', RTGETOPT_REQ_STRING }, // deprecated
{ "--intnet", 'I', RTGETOPT_REQ_NOTHING },
{ "-intnet", 'I', RTGETOPT_REQ_NOTHING }, // deprecated
};
int handleAddiSCSIDisk(HandlerArg *a)
{
HRESULT rc;
int vrc;
Bstr server;
Bstr target;
Bstr port;
Bstr lun;
Bstr username;
Bstr password;
Bstr comment;
bool fIntNet = false;
HardDiskType_T DiskType = HardDiskType_Normal;
int c;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aAddiSCSIDiskOptions, RT_ELEMENTS(g_aAddiSCSIDiskOptions), 0, 0 /* fFlags */);
while ((c = RTGetOpt(&GetState, &ValueUnion)))
{
switch (c)
{
case 's': // --server
server = ValueUnion.psz;
break;
case 'T': // --target
target = ValueUnion.psz;
break;
case 'p': // --port
port = ValueUnion.psz;
break;
case 'l': // --lun
lun = ValueUnion.psz;
break;
case 'L': // --encodedlun
lun = BstrFmt("enc%s", ValueUnion.psz);
break;
case 'u': // --username
username = ValueUnion.psz;
break;
case 'P': // --password
password = ValueUnion.psz;
break;
case 't': // --type
vrc = parseDiskType(ValueUnion.psz, &DiskType);
if (RT_FAILURE(vrc))
return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
break;
case 'c': // --comment
comment = ValueUnion.psz;
break;
case 'I': // --intnet
fIntNet = true;
break;
case VINF_GETOPT_NOT_OPTION:
return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", ValueUnion.psz);
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
return errorSyntax(USAGE_ADDISCSIDISK, "Invalid option -%c", c);
else
return errorSyntax(USAGE_ADDISCSIDISK, "Invalid option case %i", c);
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
return errorSyntax(USAGE_ADDISCSIDISK, "unknown option: %s\n", ValueUnion.psz);
else if (ValueUnion.pDef)
return errorSyntax(USAGE_ADDISCSIDISK, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
else
return errorSyntax(USAGE_ADDISCSIDISK, "error: %Rrs", c);
}
}
/* check for required options */
if (!server || !target)
return errorSyntax(USAGE_ADDISCSIDISK, "Parameters --server and --target are required");
do
{
ComPtr<IHardDisk> hardDisk;
/** @todo move the location stuff to Main, which can use pfnComposeName
* from the disk backends to construct the location properly. Also do
* not use slashes to separate the parts, as otherwise only the last
* element comtaining information will be shown. */
if (lun.isEmpty() || lun == "0" || lun == "enc0")
{
CHECK_ERROR_BREAK (a->virtualBox,
CreateHardDisk(Bstr ("iSCSI"),
BstrFmt ("%ls|%ls", server.raw(), target.raw()),
hardDisk.asOutParam()));
}
else
{
CHECK_ERROR_BREAK (a->virtualBox,
CreateHardDisk(Bstr ("iSCSI"),
BstrFmt ("%ls|%ls|%ls", server.raw(), target.raw(), lun.raw()),
hardDisk.asOutParam()));
}
CheckComRCBreakRC (rc);
if (!comment.isNull())
CHECK_ERROR(hardDisk, COMSETTER(Description)(comment));
if (!port.isNull())
server = BstrFmt ("%ls:%ls", server.raw(), port.raw());
com::SafeArray <BSTR> names;
com::SafeArray <BSTR> values;
Bstr ("TargetAddress").detachTo (names.appendedRaw());
server.detachTo (values.appendedRaw());
Bstr ("TargetName").detachTo (names.appendedRaw());
target.detachTo (values.appendedRaw());
if (!lun.isNull())
{
Bstr ("LUN").detachTo (names.appendedRaw());
lun.detachTo (values.appendedRaw());
}
if (!username.isNull())
{
Bstr ("InitiatorUsername").detachTo (names.appendedRaw());
username.detachTo (values.appendedRaw());
}
if (!password.isNull())
{
Bstr ("InitiatorSecret").detachTo (names.appendedRaw());
password.detachTo (values.appendedRaw());
}
/// @todo add --initiator option
Bstr ("InitiatorName").detachTo (names.appendedRaw());
Bstr ("iqn.2008-04.com.sun.virtualbox.initiator").detachTo (values.appendedRaw());
/// @todo add --targetName and --targetPassword options
if (fIntNet)
{
Bstr ("HostIPStack").detachTo (names.appendedRaw());
Bstr ("0").detachTo (values.appendedRaw());
}
CHECK_ERROR_BREAK (hardDisk,
SetProperties (ComSafeArrayAsInParam (names),
ComSafeArrayAsInParam (values)));
if (DiskType != HardDiskType_Normal)
{
CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
}
Bstr guid;
CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
RTPrintf("iSCSI disk created. UUID: %s\n", Utf8Str(guid).raw());
}
while (0);
return SUCCEEDED(rc) ? 0 : 1;
}
static const RTGETOPTDEF g_aShowHardDiskInfoOptions[] =
{
{ "--dummy", 256, RTGETOPT_REQ_NOTHING }, // placeholder for C++
};
int handleShowHardDiskInfo(HandlerArg *a)
{
HRESULT rc;
const char *FilenameOrUuid = NULL;
int c;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aShowHardDiskInfoOptions, RT_ELEMENTS(g_aShowHardDiskInfoOptions), 0, 0 /* fFlags */);
while ((c = RTGetOpt(&GetState, &ValueUnion)))
{
switch (c)
{
case VINF_GETOPT_NOT_OPTION:
if (!FilenameOrUuid)
FilenameOrUuid = ValueUnion.psz;
else
return errorSyntax(USAGE_SHOWHDINFO, "Invalid parameter '%s'", ValueUnion.psz);
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
return errorSyntax(USAGE_SHOWHDINFO, "Invalid option -%c", c);
else
return errorSyntax(USAGE_SHOWHDINFO, "Invalid option case %i", c);
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
return errorSyntax(USAGE_SHOWHDINFO, "unknown option: %s\n", ValueUnion.psz);
else if (ValueUnion.pDef)
return errorSyntax(USAGE_SHOWHDINFO, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
else
return errorSyntax(USAGE_SHOWHDINFO, "error: %Rrs", c);
}
}
/* check for required options */
if (!FilenameOrUuid)
return errorSyntax(USAGE_SHOWHDINFO, "Disk name or UUID required");
ComPtr<IHardDisk> hardDisk;
bool unknown = false;
/* first guess is that it's a UUID */
Bstr uuid(FilenameOrUuid);
rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
/* no? then it must be a filename */
if (FAILED (rc))
{
rc = a->virtualBox->FindHardDisk(Bstr(FilenameOrUuid), hardDisk.asOutParam());
/* no? well, then it's an unkwnown image */
if (FAILED (rc))
{
rc = a->virtualBox->OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, hardDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
char szFilenameAbs[RTPATH_MAX] = "";
int vrc = RTPathAbs(FilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs));
if (RT_FAILURE(vrc))
{
RTPrintf("Cannot convert filename \"%s\" to absolute path\n", FilenameOrUuid);
return 1;
}
CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, hardDisk.asOutParam()));
}
else if (FAILED(rc))
CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(FilenameOrUuid), AccessMode_ReadWrite, hardDisk.asOutParam()));
if (SUCCEEDED (rc))
{
unknown = true;
}
}
}
do
{
if (!SUCCEEDED(rc))
break;
hardDisk->COMGETTER(Id)(uuid.asOutParam());
RTPrintf("UUID: %s\n", Utf8Str(uuid).raw());
/* check for accessibility */
/// @todo NEWMEDIA check accessibility of all parents
/// @todo NEWMEDIA print the full state value
MediaState_T state;
CHECK_ERROR_BREAK (hardDisk, COMGETTER(State)(&state));
RTPrintf("Accessible: %s\n", state != MediaState_Inaccessible ? "yes" : "no");
if (state == MediaState_Inaccessible)
{
Bstr err;
CHECK_ERROR_BREAK (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));
RTPrintf("Access Error: %lS\n", err.raw());
}
Bstr description;
hardDisk->COMGETTER(Description)(description.asOutParam());
if (description)
{
RTPrintf("Description: %lS\n", description.raw());
}
ULONG64 logicalSize;
hardDisk->COMGETTER(LogicalSize)(&logicalSize);
RTPrintf("Logical size: %llu MBytes\n", logicalSize);
ULONG64 actualSize;
hardDisk->COMGETTER(Size)(&actualSize);
RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
ComPtr <IHardDisk> parent;
hardDisk->COMGETTER(Parent) (parent.asOutParam());
HardDiskType_T type;
hardDisk->COMGETTER(Type)(&type);
const char *typeStr = "unknown";
switch (type)
{
case HardDiskType_Normal:
if (!parent.isNull())
typeStr = "normal (differencing)";
else
typeStr = "normal (base)";
break;
case HardDiskType_Immutable:
typeStr = "immutable";
break;
case HardDiskType_Writethrough:
typeStr = "writethrough";
break;
}
RTPrintf("Type: %s\n", typeStr);
Bstr format;
hardDisk->COMGETTER(Format)(format.asOutParam());
RTPrintf("Storage format: %lS\n", format.raw());
if (!unknown)
{
com::SafeArray<BSTR> machineIds;
hardDisk->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));
for (size_t j = 0; j < machineIds.size(); ++ j)
{
ComPtr<IMachine> machine;
CHECK_ERROR(a->virtualBox, GetMachine(machineIds[j], machine.asOutParam()));
ASSERT(machine);
Bstr name;
machine->COMGETTER(Name)(name.asOutParam());
machine->COMGETTER(Id)(uuid.asOutParam());
RTPrintf("%s%lS (UUID: %lS)\n",
j == 0 ? "In use by VMs: " : " ",
name.raw(), machineIds[j]);
}
/// @todo NEWMEDIA check usage in snapshots too
/// @todo NEWMEDIA also list children
}
Bstr loc;
hardDisk->COMGETTER(Location)(loc.asOutParam());
RTPrintf("Location: %lS\n", loc.raw());
/* print out information specific for differencing hard disks */
if (!parent.isNull())
{
BOOL autoReset = FALSE;
hardDisk->COMGETTER(AutoReset)(&autoReset);
RTPrintf("Auto-Reset: %s\n", autoReset ? "on" : "off");
}
}
while (0);
if (unknown)
{
/* close the unknown hard disk to forget it again */
hardDisk->Close();
}
return SUCCEEDED(rc) ? 0 : 1;
}
static const RTGETOPTDEF g_aOpenMediumOptions[] =
{
{ "disk", 'd', RTGETOPT_REQ_NOTHING },
{ "dvd", 'D', RTGETOPT_REQ_NOTHING },
{ "floppy", 'f', RTGETOPT_REQ_NOTHING },
{ "--type", 't', RTGETOPT_REQ_STRING },
{ "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
};
int handleOpenMedium(HandlerArg *a)
{
HRESULT rc = S_OK;
int vrc;
enum {
CMD_NONE,
CMD_DISK,
CMD_DVD,
CMD_FLOPPY
} cmd = CMD_NONE;
const char *Filename = NULL;
HardDiskType_T DiskType = HardDiskType_Normal;
bool fDiskType = false;
int c;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aOpenMediumOptions, RT_ELEMENTS(g_aOpenMediumOptions), 0, 0 /* fFlags */);
while ((c = RTGetOpt(&GetState, &ValueUnion)))
{
switch (c)
{
case 'd': // disk
if (cmd != CMD_NONE)
return errorSyntax(USAGE_OPENMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
cmd = CMD_DISK;
break;
case 'D': // DVD
if (cmd != CMD_NONE)
return errorSyntax(USAGE_OPENMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
cmd = CMD_DVD;
break;
case 'f': // floppy
if (cmd != CMD_NONE)
return errorSyntax(USAGE_OPENMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
cmd = CMD_FLOPPY;
break;
case 't': // --type
vrc = parseDiskType(ValueUnion.psz, &DiskType);
if (RT_FAILURE(vrc))
return errorArgument("Invalid hard disk type '%s'", ValueUnion.psz);
fDiskType = true;
break;
case VINF_GETOPT_NOT_OPTION:
if (!Filename)
Filename = ValueUnion.psz;
else
return errorSyntax(USAGE_OPENMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
return errorSyntax(USAGE_OPENMEDIUM, "Invalid option -%c", c);
else
return errorSyntax(USAGE_OPENMEDIUM, "Invalid option case %i", c);
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
return errorSyntax(USAGE_OPENMEDIUM, "unknown option: %s\n", ValueUnion.psz);
else if (ValueUnion.pDef)
return errorSyntax(USAGE_OPENMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
else
return errorSyntax(USAGE_OPENMEDIUM, "error: %Rrs", c);
}
}
/* check for required options */
if (cmd == CMD_NONE)
return errorSyntax(USAGE_OPENMEDIUM, "Command variant disk/dvd/floppy required");
if (!Filename)
return errorSyntax(USAGE_OPENMEDIUM, "Disk name required");
/** @todo remove this hack!
* First try opening the image as is (using the regular API semantics for
* images with relative path or without path), and if that fails with a
* file related error then try it again with what the client thinks the
* relative path would mean. Requires doing the command twice in certain
* cases. This is an ugly hack and needs to be removed whevever we have a
* chance to clean up the API semantics. */
if (cmd == CMD_DISK)
{
ComPtr<IHardDisk> hardDisk;
rc = a->virtualBox->OpenHardDisk(Bstr(Filename), AccessMode_ReadWrite, hardDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
char szFilenameAbs[RTPATH_MAX] = "";
int vrc = RTPathAbs(Filename, szFilenameAbs, sizeof(szFilenameAbs));
if (RT_FAILURE(vrc))
{
RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Filename);
return 1;
}
CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(szFilenameAbs), AccessMode_ReadWrite, hardDisk.asOutParam()));
}
else if (FAILED(rc))
CHECK_ERROR(a->virtualBox, OpenHardDisk(Bstr(Filename), AccessMode_ReadWrite, hardDisk.asOutParam()));
if (SUCCEEDED(rc) && hardDisk)
{
/* change the type if requested */
if (DiskType != HardDiskType_Normal)
{
CHECK_ERROR(hardDisk, COMSETTER(Type)(DiskType));
}
}
}
else if (cmd == CMD_DVD)
{
if (fDiskType)
return errorSyntax(USAGE_OPENMEDIUM, "Invalid option for DVD images");
ComPtr<IDVDImage> dvdImage;
rc = a->virtualBox->OpenDVDImage(Bstr(Filename), Bstr(), dvdImage.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
char szFilenameAbs[RTPATH_MAX] = "";
int vrc = RTPathAbs(Filename, szFilenameAbs, sizeof(szFilenameAbs));
if (RT_FAILURE(vrc))
{
RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Filename);
return 1;
}
CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(szFilenameAbs), Bstr(), dvdImage.asOutParam()));
}
else if (FAILED(rc))
CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(Filename), Bstr(), dvdImage.asOutParam()));
}
else if (cmd == CMD_FLOPPY)
{
if (fDiskType)
return errorSyntax(USAGE_OPENMEDIUM, "Invalid option for DVD images");
ComPtr<IFloppyImage> floppyImage;
rc = a->virtualBox->OpenFloppyImage(Bstr(Filename), Bstr(), floppyImage.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
char szFilenameAbs[RTPATH_MAX] = "";
int vrc = RTPathAbs(Filename, szFilenameAbs, sizeof(szFilenameAbs));
if (RT_FAILURE(vrc))
{
RTPrintf("Cannot convert filename \"%s\" to absolute path\n", Filename);
return 1;
}
CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(szFilenameAbs), Bstr(), floppyImage.asOutParam()));
}
else if (FAILED(rc))
CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(Filename), Bstr(), floppyImage.asOutParam()));
}
return SUCCEEDED(rc) ? 0 : 1;
}
static const RTGETOPTDEF g_aCloseMediumOptions[] =
{
{ "disk", 'd', RTGETOPT_REQ_NOTHING },
{ "dvd", 'D', RTGETOPT_REQ_NOTHING },
{ "floppy", 'f', RTGETOPT_REQ_NOTHING },
};
int handleCloseMedium(HandlerArg *a)
{
HRESULT rc = S_OK;
enum {
CMD_NONE,
CMD_DISK,
CMD_DVD,
CMD_FLOPPY
} cmd = CMD_NONE;
const char *FilenameOrUuid = NULL;
int c;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aCloseMediumOptions, RT_ELEMENTS(g_aCloseMediumOptions), 0, 0 /* fFlags */);
while ((c = RTGetOpt(&GetState, &ValueUnion)))
{
switch (c)
{
case 'd': // disk
if (cmd != CMD_NONE)
return errorSyntax(USAGE_CLOSEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
cmd = CMD_DISK;
break;
case 'D': // DVD
if (cmd != CMD_NONE)
return errorSyntax(USAGE_CLOSEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
cmd = CMD_DVD;
break;
case 'f': // floppy
if (cmd != CMD_NONE)
return errorSyntax(USAGE_CLOSEMEDIUM, "Only one command can be specified: '%s'", ValueUnion.psz);
cmd = CMD_FLOPPY;
break;
case VINF_GETOPT_NOT_OPTION:
if (!FilenameOrUuid)
FilenameOrUuid = ValueUnion.psz;
else
return errorSyntax(USAGE_CLOSEMEDIUM, "Invalid parameter '%s'", ValueUnion.psz);
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
return errorSyntax(USAGE_CLOSEMEDIUM, "Invalid option -%c", c);
else
return errorSyntax(USAGE_CLOSEMEDIUM, "Invalid option case %i", c);
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
return errorSyntax(USAGE_CLOSEMEDIUM, "unknown option: %s\n", ValueUnion.psz);
else if (ValueUnion.pDef)
return errorSyntax(USAGE_CLOSEMEDIUM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
else
return errorSyntax(USAGE_CLOSEMEDIUM, "error: %Rrs", c);
}
}
/* check for required options */
if (cmd == CMD_NONE)
return errorSyntax(USAGE_CLOSEMEDIUM, "Command variant disk/dvd/floppy required");
if (!FilenameOrUuid)
return errorSyntax(USAGE_CLOSEMEDIUM, "Disk name or UUID required");
/* first guess is that it's a UUID */
Bstr uuid(FilenameOrUuid);
if (cmd == CMD_DISK)
{
ComPtr<IHardDisk> hardDisk;
rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
/* not a UUID or not registered? Then it must be a filename */
if (!hardDisk)
{
CHECK_ERROR(a->virtualBox, FindHardDisk(Bstr(FilenameOrUuid), hardDisk.asOutParam()));
}
if (SUCCEEDED(rc) && hardDisk)
{
CHECK_ERROR(hardDisk, Close());
}
}
else
if (cmd == CMD_DVD)
{
ComPtr<IDVDImage> dvdImage;
rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
/* not a UUID or not registered? Then it must be a filename */
if (!dvdImage)
{
CHECK_ERROR(a->virtualBox, FindDVDImage(Bstr(FilenameOrUuid), dvdImage.asOutParam()));
}
if (SUCCEEDED(rc) && dvdImage)
{
CHECK_ERROR(dvdImage, Close());
}
}
else
if (cmd == CMD_FLOPPY)
{
ComPtr<IFloppyImage> floppyImage;
rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
/* not a UUID or not registered? Then it must be a filename */
if (!floppyImage)
{
CHECK_ERROR(a->virtualBox, FindFloppyImage(Bstr(FilenameOrUuid), floppyImage.asOutParam()));
}
if (SUCCEEDED(rc) && floppyImage)
{
CHECK_ERROR(floppyImage, Close());
}
}
return SUCCEEDED(rc) ? 0 : 1;
}
#endif /* !VBOX_ONLY_DOCS */