Changeset 9047 in vbox for trunk/src/VBox/Devices
- Timestamp:
- May 22, 2008 5:35:37 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r8509 r9047 3645 3645 } 3646 3646 3647 /** 3648 * Allocates a new copy of the given UTF-8 string using RTMemTmpAlloc(). 3649 * 3650 * @returns Pointer to the allocated UTF-8 string. 3651 * @param pszString UTF-8 string to duplicate. 3652 */ 3653 static char * vmdkStrTmpDup(const char *pszString) 3654 { 3655 Assert(VALID_PTR(pszString)); 3656 size_t cch = strlen(pszString) + 1; 3657 char *psz = (char *)RTMemTmpAlloc(cch); 3658 if (psz) 3659 memcpy(psz, pszString, cch); 3660 return psz; 3661 } 3662 3647 3663 /** @copydoc VBOXHDDBACKEND::pfnRename */ 3648 3664 static int vmdkRename(void *pBackendData, const char *pszFilename) 3649 3665 { 3650 3666 LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename)); 3651 int rc = VERR_NOT_IMPLEMENTED; 3652 3667 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3668 int rc = VINF_SUCCESS; 3669 char **apszOldExtentBaseNames; 3670 char **apszOldExtentFullNames; 3671 char **apszNewExtentFullNames; 3672 char *pszOldImageName; 3673 char *pszNewImageName; 3674 bool fImageFreed = false; 3675 3676 /* Check arguments. */ 3677 if ( !pImage 3678 || (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_RAWDISK) 3679 || !VALID_PTR(pszFilename) 3680 || !*pszFilename) 3681 { 3682 rc = VERR_INVALID_PARAMETER; 3683 goto out; 3684 } 3685 3686 /* 3687 * Allocate an array to store old extent names in case we have to roll back the changes. 3688 * Everything is initialized with zeros. We actually save stuff when and if we change it. 3689 */ 3690 apszOldExtentBaseNames = (char **)RTMemTmpAllocZ(pImage->cExtents * sizeof(char*)); 3691 apszOldExtentFullNames = (char **)RTMemTmpAllocZ(pImage->cExtents * sizeof(char*)); 3692 apszNewExtentFullNames = (char **)RTMemTmpAllocZ(pImage->cExtents * sizeof(char*)); 3693 if (!apszOldExtentBaseNames || !apszOldExtentFullNames || !apszNewExtentFullNames) 3694 { 3695 if (apszOldExtentBaseNames) 3696 RTMemTmpFree(apszOldExtentBaseNames); 3697 if (apszOldExtentFullNames) 3698 RTMemTmpFree(apszOldExtentFullNames); 3699 if (apszNewExtentFullNames) 3700 RTMemTmpFree(apszNewExtentFullNames); 3701 rc = VERR_NO_MEMORY; 3702 goto out; 3703 } 3704 pszOldImageName = NULL; 3705 pszNewImageName = NULL; 3706 3707 do { 3708 /* Basename strings needed for constructing the extent names. */ 3709 char *pszBasenameSubstr = RTPathFilename(pszFilename); 3710 Assert(pszBasenameSubstr); 3711 size_t cbBasenameSubstr = strlen(pszBasenameSubstr) + 1; 3712 3713 /* Loop through each VMDKEXTENT in VMDKIMAGE->pExtents using VMDKIMAGE->cExtents. */ 3714 for (unsigned i = 0; i < pImage->cExtents; i++) 3715 { 3716 PVMDKEXTENT pExtent = &pImage->pExtents[i]; 3717 3718 /* @todo Store pExtent->pszFullname in array for future reference. */ 3719 /* @todo Store pExtent->pszBasename in array for future reference. */ 3720 3721 /* @todo This is copy/paste code, move to seperate function. */ 3722 /* Determine the new file name. */ 3723 /* Set up fullname/basename for extent description. Cannot use StrDup 3724 * for basename, as it is not guaranteed that the memory can be freed 3725 * with RTMemTmpFree, which must be used as in other code paths 3726 * StrDup is not usable. */ 3727 if (pImage->cExtents == 1 && pImage->enmImageType != VD_IMAGE_TYPE_FIXED) 3728 { 3729 char *pszBasename = (char *)RTMemTmpAlloc(cbBasenameSubstr); 3730 if (!pszBasename) 3731 { 3732 rc = VERR_NO_MEMORY; 3733 break; 3734 } 3735 memcpy(pszBasename, pszBasenameSubstr, cbBasenameSubstr); 3736 /* Save the old name in case we need to roll back. */ 3737 apszOldExtentBaseNames[i] = vmdkStrTmpDup(pExtent->pszBasename); 3738 pExtent->pszBasename = pszBasename; 3739 } 3740 else 3741 { 3742 char *pszBasenameExt = RTPathExt(pszBasenameSubstr); 3743 char *pszBasenameBase = RTStrDup(pszBasenameSubstr); 3744 RTPathStripExt(pszBasenameBase); 3745 char *pszTmp; 3746 size_t cbTmp; 3747 if (pImage->enmImageType == VD_IMAGE_TYPE_FIXED) 3748 { 3749 if (pImage->cExtents == 1) 3750 rc = RTStrAPrintf(&pszTmp, "%s-flat%s", pszBasenameBase, 3751 pszBasenameExt); 3752 else 3753 rc = RTStrAPrintf(&pszTmp, "%s-f%03d%s", pszBasenameBase, 3754 i+1, pszBasenameExt); 3755 } 3756 else 3757 rc = RTStrAPrintf(&pszTmp, "%s-s%03d%s", pszBasenameBase, i+1, 3758 pszBasenameExt); 3759 RTStrFree(pszBasenameBase); 3760 if (VBOX_FAILURE(rc)) 3761 break; 3762 cbTmp = strlen(pszTmp) + 1; 3763 char *pszBasename = (char *)RTMemTmpAlloc(cbTmp); 3764 if (!pszBasename) 3765 { 3766 rc = VERR_NO_MEMORY; 3767 break; 3768 } 3769 memcpy(pszBasename, pszTmp, cbTmp); 3770 RTStrFree(pszTmp); 3771 /* Save the old name in case we need to roll back. */ 3772 apszOldExtentBaseNames[i] = vmdkStrTmpDup(pExtent->pszBasename); 3773 pExtent->pszBasename = pszBasename; 3774 /* @todo ??? cbExtent = RT_MIN(cbRemaining, VMDK_2G_SPLIT_SIZE); */ 3775 } 3776 char *pszBasedirectory = RTStrDup(pImage->pszFilename); 3777 RTPathStripFilename(pszBasedirectory); 3778 char *pszFN; 3779 rc = RTStrAPrintf(&pszFN, "%s%c%s", pszBasedirectory, RTPATH_SLASH, 3780 pExtent->pszBasename); 3781 RTStrFree(pszBasedirectory); 3782 if (VBOX_FAILURE(rc)) 3783 break; 3784 3785 /* Close the VMDKEXTENT. */ 3786 vmdkFileClose(pImage, &pExtent->File, false); 3787 3788 /* Rename the file. */ 3789 rc = RTFileMove(pExtent->pszFullname, pszFN, 0); 3790 if (VBOX_FAILURE(rc)) 3791 break; 3792 3793 /* Save both names in case we need to roll back. */ 3794 apszOldExtentFullNames[i] = RTStrDup(pExtent->pszFullname); 3795 apszNewExtentFullNames[i] = RTStrDup(pszFN); 3796 pExtent->pszFullname = pszFN; 3797 } 3798 3799 if (VBOX_FAILURE(rc)) 3800 break; 3801 3802 /* After looping through all of them close the VMDKIMAGE. */ 3803 vmdkFreeImage(pImage, false); 3804 3805 fImageFreed = true; 3806 3807 /* Rename the descriptor file if it's separate. */ 3808 if (pImage->pDescData) 3809 { 3810 rc = RTFileCopy(pImage->pszFilename, pszFilename); 3811 if (VBOX_FAILURE(rc)) 3812 break; 3813 /* Save new name only if we may need to change it back. */ 3814 pszNewImageName = RTStrDup(pszFilename); 3815 } 3816 3817 /* Save the old name in case we need to roll back. */ 3818 pszOldImageName = RTStrDup(pImage->pszFilename); 3819 /* Update pImage with the new information. */ 3820 pImage->pszFilename = pszFilename; 3821 3822 /* Open the new image. */ 3823 rc = vmdkOpenImage(pImage, pImage->uOpenFlags); 3824 if (VBOX_FAILURE(rc)) 3825 break; 3826 /* Remove the old descriptor file. */ 3827 if (pszNewImageName) 3828 { 3829 rc = RTFileDelete(pszOldImageName); 3830 AssertRC(rc); 3831 } 3832 } while (0); 3833 3834 /* Roll back all changes in case of failure. */ 3835 if (VBOX_FAILURE(rc)) 3836 { 3837 int rrc; 3838 if (!fImageFreed) 3839 { 3840 /* 3841 * Some extents may have been closed, close the rest. We will 3842 * re-open the whole thing later. 3843 */ 3844 vmdkFreeImage(pImage, false); 3845 } 3846 if (pszNewImageName) 3847 { 3848 /* The image was actually copied, destroy the copy. */ 3849 rrc = RTFileDelete(pszNewImageName); 3850 AssertRC(rrc); 3851 RTStrFree(pszNewImageName); 3852 } 3853 if (pszOldImageName) 3854 { 3855 /* We end up here only if vmdkOpenImage() has failed, restore the old image name. */ 3856 pImage->pszFilename = pszOldImageName; 3857 } 3858 /* Restore renamed extents. */ 3859 for (unsigned i = 0; i < pImage->cExtents; i++) 3860 { 3861 if (apszOldExtentFullNames[i]) 3862 { 3863 rrc = RTFileMove(apszNewExtentFullNames[i], apszOldExtentFullNames[i], 0); 3864 AssertRC(rrc); 3865 RTStrFree(apszNewExtentFullNames[i]); 3866 RTStrFree(apszOldExtentFullNames[i]); 3867 } 3868 } 3869 rrc = vmdkOpenImage(pImage, pImage->uOpenFlags); 3870 AssertRC(rrc); 3871 } 3872 3873 RTMemTmpFree(apszOldExtentBaseNames); 3874 RTMemTmpFree(apszOldExtentFullNames); 3875 RTMemTmpFree(apszNewExtentFullNames); 3876 3877 out: 3653 3878 LogFlowFunc(("returns %Vrc\n", rc)); 3654 3879 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.