Changeset 12306 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Sep 9, 2008 3:51:08 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r11484 r12306 77 77 /** 78 78 * Magic number for hosted images created by VMware Workstation 4, VMware 79 * Workstation 5, VMware Server or VMware Player. 79 * Workstation 5, VMware Server or VMware Player. Not necessarily sparse. 80 80 */ 81 81 #define VMDK_SPARSE_MAGICNUMBER 0x564d444b /* 'V' 'M' 'D' 'K' */ 82 82 83 /** VMDK hosted sparse extent header. */ 83 /** 84 * VMDK hosted binary extent header. The "Sparse" is a total misnomer, as 85 * this header is also used for monolithic flat images. 86 */ 84 87 #pragma pack(1) 85 88 typedef struct SparseExtentHeader … … 784 787 size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t); 785 788 789 if (pExtent->enmType != VMDKETYPE_HOSTED_SPARSE) 790 goto out; 791 786 792 pGD = (uint32_t *)RTMemAllocZ(cbGD); 787 793 if (!pGD) … … 1453 1459 pDescriptor->aLines[cLine] = pTmp; 1454 1460 1455 if (strcmp(pDescriptor->aLines[0], "# Disk DescriptorFile")) 1461 if ( strcmp(pDescriptor->aLines[0], "# Disk DescriptorFile") 1462 && strcmp(pDescriptor->aLines[0], "# Disk Descriptor File")) 1456 1463 { 1457 1464 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor does not start as expected in '%s'"), pImage->pszFilename); … … 2016 2023 2017 2024 /** 2018 * Internal: read metadata belonging to a sparse extent. 2025 * Internal: read metadata belonging to an extent with binary header, i.e. 2026 * as found in monolithic files. 2019 2027 */ 2020 static int vmdkRead MetaSparseExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)2028 static int vmdkReadBinaryMetaExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent) 2021 2029 { 2022 2030 SparseExtentHeader Header; 2023 uint64_t c bExtentSize, cSectorsPerGDE;2031 uint64_t cSectorsPerGDE; 2024 2032 2025 2033 int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); … … 2034 2042 { 2035 2043 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect magic/version in extent header in '%s'"), pExtent->pszFullname); 2036 goto out;2037 }2038 /* The image must be a multiple of a sector in size. If not, it means the2039 * image is at least truncated, or even seriously garbled. */2040 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);2041 if (RT_FAILURE(rc))2042 {2043 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);2044 2044 goto out; 2045 2045 } … … 2053 2053 goto out; 2054 2054 } 2055 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; 2055 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; /* Just dummy value, changed later. */ 2056 2056 pExtent->cSectors = RT_LE2H_U64(Header.capacity); 2057 2057 pExtent->cSectorsPerGrain = RT_LE2H_U64(Header.grainSize); 2058 pExtent->uDescriptorSector = RT_LE2H_U64(Header.descriptorOffset); 2059 pExtent->cDescriptorSectors = RT_LE2H_U64(Header.descriptorSize); 2060 if (pExtent->uDescriptorSector && !pExtent->cDescriptorSectors) 2061 { 2062 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname); 2063 goto out; 2064 } 2065 pExtent->cGTEntries = RT_LE2H_U32(Header.numGTEsPerGT); 2066 if (RT_LE2H_U32(Header.flags) & 2) 2067 { 2068 pExtent->uSectorRGD = RT_LE2H_U64(Header.rgdOffset); 2069 pExtent->uSectorGD = RT_LE2H_U64(Header.gdOffset); 2070 } 2071 else 2072 { 2073 /** @todo this is just guesswork, the spec doesn't document this 2074 * properly and I don't have a vmdk without RGD. */ 2075 pExtent->uSectorGD = RT_LE2H_U64(Header.rgdOffset); 2076 pExtent->uSectorRGD = 0; 2077 } 2078 pExtent->cOverheadSectors = RT_LE2H_U64(Header.overHead); 2079 pExtent->fUncleanShutdown = !!Header.uncleanShutdown; 2080 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; 2081 if (!cSectorsPerGDE || cSectorsPerGDE > UINT32_MAX) 2082 { 2083 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size in '%s'"), pExtent->pszFullname); 2084 goto out; 2085 } 2086 pExtent->cSectorsPerGDE = cSectorsPerGDE; 2087 pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE; 2088 2089 /* Fix up the number of descriptor sectors, as some flat images have 2090 * really just one, and this causes failures when inserting the UUID 2091 * values and other extra information. */ 2092 if (pExtent->cDescriptorSectors != 0 && pExtent->cDescriptorSectors < 4) 2093 { 2094 /* Do it the easy way - just fix it for flat images which have no 2095 * other complicated metadata which needs space too. */ 2096 if ( pExtent->uDescriptorSector + 4 < pExtent->cOverheadSectors 2097 && pExtent->cGTEntries * pExtent->cGDEntries == 0) 2098 pExtent->cDescriptorSectors = 4; 2099 } 2100 2101 out: 2102 if (RT_FAILURE(rc)) 2103 vmdkFreeExtentData(pImage, pExtent, false); 2104 2105 return rc; 2106 } 2107 2108 /** 2109 * Internal: read additional metadata belonging to an extent. For those 2110 * extents which have no additional metadata just verify the information. 2111 */ 2112 static int vmdkReadMetaExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent) 2113 { 2114 int rc = VINF_SUCCESS; 2115 uint64_t cbExtentSize; 2116 2117 /* The image must be a multiple of a sector in size and contain the data 2118 * area (flat images only). If not, it means the image is at least 2119 * truncated, or even seriously garbled. */ 2120 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 2121 if (RT_FAILURE(rc)) 2122 { 2123 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 2124 goto out; 2125 } 2126 if ( cbExtentSize != RT_ALIGN_64(cbExtentSize, 512) 2127 && (pExtent->enmType != VMDKETYPE_FLAT || pExtent->cNominalSectors + pExtent->uSectorOffset > VMDK_BYTE2SECTOR(cbExtentSize))) 2128 { 2129 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: file size is not a multiple of 512 in '%s', file is truncated or otherwise garbled"), pExtent->pszFullname); 2130 goto out; 2131 } 2132 if (pExtent->enmType == VMDKETYPE_HOSTED_SPARSE) 2133 goto out; 2134 2058 2135 /* The spec says that this must be a power of two and greater than 8, 2059 2136 * but probably they meant not less than 8. */ … … 2064 2141 goto out; 2065 2142 } 2066 pExtent->uDescriptorSector = RT_LE2H_U64(Header.descriptorOffset); 2067 pExtent->cDescriptorSectors = RT_LE2H_U64(Header.descriptorSize); 2068 if (pExtent->uDescriptorSector && !pExtent->cDescriptorSectors) 2069 { 2070 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname); 2071 goto out; 2072 } 2073 pExtent->cGTEntries = RT_LE2H_U32(Header.numGTEsPerGT); 2143 2074 2144 /* This code requires that a grain table must hold a power of two multiple 2075 2145 * of the number of entries per GT cache entry. */ … … 2080 2150 goto out; 2081 2151 } 2082 if (RT_LE2H_U32(Header.flags) & 2)2083 {2084 pExtent->uSectorRGD = RT_LE2H_U64(Header.rgdOffset);2085 pExtent->uSectorGD = RT_LE2H_U64(Header.gdOffset);2086 }2087 else2088 {2089 /** @todo this is just guesswork, the spec doesn't document this2090 * properly and I don't have a vmdk without RGD. */2091 pExtent->uSectorGD = RT_LE2H_U64(Header.rgdOffset);2092 pExtent->uSectorRGD = 0;2093 }2094 pExtent->cOverheadSectors = RT_LE2H_U64(Header.overHead);2095 pExtent->fUncleanShutdown = !!Header.uncleanShutdown;2096 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain;2097 if (!cSectorsPerGDE || cSectorsPerGDE > UINT32_MAX)2098 {2099 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size in '%s'"), pExtent->pszFullname);2100 goto out;2101 }2102 pExtent->cSectorsPerGDE = cSectorsPerGDE;2103 pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE;2104 2152 2105 2153 rc = vmdkReadGrainDirectory(pExtent); … … 2368 2416 if (RT_LE2H_U32(u32Magic) == VMDK_SPARSE_MAGICNUMBER) 2369 2417 { 2370 /* It's a hosted s parse single-extent image. */2418 /* It's a hosted single-extent image. */ 2371 2419 rc = vmdkCreateExtents(pImage, 1); 2372 2420 if (RT_FAILURE(rc)) … … 2383 2431 goto out; 2384 2432 } 2385 rc = vmdkRead MetaSparseExtent(pImage, pExtent);2433 rc = vmdkReadBinaryMetaExtent(pImage, pExtent); 2386 2434 if (RT_FAILURE(rc)) 2387 2435 goto out; 2388 /* As we're dealing with a monolithic sparseimage here, there must2436 /* As we're dealing with a monolithic image here, there must 2389 2437 * be a descriptor embedded in the image file. */ 2390 2438 if (!pExtent->uDescriptorSector || !pExtent->cDescriptorSectors) … … 2413 2461 rc = vmdkParseDescriptor(pImage, pExtent->pDescData, 2414 2462 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors)); 2463 if (RT_FAILURE(rc)) 2464 goto out; 2465 2466 rc = vmdkReadMetaExtent(pImage, pExtent); 2415 2467 if (RT_FAILURE(rc)) 2416 2468 goto out; … … 2535 2587 goto out; 2536 2588 } 2537 rc = vmdkReadMetaSparseExtent(pImage, pExtent); 2589 rc = vmdkReadBinaryMetaExtent(pImage, pExtent); 2590 if (RT_FAILURE(rc)) 2591 goto out; 2592 rc = vmdkReadMetaExtent(pImage, pExtent); 2538 2593 if (RT_FAILURE(rc)) 2539 2594 goto out; … … 3533 3588 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 3534 3589 Assert(!(cbExtentSize % 512)); 3590 cbExtentSize = RT_ALIGN_64(cbExtentSize, 512); 3535 3591 uGTSector = VMDK_BYTE2SECTOR(cbExtentSize); 3536 3592 /* Normally the grain table is preallocated for hosted sparse extents
Note:
See TracChangeset
for help on using the changeset viewer.