Пример #1
0
STDMETHODIMP Guest::COMGETTER(AdditionsRevision)(ULONG *a_puAdditionsRevision)
{
    CheckComArgOutPointerValid(a_puAdditionsRevision);

    AutoCaller autoCaller(this);
    HRESULT hrc = autoCaller.rc();
    if (SUCCEEDED(hrc))
    {
        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

        /*
         * Return the ReportGuestInfo2 version info if available.
         */
        if (   !mData.mAdditionsVersionNew.isEmpty()
            || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None)
            *a_puAdditionsRevision = mData.mAdditionsRevision;
        else
        {
            /*
             * If we're running older guest additions (< 3.2.0) try get it from
             * the guest properties. Detected switched around Version and
             * Revision in early 3.1.x releases (see r57115).
             */
            ComPtr<IMachine> ptrMachine = mParent->machine();
            alock.release(); /* No need to hold this during the IPC fun. */

            Bstr bstr;
            hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam());
            if (SUCCEEDED(hrc))
            {
                Utf8Str str(bstr);
                uint32_t uRevision;
                int vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision);
                if (vrc != VINF_SUCCESS && str.count('.') == 2)
                {
                    hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam());
                    if (SUCCEEDED(hrc))
                    {
                        str = bstr;
                        vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision);
                    }
                }
                if (vrc == VINF_SUCCESS)
                    *a_puAdditionsRevision = uRevision;
                else
                    hrc = VBOX_E_IPRT_ERROR;
            }
            if (FAILED(hrc))
            {
                /* Return 0 if we don't know. */
                *a_puAdditionsRevision = 0;
                hrc = S_OK;
            }
        }
    }
    return hrc;
}
Пример #2
0
RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion)
{
    /*
     * Reset the variables kept in state.
     */
    pState->pDef = NULL;
    pState->uIndex = UINT32_MAX;

    /*
     * Make sure the union is completely cleared out, whatever happens below.
     */
    pValueUnion->u64 = 0;
    pValueUnion->pDef = NULL;

    /*
     * The next option.
     */
    bool            fShort;
    int             iThis;
    const char     *pszArgThis;
    PCRTGETOPTDEF   pOpt;

    if (pState->pszNextShort)
    {
        /*
         * We've got short options left over from the previous call.
         */
        pOpt = rtGetOptSearchShort(*pState->pszNextShort, pState->paOptions, pState->cOptions, pState->fFlags);
        if (!pOpt)
        {
            pValueUnion->psz = pState->pszNextShort;
            return VERR_GETOPT_UNKNOWN_OPTION;
        }
        pState->pszNextShort++;
        pszArgThis = pState->pszNextShort - 2;
        iThis = pState->iNext;
        fShort = true;
    }
    else
    {
        /*
         * Pop off the next argument.  Sorting options and dealing with the
         * dash-dash makes this a little extra complicated.
         */
        for (;;)
        {
            if (pState->iNext >= pState->argc)
                return 0;

            if (pState->cNonOptions)
            {
                if (pState->cNonOptions == INT32_MAX)
                {
                    pValueUnion->psz = pState->argv[pState->iNext++];
                    return VINF_GETOPT_NOT_OPTION;
                }

                if (pState->iNext + pState->cNonOptions >= pState->argc)
                {
                    pState->cNonOptions = INT32_MAX;
                    continue;
                }
            }

            iThis = pState->iNext++;
            pszArgThis = pState->argv[iThis + pState->cNonOptions];

            /*
             * Do a long option search first and then a short option one.
             * This way we can make sure single dash long options doesn't
             * get mixed up with short ones.
             */
            pOpt = rtGetOptSearchLong(pszArgThis, pState->paOptions, pState->cOptions, pState->fFlags);
            if (    !pOpt
                &&  pszArgThis[0] == '-'
                &&  pszArgThis[1] != '-'
                &&  pszArgThis[1] != '\0')
            {
                pOpt = rtGetOptSearchShort(pszArgThis[1], pState->paOptions, pState->cOptions, pState->fFlags);
                fShort = pOpt != NULL;
            }
            else
                fShort = false;

            /* Look for dash-dash. */
            if (!pOpt && !strcmp(pszArgThis, "--"))
            {
                rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
                pState->cNonOptions = INT32_MAX;
                continue;
            }

            /* Options first hacks. */
            if (pState->fFlags & RTGETOPTINIT_FLAGS_OPTS_FIRST)
            {
                if (pOpt)
                    rtGetOptMoveArgvEntries(&pState->argv[iThis], &pState->argv[iThis + pState->cNonOptions]);
                else if (*pszArgThis == '-')
                {
                    pValueUnion->psz = pszArgThis;
                    return VERR_GETOPT_UNKNOWN_OPTION;
                }
                else
                {
                    /* not an option, add it to the non-options and try again. */
                    pState->iNext--;
                    pState->cNonOptions++;

                    /* Switch to returning non-options if we've reached the end. */
                    if (pState->iNext + pState->cNonOptions >= pState->argc)
                        pState->cNonOptions = INT32_MAX;
                    continue;
                }
            }

            /* done */
            break;
        }
    }

    if (pOpt)
    {
        pValueUnion->pDef = pOpt; /* in case of no value or error. */

        if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
        {
            /*
             * Find the argument value.
             *
             * A value is required with the argument. We're trying to be
             * understanding here and will permit any of the following:
             *      -svalue, -s value, -s:value and -s=value
             * (Ditto for long options.)
             */
            const char *pszValue;
            if (fShort)
            {
                if (pszArgThis[2] == '\0')
                {
                    if (iThis + 1 >= pState->argc)
                        return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
                    pszValue = pState->argv[iThis + pState->cNonOptions + 1];
                    rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
                    pState->iNext++;
                }
                else /* same argument. */
                    pszValue = &pszArgThis[2  + (pszArgThis[2] == ':' || pszArgThis[2] == '=')];
                if (pState->pszNextShort)
                {
                    pState->pszNextShort = NULL;
                    pState->iNext++;
                }
            }
            else
            {
                size_t cchLong = strlen(pOpt->pszLong);
                if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
                {

                    if (pszArgThis[cchLong] == '\0')
                        return VERR_GETOPT_INDEX_MISSING;

                    uint32_t uIndex;
                    char *pszRet = NULL;
                    int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex);
                    if (rc == VWRN_TRAILING_CHARS)
                    {
                        if (   pszRet[0] != ':'
                            && pszRet[0] != '=')
                            return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
                        pState->uIndex = uIndex;
                        pszValue = pszRet + 1;
                    }
                    else if (rc == VINF_SUCCESS)
                    {
                        if (iThis + 1 >= pState->argc)
                            return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
                        pState->uIndex = uIndex;
                        pszValue = pState->argv[iThis + pState->cNonOptions + 1];
                        rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
                        pState->iNext++;
                    }
                    else
                        AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
                }
                else
                {
                    if (pszArgThis[cchLong] == '\0')
                    {
                        if (iThis + 1 >= pState->argc)
                            return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
                        pszValue = pState->argv[iThis + pState->cNonOptions + 1];
                        rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
                        pState->iNext++;
                    }
                    else /* same argument. */
                        pszValue = &pszArgThis[cchLong + 1];
                }
            }

            /*
             * Set up the ValueUnion.
             */
            int rc = rtGetOptProcessValue(pOpt->fFlags, pszValue, pValueUnion);
            if (RT_FAILURE(rc))
                return rc;
        }
        else if (fShort)
        {
            /*
             * Deal with "compressed" short option lists, correcting the next
             * state variables for the start and end cases.
             */
            if (pszArgThis[2])
            {
                if (!pState->pszNextShort)
                {
                    /* start */
                    pState->pszNextShort = &pszArgThis[2];
                    pState->iNext--;
                }
            }
            else if (pState->pszNextShort)
            {
                /* end */
                pState->pszNextShort = NULL;
                pState->iNext++;
            }
        }
        else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
        {
            size_t cchLong = strlen(pOpt->pszLong);
            if (pszArgThis[cchLong] == '\0')
                return VERR_GETOPT_INDEX_MISSING;

            uint32_t uIndex;
            if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS)
                pState->uIndex = uIndex;
            else
                AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
        }

        pState->pDef = pOpt;
        return pOpt->iShort;
    }

    /*
     * Not a known option argument. If it starts with a switch char (-) we'll
     * fail with unknown option, and if it doesn't we'll return it as a non-option.
     */
    if (*pszArgThis == '-')
    {
        pValueUnion->psz = pszArgThis;
        return VERR_GETOPT_UNKNOWN_OPTION;
    }

    pValueUnion->psz = pszArgThis;
    return VINF_GETOPT_NOT_OPTION;
}