VirtualBox

Changeset 9047 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
May 22, 2008 5:35:37 AM (17 years ago)
Author:
vboxsync
Message:

Partially implemented rename vmdk api call.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r8509 r9047  
    36453645}
    36463646
     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 */
     3653static 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
    36473663/** @copydoc VBOXHDDBACKEND::pfnRename */
    36483664static int vmdkRename(void *pBackendData, const char *pszFilename)
    36493665{
    36503666    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
     3877out:
    36533878    LogFlowFunc(("returns %Vrc\n", rc));
    36543879    return rc;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette