RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar) { AssertPtrReturn(pszVar, false); bool fExists = false; if (Env == RTENV_DEFAULT) { #ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API fExists = RTEnvExistsUtf8(pszVar); #else /* * Since RTEnvExist isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; int rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { fExists = RTEnvExist(pszVarOtherCP); RTStrFree(pszVarOtherCP); } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, false); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, false); RTENV_LOCK(pIntEnv); /* * Simple search. */ const size_t cchVar = strlen(pszVar); for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++) if (!pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)) { if (pIntEnv->papszEnv[iVar][cchVar] == '=') { fExists = true; break; } if (pIntEnv->papszEnv[iVar][cchVar] == '\0') break; } RTENV_UNLOCK(pIntEnv); } return fExists; }
RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER); AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER); AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER); AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); if (pcchActual) *pcchActual = 0; int rc; if (Env == RTENV_DEFAULT) { #ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API rc = RTEnvGetUtf8(pszVar, pszValue, cbValue, pcchActual); #else /* * Since RTEnvGet isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { const char *pszValueOtherCP = RTEnvGet(pszVarOtherCP); RTStrFree(pszVarOtherCP); if (pszValueOtherCP) { char *pszValueUtf8; rc = RTStrCurrentCPToUtf8(&pszValueUtf8, pszValueOtherCP); if (RT_SUCCESS(rc)) { rc = VINF_SUCCESS; size_t cch = strlen(pszValueUtf8); if (pcchActual) *pcchActual = cch; if (pszValue && cbValue) { if (cch < cbValue) memcpy(pszValue, pszValueUtf8, cch + 1); else rc = VERR_BUFFER_OVERFLOW; } RTStrFree(pszValueUtf8); } } else rc = VERR_ENV_VAR_NOT_FOUND; } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnv); /* * Locate the first variable and return it to the caller. */ rc = VERR_ENV_VAR_NOT_FOUND; const size_t cchVar = strlen(pszVar); size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if (!pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar)) { if (pIntEnv->papszEnv[iVar][cchVar] == '=') { rc = VINF_SUCCESS; const char *pszValueOrg = pIntEnv->papszEnv[iVar] + cchVar + 1; size_t cch = strlen(pszValueOrg); if (pcchActual) *pcchActual = cch; if (pszValue && cbValue) { if (cch < cbValue) memcpy(pszValue, pszValueOrg, cch + 1); else rc = VERR_BUFFER_OVERFLOW; } break; } if (pIntEnv->papszEnv[iVar][cchVar] == '\0') { Assert(pIntEnv->fPutEnvBlock); rc = VERR_ENV_VAR_UNSET; break; } } RTENV_UNLOCK(pIntEnv); } return rc; }
RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertReturn(*pszVar, VERR_INVALID_PARAMETER); AssertPtrReturn(pszValue, VERR_INVALID_POINTER); AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); int rc; if (Env == RTENV_DEFAULT) { #ifdef RT_OS_WINDOWS rc = RTEnvSetUtf8(pszVar, pszValue); #else /* * Since RTEnvPut isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { char *pszValueOtherCP; rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue); if (RT_SUCCESS(rc)) { rc = RTEnvSet(pszVarOtherCP, pszValueOtherCP); RTStrFree(pszValueOtherCP); } RTStrFree(pszVarOtherCP); } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); /* * Create the variable string. */ const size_t cchVar = strlen(pszVar); const size_t cchValue = strlen(pszValue); char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2); if (pszEntry) { memcpy(pszEntry, pszVar, cchVar); pszEntry[cchVar] = '='; memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1); RTENV_LOCK(pIntEnv); /* * Find the location of the variable. (iVar = cVars if new) */ rc = VINF_SUCCESS; size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if ( !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar) && ( pIntEnv->papszEnv[iVar][cchVar] == '=' || pIntEnv->papszEnv[iVar][cchVar] == '\0') ) break; if (iVar < pIntEnv->cVars) { /* * Replace the current entry. Simple. */ RTMemFree(pIntEnv->papszEnv[iVar]); pIntEnv->papszEnv[iVar] = pszEntry; } else { /* * New variable, append it. */ Assert(pIntEnv->cVars == iVar); rc = rtEnvIntAppend(pIntEnv, pszEntry); } RTENV_UNLOCK(pIntEnv); if (RT_FAILURE(rc)) RTMemFree(pszEntry); } else rc = VERR_NO_MEMORY; } return rc; }
RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar) { AssertPtrReturn(pszVar, VERR_INVALID_POINTER); AssertReturn(*pszVar, VERR_INVALID_PARAMETER); AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); int rc; if (Env == RTENV_DEFAULT) { #ifdef RTENV_IMPLEMENTS_UTF8_DEFAULT_ENV_API rc = RTEnvUnsetUtf8(pszVar); #else /* * Since RTEnvUnset isn't UTF-8 clean and actually expects the strings * to be in the current code page (codeset), we'll do the necessary * conversions here. */ char *pszVarOtherCP; rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar); if (RT_SUCCESS(rc)) { rc = RTEnvUnset(pszVarOtherCP); RTStrFree(pszVarOtherCP); } #endif } else { PRTENVINTERNAL pIntEnv = Env; AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE); RTENV_LOCK(pIntEnv); /* * Remove all variable by the given name. */ rc = VINF_ENV_VAR_NOT_FOUND; const size_t cchVar = strlen(pszVar); size_t iVar; for (iVar = 0; iVar < pIntEnv->cVars; iVar++) if ( !pIntEnv->pfnCompare(pIntEnv->papszEnv[iVar], pszVar, cchVar) && ( pIntEnv->papszEnv[iVar][cchVar] == '=' || pIntEnv->papszEnv[iVar][cchVar] == '\0') ) { if (!pIntEnv->fPutEnvBlock) { RTMemFree(pIntEnv->papszEnv[iVar]); pIntEnv->cVars--; if (pIntEnv->cVars > 0) pIntEnv->papszEnv[iVar] = pIntEnv->papszEnv[pIntEnv->cVars]; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; } else { /* Record this unset by keeping the variable without any equal sign. */ pIntEnv->papszEnv[iVar][cchVar] = '\0'; } rc = VINF_SUCCESS; /* no break, there could be more. */ } /* * If this is a change record, we may need to add it. */ if (rc == VINF_ENV_VAR_NOT_FOUND && pIntEnv->fPutEnvBlock) { char *pszEntry = (char *)RTMemDup(pszVar, cchVar + 1); if (pszEntry) { rc = rtEnvIntAppend(pIntEnv, pszEntry); if (RT_SUCCESS(rc)) rc = VINF_ENV_VAR_NOT_FOUND; else RTMemFree(pszEntry); } else rc = VERR_NO_MEMORY; } RTENV_UNLOCK(pIntEnv); } return rc; }
RTDECL(int) RTEnvCloneUtf16Block(PRTENV phEnv, PCRTUTF16 pwszzBlock, uint32_t fFlags) { AssertPtrReturn(pwszzBlock, VERR_INVALID_POINTER); AssertReturn(!fFlags, VERR_INVALID_FLAGS); /* * Count the number of variables in the block. */ uint32_t cVars = 0; PCRTUTF16 pwsz = pwszzBlock; while (*pwsz != '\0') { cVars++; pwsz += RTUtf16Len(pwsz) + 1; AssertReturn(cVars < _256K, VERR_OUT_OF_RANGE); } /* * Create the duplicate. */ PRTENVINTERNAL pIntEnv; int rc = rtEnvCreate(&pIntEnv, cVars + 1 /* NULL */, false /*fCaseSensitive*/, false /*fPutEnvBlock*/); if (RT_SUCCESS(rc)) { pIntEnv->cVars = cVars; pIntEnv->papszEnv[pIntEnv->cVars] = NULL; size_t iDst = 0; for (pwsz = pwszzBlock; *pwsz != '\0'; pwsz += RTUtf16Len(pwsz) + 1) { int rc2 = RTUtf16ToUtf8(pwsz, &pIntEnv->papszEnv[iDst]); if (RT_SUCCESS(rc2)) { /* Make sure it contains an '='. */ const char *pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); if (!pszEqual) { rc2 = RTStrAAppend(&pIntEnv->papszEnv[iDst], "="); if (RT_SUCCESS(rc2)) pszEqual = strchr(pIntEnv->papszEnv[iDst], '='); } if (pszEqual) { /* Check for duplicates, keep the last version. */ const char *pchVar = pIntEnv->papszEnv[iDst]; size_t cchVarNmAndEq = pszEqual - pchVar; for (size_t iDst2 = 0; iDst2 < iDst; iDst2++) if (pIntEnv->pfnCompare(pIntEnv->papszEnv[iDst2], pchVar, cchVarNmAndEq) == 0) { RTStrFree(pIntEnv->papszEnv[iDst2]); pIntEnv->papszEnv[iDst2] = pIntEnv->papszEnv[iDst]; pIntEnv->papszEnv[iDst] = NULL; iDst--; break; } iDst++; continue; } iDst++; } /* failed fatally. */ pIntEnv->cVars = iDst; RTEnvDestroy(pIntEnv); return rc2; } Assert(iDst <= pIntEnv->cVars); pIntEnv->cVars = iDst; /* done */ *phEnv = pIntEnv; } return rc; }