diff options
Diffstat (limited to 'src/VBox/Storage/VHD.cpp')
| -rw-r--r-- | src/VBox/Storage/VHD.cpp | 126 |
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; |
