Changeset 29649 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- May 18, 2010 4:29:31 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r28800 r29649 496 496 } 497 497 498 static int handleVDMessage(void *pvUser, const char *pszFormat, ...) 499 { 500 NOREF(pvUser); 501 va_list args; 502 va_start(args, pszFormat); 503 int rc = RTPrintfV(pszFormat, args); 504 va_end(args); 505 return rc; 506 } 507 498 508 static int CmdSetHDUUID(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) 499 509 { … … 525 535 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 526 536 vdInterfaceErrorCallbacks.pfnError = handleVDError; 527 vdInterfaceErrorCallbacks.pfnMessage = NULL;537 vdInterfaceErrorCallbacks.pfnMessage = handleVDMessage; 528 538 529 539 rc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR, … … 557 567 } 558 568 559 560 static int handleVDMessage(void *pvUser, const char *pszFormat, ...)561 {562 NOREF(pvUser);563 va_list args;564 va_start(args, pszFormat);565 int rc = RTPrintfV(pszFormat, args);566 va_end(args);567 return rc;568 }569 569 570 570 static int CmdDumpHDInfo(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) … … 769 769 } 770 770 771 /* Now do a lot of consistency checking. */772 uint64_t uPrevEnd = 0;773 for (unsigned i = 0; i < pPart->cPartitions-1; i++)774 {775 if (pPart->aPartitions[i].cPartDataSectors)776 {777 if (pPart->aPartitions[i].uPartDataStart < uPrevEnd)778 {779 RTPrintf("Overlapping partition description areas. Aborting\n");780 return VERR_INVALID_PARAMETER;781 }782 uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors;783 }784 if (pPart->aPartitions[i].uStart < uPrevEnd)785 {786 RTPrintf("Overlapping partitions. Aborting\n");787 return VERR_INVALID_PARAMETER;788 }789 if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType))790 uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize;791 }792 793 771 /* Fill out partitioning location info for MBR. */ 794 772 pPart->aPartitions[0].uPartDataStart = 0; 795 773 pPart->aPartitions[0].cPartDataSectors = pPart->aPartitions[0].uStart; 796 774 775 /* Now do a some partition table consistency checking, to reject the most 776 * obvious garbage which can lead to trouble later. */ 777 uint64_t uPrevEnd = 0; 778 for (unsigned i = 0; i < pPart->cPartitions-1; i++) 779 { 780 if (pPart->aPartitions[i].cPartDataSectors) 781 uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; 782 if (pPart->aPartitions[i].uStart < uPrevEnd) 783 { 784 RTPrintf("Overlapping partitions. Aborting\n"); 785 return VERR_INVALID_PARAMETER; 786 } 787 if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType)) 788 uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize; 789 } 790 797 791 return VINF_SUCCESS; 798 792 } … … 833 827 HOSTPARTITIONS partitions; 834 828 vrc = partRead(RawFile, &partitions); 835 if (RT_FAILURE(vrc)) 836 return vrc; 829 /* Don't bail out on errors, print the table and return the result code. */ 837 830 838 831 RTPrintf("Number Type StartCHS EndCHS Size (MiB) Start (Sect)\n"); 839 832 for (unsigned i = 0; i < partitions.cPartitions; i++) 840 833 { 841 /* Suppress printing the extended partition. Otherwise people 842 * might add it to the list of partitions for raw partition 843 * access (which is not good). */ 834 /* Don't show the extended partition, otherwise users might think they 835 * can add it to the list of partitions for raw partition access. */ 844 836 if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) 845 837 continue; … … 858 850 } 859 851 860 return 0; 852 return vrc; 853 } 854 855 static PVBOXHDDRAWPARTDESC appendPartDesc(uint32_t *pcPartDescs, PVBOXHDDRAWPARTDESC *ppPartDescs) 856 { 857 (*pcPartDescs)++; 858 PVBOXHDDRAWPARTDESC p; 859 p = (PVBOXHDDRAWPARTDESC)RTMemRealloc(*ppPartDescs, 860 *pcPartDescs * sizeof(VBOXHDDRAWPARTDESC)); 861 *ppPartDescs = p; 862 if (p) 863 { 864 p = p + *pcPartDescs - 1; 865 memset(p, '\0', sizeof(VBOXHDDRAWPARTDESC)); 866 } 867 868 return p; 861 869 } 862 870 … … 874 882 PVBOXHDD pDisk = NULL; 875 883 VBOXHDDRAW RawDescriptor; 876 HOSTPARTITIONS partitions;877 uint32_t uPartitions = 0;878 884 PVDINTERFACE pVDIfs = NULL; 879 885 … … 1138 1144 RawDescriptor.fRawDisk = false; 1139 1145 RawDescriptor.pszRawDisk = NULL; 1140 RawDescriptor.cPartitions = 0; 1146 RawDescriptor.cPartDescs = 0; 1147 RawDescriptor.pPartDescs = NULL; 1148 1149 uint32_t uPartitions = 0; 1141 1150 1142 1151 const char *p = pszPartitions; … … 1163 1172 } 1164 1173 1174 HOSTPARTITIONS partitions; 1165 1175 vrc = partRead(RawFile, &partitions); 1166 1176 if (RT_FAILURE(vrc)) … … 1186 1196 } 1187 1197 1188 RawDescriptor.cPartitions = partitions.cPartitions;1189 RawDescriptor.pPartitions = (PVBOXHDDRAWPART)RTMemAllocZ(partitions.cPartitions * sizeof(VBOXHDDRAWPART));1190 if (!RawDescriptor.pPartitions)1191 {1192 RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());1193 vrc = VERR_NO_MEMORY;1194 goto out;1195 }1196 1198 for (unsigned i = 0; i < partitions.cPartitions; i++) 1197 1199 { 1198 if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex)) 1199 { 1200 if (fRelative) 1200 PVBOXHDDRAWPARTDESC pPartDesc = NULL; 1201 1202 /* first dump the MBR/EPT data area */ 1203 if (partitions.aPartitions[i].cPartDataSectors) 1204 { 1205 pPartDesc = appendPartDesc(&RawDescriptor.cPartDescs, 1206 &RawDescriptor.pPartDescs); 1207 if (!pPartDesc) 1201 1208 { 1202 #ifdef RT_OS_LINUX 1203 /* Refer to the correct partition and use offset 0. */ 1204 char *pszRawName; 1205 vrc = RTStrAPrintf(&pszRawName, "%s%u", rawdisk.raw(), 1206 partitions.aPartitions[i].uIndex); 1207 if (RT_FAILURE(vrc)) 1208 { 1209 RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n", 1210 partitions.aPartitions[i].uIndex, vrc); 1211 goto out; 1212 } 1213 RawDescriptor.pPartitions[i].pszRawDevice = pszRawName; 1214 RawDescriptor.pPartitions[i].uPartitionStartOffset = 0; 1215 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 1216 #elif defined(RT_OS_DARWIN) 1217 /* Refer to the correct partition and use offset 0. */ 1218 char *pszRawName; 1219 vrc = RTStrAPrintf(&pszRawName, "%ss%u", rawdisk.raw(), 1220 partitions.aPartitions[i].uIndex); 1221 if (RT_FAILURE(vrc)) 1222 { 1223 RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n", 1224 partitions.aPartitions[i].uIndex, vrc); 1225 goto out; 1226 } 1227 RawDescriptor.pPartitions[i].pszRawDevice = pszRawName; 1228 RawDescriptor.pPartitions[i].uPartitionStartOffset = 0; 1229 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 1230 #else 1231 /** @todo not implemented yet for Windows host. Treat just 1232 * like not specified (this code is actually never reached). */ 1233 RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw(); 1234 RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512; 1235 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 1236 #endif 1209 RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw()); 1210 vrc = VERR_NO_MEMORY; 1211 goto out; 1237 1212 } 1238 else 1239 { 1240 /* This is the "everything refers to the base raw device" 1241 * variant. This requires opening the base device in RW 1242 * mode even for creation. */ 1243 RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw(); 1244 RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512; 1245 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 1246 } 1247 } 1248 else 1249 { 1250 /* Suppress access to this partition. */ 1251 RawDescriptor.pPartitions[i].pszRawDevice = NULL; 1252 RawDescriptor.pPartitions[i].uPartitionStartOffset = 0; 1253 /* This is used in the plausibility check in the creation 1254 * code. In theory it's a dummy, but I don't want to make 1255 * the VMDK creatiion any more complicated than what it needs 1256 * to be. */ 1257 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 1258 } 1259 if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) 1260 { 1261 /* Suppress exporting the actual extended partition. Only 1262 * logical partitions should be processed. However completely 1263 * ignoring it leads to leaving out the MBR data. */ 1264 RawDescriptor.pPartitions[i].cbPartition = 0; 1265 } 1266 else 1267 RawDescriptor.pPartitions[i].cbPartition = partitions.aPartitions[i].uSize * 512; 1268 RawDescriptor.pPartitions[i].uPartitionDataStart = partitions.aPartitions[i].uPartDataStart * 512; 1269 /** @todo the clipping below isn't 100% accurate, as it should 1270 * actually clip to the track size. However that's easier said 1271 * than done as figuring out the track size is heuristics. */ 1272 RawDescriptor.pPartitions[i].cbPartitionData = RT_MIN(partitions.aPartitions[i].cPartDataSectors, 63) * 512; 1273 if (RawDescriptor.pPartitions[i].cbPartitionData) 1274 { 1275 Assert (RawDescriptor.pPartitions[i].cbPartitionData - 1276 (size_t)RawDescriptor.pPartitions[i].cbPartitionData == 0); 1277 void *pPartData = RTMemAlloc((size_t)RawDescriptor.pPartitions[i].cbPartitionData); 1213 1214 /** @todo the clipping below isn't 100% accurate, as it should 1215 * actually clip to the track size. However that's easier said 1216 * than done as figuring out the track size is heuristics. In 1217 * any case the clipping is adjusted later after sorting, to 1218 * prevent overlapping data areas on the resulting image. */ 1219 pPartDesc->cbData = RT_MIN(partitions.aPartitions[i].cPartDataSectors, 63) * 512; 1220 pPartDesc->uStart = partitions.aPartitions[i].uPartDataStart * 512; 1221 Assert(pPartDesc->cbData - (size_t)pPartDesc->cbData == 0); 1222 void *pPartData = RTMemAlloc((size_t)pPartDesc->cbData); 1278 1223 if (!pPartData) 1279 1224 { … … 1282 1227 goto out; 1283 1228 } 1284 vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512, pPartData, (size_t)RawDescriptor.pPartitions[i].cbPartitionData, NULL); 1229 vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512, 1230 pPartData, (size_t)pPartDesc->cbData, NULL); 1285 1231 if (RT_FAILURE(vrc)) 1286 1232 { … … 1307 1253 } 1308 1254 } 1309 RawDescriptor.pPartitions[i].pvPartitionData = pPartData; 1255 pPartDesc->pvPartitionData = pPartData; 1256 } 1257 1258 if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) 1259 { 1260 /* Suppress exporting the actual extended partition. Only 1261 * logical partitions should be processed. However completely 1262 * ignoring it leads to leaving out the EBR data. */ 1263 continue; 1264 } 1265 1266 /* set up values for non-relative device names */ 1267 const char *pszRawName = rawdisk.raw(); 1268 uint64_t uStartOffset = partitions.aPartitions[i].uStart * 512; 1269 1270 pPartDesc = appendPartDesc(&RawDescriptor.cPartDescs, 1271 &RawDescriptor.pPartDescs); 1272 if (!pPartDesc) 1273 { 1274 RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw()); 1275 vrc = VERR_NO_MEMORY; 1276 goto out; 1277 } 1278 1279 if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex)) 1280 { 1281 if (fRelative) 1282 { 1283 #ifdef RT_OS_LINUX 1284 /* Refer to the correct partition and use offset 0. */ 1285 char *psz; 1286 vrc = RTStrAPrintf(&psz, "%s%u", rawdisk.raw(), 1287 partitions.aPartitions[i].uIndex); 1288 if (RT_FAILURE(vrc)) 1289 { 1290 RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n", 1291 partitions.aPartitions[i].uIndex, vrc); 1292 goto out; 1293 } 1294 pszRawName = psz; 1295 uStartOffset = 0; 1296 #elif defined(RT_OS_DARWIN) 1297 /* Refer to the correct partition and use offset 0. */ 1298 char *psz; 1299 vrc = RTStrAPrintf(&psz, "%ss%u", rawdisk.raw(), 1300 partitions.aPartitions[i].uIndex); 1301 if (RT_FAILURE(vrc)) 1302 { 1303 RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n", 1304 partitions.aPartitions[i].uIndex, vrc); 1305 goto out; 1306 } 1307 pszRawName = psz; 1308 uStartOffset = 0; 1309 #else 1310 /** @todo not implemented for other hosts. Treat just like 1311 * not specified (this code is actually never reached). */ 1312 #endif 1313 } 1314 1315 pPartDesc->pszRawDevice = pszRawName; 1316 pPartDesc->uStartOffset = uStartOffset; 1317 } 1318 else 1319 { 1320 pPartDesc->pszRawDevice = NULL; 1321 pPartDesc->uStartOffset = 0; 1322 } 1323 1324 pPartDesc->uStart = partitions.aPartitions[i].uStart * 512; 1325 pPartDesc->cbData = partitions.aPartitions[i].uSize * 512; 1326 } 1327 1328 /* Sort data areas in ascending order of start. */ 1329 for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++) 1330 { 1331 unsigned uMinIdx = i; 1332 uint64_t uMinVal = RawDescriptor.pPartDescs[i].uStart; 1333 for (unsigned j = i + 1; j < RawDescriptor.cPartDescs; j++) 1334 { 1335 if (RawDescriptor.pPartDescs[j].uStart < uMinVal) 1336 { 1337 uMinIdx = j; 1338 uMinVal = RawDescriptor.pPartDescs[j].uStart; 1339 } 1340 } 1341 if (uMinIdx != i) 1342 { 1343 /* Swap entries at index i and uMinIdx. */ 1344 VBOXHDDRAWPARTDESC tmp; 1345 memcpy(&tmp, &RawDescriptor.pPartDescs[i], sizeof(tmp)); 1346 memcpy(&RawDescriptor.pPartDescs[i], &RawDescriptor.pPartDescs[uMinIdx], sizeof(tmp)); 1347 memcpy(&RawDescriptor.pPartDescs[uMinIdx], &tmp, sizeof(tmp)); 1348 } 1349 } 1350 1351 /* Have a second go at MBR/EPT area clipping. Now that the data areas 1352 * are sorted this is much easier to get 100% right. */ 1353 for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++) 1354 { 1355 if (RawDescriptor.pPartDescs[i].pvPartitionData) 1356 { 1357 RawDescriptor.pPartDescs[i].cbData = RT_MIN(RawDescriptor.pPartDescs[i+1].uStart - RawDescriptor.pPartDescs[i].uStart, RawDescriptor.pPartDescs[i].cbData); 1358 if (!RawDescriptor.pPartDescs[i].cbData) 1359 { 1360 RTPrintf("MBR/EPT overlaps with data area\n"); 1361 vrc = VERR_INVALID_PARAMETER; 1362 goto out; 1363 } 1310 1364 } 1311 1365 } … … 1313 1367 1314 1368 RTFileClose(RawFile); 1369 1370 #ifdef DEBUG_klaus 1371 RTPrintf("# start length startoffset partdataptr device\n"); 1372 for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++) 1373 { 1374 RTPrintf("%2u %14RU64 %14RU64 %14RU64 %#18p %s\n", i, 1375 RawDescriptor.pPartDescs[i].uStart, 1376 RawDescriptor.pPartDescs[i].cbData, 1377 RawDescriptor.pPartDescs[i].uStartOffset, 1378 RawDescriptor.pPartDescs[i].pvPartitionData, 1379 RawDescriptor.pPartDescs[i].pszRawDevice); 1380 } 1381 #endif 1315 1382 1316 1383 VDINTERFACE vdInterfaceError; … … 1319 1386 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 1320 1387 vdInterfaceErrorCallbacks.pfnError = handleVDError; 1321 vdInterfaceErrorCallbacks.pfnMessage = NULL;1388 vdInterfaceErrorCallbacks.pfnMessage = handleVDMessage; 1322 1389 1323 1390 vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR, … … 1357 1424 if (pszPartitions) 1358 1425 { 1359 for (unsigned i = 0; i < partitions.cPartitions; i++) 1360 { 1361 if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex)) 1362 { 1363 if (fRelative) 1364 { 1365 #ifdef RT_OS_LINUX 1366 /* Free memory allocated above. */ 1367 RTStrFree((char *)(void *)RawDescriptor.pPartitions[i].pszRawDevice); 1368 #endif /* RT_OS_LINUX */ 1369 } 1370 } 1371 } 1426 for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++) 1427 { 1428 /* Free memory allocated for relative device name. */ 1429 if (RawDescriptor.pPartDescs[i].pszRawDevice) 1430 RTStrFree((char *)(void *)RawDescriptor.pPartDescs[i].pszRawDevice); 1431 if (RawDescriptor.pPartDescs[i].pvPartitionData) 1432 RTMemFree(RawDescriptor.pPartDescs[i].pvPartitionData); 1433 } 1434 if (RawDescriptor.pPartDescs) 1435 RTMemFree(RawDescriptor.pPartDescs); 1372 1436 } 1373 1437 … … 1429 1493 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 1430 1494 vdInterfaceErrorCallbacks.pfnError = handleVDError; 1431 vdInterfaceErrorCallbacks.pfnMessage = NULL;1495 vdInterfaceErrorCallbacks.pfnMessage = handleVDMessage; 1432 1496 1433 1497 int vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR, … … 1511 1575 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 1512 1576 vdInterfaceErrorCallbacks.pfnError = handleVDError; 1513 vdInterfaceErrorCallbacks.pfnMessage = NULL;1577 vdInterfaceErrorCallbacks.pfnMessage = handleVDMessage; 1514 1578 1515 1579 int vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR, … … 1676 1740 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 1677 1741 vdInterfaceErrorCallbacks.pfnError = handleVDError; 1678 vdInterfaceErrorCallbacks.pfnMessage = NULL;1742 vdInterfaceErrorCallbacks.pfnMessage = handleVDMessage; 1679 1743 1680 1744 vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
Note:
See TracChangeset
for help on using the changeset viewer.