/* * Convenient function to add a single attribute to pEntry. */ DWORD VmDirEntryAddSingleValueAttribute( PVDIR_ENTRY pEntry, PCSTR pszAttrName, PCSTR pszAttrValue, size_t iAttrValueLen ) { DWORD dwError = 0; PVDIR_ATTRIBUTE pAttr = NULL; if (!pEntry || !pEntry->pSchemaCtx || !pszAttrName || !pszAttrValue || iAttrValueLen < 1) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirAttributeAllocate( pszAttrName, 1, pEntry->pSchemaCtx, &pAttr); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateMemory( iAttrValueLen + 1, // want string null terminated. (PVOID*)&pAttr->vals[0].lberbv.bv_val ); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirCopyMemory( pAttr->vals[0].lberbv.bv_val, (iAttrValueLen + 1), (PCVOID)pszAttrValue, iAttrValueLen ); BAIL_ON_VMDIR_ERROR(dwError); pAttr->vals[0].bOwnBvVal = TRUE; pAttr->vals[0].lberbv.bv_len = iAttrValueLen; dwError = VmDirEntryAddAttribute( pEntry, pAttr); BAIL_ON_VMDIR_ERROR(dwError); pAttr = NULL; cleanup: return dwError; error: if (pAttr) { VmDirFreeAttribute(pAttr); } goto cleanup; }
static DWORD schemaInitFillAttrFromCache( PVDIR_SCHEMA_CTX pCtx, PSTR* ppszValues, USHORT dwValueSize, PSTR pszAttrName, PVDIR_ENTRY pEntry ) { DWORD dwError = 0; DWORD dwCnt = 0; VDIR_ATTRIBUTE* pAttr = NULL; dwError = VmDirAttributeAllocate( pszAttrName, dwValueSize, pCtx, &pAttr); BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt = 0; dwCnt < dwValueSize; dwCnt++) { char* pszStr = &ppszValues[dwCnt][0]; //ignore leading spaces while (*pszStr == ' ') pszStr++; dwError = VmDirAllocateStringA( ppszValues[dwCnt], &pAttr->vals[dwCnt].lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pAttr->vals[dwCnt].bOwnBvVal = TRUE; pAttr->vals[dwCnt].lberbv.bv_len = VmDirStringLenA(pAttr->vals[dwCnt].lberbv.bv_val); } dwError = VmDirEntryAddAttribute( pEntry, pAttr); BAIL_ON_VMDIR_ERROR(dwError); pAttr = NULL; cleanup: return dwError; error: if (pAttr) { VmDirFreeAttribute(pAttr); } goto cleanup; }
static DWORD _VmDirSchemaComputeAllowedChildClassesEffective( PVDIR_ENTRY pEntry, PVDIR_ATTRIBUTE* ppOutAttr ) { DWORD dwError = 0; PVDIR_SCHEMA_OC_DESC pStructureOCDesc = NULL; PVDIR_ATTRIBUTE pLocalAttr = NULL; int iCnt = 0; dwError = VmDirSchemaGetEntryStructureOCDesc( pEntry, &pStructureOCDesc ); BAIL_ON_VMDIR_ERROR(dwError); if ( !pStructureOCDesc ) { dwError = ERROR_INVALID_ENTRY; BAIL_ON_VMDIR_ERROR(dwError); } for (iCnt = 0; pStructureOCDesc->ppszAllowedChildOCs && pStructureOCDesc->ppszAllowedChildOCs[iCnt]; iCnt++) {} if (iCnt > 0) { dwError = VmDirAttributeAllocate( ATTR_ALLOWD_CHILD_CLASSES_EFFECTIVE, iCnt, pEntry->pSchemaCtx, &pLocalAttr); BAIL_ON_VMDIR_ERROR(dwError); for (iCnt = 0; pStructureOCDesc->ppszAllowedChildOCs[iCnt]; iCnt++) { dwError = VmDirAllocateStringA( pStructureOCDesc->ppszAllowedChildOCs[iCnt], &(pLocalAttr->vals[iCnt].lberbv_val)); BAIL_ON_VMDIR_ERROR(dwError); pLocalAttr->vals[iCnt].lberbv_len = VmDirStringLenA(pLocalAttr->vals[iCnt].lberbv_val); pLocalAttr->vals[iCnt].bOwnBvVal = TRUE; } } *ppOutAttr = pLocalAttr; cleanup: return dwError; error: VmDirFreeAttribute( pLocalAttr ); goto cleanup; }
/* * Add an array of bervalue attribute values into an entry. */ DWORD VmDirEntryAddBervArrayAttribute( PVDIR_ENTRY pEntry, PCSTR pszAttrName, VDIR_BERVARRAY attrVals, USHORT usNumVals ) { DWORD dwError = 0; PVDIR_ATTRIBUTE pAttr = NULL; USHORT usCnt = 0; if (!pEntry || !pEntry->pSchemaCtx || !pszAttrName || !attrVals) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } if (usNumVals) { dwError = VmDirAttributeAllocate( pszAttrName, usNumVals, pEntry->pSchemaCtx, &pAttr); BAIL_ON_VMDIR_ERROR(dwError); for (usCnt=0; usCnt < usNumVals; usCnt++) { dwError = VmDirBervalContentDup( &attrVals[usCnt], &pAttr->vals[usCnt]); BAIL_ON_VMDIR_ERROR(dwError); } dwError = VmDirEntryAddAttribute(pEntry, pAttr); BAIL_ON_VMDIR_ERROR(dwError); } cleanup: return dwError; error: VmDirFreeAttribute(pAttr); goto cleanup; }
int VmDirReplResolveConflicts( PVDIR_OPERATION pOperation, PVDIR_ENTRY pEntry, PLW_HASHMAP pMetaDataMap ) { int retVal = LDAP_SUCCESS; int dbRetVal = 0; PSTR pszAttrType = NULL; DWORD dwConflictCnt = 0; LW_HASHMAP_ITER iter = LW_HASHMAP_ITER_INIT; LW_HASHMAP_PAIR pair = {NULL, NULL}; PVDIR_ATTRIBUTE pConsumerAttr = NULL; PVMDIR_ATTRIBUTE_METADATA pSupplierMetaData = NULL; PVMDIR_REPLICATION_METRICS pReplMetrics = NULL; if (!pOperation || !pEntry || !pMetaDataMap) { BAIL_WITH_VMDIR_ERROR(retVal, VMDIR_ERROR_INVALID_PARAMETER); } while (LwRtlHashMapIterate(pMetaDataMap, &iter, &pair)) { pszAttrType = (PSTR) pair.pKey; pSupplierMetaData = (PVMDIR_ATTRIBUTE_METADATA) pair.pValue; if (VmDirStringCompareA(pszAttrType, ATTR_OBJECT_GUID, FALSE) == 0) { continue; } VmDirFreeAttribute(pConsumerAttr); pConsumerAttr = NULL; retVal = VmDirAttributeAllocate(pszAttrType, 0, pOperation->pSchemaCtx, &pConsumerAttr); BAIL_ON_LDAP_ERROR( retVal, LDAP_OPERATIONS_ERROR, (pOperation->ldapResult.pszErrMsg), "VmDirAttributeAllocate failed", VDIR_SAFE_STRING(pOperation->pBEErrorMsg)); dbRetVal = pOperation->pBEIF->pfnBEGetAttrMetaData( pOperation->pBECtx, pConsumerAttr, pEntry->eId); if (dbRetVal) { switch (dbRetVal) { case ERROR_BACKEND_ATTR_META_DATA_NOTFOUND: //When a new attribute is being added // => Supplier attribute meta data WINS against consumer attribute meta data break; default: BAIL_ON_LDAP_ERROR( retVal, LDAP_OPERATIONS_ERROR, (pOperation->ldapResult.pszErrMsg), "pfnBEGetAttrMetaData failed - (%d)(%s)", dbRetVal, VDIR_SAFE_STRING(pOperation->pBEErrorMsg)); } } else { BOOLEAN bSupplierWon = FALSE; BOOLEAN bIsSameAttrValue = FALSE; PSZ_METADATA_BUF pszSupplierMetaData = {'\0'}; PSZ_METADATA_BUF pszConsumerMetaData = {'\0'}; bSupplierWon = _VmDirReplAttrConflictCheck( pSupplierMetaData, pConsumerAttr->pMetaData); bIsSameAttrValue = _VmDirIsBenignReplConflict( pEntry, pConsumerAttr); //Ignore error - used only for logging VmDirMetaDataSerialize(pSupplierMetaData, &pszSupplierMetaData[0]); VmDirMetaDataSerialize(pConsumerAttr->pMetaData, &pszConsumerMetaData[0]); if (bSupplierWon == FALSE) { if (VmDirStringCompareA(pszAttrType, ATTR_USN_CHANGED, FALSE) == 0) { // Need to keep usnChanged to advance localUSN for this replication change. retVal = VmDirMetaDataCopyContent(pConsumerAttr->pMetaData, pSupplierMetaData); BAIL_ON_VMDIR_ERROR(retVal); } else { VMDIR_FREE_REPL_ATTR_IN_CONFLICT(pSupplierMetaData); } dwConflictCnt++; if (!bIsSameAttrValue) { VMDIR_LOG_WARNING( VMDIR_LOG_MASK_ALL, "%s: supplier version loses." " pszAttrType: %s supplier attr meta: %s, consumer attr meta: %s ", __FUNCTION__, pEntry->dn.lberbv.bv_val, pszAttrType, pszSupplierMetaData, pszConsumerMetaData); } } else { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "%s: supplier version wins." " pszAttrType: %s supplier attr meta: %s, consumer attr meta: %s ", __FUNCTION__, pEntry->dn.lberbv.bv_val, pszAttrType, pszSupplierMetaData, pszConsumerMetaData); } } } if (dwConflictCnt > 0) { if (VmDirReplMetricsCacheFind(pOperation->pszPartner, &pReplMetrics) == 0) { VmMetricsCounterAdd(pReplMetrics->pCountConflictResolved, dwConflictCnt); } } cleanup: VmDirFreeAttribute(pConsumerAttr); return retVal; ldaperror: error: VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "failed, error (%d)", retVal); goto cleanup; }
/* * Simple (but not efficient) function to convert list of attribute,value * into an ADD_REQUEST type entry. * (e.g. ppszAttrList = { "objectclass","person", * "objectclass", "masterdiver", * "cn","my common name", * NULL}; */ static DWORD AttrListToEntry( PVDIR_SCHEMA_CTX pSchemaCtx, PSTR pszDN, PSTR* ppszAttrList, PVDIR_ENTRY pEntry) { DWORD dwError = 0; VDIR_ATTRIBUTE* pAttr = NULL; PSTR* ppszNext = NULL; assert(pSchemaCtx && pszDN && ppszAttrList && pEntry); pEntry->allocType = ENTRY_STORAGE_FORMAT_NORMAL; // establish entry schema context association pEntry->pSchemaCtx = VmDirSchemaCtxClone(pSchemaCtx); assert(pEntry->pSchemaCtx); dwError = VmDirAllocateStringA( pszDN, &pEntry->dn.lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pEntry->dn.bOwnBvVal = TRUE; pEntry->dn.lberbv.bv_len = VmDirStringLenA(pEntry->dn.lberbv.bv_val); dwError = VmDirNormalizeDN( &(pEntry->dn), pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); for (ppszNext = ppszAttrList; *ppszNext && *(ppszNext+1); ppszNext += 2) { assert (!pAttr); if ( (*(ppszNext+1))[0] != '\0') // skip attribute with empty value { dwError = VmDirAttributeAllocate( *ppszNext, 1, pSchemaCtx, &pAttr); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateStringA( *(ppszNext+1), &pAttr->vals[0].lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pAttr->vals[0].bOwnBvVal = TRUE; pAttr->vals[0].lberbv.bv_len = VmDirStringLenA(pAttr->vals[0].lberbv.bv_val); dwError = VmDirEntryAddAttribute( pEntry, pAttr); BAIL_ON_VMDIR_ERROR(dwError); pAttr = NULL; // pEntry takes over pAttr } } cleanup: return dwError; error: if (pAttr) { VmDirFreeAttribute(pAttr); } VmDirFreeEntryContent(pEntry); memset(pEntry, 0, sizeof(*pEntry)); goto cleanup; }
static DWORD schemaInitFillAttrFromFile( PVDIR_SCHEMA_CTX pCtx, PSTR* ppszDescs, USHORT dwDescSize, PSTR pszTag, size_t dwTagSize, PVDIR_ENTRY pEntry ) { DWORD dwError = 0; DWORD dwCnt = 0; VDIR_ATTRIBUTE* pAttr = NULL; pszTag[dwTagSize] = '\0'; dwError = VmDirAttributeAllocate( pszTag, dwDescSize, pCtx, &pAttr); pszTag[dwTagSize] = ':'; BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt = 0; dwCnt < dwDescSize; dwCnt++) { char* pszStr = &ppszDescs[dwCnt][dwTagSize+1]; char* pszEndStr = &ppszDescs[dwCnt][VmDirStringLenA(ppszDescs[dwCnt])-1]; assert(ppszDescs[dwCnt][dwTagSize] == ':'); //ignore leading spaces while (*pszStr == ' ') pszStr++; //ignore trailing spaces while (*pszEndStr == ' ') pszEndStr--; *(pszEndStr+1) = '\0'; dwError = VmDirAllocateStringA( pszStr, &pAttr->vals[dwCnt].lberbv.bv_val); BAIL_ON_VMDIR_ERROR(dwError); pAttr->vals[dwCnt].bOwnBvVal = TRUE; pAttr->vals[dwCnt].lberbv.bv_len = VmDirStringLenA(pAttr->vals[dwCnt].lberbv.bv_val); } dwError = VmDirEntryAddAttribute( pEntry, pAttr); BAIL_ON_VMDIR_ERROR(dwError); pAttr = NULL; cleanup: return dwError; error: if (pAttr) { VmDirFreeAttribute(pAttr); } goto cleanup; }