VirtualBox

Changeset 35100 in vbox for trunk


Ignore:
Timestamp:
Dec 14, 2010 4:21:38 PM (14 years ago)
Author:
vboxsync
Message:

IExtPackFile::Install: Added a 'replace' parameter for automatically trying to uninstall an existing extension pack during upgrade.

Location:
trunk/src/VBox
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp

    r34971 r35100  
    819819    if (!strcmp(a->argv[0], "install"))
    820820    {
    821         if (a->argc != 2)
    822             return errorSyntax(USAGE_EXTPACK, "Incorrect number of parameters for \"extpack install\"");
     821        const char *pszName  = NULL;
     822        bool        fReplace = false;
     823
     824        static const RTGETOPTDEF s_aInstallOptions[] =
     825        {
     826            { "--replace",  'r', RTGETOPT_REQ_NOTHING },
     827        };
     828
     829        RTGetOptInit(&GetState, a->argc, a->argv, s_aInstallOptions, RT_ELEMENTS(s_aInstallOptions), 1, 0 /*fFlags*/);
     830        while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     831        {
     832            switch (ch)
     833            {
     834                case 'f':
     835                    fReplace = true;
     836                    break;
     837
     838                case VINF_GETOPT_NOT_OPTION:
     839                    if (pszName)
     840                        return errorSyntax(USAGE_EXTPACK, "Too many extension pack names given to \"extpack uninstall\"");
     841                    pszName = ValueUnion.psz;
     842                    break;
     843
     844                default:
     845                    return errorGetOpt(USAGE_EXTPACK, ch, &ValueUnion);
     846            }
     847        }
     848        if (!pszName)
     849            return errorSyntax(USAGE_EXTPACK, "No extension pack name was given to \"extpack install\"");
    823850
    824851        char szPath[RTPATH_MAX];
     
    832859        CHECK_ERROR2_RET(ptrExtPackMgr, OpenExtPackFile(bstrTarball.raw(), ptrExtPackFile.asOutParam()), RTEXITCODE_FAILURE);
    833860        CHECK_ERROR2_RET(ptrExtPackFile, COMGETTER(Name)(bstrName.asOutParam()), RTEXITCODE_FAILURE);
    834         CHECK_ERROR2_RET(ptrExtPackFile, Install(), RTEXITCODE_FAILURE);
     861        CHECK_ERROR2_RET(ptrExtPackFile, Install(fReplace), RTEXITCODE_FAILURE);
    835862        RTPrintf("Successfully installed \"%lS\".\n", bstrName.raw());
    836863    }
     
    845872        };
    846873
    847         RTGetOptInit(&GetState, a->argc, a->argv, s_aUninstallOptions, RT_ELEMENTS(s_aUninstallOptions),
    848                      1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     874        RTGetOptInit(&GetState, a->argc, a->argv, s_aUninstallOptions, RT_ELEMENTS(s_aUninstallOptions), 1, 0);
    849875        while ((ch = RTGetOpt(&GetState, &ValueUnion)))
    850876        {
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsExtension.cpp

    r35094 r35100  
    144144     */
    145145    CExtPack extPackCur = manager.Find(strPackName);
    146     bool fUninstallIt = extPackCur.isOk();
    147     if (fUninstallIt)
     146    bool fReplaceIt = extPackCur.isOk();
     147    if (fReplaceIt)
    148148    {
    149149        QString strPackVersionCur = QString("%1r%2").arg(extPackCur.GetVersion()).arg(extPackCur.GetRevision());
     
    172172
    173173    /*
    174      * Perform uninstallation of any previous package.
     174     * Install the selected package.
    175175     *
    176176     * Set the package name return value before doing this as the caller should
    177177     * do a refresh even on failure.
    178178     */
    179     if (pstrExtPackName)
    180         *pstrExtPackName = strPackName;
    181     if (fUninstallIt)
    182     {
    183         /** @todo Refuse this if any VMs are running. */
    184         manager.Uninstall(strPackName, false /*aForcedRemoval*/);
    185         if (!extPackFile.isOk())
    186         {
    187             vboxProblem().cannotUninstallExtPack(strFilePath, manager, pParent);
    188             return;
    189         }
    190     }
    191 
    192     /*
    193      * Install the selected package.
    194      */
    195     extPackFile.Install();
     179    extPackFile.Install(fReplaceIt);
    196180    if (extPackFile.isOk())
    197181        vboxProblem().notifyAboutExtPackInstalled(strPackName, pParent);
    198182    else
    199183        vboxProblem().cannotInstallExtPack(strFilePath, extPackFile, pParent);
     184
     185    if (pstrExtPackName)
     186        *pstrExtPackName = strPackName;
    200187}
    201188
  • trunk/src/VBox/Main/ExtPackManagerImpl.cpp

    r35013 r35100  
    580580}
    581581
    582 STDMETHODIMP ExtPackFile::Install(void)
     582STDMETHODIMP ExtPackFile::Install(BOOL a_fReplace)
    583583{
    584584    AutoCaller autoCaller(this);
     
    587587    {
    588588        if (m->fUsable)
    589             hrc = m->ptrExtPackMgr->doInstall(this);
     589            hrc = m->ptrExtPackMgr->doInstall(this, RT_BOOL(a_fReplace));
    590590        else
    591591            hrc = setError(E_FAIL, "%s", m->strWhyUnusable.c_str());
     
    10621062    if (m->fUsable)
    10631063    {
    1064         /** @todo not important, so it can wait. */
     1064        if (m->hMainMod == NIL_RTLDRMOD)
     1065            probeAndLoad();
     1066        else if (   !objinfoIsEqual(&ObjInfoDesc,    &m->ObjInfoDesc)
     1067                 || !objinfoIsEqual(&ObjInfoMainMod, &m->ObjInfoMainMod)
     1068                 || !objinfoIsEqual(&ObjInfoExtPack, &m->ObjInfoExtPack) )
     1069        {
     1070            /** @todo not important, so it can wait. */
     1071        }
    10651072    }
    10661073    /*
     
    19181925         */
    19191926        ExtPack *pExtPack;
    1920         hrc = refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
     1927        hrc = refreshExtPack(strName.c_str(), false /*a_fUnusableIsError*/, &pExtPack);
    19211928        if (SUCCEEDED(hrc))
    19221929        {
     
    19491956                    if (SUCCEEDED(hrc))
    19501957                    {
    1951                         hrc = refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
     1958                        hrc = refreshExtPack(strName.c_str(), false /*a_fUnusableIsError*/, &pExtPack);
    19521959                        if (SUCCEEDED(hrc))
    19531960                        {
     
    19631970                    {
    19641971                        ErrorInfoKeeper Eik;
    1965                         refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, NULL);
     1972                        refreshExtPack(strName.c_str(), false /*a_fUnusableIsError*/, NULL);
    19661973                    }
    19671974                }
     
    22912298 *
    22922299 * @param   a_pszName           The extension to update..
    2293  * @param   a_fUnsuableIsError  If @c true, report an unusable extension pack
     2300 * @param   a_fUnusableIsError  If @c true, report an unusable extension pack
    22942301 *                              as an error.
    22952302 * @param   a_ppExtPack         Where to store the pointer to the extension
     
    23002307 * @remarks Only called in VBoxSVC.
    23012308 */
    2302 HRESULT ExtPackManager::refreshExtPack(const char *a_pszName, bool a_fUnsuableIsError, ExtPack **a_ppExtPack)
     2309HRESULT ExtPackManager::refreshExtPack(const char *a_pszName, bool a_fUnusableIsError, ExtPack **a_ppExtPack)
    23032310{
    23042311    Assert(m->pVirtualBox != NULL); /* Only called from VBoxSVC. */
     
    23972404    if (   SUCCEEDED(hrc)
    23982405        && pExtPack
    2399         && a_fUnsuableIsError
     2406        && a_fUnusableIsError
    24002407        && !pExtPack->m->fUsable)
    24012408        hrc = setError(E_FAIL, "%s", pExtPack->m->strWhyUnusable.c_str());
     
    24122419 * @param   a_pExtPackFile  The extension pack file, caller checks that it's
    24132420 *                          usable.
    2414  */
    2415 HRESULT ExtPackManager::doInstall(ExtPackFile *a_pExtPackFile)
     2421 * @param   a_fReplace      Whether to replace any existing extpack or just
     2422 *                          fail.
     2423 */
     2424HRESULT ExtPackManager::doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace)
    24162425{
    24172426    AssertReturn(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON, E_UNEXPECTED);
     
    24302439         */
    24312440        ExtPack *pExtPack;
    2432         hrc = refreshExtPack(pStrName->c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
    2433         if (SUCCEEDED(hrc) && !pExtPack)
     2441        hrc = refreshExtPack(pStrName->c_str(), false /*a_fUnusableIsError*/, &pExtPack);
     2442        if (SUCCEEDED(hrc))
     2443        {
     2444            if (pExtPack && a_fReplace)
     2445                hrc = pExtPack->callUninstallHookAndClose(m->pVirtualBox, false /*a_ForcedRemoval*/);
     2446            else if (pExtPack)
     2447                hrc = setError(E_FAIL,
     2448                               tr("Extension pack '%s' is already installed."
     2449                                  " In case of a reinstallation, please uninstall it first"),
     2450                               pStrName->c_str());
     2451        }
     2452        if (SUCCEEDED(hrc))
    24342453        {
    24352454            /*
     
    24382457             * even on failure, to be on the safe side).
    24392458             */
    2440 /** @todo add a hash (SHA-256) of the tarball or maybe just the manifest. */
     2459            /** @todo add a hash (SHA-256) of the tarball or maybe just the manifest. */
    24412460            hrc = runSetUidToRootHelper("install",
    24422461                                        "--base-dir",   m->strBaseDir.c_str(),
     
    24442463                                        "--name",       pStrName->c_str(),
    24452464                                        "--tarball",    pStrTarball->c_str(),
     2465                                        pExtPack ? "--replace" : (const char *)NULL,
    24462466                                        (const char *)NULL);
    24472467            if (SUCCEEDED(hrc))
    24482468            {
    2449                 hrc = refreshExtPack(pStrName->c_str(), true /*a_fUnsuableIsError*/, &pExtPack);
     2469                hrc = refreshExtPack(pStrName->c_str(), true /*a_fUnusableIsError*/, &pExtPack);
    24502470                if (SUCCEEDED(hrc))
    24512471                {
     
    24572477            {
    24582478                ErrorInfoKeeper Eik;
    2459                 refreshExtPack(pStrName->c_str(), false /*a_fUnsuableIsError*/, NULL);
     2479                refreshExtPack(pStrName->c_str(), false /*a_fUnusableIsError*/, NULL);
    24602480            }
    24612481        }
    2462         else if (SUCCEEDED(hrc))
    2463             hrc = setError(E_FAIL,
    2464                            tr("Extension pack '%s' is already installed."
    2465                               " In case of a reinstallation, please uninstall it first"),
    2466                            pStrName->c_str());
    24672482
    24682483        /*
  • trunk/src/VBox/Main/VBoxExtPackHelperApp.cpp

    r35017 r35100  
    195195                              fTemporary ? "temporary " : "", rc, pszDir);
    196196    return RTEXITCODE_SUCCESS;
     197}
     198
     199
     200/**
     201 * Common uninstall worker used by both uninstall and install --replace.
     202 *
     203 * @returns success or failure, message displayed on failure.
     204 * @param   pszExtPackDir   The extension pack directory name.
     205 */
     206static RTEXITCODE CommonUninstallWorker(const char *pszExtPackDir)
     207{
     208    /* Rename the extension pack directory before deleting it to prevent new
     209       VM processes from picking it up. */
     210    char szExtPackUnInstDir[RTPATH_MAX];
     211    int rc = RTStrCopy(szExtPackUnInstDir, sizeof(szExtPackUnInstDir), pszExtPackDir);
     212    if (RT_SUCCESS(rc))
     213        rc = RTStrCat(szExtPackUnInstDir, sizeof(szExtPackUnInstDir), "-_-uninst");
     214    if (RT_FAILURE(rc))
     215        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to construct temporary extension pack path: %Rrc", rc);
     216
     217    rc = RTDirRename(pszExtPackDir, szExtPackUnInstDir, RTPATHRENAME_FLAGS_NO_REPLACE);
     218    if (RT_FAILURE(rc))
     219        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to rename the extension pack directory: %Rrc", rc);
     220
     221    /* Recursively delete the directory content. */
     222    return RemoveExtPackDir(szExtPackUnInstDir, false /*fTemporary*/);
    197223}
    198224
     
    565591 * @param   pszName             The extension pack name.
    566592 * @param   pszMangledName      The mangled extension pack name.
     593 * @param   fReplace            Whether to replace any existing ext pack.
    567594 */
    568595static RTEXITCODE DoInstall2(const char *pszBaseDir, const char *pszCertDir, const char *pszTarball,
    569596                             RTFILE hTarballFile, RTFILE hTarballFileOpt,
    570                              const char *pszName, const char *pszMangledName)
     597                             const char *pszName, const char *pszMangledName, bool fReplace)
    571598{
    572599    /*
     
    612639
    613640    /*
    614      * Check that they don't exist at this point in time.
    615      */
    616     rc = RTPathQueryInfoEx(szFinalPath, &ObjInfo, RTFSOBJATTRADD_NOTHING,  RTPATH_F_ON_LINK);
     641     * Check that they don't exist at this point in time, unless fReplace=true.
     642     */
     643    rc = RTPathQueryInfoEx(szFinalPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    617644    if (RT_SUCCESS(rc) && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
    618         return RTMsgErrorExit(RTEXITCODE_FAILURE, "The extension pack is already installed. You must uninstall the old one first.");
    619     if (RT_SUCCESS(rc))
     645    {
     646        if (!fReplace)
     647            return RTMsgErrorExit(RTEXITCODE_FAILURE,
     648                                  "The extension pack is already installed. You must uninstall the old one first.");
     649    }
     650    else if (RT_SUCCESS(rc))
    620651        return RTMsgErrorExit(RTEXITCODE_FAILURE,
    621652                              "Found non-directory file system object where the extension pack would be installed ('%s')",
    622653                              szFinalPath);
    623     if (rc != VERR_FILE_NOT_FOUND && rc != VERR_PATH_NOT_FOUND)
     654    else if (rc != VERR_FILE_NOT_FOUND && rc != VERR_PATH_NOT_FOUND)
    624655        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected RTPathQueryInfoEx status code %Rrc for '%s'", rc, szFinalPath);
    625656
    626     rc = RTPathQueryInfoEx(szTmpPath, &ObjInfo, RTFSOBJATTRADD_NOTHING,  RTPATH_F_ON_LINK);
     657    rc = RTPathQueryInfoEx(szTmpPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    627658    if (rc != VERR_FILE_NOT_FOUND && rc != VERR_PATH_NOT_FOUND)
    628659        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Unexpected RTPathQueryInfoEx status code %Rrc for '%s'", rc, szFinalPath);
     
    650681    {
    651682        rc = RTDirRename(szTmpPath, szFinalPath, RTPATHRENAME_FLAGS_NO_REPLACE);
     683        if (   RT_FAILURE(rc)
     684            && fReplace
     685            && RTDirExists(szFinalPath))
     686        {
     687            /* Automatic uninstall if --replace was given. */
     688            rcExit = CommonUninstallWorker(szFinalPath);
     689            if (rcExit == RTEXITCODE_SUCCESS)
     690                rc = RTDirRename(szTmpPath, szFinalPath, RTPATHRENAME_FLAGS_NO_REPLACE);
     691        }
    652692        if (RT_SUCCESS(rc))
    653693            RTMsgInfo("Successfully installed '%s' (%s)", pszName, pszTarball);
    654         else
     694        else if (rcExit == RTEXITCODE_SUCCESS)
    655695            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE,
    656696                                    "Failed to rename the temporary directory to the final one: %Rrc ('%s' -> '%s')",
     
    688728    static const RTGETOPTDEF s_aOptions[] =
    689729    {
    690         { "--base-dir",     'b',   RTGETOPT_REQ_STRING },
    691         { "--cert-dir",     'c',   RTGETOPT_REQ_STRING },
    692         { "--name",         'n',   RTGETOPT_REQ_STRING },
    693         { "--tarball",      't',   RTGETOPT_REQ_STRING },
    694         { "--tarball-fd",   'd',   RTGETOPT_REQ_UINT64 }
     730        { "--base-dir",     'b',   RTGETOPT_REQ_STRING  },
     731        { "--cert-dir",     'c',   RTGETOPT_REQ_STRING  },
     732        { "--name",         'n',   RTGETOPT_REQ_STRING  },
     733        { "--tarball",      't',   RTGETOPT_REQ_STRING  },
     734        { "--tarball-fd",   'd',   RTGETOPT_REQ_UINT64  },
     735        { "--replace",      'r',   RTGETOPT_REQ_NOTHING }
    695736    };
    696737    RTGETOPTSTATE   GetState;
     
    704745    const char     *pszTarball      = NULL;
    705746    RTFILE          hTarballFileOpt = NIL_RTFILE;
     747    bool            fReplace        = false;
    706748    RTGETOPTUNION   ValueUnion;
    707749    int             ch;
     
    753795            }
    754796
     797            case 'r':
     798                fReplace = true;
     799                break;
     800
    755801            case 'h':
    756802            case 'V':
     
    783829    {
    784830        rcExit = DoInstall2(pszBaseDir, pszCertDir, pszTarball, hTarballFile, hTarballFileOpt,
    785                             pszName, pstrMangledName->c_str());
     831                            pszName, pstrMangledName->c_str(), fReplace);
    786832        RTFileClose(hTarballFile);
    787833    }
     
    880926    }
    881927
    882     /* Rename the extension pack directory before deleting it to prevent new
    883        VM processes from picking it up. */
    884     char szExtPackUnInstDir[RTPATH_MAX];
    885     rc = RTPathJoin(szExtPackUnInstDir, sizeof(szExtPackUnInstDir), pszBaseDir, strMangledName.c_str());
    886     if (RT_SUCCESS(rc))
    887         rc = RTStrCat(szExtPackUnInstDir, sizeof(szExtPackUnInstDir), "-_-uninst");
    888     if (RT_FAILURE(rc))
    889         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to construct temporary extension pack path: %Rrc", rc);
    890 
    891     rc = RTDirRename(szExtPackDir, szExtPackUnInstDir, RTPATHRENAME_FLAGS_NO_REPLACE);
    892     if (RT_FAILURE(rc))
    893         return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to rename the extension pack directory: %Rrc", rc);
    894 
    895     /* Recursively delete the directory content. */
    896     RTEXITCODE rcExit = RemoveExtPackDir(szExtPackUnInstDir, false /*fTemporary*/);
     928    RTEXITCODE rcExit = CommonUninstallWorker(szExtPackDir);
    897929    if (rcExit == RTEXITCODE_SUCCESS)
    898930        RTMsgInfo("Successfully removed extension pack '%s'\n", pszName);
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r35088 r35100  
    1447614476  <interface
    1447714477    name="IExtPackFile" extends="IExtPackBase"
    14478     uuid="e57e5ab7-e0e8-4a55-9241-afa7ad219911"
     14478    uuid="64b65bda-eedf-442c-9fd2-d179a021031a"
    1447914479    wsmap="suppress"
    1448014480    >
     
    1449514495        Install the extension pack.
    1449614496      </desc>
     14497      <param name="replace" type="boolean" dir="in">
     14498        <desc>
     14499          Set this to automatically uninstall any existing extension pack with
     14500          the same name as the one being installed.
     14501        </desc>
     14502      </param>
    1449714503    </method>
    1449814504  </interface>
  • trunk/src/VBox/Main/include/ExtPackManagerImpl.h

    r34907 r35100  
    7070     * @{ */
    7171    STDMETHOD(COMGETTER(FilePath))(BSTR *a_pbstrPath);
    72     STDMETHOD(Install)(void);
     72    STDMETHOD(Install)(BOOL a_fReplace);
    7373    /** @}  */
    7474
     
    219219    /** @name Internal interfaces used by other Main classes.
    220220     * @{ */
    221     HRESULT     doInstall(ExtPackFile *a_pExtPackFile);
     221    HRESULT     doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace);
    222222    void        callAllVirtualBoxReadyHooks(void);
    223223    void        callAllConsoleReadyHooks(IConsole *a_pConsole);
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