VirtualBox

Changeset 55562 in vbox for trunk/src/VBox/Runtime/generic


Ignore:
Timestamp:
Apr 30, 2015 3:15:15 PM (10 years ago)
Author:
vboxsync
Message:

IPRT: Added RTEnvCreateChangeRecord, RTEnvApplyChanges RTEnvIsChangeRecord and RTEnvGetByIndexRawEx for the purpose of creating a block of environment changes. The use case for this is guest control.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/generic/env-generic.cpp

    r50644 r55562  
    8989    /** Magic value . */
    9090    uint32_t    u32Magic;
     91    /** Set if this is a record of environment changes, putenv style. */
     92    bool        fPutEnvBlock;
    9193    /** Number of variables in the array.
    9294     * This does not include the terminating NULL entry. */
     
    9698     * with the C library), so that c <= cCapacity - 1. */
    9799    size_t      cAllocated;
    98     /** Array of environment variables. */
     100    /** Array of environment variables.
     101     * These are always in "NAME=VALUE" form, where the value can be empty. If
     102     * fPutEnvBlock is set though, there will be "NAME" entries too for variables
     103     * that need to be removed when merged with another environment block. */
    99104    char      **papszEnv;
    100105    /** Array of environment variables in the process CP.
     
    132137 * @param   fCaseSensitive  Whether the environment block is case sensitive or
    133138 *                          not.
     139 * @param   fPutEnvBlock    Indicates whether this is a special environment
     140 *                          block that will be used to record change another
     141 *                          block.  We will keep unsets in putenv format, i.e.
     142 *                          just the variable name without any equal sign.
    134143 */
    135 static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated, bool fCaseSensitive)
     144static int rtEnvCreate(PRTENVINTERNAL *ppIntEnv, size_t cAllocated, bool fCaseSensitive, bool fPutEnvBlock)
    136145{
    137146    /*
     
    145154         */
    146155        pIntEnv->u32Magic = RTENV_MAGIC;
     156        pIntEnv->fPutEnvBlock = fPutEnvBlock;
    147157        pIntEnv->pfnCompare = fCaseSensitive ? RTStrNCmp : RTStrNICmp;
    148158        pIntEnv->papszEnvOtherCP = NULL;
     
    166176{
    167177    AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
    168     return rtEnvCreate(pEnv, RTENV_GROW_SIZE, false /*fCaseSensitive*/);
     178    return rtEnvCreate(pEnv, RTENV_GROW_SIZE, false /*fCaseSensitive*/, false /*fPutEnvBlock*/);
    169179}
    170180RT_EXPORT_SYMBOL(RTEnvCreate);
     
    221231     */
    222232    bool fCaseSensitive = true;
     233    bool fPutEnvBlock   = false;
    223234    size_t cVars;
    224235    const char * const *papszEnv;
     
    263274        RTENV_LOCK(pIntEnvToClone);
    264275
     276        fPutEnvBlock = pIntEnvToClone->fPutEnvBlock;
    265277        papszEnv = pIntEnvToClone->papszEnv;
    266278        cVars = pIntEnvToClone->cVars;
     
    271283     */
    272284    PRTENVINTERNAL pIntEnv;
    273     int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive);
     285    int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, fCaseSensitive, fPutEnvBlock);
    274286    if (RT_SUCCESS(rc))
    275287    {
     
    288300#endif
    289301                if (RT_SUCCESS(rc2))
     302                {
     303                    /* Make sure it contains an '='. */
    290304                    iDst++;
     305                    if (strchr(pIntEnv->papszEnv[iDst - 1], '='))
     306                        continue;
     307                    rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst - 1], "=");
     308                    if (RT_SUCCESS(rc2))
     309                        continue;
     310                }
    291311                else if (rc2 == VERR_NO_TRANSLATION)
     312                {
    292313                    rc = VWRN_ENV_NOT_FULLY_TRANSLATED;
    293                 else
    294                 {
    295                     pIntEnv->cVars = iDst;
    296                     RTEnvDestroy(pIntEnv);
    297                     return rc2;
    298                 }
     314                    continue;
     315                }
     316
     317                /* failed fatally. */
     318                pIntEnv->cVars = iDst;
     319                RTEnvDestroy(pIntEnv);
     320                return rc2;
    299321            }
    300322            pIntEnv->cVars = iDst;
     
    361383    AssertReturn(*pszVar, VERR_INVALID_PARAMETER);
    362384    AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
     385    AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME);
    363386
    364387    int rc;
     
    415438            for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
    416439                if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
    417                     &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
     440                    &&  (   pIntEnv->papszEnv[iVar][cchVar] == '='
     441                         || pIntEnv->papszEnv[iVar][cchVar] == '\0') )
    418442                    break;
    419443            if (iVar < pIntEnv->cVars)
     
    470494    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
    471495    AssertReturn(*pszVar, VERR_INVALID_PARAMETER);
     496    AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME);
    472497
    473498    int rc;
     
    507532        for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
    508533            if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
    509                 &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
    510             {
    511                 RTMemFree(pIntEnv->papszEnv[iVar]);
    512                 pIntEnv->cVars--;
    513                 if (pIntEnv->cVars > 0)
    514                     pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars];
    515                 pIntEnv->papszEnv[pIntEnv->cVars] = NULL;
     534                &&  (   pIntEnv->papszEnv[iVar][cchVar] == '='
     535                     || pIntEnv->papszEnv[iVar][cchVar] == '\0') )
     536            {
     537                if (!pIntEnv->fPutEnvBlock)
     538                {
     539                    RTMemFree(pIntEnv->papszEnv[iVar]);
     540                    pIntEnv->cVars--;
     541                    if (pIntEnv->cVars > 0)
     542                        pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars];
     543                    pIntEnv->papszEnv[pIntEnv->cVars] = NULL;
     544                }
     545                else
     546                {
     547                    /* Record this unset by keeping the variable without any equal sign. */
     548                    pIntEnv->papszEnv[iVar][cchVar] = '\0';
     549                }
    516550                rc = VINF_SUCCESS;
    517551                /* no break, there could be more. */
     
    532566    AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
    533567    AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
     568    AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME);
    534569
    535570    if (pcchActual)
     
    592627        size_t iVar;
    593628        for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
    594             if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
    595                 &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
    596             {
    597                 rc = VINF_SUCCESS;
    598                 const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1;
    599                 size_t cch = strlen(pszValueOrg);
    600                 if (pcchActual)
    601                     *pcchActual = cch;
    602                 if (pszValue && cbValue)
    603                 {
    604                     if (cch < cbValue)
    605                         memcpy(pszValue, pszValueOrg, cch + 1);
    606                     else
    607                         rc = VERR_BUFFER_OVERFLOW;
    608                 }
    609                 break;
     629            if (!pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar))
     630            {
     631                if (pIntEnv->papszEnv[iVar][cchVar] == '=')
     632                {
     633                    rc = VINF_SUCCESS;
     634                    const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1;
     635                    size_t cch = strlen(pszValueOrg);
     636                    if (pcchActual)
     637                        *pcchActual = cch;
     638                    if (pszValue && cbValue)
     639                    {
     640                        if (cch < cbValue)
     641                            memcpy(pszValue, pszValueOrg, cch + 1);
     642                        else
     643                            rc = VERR_BUFFER_OVERFLOW;
     644                    }
     645                    break;
     646                }
     647                if (pIntEnv->papszEnv[iVar][cchVar] == '\0')
     648                {
     649                    Assert(pIntEnv->fPutEnvBlock);
     650                    rc = VERR_ENV_VAR_UNSET;
     651                    break;
     652                }
    610653            }
    611654
     
    654697        const size_t cchVar = strlen(pszVar);
    655698        for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
    656             if (    !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)
    657                 &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
    658             {
    659                 fExists = true;
    660                 break;
     699            if (!pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar))
     700            {
     701                if (pIntEnv->papszEnv[iVar][cchVar] == '=')
     702                {
     703                    fExists = true;
     704                    break;
     705                }
     706                if (pIntEnv->papszEnv[iVar][cchVar] == '\0')
     707                    break;
    661708            }
    662709
     
    740787 * @param   pvUser              Ignored.
    741788 */
    742 DECLCALLBACK(int) rtEnvSortCompare(const void *pvElement1, const void *pvElement2, void *pvUser)
     789static DECLCALLBACK(int) rtEnvSortCompare(const void *pvElement1, const void *pvElement2, void *pvUser)
    743790{
    744791    NOREF(pvUser);
     
    863910
    864911
    865 RTDECL(uint32_t) RTEnvGetByIndexEx(RTENV hEnv, uint32_t iVar, char *pszVar, size_t cbVar, char *pszValue, size_t cbValue)
     912RTDECL(int) RTEnvGetByIndexEx(RTENV hEnv, uint32_t iVar, char *pszVar, size_t cbVar, char *pszValue, size_t cbValue)
    866913{
    867914    PRTENVINTERNAL pIntEnv = hEnv;
     
    882929        bool        fHasEqual   = pszSrcValue != NULL;
    883930        if (pszSrcValue)
     931        {
    884932            pszSrcValue++;
     933            rc = VINF_SUCCESS;
     934        }
    885935        else
     936        {
    886937            pszSrcValue = strchr(pszSrcVar, '\0');
    887         rc = VINF_SUCCESS;
     938            rc = VINF_ENV_VAR_UNSET;
     939        }
    888940        if (cbVar)
    889             rc = RTStrCopyEx(pszVar, cbVar, pszSrcVar, pszSrcValue - pszSrcVar - fHasEqual);
     941        {
     942            int rc2 = RTStrCopyEx(pszVar, cbVar, pszSrcVar, pszSrcValue - pszSrcVar - fHasEqual);
     943            if (RT_FAILURE(rc2))
     944                rc = rc2;
     945        }
    890946        if (cbValue)
    891947        {
     
    904960RT_EXPORT_SYMBOL(RTEnvGetByIndexEx);
    905961
     962
     963RTDECL(const char *) RTEnvGetByIndexRawEx(RTENV hEnv, uint32_t iVar)
     964{
     965    PRTENVINTERNAL pIntEnv = hEnv;
     966    AssertPtrReturn(pIntEnv, NULL);
     967    AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, NULL);
     968
     969    RTENV_LOCK(pIntEnv);
     970
     971    const char *pszRet;
     972    if (iVar < pIntEnv->cVars)
     973        pszRet = pIntEnv->papszEnv[iVar];
     974    else
     975        pszRet = NULL;
     976
     977    RTENV_UNLOCK(pIntEnv);
     978
     979    return pszRet;
     980}
     981RT_EXPORT_SYMBOL(RTEnvGetByIndexRawEx);
     982
     983
     984RTDECL(int) RTEnvCreateChangeRecord(PRTENV phEnv)
     985{
     986    AssertPtrReturn(phEnv, VERR_INVALID_POINTER);
     987    return rtEnvCreate(phEnv, RTENV_GROW_SIZE, false /*fCaseSensitive*/, true /*fPutEnvBlock*/);
     988}
     989RT_EXPORT_SYMBOL(RTEnvCreateChangeRecord);
     990
     991
     992RTDECL(bool) RTEnvIsChangeRecord(RTENV hEnv)
     993{
     994    if (hEnv == RTENV_DEFAULT)
     995        return false;
     996
     997    PRTENVINTERNAL pIntEnv = hEnv;
     998    AssertPtrReturn(pIntEnv, false);
     999    AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, false);
     1000    return pIntEnv->fPutEnvBlock;
     1001}
     1002RT_EXPORT_SYMBOL(RTEnvIsChangeRecord);
     1003
     1004
     1005RTDECL(int) RTEnvApplyChanges(RTENV hEnvDst, RTENV hEnvChanges)
     1006{
     1007    PRTENVINTERNAL pIntEnvChanges = hEnvChanges;
     1008    AssertPtrReturn(pIntEnvChanges, VERR_INVALID_HANDLE);
     1009    AssertReturn(pIntEnvChanges->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
     1010
     1011    /** @todo lock validator trouble ahead here! */
     1012    RTENV_LOCK(pIntEnvChanges);
     1013
     1014    int rc = VINF_SUCCESS;
     1015    for (uint32_t iChange = 0; iChange < pIntEnvChanges->cVars && RT_SUCCESS(rc); iChange++)
     1016        rc = RTEnvPutEx(hEnvDst, pIntEnvChanges->papszEnv[iChange]);
     1017
     1018    RTENV_UNLOCK(pIntEnvChanges);
     1019
     1020    return rc;
     1021}
     1022RT_EXPORT_SYMBOL(RTEnvApplyChanges);
     1023
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