VirtualBox

Changeset 86274 in vbox


Ignore:
Timestamp:
Sep 24, 2020 7:52:56 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
140550
Message:

bugref:9781. New function Unattended::i_getDetectedOSVersion(). New function UnattendedScriptTemplate::getGuestOSConditional(). New placeholders @@VBOX_GUEST_OS_COND_VERSION@@, @@VBOX_INSERT_GUEST_OS_VERSION@@, @@VBOX_INSERT_GUEST_OS_MAJOR_VERSION@@.

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

Legend:

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

    r84645 r86274  
    7878    bool           i_isGuestOs64Bit() const;
    7979    VBOXOSTYPE     i_getGuestOsType() const;
     80    Utf8Str const &i_getDetectedOSVersion();
    8081
    8182
  • trunk/src/VBox/Main/include/UnattendedScript.h

    r84564 r86274  
    9595     */
    9696    virtual HRESULT getConditional(const char *pachPlaceholder, size_t cchPlaceholder, bool *pfOutputting);
     97
     98
     99    /**
     100     * Get the result of a conditional for special version of guest OS.
     101     *
     102     * @returns COM status code.
     103     * @param   pachPlaceholder     The placholder string.  Not zero terminated.
     104     * @param   cchPlaceholder      The length of the placeholder.
     105     * @param   cchContent          The length of placeholder content.
     106     * @param   pcchCorrect         The length of part which must be excluded from the final content of
     107     *                              the placeholder.
     108     * @param   pfOutputting        Where to return the result of the conditional.
     109     *                              This holds the current outputting state on input
     110     *                              in case someone want to sanity check anything.
     111     */
     112    virtual HRESULT getGuestOSConditional(const char *pachPlaceholder,
     113                                          size_t cchPlaceholder,
     114                                          size_t cchContent,
     115                                          size_t *pcchCorrect,
     116                                          bool *pfOutputting);
    97117};
    98118
  • trunk/src/VBox/Main/src-server/UnattendedImpl.cpp

    r85277 r86274  
    26822682}
    26832683
     2684Utf8Str const & Unattended::i_getDetectedOSVersion()
     2685{
     2686    Assert(isReadLockedOnCurrentThread());
     2687    return mStrDetectedOSVersion;
     2688}
     2689
    26842690HRESULT Unattended::i_attachImage(UnattendedInstallationDisk const *pImage, ComPtr<IMachine> const &rPtrSessionMachine,
    26852691                                  AutoMultiWriteLock2 &rLock)
  • trunk/src/VBox/Main/src-server/UnattendedScript.cpp

    r84645 r86274  
    5959    static const char s_szPrefixCond[]     = "@@VBOX_COND_";
    6060    static const char s_szPrefixCondEnd[]  = "@@VBOX_COND_END@@";
     61    static const char s_szPrefixCondGuestOs[]     = "@@VBOX_GUEST_OS_COND_";
     62    static const char s_szPrefixCondGuestOsEnd[]  = "@@VBOX_GUEST_OS_COND_END@@";
    6163
    6264    struct
     
    6971    size_t      offTemplate = 0;
    7072    size_t      cchTemplate = mStrScriptFullContent.length();
     73    size_t      cchInternalCorrect = 0;//used in logic handling the placeholder @@VBOX_GUEST_OS_COND_XXX@@
    7174    rStrDst.setNull();
    7275    for (;;)
     
    8386                try
    8487                {
    85                     rStrDst.append(mStrScriptFullContent, offTemplate, cchToCopy);
     88                    rStrDst.append(mStrScriptFullContent, offTemplate + cchInternalCorrect, cchToCopy - + cchInternalCorrect);
    8689                }
    8790                catch (std::bad_alloc &)
     
    9295            }
    9396            offTemplate += cchToCopy;
     97            cchInternalCorrect = 0;//don't forget to reset
    9498        }
    9599
     
    124128                || pszPlaceholder[cchPlaceholder - 2] != '@'
    125129                || (   strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) != 0
    126                     && strncmp(pszPlaceholder, s_szPrefixCond,   sizeof(s_szPrefixCond)   - 1) != 0) )
     130                    && strncmp(pszPlaceholder, s_szPrefixCond,   sizeof(s_szPrefixCond)   - 1) != 0
     131                    && strncmp(pszPlaceholder, s_szPrefixCondGuestOs,   sizeof(s_szPrefixCondGuestOs) - 1) != 0) )
    127132            {
    128133                hrc = mpSetError->setError(E_FAIL, mpSetError->tr("Malformed template placeholder '%.*s'"),
     
    136141             * @@VBOX_INSERT_XXX@@:
    137142             */
    138             if (strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) == 0)
     143            if ( strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) == 0 )
    139144            {
    140145                /*
     
    164169             * @@VBOX_COND_END@@: Pop one item of the conditional stack.
    165170             */
    166             else if (   cchPlaceholder == sizeof(s_szPrefixCondEnd) - 1U
    167                      && strncmp(pszPlaceholder, s_szPrefixCondEnd, sizeof(s_szPrefixCondEnd) - 1U) == 0)
     171            else if ( strncmp(pszPlaceholder, s_szPrefixCondEnd, sizeof(s_szPrefixCondEnd) - 1U) == 0 )
    168172            {
    169173                if (cConds > 0)
     
    184188             *                    one from the condition.
    185189             */
    186             else
    187             {
    188                 Assert(strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) == 0);
     190            else if ( strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1U) == 0 )
     191            {
    189192                if (cConds + 1 < RT_ELEMENTS(aConds))
    190193                {
     
    192195                    bool fNewOutputting = fOutputting;
    193196                    hrc = getConditional(pszPlaceholder, cchPlaceholder, &fNewOutputting);
     197                    if (SUCCEEDED(hrc))
     198                        fOutputting = fOutputting && fNewOutputting;
     199                    else
     200                        break;
     201                    cConds++;
     202                }
     203                else
     204                {
     205                    hrc = mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     206                                                   mpSetError->tr("Too deep conditional nesting at offset %zu (%#zx)"),
     207                                                   offPlaceholder, offPlaceholder);
     208                    break;
     209                }
     210            }
     211            /*
     212             * @@VBOX_GUEST_OS_COND_END@@: Pop one item of the conditional stack.
     213             */
     214            else if ( strncmp(pszPlaceholder, s_szPrefixCondGuestOsEnd, sizeof(s_szPrefixCondGuestOsEnd) - 1U) == 0 )
     215            {
     216                if (cConds > 0)
     217                {
     218                    cConds--;
     219                    fOutputting = aConds[cConds].fSavedOutputting;
     220                }
     221                else
     222                {
     223                    hrc = mpSetError->setErrorBoth(E_FAIL, VERR_PARSE_ERROR,
     224                                                   mpSetError->tr("%s without @@VBOX_GUEST_OS_COND_XXX@@ at offset %zu (%#zx)"),
     225                                                   s_szPrefixCondGuestOsEnd, offPlaceholder, offPlaceholder);
     226                    break;
     227                }
     228            }
     229            /*
     230             * @@VBOX_GUEST_OS_COND_XXX@@: Push the previous outputting state and combine it with the
     231             *                             one from the condition.
     232             */
     233            else
     234            {
     235                Assert(strncmp(pszPlaceholder, s_szPrefixCondGuestOs, sizeof(s_szPrefixCondGuestOs) - 1) == 0);
     236                if (cConds + 1 < RT_ELEMENTS(aConds))
     237                {
     238                    aConds[cConds].fSavedOutputting = fOutputting;
     239                    bool fNewOutputting = fOutputting;
     240
     241                    //offTemplate is the beginning of content, offEndContent is the end of content
     242                    //@@PLACEHOLDER_BEGIN@@Content@@PLACEHOLDER_END@@
     243                    //                 ^       ^
     244                    //                 |       |
     245                    //         offTemplate  offEndContent
     246                    size_t offEndContent = mStrScriptFullContent.find(s_szPrefix, offTemplate);
     247                    size_t cchContent = offEndContent - offTemplate - 1;
     248                    hrc = getGuestOSConditional(pszPlaceholder, cchPlaceholder, cchContent, &cchInternalCorrect, &fNewOutputting);
    194249                    if (SUCCEEDED(hrc))
    195250                        fOutputting = fOutputting && fNewOutputting;
     
    379434    else if (IS_PLACEHOLDER_MATCH("OS_ARCH6"))
    380435        rValue = mpUnattended->i_isGuestOs64Bit() ? "x86_64" : "i686";
     436    else if (IS_PLACEHOLDER_MATCH("GUEST_OS_VERSION"))
     437        rValue = mpUnattended->i_getDetectedOSVersion();
     438    else if (IS_PLACEHOLDER_MATCH("GUEST_OS_MAJOR_VERSION"))
     439    {
     440        Utf8Str strOsVer(mpUnattended->i_getDetectedOSVersion());
     441        RTCList<RTCString> partList = strOsVer.split(".");
     442        if (partList.size() < 1)
     443        {
     444            rValue.setNull();
     445            return mpSetError->setErrorBoth(E_FAIL, VERR_NOT_FOUND, mpSetError->tr("Unknown guest OS major version '%s'"),
     446                                            partList.at(0).c_str());
     447        }
     448        rValue = partList.at(0);
     449    }
    381450    else if (IS_PLACEHOLDER_MATCH("TIME_ZONE_UX"))
    382451        rValue = mpUnattended->i_getTimeZoneInfo()
     
    426495                                        cchFullPlaceholder, pachPlaceholder);
    427496    }
     497    return S_OK;
     498#undef IS_PLACEHOLDER_MATCH
     499}
     500
     501HRESULT UnattendedScriptTemplate::getGuestOSConditional(const char *pachPlaceholder,
     502                                                        size_t cchPlaceholder,
     503                                                        size_t cchContent,
     504                                                        size_t *cchCorrect,
     505                                                        bool *pfOutputting)
     506{
     507#define IS_PLACEHOLDER_MATCH(a_szMatch) \
     508        (   cchPlaceholder == sizeof("@@VBOX_GUEST_OS_COND_" a_szMatch "@@") - 1U \
     509         && memcmp(pachPlaceholder, "@@VBOX_GUEST_OS_COND_" a_szMatch "@@", sizeof("@@VBOX_GUEST_OS_COND_" a_szMatch "@@") - 1U) == 0)
     510
     511    if ( IS_PLACEHOLDER_MATCH("VERSION") )
     512    {
     513        Utf8Str strT(pachPlaceholder + cchPlaceholder, cchContent);
     514        RTCList<RTCString> partList = strT.split("**");
     515        Utf8Str strRequiredOSVersion;
     516        if (partList.size() == 2)//when the version is placed together with the placeholder in one line in the file
     517        {
     518            //The case when the string has been splitted on the 2 parts:
     519            //1. OS version
     520            //2. Actual content
     521            strRequiredOSVersion.assign(partList.at(0));
     522            //cchCorrect = "**" + length of OS version string + "**"
     523            *cchCorrect = 2 + partList.at(0).length() + 2;// must be subtracted from the cchContent
     524        }
     525        else if (partList.size() == 3)//when the version is placed on a standalone line in the file
     526        {
     527            //The case when the string has been splitted on the 3 parts:
     528            //1. Empty string or string with only "\n"
     529            //2. OS version
     530            //3. Actual content
     531            strRequiredOSVersion.assign(partList.at(1));
     532            *cchCorrect = 2 + partList.at(0).length() + partList.at(1).length() + 2;// must be subtracted from the cchContent
     533        }
     534        else//case with wrong string syntax
     535        {
     536            *cchCorrect = 0;
     537            *pfOutputting = false;
     538            LogRel(("Malformed content of the template @@VBOX_GUEST_OS_COND_VERSION@@\n"));
     539            return S_OK;
     540        }
     541
     542        if (strRequiredOSVersion.isEmpty())
     543            *pfOutputting = false;
     544        else
     545        {
     546            Utf8Str strDetectedOSVersion = mpUnattended->i_getDetectedOSVersion();
     547            RTCList<RTCString> partListRequired = strRequiredOSVersion.split(".");
     548            RTCList<RTCString> partListDetected = strDetectedOSVersion.split(".");
     549            *pfOutputting = false;//initially is set to "false"
     550
     551            /** @todo r=vvp: Should we check the string with a requested OS version for digits?
     552             *        (with RTLocCIsDigit()) */
     553            //Major version must be presented
     554            if ( partListDetected.at(0).toUInt32() >= partListRequired.at(0).toUInt32() )//comparison major versions
     555            {
     556                //OS major versions are equal or detected guest OS major version is greater. Go further.
     557                if (partListDetected.size() > 1 && partListRequired.size() > 1)//comparison minor versions
     558                {
     559                    if (partListDetected.at(1).toUInt32() >= partListRequired.at(1).toUInt32())
     560                        //OS minor versions are equal or detected guest OS minor version is greater. Go further.
     561                        *pfOutputting = true;
     562                    else
     563                        //The detected guest OS minor version is less than the requested one.
     564                        *pfOutputting = false;
     565                }
     566                else
     567                    //OS minor versions are absent.
     568                    *pfOutputting = true;
     569            }
     570            else
     571                //The detected guest OS major version is less than the requested one.
     572                *pfOutputting = false;
     573        }
     574    }
     575    else
     576        return mpSetError->setErrorBoth(E_FAIL, VERR_NOT_FOUND, mpSetError->tr("Unknown conditional placeholder '%.*s'"),
     577                                        cchPlaceholder, pachPlaceholder);
    428578    return S_OK;
    429579#undef IS_PLACEHOLDER_MATCH
Note: See TracChangeset for help on using the changeset viewer.

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