summaryrefslogtreecommitdiff
path: root/src/VBox/Storage/VHD.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Storage/VHD.cpp')
-rw-r--r--src/VBox/Storage/VHD.cpp126
1 files changed, 78 insertions, 48 deletions
diff --git a/src/VBox/Storage/VHD.cpp b/src/VBox/Storage/VHD.cpp
index c246727e8..9a4d3a958 100644
--- a/src/VBox/Storage/VHD.cpp
+++ b/src/VBox/Storage/VHD.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -304,37 +304,68 @@ static int vhdLocatorUpdate(PVHDIMAGE pImage, PVHDPLE pLocator, const char *pszF
char *pszTmp;
if (!pvBuf)
- {
- rc = VERR_NO_MEMORY;
- goto out;
- }
+ return VERR_NO_MEMORY;
switch (RT_BE2H_U32(pLocator->u32Code))
{
case VHD_PLATFORM_CODE_WI2R:
- /* Update plain relative name. */
- cb = (uint32_t)strlen(pszFilename);
- if (cb > cbMaxLen)
+ {
+ if (RTPathStartsWithRoot(pszFilename))
{
- rc = VERR_FILENAME_TOO_LONG;
- goto out;
+ /* Convert to relative path. */
+ char szPath[RTPATH_MAX];
+ rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename,
+ pszFilename);
+ if (RT_SUCCESS(rc))
+ {
+ /* Update plain relative name. */
+ cb = (uint32_t)strlen(szPath);
+ if (cb > cbMaxLen)
+ {
+ rc = VERR_FILENAME_TOO_LONG;
+ break;
+ }
+ memcpy(pvBuf, szPath, cb);
+ }
+ }
+ else
+ {
+ /* Update plain relative name. */
+ cb = (uint32_t)strlen(pszFilename);
+ if (cb > cbMaxLen)
+ {
+ rc = VERR_FILENAME_TOO_LONG;
+ break;
+ }
+ memcpy(pvBuf, pszFilename, cb);
}
- memcpy(pvBuf, pszFilename, cb);
pLocator->u32DataLength = RT_H2BE_U32(cb);
break;
+ }
case VHD_PLATFORM_CODE_WI2K:
/* Update plain absolute name. */
rc = RTPathAbs(pszFilename, (char *)pvBuf, cbMaxLen);
- if (RT_FAILURE(rc))
- goto out;
- pLocator->u32DataLength = RT_H2BE_U32((uint32_t)strlen((const char *)pvBuf));
+ if (RT_SUCCESS(rc))
+ pLocator->u32DataLength = RT_H2BE_U32((uint32_t)strlen((const char *)pvBuf));
break;
case VHD_PLATFORM_CODE_W2RU:
- /* Update unicode relative name. */
- rc = vhdFilenameToUtf16(pszFilename, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
- if (RT_FAILURE(rc))
- goto out;
- pLocator->u32DataLength = RT_H2BE_U32(cb);
+ if (RTPathStartsWithRoot(pszFilename))
+ {
+ /* Convert to relative path. */
+ char szPath[RTPATH_MAX];
+ rc = RTPathCalcRelative(szPath, sizeof(szPath), pImage->pszFilename,
+ pszFilename);
+ if (RT_SUCCESS(rc))
+ rc = vhdFilenameToUtf16(szPath, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
+ }
+ else
+ {
+ /* Update unicode relative name. */
+ rc = vhdFilenameToUtf16(pszFilename, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
+ }
+
+ if (RT_SUCCESS(rc))
+ pLocator->u32DataLength = RT_H2BE_U32(cb);
break;
case VHD_PLATFORM_CODE_W2KU:
/* Update unicode absolute name. */
@@ -342,30 +373,30 @@ static int vhdLocatorUpdate(PVHDIMAGE pImage, PVHDPLE pLocator, const char *pszF
if (!pszTmp)
{
rc = VERR_NO_MEMORY;
- goto out;
+ break;
}
rc = RTPathAbs(pszFilename, pszTmp, cbMaxLen);
if (RT_FAILURE(rc))
{
RTMemTmpFree(pszTmp);
- goto out;
+ break;
}
rc = vhdFilenameToUtf16(pszTmp, (uint16_t *)pvBuf, cbMaxLen, &cb, false);
RTMemTmpFree(pszTmp);
- if (RT_FAILURE(rc))
- goto out;
- pLocator->u32DataLength = RT_H2BE_U32(cb);
+ if (RT_SUCCESS(rc))
+ pLocator->u32DataLength = RT_H2BE_U32(cb);
break;
default:
rc = VERR_NOT_IMPLEMENTED;
- goto out;
+ break;
}
- rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
- RT_BE2H_U64(pLocator->u64DataOffset),
- pvBuf, RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE,
- NULL);
-out:
+ if (RT_SUCCESS(rc))
+ rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
+ RT_BE2H_U64(pLocator->u64DataOffset),
+ pvBuf, RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE,
+ NULL);
+
if (pvBuf)
RTMemTmpFree(pvBuf);
return rc;
@@ -958,29 +989,26 @@ static void vhdSetDiskGeometry(PVHDIMAGE pImage, uint64_t cbSize)
static uint32_t vhdAllocateParentLocators(PVHDIMAGE pImage, VHDDynamicDiskHeader *pDDH, uint64_t u64Offset)
{
PVHDPLE pLocator = pDDH->ParentLocatorEntry;
- /* Relative Windows path. */
- pLocator->u32Code = RT_H2BE_U32(VHD_PLATFORM_CODE_WI2R);
- pLocator->u32DataSpace = RT_H2BE_U32(VHD_RELATIVE_MAX_PATH / VHD_SECTOR_SIZE);
- pLocator->u64DataOffset = RT_H2BE_U64(u64Offset);
- u64Offset += VHD_RELATIVE_MAX_PATH;
- pLocator++;
- /* Absolute Windows path. */
- pLocator->u32Code = RT_H2BE_U32(VHD_PLATFORM_CODE_WI2K);
- pLocator->u32DataSpace = RT_H2BE_U32(VHD_ABSOLUTE_MAX_PATH / VHD_SECTOR_SIZE);
+
+ /*
+ * The VHD spec states that the DataSpace field holds the number of sectors
+ * required to store the parent locator path.
+ * As it turned out VPC and Hyper-V store the amount of bytes reserved for the
+ * path and not the number of sectors.
+ */
+
+ /* Unicode absolute Windows path. */
+ pLocator->u32Code = RT_H2BE_U32(VHD_PLATFORM_CODE_W2KU);
+ pLocator->u32DataSpace = RT_H2BE_U32(VHD_ABSOLUTE_MAX_PATH * sizeof(RTUTF16));
pLocator->u64DataOffset = RT_H2BE_U64(u64Offset);
- u64Offset += VHD_ABSOLUTE_MAX_PATH;
pLocator++;
+ u64Offset += VHD_ABSOLUTE_MAX_PATH * sizeof(RTUTF16);
/* Unicode relative Windows path. */
pLocator->u32Code = RT_H2BE_U32(VHD_PLATFORM_CODE_W2RU);
- pLocator->u32DataSpace = RT_H2BE_U32(VHD_RELATIVE_MAX_PATH * sizeof(RTUTF16) / VHD_SECTOR_SIZE);
+ pLocator->u32DataSpace = RT_H2BE_U32(VHD_RELATIVE_MAX_PATH * sizeof(RTUTF16));
pLocator->u64DataOffset = RT_H2BE_U64(u64Offset);
u64Offset += VHD_RELATIVE_MAX_PATH * sizeof(RTUTF16);
- pLocator++;
- /* Unicode absolute Windows path. */
- pLocator->u32Code = RT_H2BE_U32(VHD_PLATFORM_CODE_W2KU);
- pLocator->u32DataSpace = RT_H2BE_U32(VHD_ABSOLUTE_MAX_PATH * sizeof(RTUTF16) / VHD_SECTOR_SIZE);
- pLocator->u64DataOffset = RT_H2BE_U64(u64Offset);
- return u64Offset + VHD_ABSOLUTE_MAX_PATH * sizeof(RTUTF16);
+ return u64Offset;
}
/**
@@ -1924,7 +1952,9 @@ static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
int rc;
/* Image must be opened and the new flags must be valid. */
- if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
+ if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
+ | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
+ | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
{
rc = VERR_INVALID_PARAMETER;
goto out;