VirtualBox

Changeset 13293 in vbox


Ignore:
Timestamp:
Oct 15, 2008 4:19:36 PM (16 years ago)
Author:
vboxsync
Message:

HostServices/GuestProperties and Main: support property flags - the values are not yet checked

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestPropertySvc.h

    r13159 r13293  
    3535#include <VBox/VBoxGuest.h>
    3636#include <VBox/hgcmsvc.h>
     37#include <VBox/log.h>
     38#include <iprt/assert.h>
     39
     40#include <string.h>
     41
     42#ifdef RT_OS_WINDOWS
     43# define strncasecmp strnicmp
     44#endif
    3745
    3846/** Everything defined in this file lives in this namespace. */
    3947namespace guestProp {
     48
     49/******************************************************************************
     50* Typedefs, constants and inlines                                             *
     51******************************************************************************/
     52
     53/** Maximum length for property names */
     54enum { MAX_NAME_LEN = 64 };
     55/** Maximum length for property values */
     56enum { MAX_VALUE_LEN = 128 };
     57/** Maximum number of properties per guest */
     58enum { MAX_PROPS = 256 };
     59
     60/**
     61 * The guest property flag values which are currently accepted.
     62 */
     63enum ePropFlags
     64{
     65    NILFLAG    = 0,
     66    TRANSIENT  = RT_BIT(1),
     67    HOSTWRITE  = RT_BIT(2),
     68    GUESTWRITE = RT_BIT(3),
     69    READONLY   = RT_BIT(4)
     70};
     71
     72/**
     73 * A structure to map the guest property flag values to names. I know it is
     74 * ugly to have constants inline, but it has to be accessible in different
     75 * modules and it does not seem reasonable to put it into its own library.
     76 */
     77const struct
     78{
     79    /** The flag value */
     80    uint32_t fFlag;
     81    /** And the name of the flag */
     82    const char *pcszName;
     83} flagNames[] =
     84{
     85    { TRANSIENT,  "TRANSIENT" },
     86    { HOSTWRITE,  "HOSTWRITE" },
     87    { GUESTWRITE, "GUESTWRITE" },
     88    { READONLY,   "READONLY" },
     89    { NILFLAG,    NULL }
     90};
     91
     92/** Maximum length for the property flags field */
     93enum { MAX_FLAGS_LEN =   sizeof(flagNames[0]) + 2  /* + 2 for ", " */
     94                       + sizeof(flagNames[1]) + 2
     95                       + sizeof(flagNames[2]) + 2
     96                       + sizeof(flagNames[3])
     97     };
     98
     99/**
     100 * Parse a guest properties flags string for the flags in flagNames.
     101 * @returns  IPRT status code
     102 * @returns  VERR_INVALID_PARAM if the flag string is not valid
     103 * @param    pcszFlags  the flag string to parse
     104 * @param    pfFlags    where to store the parse result.  May not be NULL.
     105 * @note     This function is also inline because it must be accessible from
     106 *           several modules and it does not seem reasonable to put it into
     107 *           its own library.
     108 */
     109DECLINLINE(int) validateFlags(const char *pcszFlags, uint32_t *pfFlags)
     110{
     111    const char *pcszNext = pcszFlags;
     112    int rc = VINF_SUCCESS;
     113    uint32_t fFlags = 0;
     114    AssertLogRelReturn(VALID_PTR(pfFlags), VERR_INVALID_POINTER);
     115    AssertLogRelReturn(VALID_PTR(pcszFlags), VERR_INVALID_POINTER);
     116    while (' ' == *pcszNext)
     117        ++pcszNext;
     118    while ((*pcszNext != '\0') && RT_SUCCESS(rc))
     119    {
     120        int i = 0;
     121        for (; flagNames[i].fFlag != NILFLAG; ++i)
     122            if (strncasecmp(pcszNext, flagNames[i].pcszName,
     123                            strlen(flagNames[i].pcszName)) == 0)
     124                break;
     125        if (NILFLAG == flagNames[i].fFlag)
     126            rc = VERR_INVALID_PARAMETER;
     127        else
     128        {
     129            fFlags |= flagNames[i].fFlag;
     130            pcszNext += strlen(flagNames[i].pcszName);
     131        }
     132        while (' ' == *pcszNext)
     133            ++pcszNext;
     134        if (',' == *pcszNext)
     135            ++pcszNext;
     136        while (' ' == *pcszNext)
     137            ++pcszNext;
     138    }
     139    if (RT_SUCCESS(rc))
     140        *pfFlags = fFlags;
     141    return rc;
     142}
     143
     144/**
     145 * Write out flags to a string.
     146 * @returns  IPRT status code
     147 * @param    fFlags    the flags to write out
     148 * @param    pszFlags  where to write the flags string.  This must point to
     149 *                     a buffer of size (at least) MAX_FLAGS_LEN + 1.
     150 */
     151DECLINLINE(int) writeFlags(uint32_t fFlags, char *pszFlags)
     152{
     153    char *pszNext = pszFlags;
     154    int rc = VINF_SUCCESS;
     155    AssertLogRelReturn(VALID_PTR(pszFlags), VERR_INVALID_POINTER);
     156    int i = 0;
     157    for (; flagNames[i].fFlag != NILFLAG; ++i)
     158    {
     159        if (fFlags & flagNames[i].fFlag)
     160        {
     161            strcpy(pszNext, flagNames[i].pcszName);
     162            pszNext += strlen(flagNames[i].pcszName);
     163            fFlags &= ~flagNames[i].fFlag;
     164            if ((flagNames[i + 1].fFlag != NILFLAG) && (fFlags != NILFLAG))
     165            {
     166                strcpy(pszNext, ", ");
     167                pszNext += 2;
     168            }
     169        }
     170    }
     171    *pszNext = '\0';
     172    if (fFlags != NILFLAG)
     173        rc = VERR_INVALID_PARAMETER;  /* But pszFlags will still be set right. */
     174    return rc;
     175}
    40176
    41177/*
     
    111247};
    112248
    113 /** Maximum length for property names */
    114 enum { MAX_NAME_LEN = 64 };
    115 /** Maximum length for property values */
    116 enum { MAX_VALUE_LEN = 128 };
    117 /** Maximum length for the property flags field */
    118 enum { MAX_FLAGS_LEN = 128 };
    119 /** Maximum number of properties per guest */
    120 enum { MAX_PROPS = 256 };
    121 
    122249/**
    123250 * HGCM parameter structures.  Packing is explicitly defined as this is a wire format.
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r13212 r13293  
    327327
    328328    LogFlowThisFunc(("\n"));
     329    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */
    329330    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */
    330331        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* name */
     
    373374    uint32_t cchName, cchBuf;
    374375    size_t cchValue, cchFlags, cchBufActual;
     376    char szFlags[MAX_FLAGS_LEN + 1];
     377    uint32_t fFlags;
    375378
    376379    /*
     
    378381     */
    379382    LogFlowThisFunc(("\n"));
     383    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */
    380384    if (   (cParms != 4)  /* Hardcoded value as the next lines depend on it. */
    381385        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)    /* name */
     
    389393    if (RT_SUCCESS(rc))
    390394        rc = validateName(pszName, cchName);
    391     /* Get the value size */
    392     if (RT_SUCCESS(rc))
    393         rc = CFGMR3QuerySize(mpValueNode, pszName, &cchValue);
    394395
    395396    /*
    396397     * Read and set the values we will return
    397398     */
    398     /* Get the flags size */
    399     cchFlags = 1;  /* Empty string if no flags set. */
    400     if (RT_SUCCESS(rc) && (mpFlagsNode != NULL))
    401         CFGMR3QuerySize(mpFlagsNode, pszName, &cchFlags);  /* Ignore failure. */
     399
     400    /* Get the value size */
     401    if (RT_SUCCESS(rc))
     402        rc = CFGMR3QuerySize(mpValueNode, pszName, &cchValue);
     403    /* Get the flags and their size */
     404    if (RT_SUCCESS(rc))
     405        CFGMR3QueryU32(mpFlagsNode, pszName, (uint32_t *)&fFlags);
     406    if (RT_SUCCESS(rc))
     407        rc = writeFlags(fFlags, szFlags);
     408    if (RT_SUCCESS(rc))
     409        cchFlags = strlen(szFlags);
    402410    /* Check that the buffer is big enough */
    403411    if (RT_SUCCESS(rc))
     
    411419    if (RT_SUCCESS(rc))
    412420        rc = CFGMR3QueryString(mpValueNode, pszName, pchBuf, cchBuf);
    413     /* Write the flags if there are any */
    414     if (RT_SUCCESS(rc))
    415         pchBuf[cchValue] = '\0';  /* In case there aren't */
    416     if (RT_SUCCESS(rc) && (mpFlagsNode != NULL) && (cchFlags != 1))
    417         CFGMR3QueryString(mpFlagsNode, pszName, pchBuf + cchValue,
    418                           cchBuf - cchValue);
     421    /* Write the flags */
     422    if (RT_SUCCESS(rc))
     423        strcpy(pchBuf + cchValue, szFlags);
    419424    /* Timestamp */
    420425    uint64_t u64Timestamp = 0;
    421     if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))
     426    if (RT_SUCCESS(rc))
    422427        CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp);
    423428    VBoxHGCMParmUInt64Set(&paParms[2], u64Timestamp);
     
    449454{
    450455    int rc = VINF_SUCCESS;
    451     char *pszName, *pszValue, *pszFlags;
    452     uint32_t cchName, cchValue, cchFlags = 0;
     456    char *pszName, *pszValue;
     457    uint32_t cchName, cchValue;
     458    uint32_t fFlags = NILFLAG;
    453459
    454460    LogFlowThisFunc(("\n"));
     461    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */
    455462    /*
    456463     * First of all, make sure that we won't exceed the maximum number of properties.
     
    485492    if (RT_SUCCESS(rc))
    486493        rc = validateValue(pszValue, cchValue);
    487     /* For now, we do not support any flags */
    488     if (RT_SUCCESS(rc) && (3 == cParms))
    489     {
    490         rc = VBoxHGCMParmPtrGet(&paParms[2], (void **) &pszFlags, &cchFlags);
    491         for (size_t i = 0; (i < cchFlags - 1) && RT_SUCCESS(rc); ++i)
    492             if (pszFlags[i] != ' ')
    493                 rc = VERR_INVALID_PARAMETER;
     494    if (RT_SUCCESS(rc))
     495    {
     496        /* We deal with flags as follows:
     497         *  1) if flags are specified by the user, use them.
     498         *  2) if no flags are specified, but the property exists, use the
     499         *     existing flags.
     500         *  3) if no flags are specified and the property does not exist,
     501         *     start with empty flags (the default value of fFlags above). */
     502        if (3 == cParms)
     503        {
     504            char *pszFlags;
     505            uint32_t cchFlags;
     506            rc = VBoxHGCMParmPtrGet(&paParms[2], (void **) &pszFlags, &cchFlags);
     507            if (RT_SUCCESS(rc))
     508                rc = validateFlags(pszFlags, &fFlags);
     509        }
     510        else
     511            /* If this fails then fFlags will remain at zero, as per our spec. */
     512            CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags);
    494513    }
    495514    /*
     
    500519        RTTIMESPEC time;
    501520        CFGMR3RemoveValue(mpValueNode, pszName);
    502         if (mpTimestampNode != NULL)
    503             CFGMR3RemoveValue(mpTimestampNode, pszName);
    504         if ((3 == cParms) && (mpFlagsNode != NULL))
    505             CFGMR3RemoveValue(mpFlagsNode, pszName);
     521        CFGMR3RemoveValue(mpTimestampNode, pszName);
     522        CFGMR3RemoveValue(mpFlagsNode, pszName);
    506523        rc = CFGMR3InsertString(mpValueNode, pszName, pszValue);
    507524        if (RT_SUCCESS(rc))
    508525            rc = CFGMR3InsertInteger(mpTimestampNode, pszName,
    509526                                     RTTimeSpecGetNano(RTTimeNow(&time)));
    510         if (RT_SUCCESS(rc) && (3 == cParms))
    511             rc = CFGMR3InsertString(mpFlagsNode, pszName, pszFlags);
    512         /* If we are not setting flags, make sure that there are some */
    513         if (RT_SUCCESS(rc) && (mpFlagsNode != NULL) && (cParms != 3))
     527        if (RT_SUCCESS(rc))
     528            rc = CFGMR3InsertInteger(mpFlagsNode, pszName, fFlags);
     529        /* If anything goes wrong, make sure that we leave a clean state
     530         * behind. */
     531        if (!RT_SUCCESS(rc))
    514532        {
    515             CFGMVALUETYPE dummy;
    516             if (   CFGMR3QueryType(mpFlagsNode, pszName, &dummy)
    517                 == VERR_CFGM_VALUE_NOT_FOUND)
    518                 rc = CFGMR3InsertString(mpFlagsNode, pszName, "");
     533            CFGMR3RemoveValue(mpValueNode, pszName);
     534            CFGMR3RemoveValue(mpTimestampNode, pszName);
     535            CFGMR3RemoveValue(mpFlagsNode, pszName);
    519536        }
    520537    }
     
    549566
    550567    LogFlowThisFunc(("\n"));
     568    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */
    551569    if (   (cParms != 1)  /* Hardcoded value as the next lines depend on it. */
    552570        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* name */
     
    676694    uint32_t cchPatterns = 0, cchBuf = 0;
    677695    LogFlowThisFunc(("\n"));
     696    AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER);  /* a.k.a. VERR_NOT_INITIALIZED */
    678697    if (   (cParms != 3)  /* Hardcoded value as the next lines depend on it. */
    679698        || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* patterns */
     
    722741                iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1;
    723742                uint64_t u64Timestamp = 0;
    724                 if (mpTimestampNode != NULL)
    725                     CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp);
     743                CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp);
    726744                iTmpBuf += RTStrFormatNumber(&TmpBuf[iTmpBuf], u64Timestamp,
    727745                                             10, 0, 0, 0) + 1;
    728746                /* Get flags */
    729                 TmpBuf[iTmpBuf] = '\0';  /* In case there are none. */
    730                 if (mpFlagsNode != NULL)
    731                     CFGMR3QueryString(mpFlagsNode, pszName, &TmpBuf[iTmpBuf],
    732                                       cchTmpBuf - iTmpBuf);  /* Ignore failure */
     747                uint32_t fFlags = NILFLAG;
     748                CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags);
     749                TmpBuf[iTmpBuf] = '\0';  /* Bad (== in)sanity, will be fixed. */
     750                writeFlags(fFlags, &TmpBuf[iTmpBuf]);
    733751                iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1;
    734752            }
     
    767785    char szValue[MAX_VALUE_LEN];
    768786    uint64_t u64Timestamp = 0;
    769     char szFlags[MAX_FLAGS_LEN];
     787    uint32_t fFlags = NILFLAG;
     788    char szFlags[MAX_FLAGS_LEN + 1];
    770789    char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;
    771790
     791    AssertPtr(mpValueNode);
    772792    if (NULL == mpfnHostCallback)
    773793        return;  /* Nothing to do. */
     
    779799    if (rc != VERR_CFGM_VALUE_NOT_FOUND)
    780800    {
    781         if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))
     801        if (RT_SUCCESS(rc))
    782802            rc = CFGMR3QueryU64(mpTimestampNode, pszProperty, &u64Timestamp);
    783         if (RT_SUCCESS(rc) && (mpFlagsNode != NULL))
    784             rc = CFGMR3QueryString(mpFlagsNode, pszProperty, szFlags,
    785                                    sizeof(szFlags));
     803        if (RT_SUCCESS(rc))
     804            rc = CFGMR3QueryU32(mpFlagsNode, pszProperty, &fFlags);
     805        if (RT_SUCCESS(rc))
     806            rc = writeFlags(fFlags, szFlags);
    786807        if (RT_SUCCESS(rc))
    787808            rc = RTStrDupEx(&pszName, pszProperty);
    788         if (RT_SUCCESS(rc) && (mpTimestampNode != NULL))
     809        if (RT_SUCCESS(rc))
    789810            rc = RTStrDupEx(&pszValue, szValue);
    790         if (RT_SUCCESS(rc) && (mpFlagsNode != NULL))
     811        if (RT_SUCCESS(rc))
    791812            rc = RTStrDupEx(&pszFlags, szFlags);
    792813        if (RT_SUCCESS(rc))
     
    934955            LogFlowFunc(("SET_CFGM_NODE\n"));
    935956
    936             if ((cParms < 1) || (cParms > 3))
    937             {
     957            if (   (cParms != 3)
     958                || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)   /* pValue */
     959                || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR)   /* pTimestamp */
     960                || (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR)   /* pFlags */
     961               )
    938962                rc = VERR_INVALID_PARAMETER;
    939             }
    940             else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* pValue */
    941                      || ((cParms > 1) && (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR))   /* pTimestamp */
    942                      || ((cParms > 2) && (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR))   /* pFlags */
    943                     )
    944             {
    945                 rc = VERR_INVALID_PARAMETER;
    946             }
    947963            else
    948964            {
    949                 PCFGMNODE pNode = NULL;
     965                PCFGMNODE pValue = NULL, pTimestamp = NULL, pFlags = NULL;
    950966                uint32_t cbDummy;
    951967
    952                 rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &pNode, &cbDummy);
     968                rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &pValue, &cbDummy);
    953969                if (RT_SUCCESS(rc))
    954                     mpValueNode = pNode;
    955                 if (RT_SUCCESS(rc) && (cParms > 1))
     970                    rc = VBoxHGCMParmPtrGet (&paParms[1], (void **) &pTimestamp, &cbDummy);
     971                if (RT_SUCCESS(rc))
     972                    rc = VBoxHGCMParmPtrGet (&paParms[2], (void **) &pFlags, &cbDummy);
     973                if (RT_SUCCESS(rc))
    956974                {
    957                     rc = VBoxHGCMParmPtrGet (&paParms[1], (void **) &pNode, &cbDummy);
    958                     mpTimestampNode = pNode;
    959                 }
    960                 if (RT_SUCCESS(rc) && (cParms > 2))
    961                 {
    962                     rc = VBoxHGCMParmPtrGet (&paParms[2], (void **) &pNode, &cbDummy);
    963                     mpFlagsNode = pNode;
     975                    mpValueNode     = pValue;
     976                    mpTimestampNode = pTimestamp;
     977                    mpFlagsNode     = pFlags;
    964978                }
    965979            }
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r13165 r13293  
    44944494        char szPropFlags[MAX_FLAGS_LEN + 1];
    44954495        ULONG64 u64Timestamp = 0;  /* default */
    4496         szPropFlags[0] = '\0';  /* default */
    44974496        vrc = CFGMR3GetValueName (pValue, szPropName, sizeof(szPropName));
    44984497        if (RT_SUCCESS(vrc))
     
    45004499        if (RT_SUCCESS(vrc))
    45014500        {
    4502             CFGMR3QueryString (pFlags, szPropName, szPropFlags, sizeof(szPropFlags));
     4501            uint32_t fFlags;
     4502            CFGMR3QueryU32 (pFlags, szPropName, &fFlags);
     4503            writeFlags(fFlags, szPropFlags);
    45034504            CFGMR3QueryU64 (pTimestamps, szPropName, &u64Timestamp);
    45044505            Bstr(szPropName).cloneTo(&names[iProp]);
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r13286 r13293  
    18131813            for (size_t i = 0; i < cProps; ++i)
    18141814            {
    1815                 rc = CFGMR3InsertString(pValues, Utf8Str(names[i]).raw(), Utf8Str(values[i]).raw()); RC_CHECK();
    1816                 rc = CFGMR3InsertInteger(pTimestamps, Utf8Str(names[i]).raw(), timestamps[i]);           RC_CHECK();
    1817                 rc = CFGMR3InsertString(pFlags, Utf8Str(names[i]).raw(), Utf8Str(flags[i]).raw());   RC_CHECK();
     1815                rc = CFGMR3InsertString(pValues, Utf8Str(names[i]).raw(), Utf8Str(values[i]).raw());    RC_CHECK();
     1816                rc = CFGMR3InsertInteger(pTimestamps, Utf8Str(names[i]).raw(), timestamps[i]);          RC_CHECK();
     1817                uint32_t fFlags;
     1818                rc = guestProp::validateFlags(Utf8Str(flags[i]).raw(), &fFlags);
     1819                AssertLogRelRCReturn(rc, VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     1820                    N_("Guest property '%lS' has invalid flags '%lS' in machine definition file"),
     1821                       names[i], flags[i]));
     1822                rc = CFGMR3InsertInteger(pFlags, Utf8Str(names[i]).raw(), fFlags);                      RC_CHECK();
    18181823            }
    18191824
  • trunk/src/VBox/Main/MachineImpl.cpp

    r13221 r13293  
    28042804        return E_INVALIDARG;
    28052805
    2806     /* For now there are no valid flags, so check this. */
    2807     if (aFlags != NULL)
    2808         for (size_t i = 0; aFlags[i] != '\0'; ++i)
    2809             if (aFlags[i] != ' ')
    2810                 return E_INVALIDARG;
    2811 
    28122806    AutoCaller autoCaller (this);
    28132807    CheckComRCReturnRC (autoCaller.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