VirtualBox

Changeset 42177 in vbox for trunk/src


Ignore:
Timestamp:
Jul 17, 2012 12:27:22 PM (13 years ago)
Author:
vboxsync
Message:

Main/VirtualBox+Machine: implement the directory handling/renaming logic for gro
up changes, plus strict validation of the VM groups to avoid trouble when using
it as a directory component

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r42129 r42177  
    222222                        ComObjPtr<Machine> *machine = NULL);
    223223
     224    HRESULT validateMachineGroup(const Utf8Str &aGroup);
    224225    HRESULT convertMachineGroups(ComSafeArrayIn(IN_BSTR, aMachineGroups), StringsList *pllMachineGroups);
    225226
     
    314315    HRESULT unregisterDHCPServer(DHCPServer *aDHCPServer,
    315316                                 bool aSaveRegistry = true);
    316    
     317
    317318    void decryptSettings();
    318319    void decryptMediumSettings(Medium *pMedium);
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r42129 r42177  
    315315
    316316        mUserData->s.strName = strName;
    317        
     317
    318318        mUserData->s.llGroups = llGroups;
    319319
     
    89428942    if (    mUserData->s.fNameSync
    89438943         && mUserData.isBackedUp()
    8944          && mUserData.backedUpData()->s.strName != mUserData->s.strName
     8944         && (   mUserData.backedUpData()->s.strName != mUserData->s.strName
     8945             || mUserData.backedUpData()->s.llGroups.front() != mUserData->s.llGroups.front())
    89458946       )
    89468947    {
     
    89588959            Utf8Str name = mUserData.backedUpData()->s.strName;
    89598960            Utf8Str newName = mUserData->s.strName;
     8961            Utf8Str group = mUserData.backedUpData()->s.llGroups.front();
     8962            if (group == "/")
     8963                group.setNull();
     8964            Utf8Str newGroup = mUserData->s.llGroups.front();
     8965            if (newGroup == "/")
     8966                newGroup.setNull();
    89608967
    89618968            configFile = mData->m_strConfigFileFull;
    89628969
    8963             /* first, rename the directory if it matches the machine name */
     8970            /* first, rename the directory if it matches the group and machine name */
     8971            Utf8Str groupPlusName = Utf8StrFmt("%s%c%s",
     8972                group.c_str(), RTPATH_DELIMITER, name.c_str());
     8973            Utf8Str newGroupPlusName = Utf8StrFmt("%s%c%s",
     8974                newGroup.c_str(), RTPATH_DELIMITER, newName.c_str());
    89648975            configDir = configFile;
    89658976            configDir.stripFilename();
    89668977            newConfigDir = configDir;
    8967             if (!strcmp(RTPathFilename(configDir.c_str()), name.c_str()))
     8978            if (   configDir.length() >= groupPlusName.length()
     8979                && configDir.substr(configDir.length() - groupPlusName.length(), groupPlusName.length()).equals(groupPlusName.c_str()))
    89688980            {
    8969                 newConfigDir.stripFilename();
    8970                 newConfigDir.append(RTPATH_DELIMITER);
    8971                 newConfigDir.append(newName);
     8981                newConfigDir = newConfigDir.substr(0, configDir.length() - groupPlusName.length());
     8982                Utf8Str newConfigBaseDir(newConfigDir);
     8983                newConfigDir.append(newGroupPlusName);
    89728984                /* new dir and old dir cannot be equal here because of 'if'
    89738985                 * above and because name != newName */
     
    89778989                    /* perform real rename only if the machine is not new */
    89788990                    vrc = RTPathRename(configDir.c_str(), newConfigDir.c_str(), 0);
     8991                    if (vrc == VERR_FILE_NOT_FOUND)
     8992                    {
     8993                        /* create the parent directory, then retry renaming */
     8994                        Utf8Str parent(newConfigDir);
     8995                        parent.stripFilename();
     8996                        (void)RTDirCreateFullPath(parent.c_str(), 0700);
     8997                        vrc = RTPathRename(configDir.c_str(), newConfigDir.c_str(), 0);
     8998                    }
    89798999                    if (RT_FAILURE(vrc))
    89809000                    {
     
    89859005                                      vrc);
    89869006                        break;
     9007                    }
     9008                    /* delete subdirectories which are no longer needed */
     9009                    Utf8Str dir(configDir);
     9010                    dir.stripFilename();
     9011                    while (dir != newConfigBaseDir && dir != ".")
     9012                    {
     9013                        vrc = RTDirRemove(dir.c_str());
     9014                        if (RT_FAILURE(vrc))
     9015                            break;
     9016                        dir.stripFilename();
    89879017                    }
    89889018                    dirRenamed = true;
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r42168 r42177  
    13751375                                                BSTR *aFilename)
    13761376{
    1377     /// @todo implement aGroup
    1378     NOREF(aGroup);
    13791377    LogFlowThisFuncEnter();
    13801378    LogFlowThisFunc(("aName=\"%ls\",aBaseFolder=\"%ls\"\n", aName, aBaseFolder));
     
    13861384    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    13871385
     1386    Utf8Str strGroup(aGroup);
     1387    if (strGroup.isEmpty())
     1388        strGroup = "/";
     1389    HRESULT rc = validateMachineGroup(strGroup);
     1390    if (FAILED(rc))
     1391        return rc;
     1392
    13881393    /* Compose the settings file name using the following scheme:
    13891394     *
    1390      *     <base_folder>/<machine_name>/<machine_name>.xml
     1395     *     <base_folder><group>/<machine_name>/<machine_name>.xml
    13911396     *
    13921397     * If a non-null and non-empty base folder is specified, the default
     
    14051410    calculateFullPath(strBase, strBase);
    14061411
    1407     Bstr bstrSettingsFile = BstrFmt("%s%c%s%c%s.vbox",
     1412    /* eliminate toplevel group to avoid // in the result */
     1413    if (strGroup == "/")
     1414        strGroup.setNull();
     1415    Bstr bstrSettingsFile = BstrFmt("%s%s%c%s%c%s.vbox",
    14081416                                    strBase.c_str(),
     1417                                    strGroup.c_str(),
    14091418                                    RTPATH_DELIMITER,
    14101419                                    strName.c_str(),
    14111420                                    RTPATH_DELIMITER,
    14121421                                    strName.c_str());
    1413 
    1414 #if 0  /* Try to get a unique name. */
    1415     for (unsigned i = 1; RTFileExists(bstrSettingsFile.c_str() && i < 100; ++i)
    1416         bstrSettingsFile = BstrFmt("%s%c%s%u%c%s%u.vbox",
    1417                                    strBase.c_str(),
    1418                                    RTPATH_DELIMITER,
    1419                                    strName.c_str(), i,
    1420                                    RTPATH_DELIMITER,
    1421                                    strName.c_str());
    1422 #endif
    14231422
    14241423    bstrSettingsFile.detachTo(aFilename);
     
    30223021}
    30233022
     3023static HRESULT validateMachineGroupHelper(const Utf8Str &aGroup)
     3024{
     3025    /* empty strings are invalid */
     3026    if (aGroup.isEmpty())
     3027        return E_INVALIDARG;
     3028    /* the toplevel group is valid */
     3029    if (aGroup == "/")
     3030        return S_OK;
     3031    /* any other strings of length 1 are invalid */
     3032    if (aGroup.length() == 1)
     3033        return E_INVALIDARG;
     3034    /* must start with a slash */
     3035    if (aGroup.c_str()[0] != '/')
     3036        return E_INVALIDARG;
     3037    /* must not end with a slash */
     3038    if (aGroup.c_str()[aGroup.length() - 1] == '/')
     3039        return E_INVALIDARG;
     3040    /* check the group components */
     3041    const char *pStr = aGroup.c_str() + 1;  /* first char is /, skip it */
     3042    while (pStr)
     3043    {
     3044        char *pSlash = RTStrStr(pStr, "/");
     3045        if (pSlash)
     3046        {
     3047            /* no empty components (or // sequences in other words) */
     3048            if (pSlash == pStr)
     3049                return E_INVALIDARG;
     3050            /* check if the machine name rules are violated, because that means
     3051             * the group components is too close to the limits. */
     3052            Utf8Str tmp((const char *)pStr, (size_t)(pSlash - pStr));
     3053            Utf8Str tmp2(tmp);
     3054            sanitiseMachineFilename(tmp);
     3055            if (tmp != tmp2)
     3056                return E_INVALIDARG;
     3057            pStr = pSlash + 1;
     3058        }
     3059        else
     3060        {
     3061            /* check if the machine name rules are violated, because that means
     3062             * the group components is too close to the limits. */
     3063            Utf8Str tmp(pStr);
     3064            Utf8Str tmp2(tmp);
     3065            sanitiseMachineFilename(tmp);
     3066            if (tmp != tmp2)
     3067                return E_INVALIDARG;
     3068            pStr = NULL;
     3069        }
     3070    }
     3071    return S_OK;
     3072}
     3073
     3074/**
     3075 * Validates a machine group.
     3076 *
     3077 * @param aMachineGroup     Machine group.
     3078 *
     3079 * @return S_OK or E_INVALIDARG
     3080 */
     3081HRESULT VirtualBox::validateMachineGroup(const Utf8Str &aGroup)
     3082{
     3083    HRESULT rc = validateMachineGroupHelper(aGroup);
     3084    if (FAILED(rc))
     3085        rc = setError(rc,
     3086                      tr("Invalid machine group '%s'"),
     3087                      aGroup.c_str());
     3088    return rc;
     3089}
     3090
    30243091/**
    30253092 * Takes a list of machine groups, and sanitizes/validates it.
     
    30303097 * @return S_OK or E_INVALIDARG
    30313098 */
    3032 
    30333099HRESULT VirtualBox::convertMachineGroups(ComSafeArrayIn(IN_BSTR, aMachineGroups), StringsList *pllMachineGroups)
    30343100{
     
    30423108            if (group.length() == 0)
    30433109                group = "/";
    3044             /* must start with a slash */
    3045             if (group.c_str()[0] != '/')
    3046                 return E_INVALIDARG;
    3047             /* must not end with a slash */
    3048             if (group.length() > 1 && group.c_str()[group.length() - 1] == '/')
    3049                 return E_INVALIDARG;
    3050 
    3051             /** @todo validate each component of the group hierarchy */
     3110
     3111            HRESULT rc = validateMachineGroup(group);
     3112            if (FAILED(rc))
     3113                return rc;
    30523114
    30533115            /* no duplicates please */
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