Index: trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 27525)
+++ trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 27531)
@@ -599,9 +599,14 @@
     }
 #else
+    unsigned uOpenFlags = 0;
+
+    if ((fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ)
+        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY;
+    if ((fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE)
+        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
+
     rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
                                                         pszFilename,
-                                                        pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY
-                                                        ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
-                                                        : 0,
+                                                        uOpenFlags,
                                                         NULL,
                                                         pImage->pVDIfsDisk,
@@ -2455,5 +2460,4 @@
         uOffset = VMDK_SECTOR2BYTE(pImage->pExtents[0].uDescriptorSector);
         cbLimit = VMDK_SECTOR2BYTE(pImage->pExtents[0].cDescriptorSectors);
-        cbLimit += uOffset;
         pDescFile = pImage->pExtents[0].pFile;
     }
@@ -2461,4 +2465,17 @@
     if (pDescFile == NULL)
         return VERR_INVALID_PARAMETER;
+
+    /*
+     * Allocate temporary descriptor buffer.
+     * In case there is no limit allocate a default
+     * and increase if required.
+     */
+    size_t cbDescriptor = cbLimit ? cbLimit : 4 * _1K;
+    char *pszDescriptor = (char *)RTMemAllocZ(cbDescriptor);
+    unsigned offDescriptor = 0;
+
+    if (!pszDescriptor)
+        return VERR_NO_MEMORY;
+
     for (unsigned i = 0; i < pImage->Descriptor.cLines; i++)
     {
@@ -2466,38 +2483,61 @@
         size_t cb = strlen(psz);
 
-        if (cbLimit && uOffset + cb + 1 > cbLimit)
-            return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename);
+        /*
+         * Increase the descriptor if there is no limit and
+         * there is not enough room left for this line.
+         */
+        if (offDescriptor + cb + 1 > cbDescriptor)
+        {
+            if (cbLimit)
+            {
+                rc = vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename);
+                break;
+            }
+            else
+            {
+                char *pszDescriptorNew = NULL;
+                LogFlow(("Increasing descriptor cache\n"));
+
+                pszDescriptorNew = (char *)RTMemAllocZ(cbDescriptor + cb + 4 * _1K);
+                if (!pszDescriptorNew)
+                {
+                    rc = VERR_NO_MEMORY;
+                    break;
+                }
+                memcpy(pszDescriptorNew, pszDescriptor, cbDescriptor);
+                RTMemFree(pszDescriptor);
+                pszDescriptorNew = pszDescriptor;
+                cbDescriptor += cb + 4 * _1K;
+            }
+        }
 
         if (cb > 0)
         {
-            rc = vmdkFileWriteAt(pDescFile, uOffset, psz, cb, NULL);
-            if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
-            uOffset += cb;
-        }
-
-        rc = vmdkFileWriteAt(pDescFile, uOffset, "\n", 1, NULL);
+            memcpy(pszDescriptor + offDescriptor, psz, cb);
+            offDescriptor += cb;
+        }
+
+        memcpy(pszDescriptor + offDescriptor, "\n", 1);
+        offDescriptor++;
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        rc = vmdkFileWriteAt(pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
-        uOffset++;
-    }
-    if (cbLimit)
-    {
-        /* Inefficient, but simple. */
-        while (uOffset < cbLimit)
-        {
-            rc = vmdkFileWriteAt(pDescFile, uOffset, "", 1, NULL);
-            if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
-            uOffset++;
-        }
-    }
-    else
-    {
-        rc = vmdkFileSetSize(pDescFile, uOffset);
+            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
+    }
+
+    if (RT_SUCCESS(rc) && !cbLimit)
+    {
+        rc = vmdkFileSetSize(pDescFile, offDescriptor);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
-    }
-    pImage->Descriptor.fDirty = false;
+            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
+    }
+
+    if (RT_SUCCESS(rc))
+        pImage->Descriptor.fDirty = false;
+
+    RTMemFree(pszDescriptor);
     return rc;
 }
