Index: /trunk/src/VBox/Storage/testcase/vbox-img.cpp
===================================================================
--- /trunk/src/VBox/Storage/testcase/vbox-img.cpp	(revision 51285)
+++ /trunk/src/VBox/Storage/testcase/vbox-img.cpp	(revision 51286)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -35,5 +35,5 @@
 #include <iprt/vfs.h>
 
-const char *g_pszProgName = "";
+static const char *g_pszProgName = "";
 static void printUsage(PRTSTREAM pStrm)
 {
@@ -45,4 +45,11 @@
                  "                [--parentuuid <uuid>]\n"
                  "                [--zeroparentuuid]\n"
+                 "\n"
+                 "   geometry     --filename <filename>\n"
+                 "                [--format VDI|VMDK|VHD|...]\n"
+                 "                [--clearchs]\n"
+                 "                [--cylinders <number>]\n"
+                 "                [--heads <number>]\n"
+                 "                [--sectors <number>]\n"
                  "\n"
                  "   convert      --srcfilename <filename>\n"
@@ -75,5 +82,5 @@
 }
 
-void showLogo(PRTSTREAM pStrm)
+static void showLogo(PRTSTREAM pStrm)
 {
     static bool s_fShown; /* show only once */
@@ -96,5 +103,5 @@
 };
 
-PVDINTERFACE pVDIfs;
+static PVDINTERFACE pVDIfs;
 
 static DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL,
@@ -116,5 +123,5 @@
  * Print a usage synopsis and the syntax error message.
  */
-int errorSyntax(const char *pszFormat, ...)
+static int errorSyntax(const char *pszFormat, ...)
 {
     va_list args;
@@ -127,5 +134,5 @@
 }
 
-int errorRuntime(const char *pszFormat, ...)
+static int errorRuntime(const char *pszFormat, ...)
 {
     va_list args;
@@ -185,5 +192,5 @@
 
 
-int handleSetUUID(HandlerArg *a)
+static int handleSetUUID(HandlerArg *a)
 {
     const char *pszFilename = NULL;
@@ -301,4 +308,137 @@
         if (RT_FAILURE(rc))
             return errorRuntime("Cannot set parent UUID of virtual disk image \"%s\": %Rrc\n",
+                                pszFilename, rc);
+    }
+
+    VDDestroy(pVD);
+
+    if (pszFormat)
+    {
+        RTStrFree(pszFormat);
+        pszFormat = NULL;
+    }
+
+    return 0;
+}
+
+
+static int handleGeometry(HandlerArg *a)
+{
+    const char *pszFilename = NULL;
+    char *pszFormat = NULL;
+    VDTYPE enmType = VDTYPE_INVALID;
+    uint16_t cCylinders = 0;
+    uint8_t cHeads = 0;
+    uint8_t cSectors = 0;
+    bool fCylinders = false;
+    bool fHeads = false;
+    bool fSectors = false;
+    int rc;
+
+    /* Parse the command line. */
+    static const RTGETOPTDEF s_aOptions[] =
+    {
+        { "--filename", 'f', RTGETOPT_REQ_STRING },
+        { "--format", 'o', RTGETOPT_REQ_STRING },
+        { "--clearchs", 'C', RTGETOPT_REQ_NOTHING },
+        { "--cylinders", 'c', RTGETOPT_REQ_UINT16 },
+        { "--heads", 'e', RTGETOPT_REQ_UINT8 },
+        { "--sectors", 's', RTGETOPT_REQ_UINT8 }
+    };
+    int ch;
+    RTGETOPTUNION ValueUnion;
+    RTGETOPTSTATE GetState;
+    RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0 /* fFlags */);
+    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
+    {
+        switch (ch)
+        {
+            case 'f':   // --filename
+                pszFilename = ValueUnion.psz;
+                break;
+            case 'o':   // --format
+                pszFormat = RTStrDup(ValueUnion.psz);
+                break;
+            case 'C':   // --clearchs
+                cCylinders = 0;
+                cHeads = 0;
+                cSectors = 0;
+                fCylinders = true;
+                fHeads = true;
+                fSectors = true;
+                break;
+            case 'c':   // --cylinders
+                cCylinders = ValueUnion.u16;
+                fCylinders = true;
+                break;
+            case 'e':   // --heads
+                cHeads = ValueUnion.u8;
+                fHeads = true;
+                break;
+            case 's':   // --sectors
+                cSectors = ValueUnion.u8;
+                fSectors = true;
+                break;
+
+            default:
+                ch = RTGetOptPrintError(ch, &ValueUnion);
+                printUsage(g_pStdErr);
+                return ch;
+        }
+    }
+
+    /* Check for mandatory parameters. */
+    if (!pszFilename)
+        return errorSyntax("Mandatory --filename option missing\n");
+
+    /* Autodetect image format. */
+    if (!pszFormat)
+    {
+        /* Don't pass error interface, as that would triggers error messages
+         * because some backends fail to open the image. */
+        rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
+        if (RT_FAILURE(rc))
+            return errorRuntime("Format autodetect failed: %Rrc\n", rc);
+    }
+
+    PVBOXHDD pVD = NULL;
+    rc = VDCreate(pVDIfs, enmType, &pVD);
+    if (RT_FAILURE(rc))
+        return errorRuntime("Cannot create the virtual disk container: %Rrc\n", rc);
+
+    /* Open in info mode to be able to open diff images without their parent. */
+    rc = VDOpen(pVD, pszFormat, pszFilename, VD_OPEN_FLAGS_INFO, NULL);
+    if (RT_FAILURE(rc))
+        return errorRuntime("Cannot open the virtual disk image \"%s\": %Rrc\n",
+                            pszFilename, rc);
+
+    VDGEOMETRY oldLCHSGeometry;
+    rc = VDGetLCHSGeometry(pVD, VD_LAST_IMAGE, &oldLCHSGeometry);
+    if (rc == VERR_VD_GEOMETRY_NOT_SET)
+    {
+        memset(&oldLCHSGeometry, 0, sizeof(oldLCHSGeometry));
+        rc = VINF_SUCCESS;
+    }
+    if (RT_FAILURE(rc))
+        return errorRuntime("Cannot get LCHS geometry of virtual disk image \"%s\": %Rrc\n",
+                            pszFilename, rc);
+
+    RTPrintf("Old image LCHS: %u/%u/%u\n", oldLCHSGeometry.cCylinders, oldLCHSGeometry.cHeads, oldLCHSGeometry.cSectors);
+
+    VDGEOMETRY newLCHSGeometry = oldLCHSGeometry;
+    if (fCylinders)
+        newLCHSGeometry.cCylinders = cCylinders;
+    if (fHeads)
+        newLCHSGeometry.cHeads = cHeads;
+    if (fSectors)
+        newLCHSGeometry.cSectors = cSectors;
+
+    if (fCylinders || fHeads || fSectors)
+    {
+        RTPrintf("New image LCHS: %u/%u/%u\n", newLCHSGeometry.cCylinders, newLCHSGeometry.cHeads, newLCHSGeometry.cSectors);
+
+        rc = VDSetLCHSGeometry(pVD, VD_LAST_IMAGE, &newLCHSGeometry);
+        if (RT_FAILURE(rc))
+            return errorRuntime("Cannot set LCHS geometry of virtual disk image \"%s\": %Rrc\n",
                                 pszFilename, rc);
     }
@@ -688,5 +828,5 @@
 }
 
-int handleConvert(HandlerArg *a)
+static int handleConvert(HandlerArg *a)
 {
     const char *pszSrcFilename = NULL;
@@ -914,5 +1054,5 @@
 
 
-int handleInfo(HandlerArg *a)
+static int handleInfo(HandlerArg *a)
 {
     int rc = VINF_SUCCESS;
@@ -1063,5 +1203,5 @@
 } VBOXIMGVFS, *PVBOXIMGVFS;
 
-int handleCompact(HandlerArg *a)
+static int handleCompact(HandlerArg *a)
 {
     int rc = VINF_SUCCESS;
@@ -1244,5 +1384,5 @@
 
 
-int handleCreateCache(HandlerArg *a)
+static int handleCreateCache(HandlerArg *a)
 {
     int rc = VINF_SUCCESS;
@@ -1339,5 +1479,5 @@
 }
 
-int handleCreateBase(HandlerArg *a)
+static int handleCreateBase(HandlerArg *a)
 {
     int rc = VINF_SUCCESS;
@@ -1353,6 +1493,6 @@
     VDINTERFACECONFIG vdIfCfg;
 
-    memset(&LCHSGeometry, 0, sizeof(VDGEOMETRY));
-    memset(&PCHSGeometry, 0, sizeof(VDGEOMETRY));
+    memset(&LCHSGeometry, 0, sizeof(LCHSGeometry));
+    memset(&PCHSGeometry, 0, sizeof(PCHSGeometry));
 
     /* Parse the command line. */
@@ -1441,5 +1581,5 @@
 
 
-int handleRepair(HandlerArg *a)
+static int handleRepair(HandlerArg *a)
 {
     int rc = VINF_SUCCESS;
@@ -1508,5 +1648,5 @@
 
 
-int handleClearComment(HandlerArg *a)
+static int handleClearComment(HandlerArg *a)
 {
     int rc = VINF_SUCCESS;
@@ -1649,4 +1789,5 @@
     {
         { "setuuid",      handleSetUUID      },
+        { "geometry",     handleGeometry     },
         { "convert",      handleConvert      },
         { "info",         handleInfo         },
