VBoxManageDisk.cpp revision 53c715b46bccd175005ee523f7acc7962cfcdf94
/* $Id$ */
/** @file
* VBoxManage - The disk related commands.
*/
/*
* Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef VBOX_ONLY_DOCS
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "VBoxManage.h"
using namespace com;
// funcs
///////////////////////////////////////////////////////////////////////////////
static DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
{
}
{
int rc = VINF_SUCCESS;
unsigned DiskVariant = (unsigned)(*pDiskVariant);
{
if (pszComma)
else
if (len > 0)
{
// Parsing is intentionally inconsistent: "standard" resets the
// variant, whereas the other flags are cumulative.
else
}
if (pszComma)
else
}
if (RT_SUCCESS(rc))
return rc;
}
{
int rc = VINF_SUCCESS;
else
if (RT_SUCCESS(rc))
return rc;
}
/** @todo move this into getopt, as getting bool values is generic */
{
int rc = VINF_SUCCESS;
{
*pb = true;
}
{
*pb = false;
}
else
return rc;
}
static const RTGETOPTDEF g_aCreateHardDiskOptions[] =
{
};
int handleCreateHardDisk(HandlerArg *a)
{
int vrc;
bool fRemember = false;
int c;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aCreateHardDiskOptions, RT_ELEMENTS(g_aCreateHardDiskOptions),
{
switch (c)
{
case 'f': // --filename
break;
case 's': // --size
break;
case 'S': // --sizebyte
break;
case 'o': // --format
break;
case 'F': // --static ("fixed"/"flat")
{
unsigned uDiskVariant = (unsigned)DiskVariant;
break;
}
case 'm': // --variant
if (RT_FAILURE(vrc))
break;
case 'c': // --comment
break;
case 'r': // --remember
fRemember = true;
break;
case 't': // --type
if ( RT_FAILURE(vrc)
|| ( DiskType != MediumType_Normal
&& DiskType != MediumType_Shareable))
break;
case VINF_GETOPT_NOT_OPTION:
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
/* check the outcome */
|| size == 0)
/* check for filename extension */
{
else
}
hardDisk.asOutParam()));
{
/* we will close the hard disk after the storage has been successfully
* created unless fRemember is set */
bool doClose = false;
{
}
{
{
if (info.isBasicAvailable())
else
RTMsgError("Failed to create hard disk. No error message available!");
}
else
{
if ( DiskType == MediumType_Writethrough
|| DiskType == MediumType_Shareable)
{
}
}
}
if (doClose)
{
}
}
}
static const RTGETOPTDEF g_aModifyHardDiskOptions[] =
{
};
int handleModifyHardDisk(HandlerArg *a)
{
int vrc;
bool AutoReset = false;
bool fModifyResize = false;
const char *FilenameOrUuid = NULL;
int c;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aModifyHardDiskOptions, RT_ELEMENTS(g_aModifyHardDiskOptions),
{
switch (c)
{
case 't': // --type
if (RT_FAILURE(vrc))
fModifyDiskType = true;
break;
case 'z': // --autoreset
if (RT_FAILURE(vrc))
fModifyAutoReset = true;
break;
case 'c': // --compact
fModifyCompact = true;
break;
case 'r': // --resize
fModifyResize = true;
break;
case VINF_GETOPT_NOT_OPTION:
if (!FilenameOrUuid)
else
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
if (!FilenameOrUuid)
/* first guess is that it's a UUID */
hardDisk.asOutParam()));
return 1;
if (fModifyDiskType)
{
/* hard disk must be registered */
{
}
else
return errorArgument("Hard disk image not registered");
}
if (fModifyAutoReset)
{
}
if (fModifyCompact)
{
bool unknown = false;
/* the hard disk image might not be registered */
if (!hardDisk)
{
unknown = true;
hardDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
if (RT_FAILURE(irc))
{
return 1;
}
hardDisk.asOutParam()));
}
}
{
{
RTMsgError("Compact hard disk operation is not implemented!");
else if (rc == VBOX_E_NOT_SUPPORTED)
RTMsgError("Compact hard disk operation for this format is not implemented yet!");
else
}
if (unknown)
}
}
if (fModifyResize)
{
bool unknown = false;
/* the hard disk image might not be registered */
if (!hardDisk)
{
unknown = true;
hardDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
if (RT_FAILURE(irc))
{
return 1;
}
hardDisk.asOutParam()));
}
}
{
{
RTMsgError("Resize hard disk operation is not implemented!");
else if (rc == VBOX_E_NOT_SUPPORTED)
RTMsgError("Resize hard disk operation for this format is not implemented yet!");
else
}
if (unknown)
}
}
}
static const RTGETOPTDEF g_aCloneHardDiskOptions[] =
{
};
int handleCloneHardDisk(HandlerArg *a)
{
int vrc;
bool fExisting = false;
bool fRemember = false;
bool fSetDiskType = false;
int c;
// start at 0 because main() has hacked both the argc and argv given to us
RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneHardDiskOptions, RT_ELEMENTS(g_aCloneHardDiskOptions),
{
switch (c)
{
case 'o': // --format
break;
case 'F': // --static
{
unsigned uDiskVariant = (unsigned)DiskVariant;
break;
}
case 'E': // --existing
fExisting = true;
break;
case 'm': // --variant
if (RT_FAILURE(vrc))
break;
case 'r': // --remember
fRemember = true;
break;
case 't': // --type
if (RT_FAILURE(vrc))
fSetDiskType = true;
break;
case VINF_GETOPT_NOT_OPTION:
else
break;
default:
if (c > 0)
{
if (RT_C_IS_GRAPH(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
bool fSrcUnknown = false;
bool fDstUnknown = false;
srcDisk.asOutParam());
/* no? well, then it's an unknown image */
{
srcDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
if (RT_FAILURE(irc))
{
return 1;
}
srcDisk.asOutParam()));
}
fSrcUnknown = true;
else
{
return 1;
}
}
do
{
if (fExisting)
{
dstDisk.asOutParam());
/* no? well, then it's an unknown image */
{
dstDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
if (RT_FAILURE(irc))
{
return 1;
}
dstDisk.asOutParam()));
}
fDstUnknown = true;
else
{
break;
}
}
else
fRemember = true;
{
/* Perform accessibility check now. */
}
}
else
{
/* use the format of the source hard disk if unspecified */
dstDisk.asOutParam()));
}
{
if (info.isBasicAvailable())
else
RTMsgError("Failed to clone hard disk. No error message available!");
break;
}
RTPrintf("Clone hard disk created in format '%ls'. UUID: %s\n",
}
while (0);
{
/* forget the created clone */
}
else if (fSetDiskType)
{
}
if (fSrcUnknown)
{
/* close the unknown hard disk to forget it again */
}
}
static const RTGETOPTDEF g_aConvertFromRawHardDiskOptions[] =
{
};
{
int rc = VINF_SUCCESS;
bool fReadFromStdIn = false;
const char *format = "VDI";
const char *srcfilename = NULL;
const char *dstfilename = NULL;
unsigned uImageFlags = VD_IMAGE_FLAGS_NONE;
int c;
// 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),
{
switch (c)
{
case 'o': // --format
break;
case 'm': // --variant
if (RT_FAILURE(rc))
/// @todo cleaner solution than assuming 1:1 mapping?
uImageFlags = (unsigned)DiskVariant;
break;
case VINF_GETOPT_NOT_OPTION:
if (!srcfilename)
{
// If you change the OS list here don't forget to update VBoxManageHelp.cpp.
#ifndef RT_OS_WINDOWS
#endif
}
else if (!dstfilename)
else if (fReadFromStdIn && !filesize)
else
break;
default:
}
}
/* open raw image file. */
if (fReadFromStdIn)
File = 0;
else
if (RT_FAILURE(rc))
{
goto out;
}
/* get image size. */
if (fReadFromStdIn)
else
if (RT_FAILURE(rc))
{
goto out;
}
char pszComment[256];
if (RT_FAILURE(rc))
{
goto out;
}
LCHS.cCylinders = 0;
if (RT_FAILURE(rc))
{
goto out;
}
if (!pvBuf)
{
rc = VERR_NO_MEMORY;
goto out;
}
offFile = 0;
{
cbRead = 0;
break;
if (RT_FAILURE(rc))
{
goto out;
}
}
out:
if (pvBuf)
if (pDisk)
if (File != NIL_RTFILE)
}
static const RTGETOPTDEF g_aAddiSCSIDiskOptions[] =
{
};
int handleAddiSCSIDisk(HandlerArg *a)
{
int vrc;
bool fIntNet = false;
int c;
// 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),
{
switch (c)
{
case 's': // --server
break;
case 'T': // --target
break;
case 'p': // --port
break;
case 'l': // --lun
break;
case 'L': // --encodedlun
break;
case 'u': // --username
break;
case 'P': // --password
break;
case 't': // --type
if (RT_FAILURE(vrc))
break;
case 'I': // --intnet
fIntNet = true;
break;
case VINF_GETOPT_NOT_OPTION:
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
/* check for required options */
do
{
/** @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 containing information will be shown. */
{
BstrFmt("%ls|%ls",
hardDisk.asOutParam()));
}
else
{
BstrFmt("%ls|%ls|%ls",
hardDisk.asOutParam()));
}
{
}
{
}
{
}
/// @todo add --initiator option - until that happens rely on the
// defaults of the iSCSI initiator code. Setting it to a constant
// value does more harm than good, as the initiator name is supposed
// to identify a particular initiator uniquely.
// Bstr("InitiatorName").detachTo(names.appendedRaw());
// Bstr("iqn.2008-04.com.sun.virtualbox.initiator").detachTo(values.appendedRaw());
/// @todo add --targetName and --targetPassword options
if (fIntNet)
{
}
if (DiskType != MediumType_Normal)
{
}
}
while (0);
}
static const RTGETOPTDEF g_aShowHardDiskInfoOptions[] =
{
};
int handleShowHardDiskInfo(HandlerArg *a)
{
const char *FilenameOrUuid = NULL;
int c;
// 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),
{
switch (c)
{
case VINF_GETOPT_NOT_OPTION:
if (!FilenameOrUuid)
else
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
/* check for required options */
if (!FilenameOrUuid)
bool unknown = false;
/* first guess is that it's a UUID */
hardDisk.asOutParam());
/* no? well, then it's an unknown image */
{
hardDisk.asOutParam());
if (rc == VBOX_E_FILE_ERROR)
{
if (RT_FAILURE(vrc))
{
return 1;
}
hardDisk.asOutParam()));
}
unknown = true;
else
{
return 1;
}
}
do
{
/* check for accessibility */
/// @todo NEWMEDIA check accessibility of all parents
/// @todo NEWMEDIA print the full state value
if (state == MediumState_Inaccessible)
{
}
if (!description.isEmpty())
{
}
const char *typeStr = "unknown";
switch (type)
{
case MediumType_Normal:
typeStr = "normal (differencing)";
else
typeStr = "normal (base)";
break;
case MediumType_Immutable:
typeStr = "immutable";
break;
case MediumType_Writethrough:
typeStr = "writethrough";
break;
case MediumType_Shareable:
typeStr = "shareable";
break;
}
/// @todo also dump config parameters (iSCSI)
if (!unknown)
{
{
RTPrintf("%s%lS (UUID: %lS)\n",
j == 0 ? "In use by VMs: " : " ",
}
/// @todo NEWMEDIA check usage in snapshots too
/// @todo NEWMEDIA also list children
}
/* print out information specific for differencing hard disks */
{
}
}
while (0);
if (unknown)
{
/* close the unknown hard disk to forget it again */
}
}
static const RTGETOPTDEF g_aCloseMediumOptions[] =
{
};
int handleCloseMedium(HandlerArg *a)
{
enum {
const char *FilenameOrUuid = NULL;
bool fDelete = false;
int c;
// 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),
{
switch (c)
{
case 'd': // disk
break;
case 'D': // DVD
break;
case 'f': // floppy
cmd = CMD_FLOPPY;
break;
case 'r': // --delete
fDelete = true;
break;
case VINF_GETOPT_NOT_OPTION:
if (!FilenameOrUuid)
else
break;
default:
if (c > 0)
{
if (RT_C_IS_PRINT(c))
else
}
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
}
}
/* check for required options */
if (!FilenameOrUuid)
medium.asOutParam()));
medium.asOutParam()));
else if (cmd == CMD_FLOPPY)
medium.asOutParam()));
{
if (fDelete)
{
{
{
if (info.isBasicAvailable())
else
RTMsgError("Failed to delete medium. No error message available!");
}
}
else
}
}
}
#endif /* !VBOX_ONLY_DOCS */