Changeset 2650 in vbox for trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
- Timestamp:
- May 15, 2007 3:59:11 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r2589 r2650 34 34 #include <iprt/path.h> 35 35 #include <iprt/string.h> 36 #include <iprt/rand.h> 36 37 37 38 … … 148 149 RTFILE File; 149 150 /** Base name of the image extent. */ 150 c har*pszBasename;151 const char *pszBasename; 151 152 /** Full name of the image extent. */ 152 c har*pszFullname;153 const char *pszFullname; 153 154 /** Number of sectors in this extent. */ 154 155 uint64_t cSectors; … … 164 165 uint64_t uSectorRGD; 165 166 /** Total number of metadata sectors. */ 166 uint64_t uOverheadSectors;167 uint64_t cOverheadSectors; 167 168 /** Nominal size (i.e. as described by the descriptor) of this extent. */ 168 169 uint64_t cNominalSectors; … … 216 217 * making it variable. Descriptor files are generally very short (~20 lines). 217 218 */ 218 #define VMDK_DESCRIPTOR_LINES_MAX 100 219 #define VMDK_DESCRIPTOR_LINES_MAX 100U 219 220 220 221 /** … … 234 235 /** Total amount of memory available for the descriptor. */ 235 236 size_t cbDescAlloc; 236 /** Set if descriptor has been changed and not ye rwritten to disk. */237 /** Set if descriptor has been changed and not yet written to disk. */ 237 238 bool fDirty; 238 239 /** Array of pointers to the data in the descriptor. */ … … 335 336 static int vmdkReadMetaESXSparseExtent(PVMDKEXTENT pExtent); 336 337 #endif /* VBOX_WITH_VMDK_ESX */ 337 static void vmdkFreeExtentData(PVMDKEXTENT pExtent );338 static void vmdkFreeExtentData(PVMDKEXTENT pExtent, bool fDelete); 338 339 339 340 static int vmdkCreateExtents(PVMDKIMAGE pImage, unsigned cExtents); 340 341 static int vmdkOpenImage(PVMDKIMAGE pImage, const char *pszFilename, unsigned uOpenFlags); 341 342 static int vmdkFlushImage(PVMDKIMAGE pImage); 342 static void vmdkFreeImage(PVMDKIMAGE pImage );343 static void vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete); 343 344 344 345 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData); 345 static int vmdkClose(void *pBackendData );346 static int vmdkClose(void *pBackendData, bool fDelete); 346 347 347 348 … … 374 375 if (VBOX_FAILURE(rc)) 375 376 { 376 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory for file'%s'"), pExtent->pszFullname);377 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s'"), pExtent->pszFullname); 377 378 goto out; 378 379 } … … 394 395 if (VBOX_FAILURE(rc)) 395 396 { 396 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory for file'%s'"), pExtent->pszFullname);397 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname); 397 398 goto out; 398 399 } … … 429 430 RTMemTmpFree(pTmpGT1); 430 431 RTMemTmpFree(pTmpGT2); 431 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in file'%s'"), pExtent->pszFullname);432 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname); 432 433 goto out; 433 434 } … … 436 437 if (VBOX_FAILURE(rc)) 437 438 { 438 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in file'%s'"), pExtent->pszFullname);439 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname); 439 440 RTMemTmpFree(pTmpGT1); 440 441 RTMemTmpFree(pTmpGT2); … … 445 446 if (VBOX_FAILURE(rc)) 446 447 { 447 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in file'%s'"), pExtent->pszFullname);448 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname); 448 449 RTMemTmpFree(pTmpGT1); 449 450 RTMemTmpFree(pTmpGT2); … … 454 455 RTMemTmpFree(pTmpGT1); 455 456 RTMemTmpFree(pTmpGT2); 456 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table "));457 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname); 457 458 goto out; 458 459 } … … 468 469 } 469 470 471 static int vmdkCreateGrainDirectory(PVMDKEXTENT pExtent, uint64_t uStartSector, bool fPreAlloc) 472 { 473 int rc = VINF_SUCCESS; 474 unsigned i; 475 uint32_t *pGD = NULL, *pRGD = NULL; 476 size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t); 477 size_t cbGDRounded = RT_ALIGN_64(pExtent->cGDEntries * sizeof(uint32_t), 512); 478 size_t cbGTRounded; 479 uint64_t cbOverhead; 480 481 if (fPreAlloc) 482 cbGTRounded = RT_ALIGN_64(pExtent->cGDEntries * pExtent->cGTEntries * sizeof(uint32_t), 512); 483 else 484 cbGTRounded = 0; 485 486 pGD = (uint32_t *)RTMemAllocZ(cbGD); 487 if (!pGD) 488 { 489 rc = VERR_NO_MEMORY; 490 goto out; 491 } 492 pExtent->pGD = pGD; 493 pRGD = (uint32_t *)RTMemAllocZ(cbGD); 494 if (!pRGD) 495 { 496 rc = VERR_NO_MEMORY; 497 goto out; 498 } 499 pExtent->pRGD = pRGD; 500 501 cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 502 rc = RTFileSetSize(pExtent->File, cbOverhead); 503 if (VBOX_FAILURE(rc)) 504 goto out; 505 pExtent->uSectorRGD = uStartSector; 506 pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded); 507 508 if (fPreAlloc) 509 { 510 uint32_t uGTSectorLE; 511 uint32_t uOffsetSectors; 512 513 uOffsetSectors = pExtent->uSectorRGD + VMDK_BYTE2SECTOR(cbGDRounded); 514 for (i = 0; i < pExtent->cGDEntries; i++) 515 { 516 pRGD[i] = uOffsetSectors; 517 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 518 /* Write the redundant grain directory entry to disk. */ 519 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE), &uGTSectorLE, sizeof(uGTSectorLE), NULL); 520 if (VBOX_FAILURE(rc)) 521 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname); 522 uOffsetSectors += VMDK_BYTE2SECTOR(pExtent->cGTEntries * sizeof(uint32_t)); 523 } 524 525 uOffsetSectors = pExtent->uSectorGD + VMDK_BYTE2SECTOR(cbGDRounded); 526 for (i = 0; i < pExtent->cGDEntries; i++) 527 { 528 pGD[i] = uOffsetSectors; 529 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 530 /* Write the grain directory entry to disk. */ 531 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE), &uGTSectorLE, sizeof(uGTSectorLE), NULL); 532 if (VBOX_FAILURE(rc)) 533 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname); 534 uOffsetSectors += VMDK_BYTE2SECTOR(pExtent->cGTEntries * sizeof(uint32_t)); 535 } 536 } 537 pExtent->cOverheadSectors = VMDK_BYTE2SECTOR(cbOverhead); 538 539 out: 540 if (VBOX_FAILURE(rc)) 541 vmdkFreeGrainDirectory(pExtent); 542 return rc; 543 } 544 470 545 static void vmdkFreeGrainDirectory(PVMDKEXTENT pExtent) 471 546 { 472 547 if (pExtent->pszBasename) 473 548 { 474 RTMemTmpFree( pExtent->pszBasename);549 RTMemTmpFree((void *)pExtent->pszBasename); 475 550 pExtent->pszBasename = NULL; 476 551 } … … 496 571 pszStr++; 497 572 if (*pszStr++ != '"') 498 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor "));573 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor in '%s'"), pImage->pszFilename); 499 574 500 575 pszQ = (char*)strchr(pszStr, '"'); 501 576 if (pszQ == NULL) 502 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor "));577 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor in '%s'"), pImage->pszFilename); 503 578 pszUnquoted = (char *)RTMemTmpAlloc(pszQ - pszStr + 1); 504 579 if (!pszUnquoted) … … 509 584 if (ppszNext) 510 585 *ppszNext = pszQ + 1; 586 return VINF_SUCCESS; 587 } 588 589 static int vmdkDescInitStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, 590 const char *pszLine) 591 { 592 char *pEnd = pDescriptor->aLines[pDescriptor->cLines]; 593 ssize_t cbDiff = strlen(pszLine) + 1; 594 595 if ( pDescriptor->cLines >= VMDK_DESCRIPTOR_LINES_MAX - 1 596 && pEnd - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff) 597 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename); 598 599 memcpy(pEnd, pszLine, cbDiff); 600 pDescriptor->cLines++; 601 pDescriptor->aLines[pDescriptor->cLines] = pEnd + cbDiff; 602 pDescriptor->fDirty = true; 603 511 604 return VINF_SUCCESS; 512 605 } … … 573 666 if ( pDescriptor->aLines[pDescriptor->cLines] 574 667 - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff) 575 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big "));668 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename); 576 669 577 670 memmove(pszTmp + cbNewVal, pszTmp + cbOldVal, … … 591 684 || ( pDescriptor->aLines[pDescriptor->cLines] 592 685 - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff)) 593 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big "));686 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename); 594 687 for (unsigned i = pDescriptor->cLines + 1; i > uLast + 1; i--) 595 688 { 596 689 pDescriptor->aLines[i] = pDescriptor->aLines[i - 1]; 597 if (pDescriptor->aNextLines[i]) 598 pDescriptor->aNextLines[i]++; 690 if (pDescriptor->aNextLines[i - 1]) 691 pDescriptor->aNextLines[i] = pDescriptor->aNextLines[i - 1] + 1; 692 else 693 pDescriptor->aNextLines[i] = 0; 599 694 } 600 695 uStart = uLast + 1; … … 610 705 for (unsigned i = uStart + 1; i <= pDescriptor->cLines; i++) 611 706 pDescriptor->aLines[i] += cbDiff; 707 708 /* Adjust starting line numbers of following descriptor sections. */ 709 if (uStart <= pDescriptor->uFirstExtent) 710 pDescriptor->uFirstExtent++; 711 if (uStart <= pDescriptor->uFirstDDB) 712 pDescriptor->uFirstDDB++; 612 713 } 613 714 pDescriptor->fDirty = true; … … 625 726 } 626 727 728 static void vmdkDescExtRemoveDummy(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor) 729 { 730 unsigned uEntry = pDescriptor->uFirstExtent; 731 ssize_t cbDiff; 732 733 if (!uEntry) 734 return; 735 736 cbDiff = strlen(pDescriptor->aLines[uEntry]) + 1; 737 /* Move everything including the \0 in the entry marking the end of buffer. */ 738 memmove(pDescriptor->aLines[uEntry], pDescriptor->aLines[uEntry + 1], 739 pDescriptor->aLines[pDescriptor->cLines] - pDescriptor->aLines[uEntry + 1] + 1); 740 for (unsigned i = uEntry + 1; i <= pDescriptor->cLines; i++) 741 { 742 pDescriptor->aLines[i - 1] = pDescriptor->aLines[i] - cbDiff; 743 if (pDescriptor->aNextLines[i]) 744 pDescriptor->aNextLines[i - 1] = pDescriptor->aNextLines[i] - 1; 745 else 746 pDescriptor->aNextLines[i - 1] = 0; 747 } 748 pDescriptor->cLines--; 749 if (pDescriptor->uFirstDDB) 750 pDescriptor->uFirstDDB--; 751 752 return; 753 } 754 755 static int vmdkDescExtInsert(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, 756 VMDKACCESS enmAccess, uint64_t cNominalSectors, 757 VMDKETYPE enmType, const char *pszBasename, 758 uint64_t uSectorOffset) 759 { 760 static const char *apszAccess[] = { "NOACCESS", "RDONLY", "RW" }; 761 static const char *apszType[] = { "", "SPARSE", "FLAT", "ZERO" }; 762 char *pszTmp; 763 unsigned uStart = pDescriptor->uFirstExtent, uLast; 764 char szExt[1024]; 765 ssize_t cbDiff; 766 767 /* Find last entry in extent description. */ 768 while (uStart) 769 { 770 if (!pDescriptor->aNextLines[uStart]) 771 uLast = uStart; 772 uStart = pDescriptor->aNextLines[uStart]; 773 } 774 775 if (enmType == VMDKETYPE_ZERO) 776 { 777 RTStrPrintf(szExt, sizeof(szExt), "%s %llu %s ", apszAccess[enmAccess], 778 cNominalSectors, apszType[enmType]); 779 } 780 else 781 { 782 if (!uSectorOffset) 783 RTStrPrintf(szExt, sizeof(szExt), "%s %llu %s \"%s\"", 784 apszAccess[enmAccess], cNominalSectors, 785 apszType[enmType], pszBasename); 786 else 787 RTStrPrintf(szExt, sizeof(szExt), "%s %llu %s \"%s\" %llu", 788 apszAccess[enmAccess], cNominalSectors, 789 apszType[enmType], pszBasename, uSectorOffset); 790 } 791 cbDiff = strlen(szExt) + 1; 792 793 /* Check for buffer overflow. */ 794 if ( (pDescriptor->cLines >= VMDK_DESCRIPTOR_LINES_MAX - 1) 795 || ( pDescriptor->aLines[pDescriptor->cLines] 796 - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff)) 797 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename); 798 799 for (unsigned i = pDescriptor->cLines + 1; i > uLast + 1; i--) 800 { 801 pDescriptor->aLines[i] = pDescriptor->aLines[i - 1]; 802 if (pDescriptor->aNextLines[i - 1]) 803 pDescriptor->aNextLines[i] = pDescriptor->aNextLines[i - 1] + 1; 804 else 805 pDescriptor->aNextLines[i] = 0; 806 } 807 uStart = uLast + 1; 808 pDescriptor->aNextLines[uLast] = uStart; 809 pDescriptor->aNextLines[uStart] = 0; 810 pDescriptor->cLines++; 811 pszTmp = pDescriptor->aLines[uStart]; 812 memmove(pszTmp + cbDiff, pszTmp, 813 pDescriptor->aLines[pDescriptor->cLines] - pszTmp); 814 memcpy(pDescriptor->aLines[uStart], szExt, cbDiff); 815 for (unsigned i = uStart + 1; i <= pDescriptor->cLines; i++) 816 pDescriptor->aLines[i] += cbDiff; 817 818 /* Adjust starting line numbers of following descriptor sections. */ 819 if (uStart <= pDescriptor->uFirstDDB) 820 pDescriptor->uFirstDDB++; 821 822 pDescriptor->fDirty = true; 823 return VINF_SUCCESS; 824 } 825 627 826 static int vmdkDescDDBGetU32(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, 628 827 const char *pszKey, uint32_t *puValue) … … 657 856 } 658 857 858 int vmdkDescDDBSetStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, const char *pszKey, const char *pszVal) 859 { 860 char *pszValQuoted; 861 862 int rc = RTStrAPrintf(&pszValQuoted, "\"%s\"", pszVal); 863 if (VBOX_FAILURE(rc)) 864 return rc; 865 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, pszValQuoted); 866 RTStrFree(pszValQuoted); 867 return rc; 868 } 869 659 870 int vmdkDescDDBSetUuid(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, const char *pszKey, PCRTUUID pUuid) 660 871 { … … 693 904 if (cLine >= VMDK_DESCRIPTOR_LINES_MAX) 694 905 { 695 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor too long"));906 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename); 696 907 goto out; 697 908 } … … 703 914 if (*(pTmp + 1) != '\n') 704 915 { 705 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: unsupported end of line in descriptor "));916 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: unsupported end of line in descriptor in '%s'"), pImage->pszFilename); 706 917 goto out; 707 918 } … … 727 938 if (strcmp(pDescriptor->aLines[0], "# Disk DescriptorFile")) 728 939 { 729 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor does not start as expected "));940 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor does not start as expected in '%s'"), pImage->pszFilename); 730 941 goto out; 731 942 } … … 747 958 { 748 959 /* Incorrect ordering of entries. */ 749 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor "));960 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename); 750 961 goto out; 751 962 } … … 762 973 { 763 974 /* Incorrect ordering of entries. */ 764 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor "));975 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename); 765 976 goto out; 766 977 } … … 777 988 { 778 989 /* Incorrect ordering of entries. */ 779 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor "));990 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename); 780 991 goto out; 781 992 } … … 796 1007 } 797 1008 1009 static int vmdkCreateDescriptor(PVMDKIMAGE pImage, char *pDescData, size_t cbDescData, PVMDKDESCRIPTOR pDescriptor) 1010 { 1011 int rc; 1012 1013 pDescriptor->uFirstDesc = 0; 1014 pDescriptor->uFirstExtent = 0; 1015 pDescriptor->uFirstDDB = 0; 1016 pDescriptor->cLines = 0; 1017 pDescriptor->cbDescAlloc = cbDescData; 1018 pDescriptor->fDirty = false; 1019 pDescriptor->aLines[pDescriptor->cLines] = pDescData; 1020 memset(pDescriptor->aNextLines, '\0', sizeof(pDescriptor->aNextLines)); 1021 1022 rc = vmdkDescInitStr(pImage, pDescriptor, "# Disk DescriptorFile"); 1023 if (VBOX_FAILURE(rc)) 1024 goto out; 1025 rc = vmdkDescInitStr(pImage, pDescriptor, "version=1"); 1026 if (VBOX_FAILURE(rc)) 1027 goto out; 1028 pDescriptor->uFirstDesc = pDescriptor->cLines - 1; 1029 rc = vmdkDescInitStr(pImage, pDescriptor, ""); 1030 if (VBOX_FAILURE(rc)) 1031 goto out; 1032 rc = vmdkDescInitStr(pImage, pDescriptor, "# Extent description"); 1033 if (VBOX_FAILURE(rc)) 1034 goto out; 1035 rc = vmdkDescInitStr(pImage, pDescriptor, "NOACCESS 0 ZERO "); 1036 if (VBOX_FAILURE(rc)) 1037 goto out; 1038 pDescriptor->uFirstExtent = pDescriptor->cLines - 1; 1039 rc = vmdkDescInitStr(pImage, pDescriptor, ""); 1040 if (VBOX_FAILURE(rc)) 1041 goto out; 1042 /* The trailing space is created by VMware, too. */ 1043 rc = vmdkDescInitStr(pImage, pDescriptor, "# The disk Data Base "); 1044 if (VBOX_FAILURE(rc)) 1045 goto out; 1046 rc = vmdkDescInitStr(pImage, pDescriptor, "# DDB"); 1047 if (VBOX_FAILURE(rc)) 1048 goto out; 1049 rc = vmdkDescInitStr(pImage, pDescriptor, ""); 1050 if (VBOX_FAILURE(rc)) 1051 goto out; 1052 rc = vmdkDescInitStr(pImage, pDescriptor, "ddb.virtualHWVersion = \"4\""); 1053 if (VBOX_FAILURE(rc)) 1054 goto out; 1055 pDescriptor->uFirstDDB = pDescriptor->cLines - 1; 1056 1057 /* Now that the framework is in place, use the normal functions to insert 1058 * the remaining keys. */ 1059 char szBuf[9]; 1060 RTStrPrintf(szBuf, sizeof(szBuf), "%08x", RTRandU32()); 1061 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, "CID", szBuf); 1062 if (VBOX_FAILURE(rc)) 1063 goto out; 1064 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, "parentCID", "ffffffff"); 1065 if (VBOX_FAILURE(rc)) 1066 goto out; 1067 1068 rc = vmdkDescDDBSetStr(pImage, pDescriptor, "ddb.adapterType", "ide"); 1069 if (VBOX_FAILURE(rc)) 1070 goto out; 1071 1072 out: 1073 return rc; 1074 } 1075 798 1076 static int vmdkParseDescriptor(PVMDKIMAGE pImage, char *pDescData, size_t cbDescData) 799 1077 { … … 810 1088 rc = vmdkDescBaseGetU32(&pImage->Descriptor, "version", &uVersion); 811 1089 if (VBOX_FAILURE(rc)) 812 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error finding key 'version' in descriptor "));1090 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error finding key 'version' in descriptor in '%s'"), pImage->pszFilename); 813 1091 if (uVersion != 1) 814 return vmdkError(pImage, VERR_VDI_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: unsupported format version in descriptor "));1092 return vmdkError(pImage, VERR_VDI_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: unsupported format version in descriptor in '%s'"), pImage->pszFilename); 815 1093 816 1094 /* Count the number of extent config entries. */ … … 823 1101 { 824 1102 /* Monolithic image, must have only one extent (already opened). */ 825 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image may only have one extent "));1103 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image may only have one extent in '%s'"), pImage->pszFilename); 826 1104 } 827 1105 … … 856 1134 } 857 1135 else 858 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1136 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 859 1137 if (*pszLine++ != ' ') 860 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1138 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 861 1139 862 1140 /* Nominal size of the extent. */ … … 864 1142 &pImage->pExtents[i].cNominalSectors); 865 1143 if (VBOX_FAILURE(rc)) 866 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1144 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 867 1145 if (*pszLine++ != ' ') 868 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1146 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 869 1147 870 1148 /* Type of the extent. */ … … 890 1168 } 891 1169 else 892 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1170 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 893 1171 if (pImage->pExtents[i].enmType == VMDKETYPE_ZERO) 894 1172 { … … 897 1175 pszLine++; 898 1176 if (*pszLine != '\0') 899 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1177 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 900 1178 pImage->pExtents[i].pszBasename = NULL; 901 1179 } … … 904 1182 /* All other extent types have basename and optional offset. */ 905 1183 if (*pszLine++ != ' ') 906 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1184 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 907 1185 908 1186 /* Basename of the image. Surrounded by quotes. */ 909 rc = vmdkStringUnquote(pImage, pszLine,910 &pImage->pExtents[i].pszBasename, &pszLine);1187 char *pszBasename; 1188 rc = vmdkStringUnquote(pImage, pszLine, &pszBasename, &pszLine); 911 1189 if (VBOX_FAILURE(rc)) 912 1190 return rc; 1191 pImage->pExtents[i].pszBasename = pszBasename; 913 1192 if (*pszLine == ' ') 914 1193 { … … 920 1199 &pImage->pExtents[i].uSectorOffset); 921 1200 if (VBOX_FAILURE(rc)) 922 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1201 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 923 1202 } 924 1203 } 925 1204 926 1205 if (*pszLine != '\0') 927 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description "));1206 return vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename); 928 1207 } 929 1208 } … … 932 1211 "ddb.geometry.cylinders", &pImage->cCylinders); 933 1212 if (VBOX_FAILURE(rc)) 934 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description "));1213 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description in '%s'"), pImage->pszFilename); 935 1214 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 936 1215 "ddb.geometry.heads", &pImage->cHeads); 937 1216 if (VBOX_FAILURE(rc)) 938 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description "));1217 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description in '%s'"), pImage->pszFilename); 939 1218 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 940 1219 "ddb.geometry.sectors", &pImage->cSectors); 941 1220 if (VBOX_FAILURE(rc)) 942 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description "));1221 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description in '%s'"), pImage->pszFilename); 943 1222 if (pImage->cCylinders >= 1024 || pImage->cHeads != 16) 944 1223 pImage->enmTranslation = PDMBIOSTRANSLATION_LBA; … … 964 1243 "ddb.uuid.image", &pImage->ImageUuid); 965 1244 if (VBOX_FAILURE(rc)) 966 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor "));1245 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename); 967 1246 } 968 1247 } … … 988 1267 "ddb.uuid.modification", &pImage->ModificationUuid); 989 1268 if (VBOX_FAILURE(rc)) 990 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image modification UUID in descriptor "));1269 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image modification UUID in descriptor in '%s'"), pImage->pszFilename); 991 1270 } 992 1271 } … … 1012 1291 "ddb.uuid.parent", &pImage->ParentUuid); 1013 1292 if (VBOX_FAILURE(rc)) 1014 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent UUID in descriptor "));1293 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent UUID in descriptor in '%s'"), pImage->pszFilename); 1015 1294 } 1016 1295 } … … 1049 1328 1050 1329 if (cbLimit && uOffset + cb + 1 > cbLimit) 1051 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long "));1330 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename); 1052 1331 rc = RTFileWriteAt(DescFile, uOffset, psz, cb, NULL); 1053 1332 if (VBOX_FAILURE(rc)) 1054 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor for'%s'"), pImage->pszFilename);1333 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); 1055 1334 uOffset += cb; 1056 1335 rc = RTFileWriteAt(DescFile, uOffset, "\n", 1, NULL); 1057 1336 if (VBOX_FAILURE(rc)) 1058 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor for'%s'"), pImage->pszFilename);1337 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); 1059 1338 uOffset++; 1060 1339 } … … 1066 1345 rc = RTFileWriteAt(DescFile, uOffset, "", 1, NULL); 1067 1346 if (VBOX_FAILURE(rc)) 1068 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor for'%s'"), pImage->pszFilename);1347 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); 1069 1348 uOffset++; 1070 1349 } … … 1074 1353 rc = RTFileSetSize(DescFile, uOffset); 1075 1354 if (VBOX_FAILURE(rc)) 1076 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor file'%s'"), pImage->pszFilename);1355 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename); 1077 1356 } 1078 1357 pImage->Descriptor.fDirty = false; … … 1089 1368 if (VBOX_FAILURE(rc)) 1090 1369 { 1091 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading extent header of file'%s'"), pExtent->pszFullname);1370 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading extent header in '%s'"), pExtent->pszFullname); 1092 1371 goto out; 1093 1372 } … … 1095 1374 || RT_LE2H_U32(Header.version) != 1) 1096 1375 { 1097 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect magic/version in extent header of file'%s'"), pExtent->pszFullname);1376 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect magic/version in extent header in '%s'"), pExtent->pszFullname); 1098 1377 goto out; 1099 1378 } … … 1103 1382 if (VBOX_FAILURE(rc)) 1104 1383 { 1105 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size of file'%s'"), pExtent->pszFullname);1384 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 1106 1385 goto out; 1107 1386 } … … 1112 1391 || Header.doubleEndLineChar2 != '\n') ) 1113 1392 { 1114 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: file '%s' is corrupted by CR/LF translation"), pExtent->pszFullname);1393 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: corrupted by CR/LF translation in '%s'"), pExtent->pszFullname); 1115 1394 goto out; 1116 1395 } … … 1123 1402 || pExtent->cSectorsPerGrain < 8) 1124 1403 { 1125 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: invalid extent grain size %u for file'%s'"), pExtent->cSectorsPerGrain, pExtent->pszFullname);1404 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: invalid extent grain size %u in '%s'"), pExtent->cSectorsPerGrain, pExtent->pszFullname); 1126 1405 goto out; 1127 1406 } … … 1130 1409 if (pExtent->uDescriptorSector && !pExtent->cDescriptorSectors) 1131 1410 { 1132 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config for file'%s'"), pExtent->pszFullname);1411 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname); 1133 1412 goto out; 1134 1413 } … … 1139 1418 || pExtent->cGTEntries < VMDK_GT_CACHELINE_SIZE) 1140 1419 { 1141 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: grain table cache size problem for file'%s'"), pExtent->pszFullname);1420 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: grain table cache size problem in '%s'"), pExtent->pszFullname); 1142 1421 goto out; 1143 1422 } … … 1154 1433 pExtent->uSectorRGD = 0; 1155 1434 } 1156 pExtent-> uOverheadSectors = RT_LE2H_U64(Header.overHead);1435 pExtent->cOverheadSectors = RT_LE2H_U64(Header.overHead); 1157 1436 pExtent->fUncleanShutdown = !!Header.uncleanShutdown; 1158 1437 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; 1159 1438 if (!cSectorsPerGDE || cSectorsPerGDE > UINT32_MAX) 1160 1439 { 1161 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size for file'%s'"), pExtent->pszFullname);1440 rc = vmdkError(pExtent->pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size in '%s'"), pExtent->pszFullname); 1162 1441 goto out; 1163 1442 } … … 1169 1448 out: 1170 1449 if (VBOX_FAILURE(rc)) 1171 { 1172 vmdkFreeExtentData(pExtent); 1173 } 1450 vmdkFreeExtentData(pExtent, false); 1174 1451 1175 1452 return rc; … … 1200 1477 Header.rgdOffset = RT_H2LE_U64(pExtent->uSectorGD); 1201 1478 } 1202 Header.overHead = RT_H2LE_U64(pExtent-> uOverheadSectors);1479 Header.overHead = RT_H2LE_U64(pExtent->cOverheadSectors); 1203 1480 Header.uncleanShutdown = pExtent->fUncleanShutdown; 1204 1481 Header.singleEndLineChar = '\n'; … … 1210 1487 AssertRC(rc); 1211 1488 if (VBOX_FAILURE(rc)) 1212 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header to file'%s'"), pExtent->pszFullname);1489 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname); 1213 1490 return rc; 1214 1491 } … … 1247 1524 pExtent->uSectorGD = RT_LE2H_U32(Header.gdOffset); 1248 1525 pExtent->uSectorRGD = 0; 1249 pExtent-> uOverheadSectors = 0;1526 pExtent->cOverheadSectors = 0; 1250 1527 pExtent->cGTEntries = 4096; 1251 1528 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; … … 1271 1548 out: 1272 1549 if (VBOX_FAILURE(rc)) 1273 { 1274 vmdkFreeExtentData(pExtent); 1275 } 1550 vmdkFreeExtentData(pExtent, false); 1276 1551 1277 1552 return rc; … … 1279 1554 #endif /* VBOX_WITH_VMDK_ESX */ 1280 1555 1281 static void vmdkFreeExtentData(PVMDKEXTENT pExtent )1556 static void vmdkFreeExtentData(PVMDKEXTENT pExtent, bool fDelete) 1282 1557 { 1283 1558 vmdkFreeGrainDirectory(pExtent); … … 1287 1562 pExtent->pDescData = NULL; 1288 1563 } 1289 if (pExtent->pszFullname)1290 {1291 RTStrFree(pExtent->pszFullname);1292 pExtent->pszFullname = NULL;1293 }1294 1564 if (pExtent->File != NIL_RTFILE) 1295 1565 { 1296 1566 RTFileClose(pExtent->File); 1297 1567 pExtent->File = NIL_RTFILE; 1298 } 1299 } 1300 1568 if (fDelete && pExtent->pszFullname) 1569 RTFileDelete(pExtent->pszFullname); 1570 } 1571 if (pExtent->pszFullname) 1572 { 1573 RTStrFree((char *)(void *)pExtent->pszFullname); 1574 pExtent->pszFullname = NULL; 1575 } 1576 } 1577 1578 static int vmdkAllocateGrainTableCache(PVMDKIMAGE pImage) 1579 { 1580 PVMDKEXTENT pExtent; 1581 1582 /* Allocate grain table cache if any sparse extent is present. */ 1583 for (unsigned i = 0; i < pImage->cExtents; i++) 1584 { 1585 pExtent = &pImage->pExtents[i]; 1586 if ( pExtent->enmType == VMDKETYPE_HOSTED_SPARSE 1587 #ifdef VBOX_WITH_VMDK_ESX 1588 || pExtent->enmType == VMDKETYPE_ESX_SPARSE 1589 #endif /* VBOX_WITH_VMDK_ESX */ 1590 ) 1591 { 1592 /* Allocate grain table cache. */ 1593 pImage->pGTCache = (PVMDKGTCACHE)RTMemAllocZ(sizeof(VMDKGTCACHE)); 1594 if (!pImage->pGTCache) 1595 return VERR_NO_MEMORY; 1596 for (unsigned i = 0; i < VMDK_GT_CACHE_SIZE; i++) 1597 { 1598 PVMDKGTCACHEENTRY pGCE = &pImage->pGTCache->aGTCache[i]; 1599 pGCE->uExtent = UINT32_MAX; 1600 } 1601 pImage->pGTCache->cEntries = VMDK_GT_CACHE_SIZE; 1602 break; 1603 } 1604 } 1605 1606 return VINF_SUCCESS; 1607 } 1301 1608 static int vmdkCreateExtents(PVMDKIMAGE pImage, unsigned cExtents) 1302 1609 { … … 1334 1641 pImage->uOpenFlags = uOpenFlags; 1335 1642 1336 /** @todo check the image file name for invalid characters, especially double quotes. */1337 1338 1643 /** @todo check whether the same file is used somewhere else. don't open any file twice, leads to locking problems and can cause trouble with file caching. */ 1339 1644 … … 1355 1660 if (VBOX_FAILURE(rc)) 1356 1661 { 1357 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading the magic number from file'%s'"), pszFilename);1662 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading the magic number in '%s'"), pszFilename); 1358 1663 goto out; 1359 1664 } … … 1378 1683 if (!pExtent->uDescriptorSector || !pExtent->cDescriptorSectors) 1379 1684 { 1380 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image without descriptor in file'%s'"), pszFilename);1685 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image without descriptor in '%s'"), pszFilename); 1381 1686 goto out; 1382 1687 } … … 1395 1700 if (VBOX_FAILURE(rc)) 1396 1701 { 1397 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in file'%s'"), pExtent->pszFullname);1702 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pExtent->pszFullname); 1398 1703 goto out; 1399 1704 } … … 1426 1731 if (VBOX_FAILURE(rc)) 1427 1732 { 1428 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in file'%s'"), pszFilename);1733 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pszFilename); 1429 1734 goto out; 1430 1735 } … … 1433 1738 /* Likely the read is truncated. Better fail a bit too early 1434 1739 * (normally the descriptor is much smaller than our buffer). */ 1435 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot read descriptor in file'%s'"), pszFilename);1740 rc = vmdkError(pImage, VERR_VDI_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot read descriptor in '%s'"), pszFilename); 1436 1741 goto out; 1437 1742 } … … 1569 1874 } 1570 1875 1571 /* Allocate grain table cache if any sparse extent is present. */ 1876 rc = vmdkAllocateGrainTableCache(pImage); 1877 if (VBOX_FAILURE(rc)) 1878 goto out; 1879 1880 out: 1881 if (VBOX_FAILURE(rc)) 1882 vmdkFreeImage(pImage, false); 1883 return rc; 1884 } 1885 1886 static int vmdkCreateImage(PVMDKIMAGE pImage, const char *pszFilename, VDIMAGETYPE enmType, uint64_t cbSize, unsigned uImageFlags, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors) 1887 { 1888 int rc; 1889 uint64_t cSectorsPerGDE, cSectorsPerGD; 1890 PVMDKEXTENT pExtent; 1891 1892 rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc, &pImage->Descriptor); 1893 if (VBOX_FAILURE(rc)) 1894 { 1895 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pszFilename); 1896 goto out; 1897 } 1898 1899 if ( enmType == VD_IMAGE_TYPE_FIXED 1900 || uImageFlags == VD_VMDK_IMAGE_FLAGS_SPLIT_2G) 1901 { 1902 /* Fixed images and split images in general have a separate descriptor 1903 * file. This is the more complicated case, as it requires setting up 1904 * potentially more than one extent, including filename generation. */ 1905 rc = VERR_NOT_IMPLEMENTED; 1906 goto out; 1907 } 1908 else 1909 { 1910 /* Normal (growing) image which is not split into pieces. */ 1911 rc = vmdkCreateExtents(pImage, 1); 1912 if (VBOX_FAILURE(rc)) 1913 { 1914 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 1915 goto out; 1916 } 1917 pExtent = &pImage->pExtents[0]; 1918 pImage->File = NIL_RTFILE; 1919 rc = RTFileOpen(&pExtent->File, pszFilename, 1920 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 1921 if (VBOX_FAILURE(rc)) 1922 { 1923 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pszFilename); 1924 goto out; 1925 } 1926 1927 /* Set up basename for extent description. Cannot use StrDup, as it is 1928 * not guaranteed that the memory can be freed with RTMemTmpFree, which 1929 * must be used as in other code paths StrDup is not usable. */ 1930 char *pszBasenameSubstr = RTPathFilename(pszFilename); 1931 Assert(pszBasenameSubstr); 1932 size_t cbBasenameSubstr = strlen(pszBasenameSubstr) + 1; 1933 char *pszBasename = (char *)RTMemTmpAlloc(cbBasenameSubstr); 1934 if (!pszBasename) 1935 { 1936 rc = VERR_NO_MEMORY; 1937 goto out; 1938 } 1939 memcpy(pszBasename, pszBasenameSubstr, cbBasenameSubstr); 1940 pExtent->pszBasename = pszBasename; 1941 pExtent->pszFullname = RTStrDup(pszFilename); 1942 if (!pExtent->pszFullname) 1943 { 1944 rc = VERR_NO_MEMORY; 1945 goto out; 1946 } 1947 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; 1948 pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbSize, 65536)); 1949 pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR(65536); 1950 pExtent->uDescriptorSector = 1; 1951 pExtent->cDescriptorSectors = VMDK_BYTE2SECTOR(pImage->cbDescAlloc); 1952 pExtent->cGTEntries = 512; 1953 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; 1954 pExtent->cSectorsPerGDE = cSectorsPerGDE; 1955 pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE; 1956 cSectorsPerGD = (pExtent->cGDEntries + (512 / sizeof(uint32_t) - 1)) / (512 / sizeof(uint32_t)); 1957 pExtent->enmAccess = VMDKACCESS_READWRITE; 1958 pExtent->fUncleanShutdown = true; 1959 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(cbSize); 1960 pExtent->uSectorOffset = 0; 1961 pExtent->fMetaDirty = true; 1962 1963 rc = vmdkCreateGrainDirectory(pExtent, pExtent->uDescriptorSector + pExtent->cDescriptorSectors, true); 1964 if (VBOX_FAILURE(rc)) 1965 { 1966 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pszFilename); 1967 goto out; 1968 } 1969 1970 pImage->enmImageType = enmType; 1971 rc = vmdkDescSetStr(pImage, &pImage->Descriptor, pImage->Descriptor.uFirstDesc, "createType", "\"monolithicSparse\""); 1972 if (VBOX_FAILURE(rc)) 1973 { 1974 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pszFilename); 1975 goto out; 1976 } 1977 1978 /* The descriptor is part of the extent, move info to extent. */ 1979 pExtent->pDescData = pImage->pDescData; 1980 pImage->pDescData = NULL; 1981 } 1982 1983 pImage->cbSize = cbSize; 1984 if (pImage->cCylinders >= 1024 || pImage->cHeads != 16) 1985 pImage->enmTranslation = PDMBIOSTRANSLATION_LBA; 1986 else 1987 pImage->enmTranslation = PDMBIOSTRANSLATION_NONE; 1988 1572 1989 for (unsigned i = 0; i < pImage->cExtents; i++) 1573 1990 { 1574 1991 pExtent = &pImage->pExtents[i]; 1575 if ( pExtent->enmType == VMDKETYPE_HOSTED_SPARSE 1992 1993 rc = vmdkDescExtInsert(pImage, &pImage->Descriptor, pExtent->enmAccess, 1994 pExtent->cNominalSectors, pExtent->enmType, 1995 pExtent->pszBasename, pExtent->uSectorOffset); 1996 if (VBOX_FAILURE(rc)) 1997 { 1998 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not insert the extent list into descriptor in '%s'"), pszFilename); 1999 goto out; 2000 } 2001 } 2002 vmdkDescExtRemoveDummy(pImage, &pImage->Descriptor); 2003 2004 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 2005 "ddb.geometry.cylinders", cCylinders); 2006 if (VBOX_FAILURE(rc)) 2007 goto out; 2008 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 2009 "ddb.geometry.heads", cHeads); 2010 if (VBOX_FAILURE(rc)) 2011 goto out; 2012 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 2013 "ddb.geometry.sectors", cSectors); 2014 if (VBOX_FAILURE(rc)) 2015 goto out; 2016 2017 pImage->cCylinders = cCylinders; 2018 pImage->cHeads = cHeads; 2019 pImage->cSectors = cSectors; 2020 2021 rc = RTUuidCreate(&pImage->ImageUuid); 2022 if (VBOX_FAILURE(rc)) 2023 goto out; 2024 rc = vmdkDescDDBSetUuid(pImage, &pImage->Descriptor, 2025 "ddb.uuid.image", &pImage->ImageUuid); 2026 if (VBOX_FAILURE(rc)) 2027 { 2028 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in new descriptor in '%s'"), pszFilename); 2029 goto out; 2030 } 2031 RTUuidClear(&pImage->ParentUuid); 2032 rc = vmdkDescDDBSetUuid(pImage, &pImage->Descriptor, 2033 "ddb.uuid.parent", &pImage->ParentUuid); 2034 if (VBOX_FAILURE(rc)) 2035 { 2036 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in new descriptor in '%s'"), pszFilename); 2037 goto out; 2038 } 2039 RTUuidClear(&pImage->ModificationUuid); 2040 rc = vmdkDescDDBSetUuid(pImage, &pImage->Descriptor, 2041 "ddb.uuid.modification", &pImage->ModificationUuid); 2042 if (VBOX_FAILURE(rc)) 2043 { 2044 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in new descriptor in '%s'"), pszFilename); 2045 goto out; 2046 } 2047 2048 rc = vmdkAllocateGrainTableCache(pImage); 2049 if (VBOX_FAILURE(rc)) 2050 goto out; 2051 2052 rc = vmdkFlushImage(pImage); 2053 2054 out: 2055 if (VBOX_FAILURE(rc)) 2056 vmdkFreeImage(pImage, rc != VERR_ALREADY_EXISTS); 2057 return rc; 2058 } 2059 2060 static void vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete) 2061 { 2062 if (pImage->enmImageType) 2063 { 2064 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2065 { 2066 /* Mark all extents as clean. */ 2067 for (unsigned i = 0; i < pImage->cExtents; i++) 2068 { 2069 if (( pImage->pExtents[i].enmType == VMDKETYPE_HOSTED_SPARSE 1576 2070 #ifdef VBOX_WITH_VMDK_ESX 1577 || pExtent->enmType == VMDKETYPE_ESX_SPARSE2071 || pImage->pExtents[i].enmType == VMDKETYPE_ESX_SPARSE 1578 2072 #endif /* VBOX_WITH_VMDK_ESX */ 1579 ) 1580 { 1581 /* Allocate grain table cache. */ 1582 pImage->pGTCache = (PVMDKGTCACHE)RTMemAllocZ(sizeof(VMDKGTCACHE)); 1583 if (!pImage->pGTCache) 1584 { 1585 rc = VERR_NO_MEMORY; 1586 goto out; 2073 ) 2074 && pImage->pExtents[i].fUncleanShutdown) 2075 { 2076 pImage->pExtents[i].fUncleanShutdown = false; 2077 pImage->pExtents[i].fMetaDirty = true; 2078 } 1587 2079 } 1588 for (unsigned i = 0; i < VMDK_GT_CACHE_SIZE; i++) 1589 { 1590 PVMDKGTCACHEENTRY pGCE = &pImage->pGTCache->aGTCache[i]; 1591 pGCE->uExtent = UINT32_MAX; 1592 } 1593 pImage->pGTCache->cEntries = VMDK_GT_CACHE_SIZE; 1594 break; 1595 } 1596 } 1597 1598 out: 1599 if (VBOX_FAILURE(rc)) 1600 vmdkFreeImage(pImage); 1601 return rc; 1602 } 1603 1604 static void vmdkFreeImage(PVMDKIMAGE pImage) 1605 { 1606 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1607 { 1608 /* Mark all extents as clean. */ 1609 for (unsigned i = 0; i < pImage->cExtents; i++) 1610 { 1611 if (( pImage->pExtents[i].enmType == VMDKETYPE_HOSTED_SPARSE 1612 #ifdef VBOX_WITH_VMDK_ESX 1613 || pImage->pExtents[i].enmType == VMDKETYPE_ESX_SPARSE 1614 #endif /* VBOX_WITH_VMDK_ESX */ 1615 ) 1616 && pImage->pExtents[i].fUncleanShutdown) 1617 { 1618 pImage->pExtents[i].fUncleanShutdown = false; 1619 pImage->pExtents[i].fMetaDirty = true; 1620 } 1621 } 1622 } 1623 (void)vmdkFlushImage(pImage); 2080 } 2081 (void)vmdkFlushImage(pImage); 2082 } 1624 2083 if (pImage->pExtents != NULL) 1625 2084 { 1626 2085 for (unsigned i = 0 ; i < pImage->cExtents; i++) 1627 vmdkFreeExtentData(&pImage->pExtents[i] );2086 vmdkFreeExtentData(&pImage->pExtents[i], fDelete); 1628 2087 RTMemFree(pImage->pExtents); 1629 2088 pImage->pExtents = NULL; … … 1634 2093 pImage->File = NIL_RTFILE; 1635 2094 } 2095 if (fDelete && pImage->pszFilename) 2096 RTFileDelete(pImage->pszFilename); 1636 2097 } 1637 2098 … … 1762 2223 aGTDataTmp, sizeof(aGTDataTmp), NULL); 1763 2224 if (VBOX_FAILURE(rc)) 1764 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in file'%s'"), pExtent->pszFullname);2225 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname); 1765 2226 pGTCacheEntry->uExtent = pExtent->uExtent; 1766 2227 pGTCacheEntry->uGTBlock = uGTBlock; … … 1805 2266 rc = RTFileGetSize(pExtent->File, &cbExtentSize); 1806 2267 if (VBOX_FAILURE(rc)) 1807 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size of file'%s'"), pExtent->pszFullname);2268 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 1808 2269 Assert(!(cbExtentSize % 512)); 1809 2270 uGTSector = VMDK_BYTE2SECTOR(cbExtentSize); … … 1822 2283 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp), aGTDataTmp, sizeof(aGTDataTmp), NULL); 1823 2284 if (VBOX_FAILURE(rc)) 1824 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in file'%s'"), pExtent->pszFullname);2285 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname); 1825 2286 } 1826 2287 if (pExtent->pRGD) … … 1828 2289 rc = RTFileGetSize(pExtent->File, &cbExtentSize); 1829 2290 if (VBOX_FAILURE(rc)) 1830 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size of file'%s'"), pExtent->pszFullname);2291 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 1831 2292 Assert(!(cbExtentSize % 512)); 1832 2293 uRGTSector = VMDK_BYTE2SECTOR(cbExtentSize); … … 1839 2300 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp), aGTDataTmp, sizeof(aGTDataTmp), NULL); 1840 2301 if (VBOX_FAILURE(rc)) 1841 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in file'%s'"), pExtent->pszFullname);2302 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname); 1842 2303 } 1843 2304 } … … 1850 2311 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), &uGTSectorLE, sizeof(uGTSectorLE), NULL); 1851 2312 if (VBOX_FAILURE(rc)) 1852 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in file'%s'"), pExtent->pszFullname);2313 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname); 1853 2314 if (pExtent->pRGD) 1854 2315 { … … 1856 2317 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE), &uRGTSectorLE, sizeof(uRGTSectorLE), NULL); 1857 2318 if (VBOX_FAILURE(rc)) 1858 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in file'%s'"), pExtent->pszFullname);2319 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname); 1859 2320 } 1860 2321 … … 1867 2328 rc = RTFileGetSize(pExtent->File, &cbExtentSize); 1868 2329 if (VBOX_FAILURE(rc)) 1869 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size of file'%s'"), pExtent->pszFullname);2330 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); 1870 2331 Assert(!(cbExtentSize % 512)); 1871 2332 … … 1873 2334 rc = RTFileWriteAt(pExtent->File, cbExtentSize, pvBuf, cbWrite, NULL); 1874 2335 if (VBOX_FAILURE(rc)) 1875 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in file'%s'"), pExtent->pszFullname);2336 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); 1876 2337 1877 2338 /* Update the grain table (and the cache). */ … … 1887 2348 aGTDataTmp, sizeof(aGTDataTmp), NULL); 1888 2349 if (VBOX_FAILURE(rc)) 1889 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in file'%s'"), pExtent->pszFullname);2350 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname); 1890 2351 pGTCacheEntry->uExtent = pExtent->uExtent; 1891 2352 pGTCacheEntry->uGTBlock = uGTBlock; … … 1908 2369 aGTDataTmp, sizeof(aGTDataTmp), NULL); 1909 2370 if (VBOX_FAILURE(rc)) 1910 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in file'%s'"), pExtent->pszFullname);2371 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname); 1911 2372 if (pExtent->pRGD) 1912 2373 { … … 1916 2377 aGTDataTmp, sizeof(aGTDataTmp), NULL); 1917 2378 if (VBOX_FAILURE(rc)) 1918 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in file'%s'"), pExtent->pszFullname);2379 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname); 1919 2380 } 1920 2381 #ifdef VBOX_WITH_VMDK_ESX … … 1930 2391 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData) 1931 2392 { 1932 int rc = VINF_SUCCESS;2393 int rc; 1933 2394 PVMDKIMAGE pImage; 1934 2395 1935 /* Check open flags. Just readonly flag is supported. */ 1936 if (uOpenFlags & ~VD_OPEN_FLAGS_READONLY) 2396 /** @todo check the image file name for invalid characters, especially double quotes. */ 2397 2398 /* Check open flags. All valid flags are supported. */ 2399 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 1937 2400 { 1938 2401 rc = VERR_INVALID_PARAMETER; … … 1954 2417 pImage->pvErrorUser = pvErrorUser; 1955 2418 2419 rc = vmdkOpenImage(pImage, pszFilename, uOpenFlags); 1956 2420 if (VBOX_SUCCESS(rc)) 1957 { 1958 rc = vmdkOpenImage(pImage, pszFilename, uOpenFlags); 1959 if (VBOX_SUCCESS(rc)) 1960 *ppvBackendData = pImage; 1961 } 2421 *ppvBackendData = pImage; 1962 2422 1963 2423 out: … … 1966 2426 } 1967 2427 1968 static int vmdkCreate(const char *pszFilename, VDIMAGETYPE penmType,2428 static int vmdkCreate(const char *pszFilename, VDIMAGETYPE enmType, 1969 2429 uint64_t cbSize, unsigned uImageFlags, 1970 const char *pszComment, unsigned uOpenFlags, 2430 const char *pszComment, uint32_t cCylinders, 2431 uint32_t cHeads, uint32_t cSectors, unsigned uOpenFlags, 1971 2432 PFNVMPROGRESS pfnProgress, void *pvUser, 1972 2433 PFNVDERROR pfnError, void *pvErrorUser, 1973 2434 void **ppvBackendData) 1974 2435 { 1975 return VERR_NOT_IMPLEMENTED; 1976 } 1977 1978 static int vmdkClose(void *pBackendData) 2436 int rc; 2437 PVMDKIMAGE pImage; 2438 2439 /** @todo check the image file name for invalid characters, especially double quotes. */ 2440 2441 /* Check open flags. All valid flags are supported. */ 2442 if (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 2443 { 2444 rc = VERR_INVALID_PARAMETER; 2445 goto out; 2446 } 2447 2448 pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE)); 2449 if (!pImage) 2450 { 2451 rc = VERR_NO_MEMORY; 2452 goto out; 2453 } 2454 pImage->pszFilename = pszFilename; 2455 pImage->File = NIL_RTFILE; 2456 pImage->pExtents = NULL; 2457 pImage->pGTCache = NULL; 2458 pImage->pDescData = NULL; 2459 pImage->pfnError = pfnError; 2460 pImage->pvErrorUser = pvErrorUser; 2461 pImage->cbDescAlloc = VMDK_SECTOR2BYTE(20); 2462 pImage->pDescData = (char *)RTMemAllocZ(pImage->cbDescAlloc); 2463 if (!pImage->pDescData) 2464 { 2465 rc = VERR_NO_MEMORY; 2466 goto out; 2467 } 2468 2469 rc = vmdkCreateImage(pImage, pszFilename, enmType, cbSize, uImageFlags, 2470 cCylinders, cHeads, cSectors); 2471 if (VBOX_SUCCESS(rc)) 2472 { 2473 /* So far the image is opened in read/write mode. Make sure the 2474 * image is opened in read-only mode if the caller requested that. */ 2475 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 2476 { 2477 vmdkFreeImage(pImage, false); 2478 rc = vmdkOpenImage(pImage, pszFilename, uOpenFlags); 2479 if (VBOX_FAILURE(rc)) 2480 goto out; 2481 } 2482 *ppvBackendData = pImage; 2483 } 2484 2485 out: 2486 /** @todo implement meaningful progress stuff (especially for fixed images). */ 2487 if ( VBOX_SUCCESS(rc) 2488 && pfnProgress) 2489 pfnProgress(NULL /* WARNING! pVM=NULL */, 100, pvUser); 2490 2491 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 2492 return rc; 2493 } 2494 2495 static int vmdkClose(void *pBackendData, bool fDelete) 1979 2496 { 1980 2497 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; … … 1984 2501 * not signalled as an error. After all nothing bad happens. */ 1985 2502 if (pImage) 1986 vmdkFreeImage(pImage );2503 vmdkFreeImage(pImage, fDelete); 1987 2504 1988 2505 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); … … 2332 2849 /* Implement this operation via reopening the image. */ 2333 2850 pszFilename = pImage->pszFilename; 2334 vmdkFreeImage(pImage );2851 vmdkFreeImage(pImage, false); 2335 2852 rc = vmdkOpenImage(pImage, pszFilename, uOpenFlags); 2336 2853 … … 2372 2889 "ddb.uuid.image", pUuid); 2373 2890 if (VBOX_FAILURE(rc)) 2374 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor "));2891 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename); 2375 2892 rc = VINF_SUCCESS; 2376 2893 } … … 2413 2930 "ddb.uuid.modification", pUuid); 2414 2931 if (VBOX_FAILURE(rc)) 2415 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in descriptor "));2932 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in descriptor in '%s'"), pImage->pszFilename); 2416 2933 rc = VINF_SUCCESS; 2417 2934 } … … 2454 2971 "ddb.uuid.parent", pUuid); 2455 2972 if (VBOX_FAILURE(rc)) 2456 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor "));2973 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename); 2457 2974 rc = VINF_SUCCESS; 2458 2975 }
Note:
See TracChangeset
for help on using the changeset viewer.