/* * Create a schema cache from pEntry * 1. parse AT * 2. parse OC * 2.1 parse ContentRule * 2.2 parse StructureRule * 2.3 parse Nameform * 3. load AT and OC and Content and Structure Rule and Nameform into cache * 4. resolve AT and OC and Content and Structure Rule (SUP, alias, syntax, matchingrule...etc.) * 5. verify cache * 6. generate/modify vmwAttributeToIdMap (this modifies pEntry contents) * 7. patch pEntry to use new schema */ DWORD VdirSchemaInstanceInitViaEntry( PVDIR_ENTRY pEntry, PVDIR_SCHEMA_INSTANCE* ppSchema ) { DWORD dwError = 0; PVDIR_SCHEMA_INSTANCE pSchema = NULL; dwError = _VmDirSchemaEntryToInstance( pEntry, &pSchema); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirSchemaLoadInstance(pSchema); BAIL_ON_VMDIR_ERROR(dwError); dwError = VdirSchemaAttrToIdMapInit(pSchema, pEntry); BAIL_ON_VMDIR_ERROR(dwError); if (! VmDirSchemaVerifyIntegrity(pSchema)) { dwError = ERROR_INVALID_SCHEMA; BAIL_ON_VMDIR_ERROR(dwError); } pSchema->usRefCount++; dwError = VdirSchemaADCompatibleSetup(pSchema); pSchema->usRefCount--; BAIL_ON_VMDIR_ERROR(dwError); // always patch at the very end of this function call dwError = _VmDirSchemaInitFixBootstrapEntry( pSchema, pEntry); BAIL_ON_VMDIR_ERROR(dwError); *ppSchema = pSchema; cleanup: return dwError; error: //TODO, need to unpatch entry? if (pSchema) { VdirSchemaInstanceFree(pSchema); } *ppSchema = NULL; goto cleanup; }
/* * Caller release schema ctx */ VOID VmDirSchemaCtxRelease( PVDIR_SCHEMA_CTX pCtx ) { BOOLEAN bInLock = FALSE; USHORT usRefCnt = 0; USHORT usSelfRef = 0; if ( pCtx ) { if ( pCtx->pSchema ) { VMDIR_LOCK_MUTEX(bInLock, pCtx->pSchema->mutex); pCtx->pSchema->usRefCount--; usRefCnt = pCtx->pSchema->usRefCount; usSelfRef = pCtx->pSchema->usNumSelfRef; VMDIR_UNLOCK_MUTEX(bInLock, pCtx->pSchema->mutex); if (usRefCnt == usSelfRef) { // only self reference within pSchema exists, free pSchema itself. // self references are established during init before normal references. VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "Free unreferenced schema instance (%p)", pCtx->pSchema); #if 0 /* BUGBUG - reenable this when Purify report is clean */ VdirSchemaInstanceFree(pCtx->pSchema); #endif } } VMDIR_SAFE_FREE_STRINGA(pCtx->pszErrorMsg); VMDIR_SAFE_FREE_MEMORY(pCtx); } return; }
/* * Bootstrap initial schema from default data. * Not a full schema as ones that initialize from file or entry, * but with limited information that we can bootstrap schema entry from * data store or file. * 1. pSchema->ats.pSortName (in sort order) * 1.1 pSchema->ats.pSortName(pszName, usIdMap) * 2. pSchema->ats.dwNumATs * 3. pSchema->ats.ppSortIdMap (in sort order) * 4. pSchema-> bIsBootStrapSchema = TRUE * 5. pSchema->usNextId = 100 * * gVdirSchemaGlobals.pInstances[0] = bootstrap schema * */ DWORD VmDirSchemaLibInit( VOID ) { BOOLEAN bInLock = FALSE; DWORD dwError = 0; DWORD dwCnt = 0; PVDIR_SCHEMA_INSTANCE pSchema = NULL; PSTR OCTable[] = VDIR_SCHEMA_BOOTSTRP_OC_INITIALIZER; VDIR_SCHEMA_BOOTSTRAP_TABLE ATTable[] = VDIR_SCHEMA_BOOTSTRP_ATTR_INITIALIZER; // initialize gVdirSchemaGlobals dwError = VmDirAllocateMutex(&gVdirSchemaGlobals.mutex); BAIL_ON_VMDIR_ERROR(dwError); dwError = VdirSchemaInstanceAllocate( &pSchema, sizeof(ATTable)/sizeof(ATTable[0]), sizeof(OCTable)/sizeof(OCTable[0]), 0, // no content rule in bootstrap 0, // no structure rule in bootstrap 0); // no fnameforma in bootstrap BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt = 0 ; dwCnt < sizeof(ATTable)/sizeof(ATTable[0]); dwCnt++) { dwError = VmDirSchemaParseStrToATDesc( ATTable[dwCnt].pszDesc, pSchema->ats.pATSortName+dwCnt); BAIL_ON_VMDIR_ERROR(dwError); pSchema->ats.pATSortName[dwCnt].usAttrID = ATTable[dwCnt].usAttrID; } qsort(pSchema->ats.pATSortName, pSchema->ats.usNumATs, sizeof(VDIR_SCHEMA_AT_DESC), VdirSchemaPATNameCmp); dwError = VmDirAllocateMemory( sizeof(PVDIR_SCHEMA_AT_DESC) * pSchema->ats.usNumATs, (PVOID*)&pSchema->ats.ppATSortIdMap); BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt = 0 ; dwCnt < sizeof(ATTable)/sizeof(ATTable[0]); dwCnt++) { pSchema->ats.ppATSortIdMap[pSchema->ats.pATSortName[dwCnt].usAttrID -1] = &pSchema->ats.pATSortName[dwCnt]; } pSchema-> bIsBootStrapSchema = TRUE; pSchema->ats.usNextId = MAX_RESERVED_ATTR_ID_MAP + 1; dwError = VdirSyntaxLoad(); BAIL_ON_VMDIR_ERROR(dwError); dwError = VdirMatchingRuleLoad(); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); gVdirSchemaGlobals.pSchema = pSchema; dwError = VdirSchemaCtxAcquireInLock(TRUE, &gVdirSchemaGlobals.pCtx); // add self reference BAIL_ON_VMDIR_ERROR(dwError); assert(gVdirSchemaGlobals.pCtx); VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "Startup bootstrap schema instance (%p)", gVdirSchemaGlobals.pSchema); cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "VmDirSchemaLibInit failed (%d)", dwError); gVdirSchemaGlobals.pSchema = NULL; if (pSchema) { VdirSchemaInstanceFree(pSchema); } goto cleanup; }
/* * Create a new schema cache via pEntry, then active this cache. */ DWORD VmDirSchemaInitializeViaEntry( PVDIR_ENTRY pEntry ) { BOOLEAN bLoadOk = TRUE; BOOLEAN bInLock = FALSE; DWORD dwError = 0; PVDIR_SCHEMA_CTX pLiveCtx = NULL; PVDIR_SCHEMA_INSTANCE pInstance = NULL; PVDIR_SCHEMA_INSTANCE pLiveInstance = NULL; VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); // get reference to current schema, to clean up later pLiveInstance = gVdirSchemaGlobals.pSchema; pLiveCtx = gVdirSchemaGlobals.pCtx; // instantiate a schema cache - pInstance dwError = VdirSchemaInstanceInitViaEntry( pEntry, &pInstance); BAIL_ON_VMDIR_ERROR(dwError); gVdirSchemaGlobals.pSchema = pInstance; dwError = VdirSchemaCtxAcquireInLock(TRUE, &gVdirSchemaGlobals.pCtx); // add self reference BAIL_ON_VMDIR_ERROR(dwError); assert(gVdirSchemaGlobals.pCtx); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Startup schema instance (%p)", gVdirSchemaGlobals.pSchema); VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); cleanup: if (bLoadOk) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "Schema - AttributeTypes:(size=%d, nextid=%d) Objectclasses:(size=%d)", pEntry->pSchemaCtx->pSchema->ats.usNumATs, pEntry->pSchemaCtx->pSchema->ats.usNextId, pEntry->pSchemaCtx->pSchema->ocs.usNumOCs); } VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); if (pLiveCtx) { VmDirSchemaCtxRelease(pLiveCtx); } return dwError; error: if (pInstance) { VdirSchemaInstanceFree(pInstance); } gVdirSchemaGlobals.pSchema = pLiveInstance; gVdirSchemaGlobals.pCtx = pLiveCtx; pLiveCtx = NULL; bLoadOk = FALSE; goto cleanup; }
/* * Before modify schema cache, make sure new schema is valid. * 1. schema of pEntry must be live one * 2. create new schema instance via pEntry * 3. check active and new schema compatibility * NOT compatible - reject this operation * Compatible but NO semantic chnage - update schema entry * Compatible and has semantic chnage - update schema entry and cache * 4. make new instance pending in gVdirSchemaGlobals */ DWORD VmDirSchemaCacheModifyPrepare( PVDIR_OPERATION pOperation, VDIR_MODIFICATION* pMods, PVDIR_ENTRY pSchemaEntry ) { DWORD dwError = 0; BOOLEAN bInLock = FALSE; PSTR pszLocalErrMsg = NULL; BOOLEAN bOwnNewInstance = FALSE; BOOLEAN bCompatible = FALSE; // schema compatible BOOLEAN bNeedCachePatch = FALSE; // schema semantic/cache change PVDIR_SCHEMA_INSTANCE pNewInstance = NULL; // DO NOT free, pEntry should take over it. PVDIR_SCHEMA_INSTANCE pEntryOrgSchemaInstance = NULL; if ( !pMods || !pSchemaEntry || !pOperation ) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } { PVDIR_MODIFICATION pLocalMods = NULL; PCSTR immutableList[] = VDIR_IMMUTABLE_SCHEMA_ELEMENT_INITIALIZER; int iImmutableSize = sizeof(immutableList)/sizeof(immutableList[0]); for (pLocalMods = pMods; pLocalMods; pLocalMods = pLocalMods->next) { BOOLEAN bImmutableElement = _VmDirIsNameInCaseIgnoreList( pLocalMods->attr.pATDesc->pszName, immutableList, iImmutableSize); if ( bImmutableElement ) { dwError = ERROR_OPERATION_NOT_PERMITTED; BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "modify (%s) not allowed", pLocalMods->attr.pATDesc->pszName); } } } // make sure pEntry uses live schema if (! vdirIsLiveSchema(pSchemaEntry->pSchemaCtx->pSchema)) { dwError = LDAP_UNWILLING_TO_PERFORM; BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "Out dated schema"); } pEntryOrgSchemaInstance = pSchemaEntry->pSchemaCtx->pSchema; // instantiate a schema cache - pNewInstance // If this call succeed, do NOT free pNewInstance. pEntry->pSchemaCtx takes it over. dwError = VdirSchemaInstanceInitViaEntry( pSchemaEntry, &pNewInstance); if ( dwError != 0 && pSchemaEntry->pSchemaCtx->pSchema != pNewInstance ) { // we still own pNewInstance and need to free it. bOwnNewInstance = TRUE; } BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "Entry to schema instance failed (%d)", dwError); // check if two instances are compatible and if schema patching is needed dwError = VmDirSchemaInstancePatchCheck( pEntryOrgSchemaInstance, pNewInstance, &bCompatible, &bNeedCachePatch); BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "VmDirSchemaInstancePatch (%d)", dwError); if ( !bCompatible ) { dwError = LDAP_UNWILLING_TO_PERFORM; BAIL_ON_VMDIR_ERROR_WITH_MSG(dwError, pszLocalErrMsg, "Schema NOT compatible (%d)", dwError); } if ( !bNeedCachePatch ) { // no semantic change, just update schema entry VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Prepare schema entry update"); } else { // need schema entry and cache update VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Prepare schema entry and instance update (%p)", pNewInstance); } VMDIR_LOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); if ( bNeedCachePatch ) { gVdirSchemaGlobals.bHasPendingChange = TRUE; } VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); cleanup: VMDIR_UNLOCK_MUTEX(bInLock, gVdirSchemaGlobals.mutex); VMDIR_SAFE_FREE_MEMORY(pszLocalErrMsg); return dwError; error: if ( bOwnNewInstance ) { VdirSchemaInstanceFree( pNewInstance ); } VMDIR_SET_LDAP_RESULT_ERROR( &pOperation->ldapResult, dwError, pszLocalErrMsg ); goto cleanup; }
DWORD VdirSchemaInstanceAllocate( PVDIR_SCHEMA_INSTANCE* ppSchema, USHORT dwATSize, USHORT dwOCSize, USHORT dwContentSize, USHORT dwStructureSize, USHORT dwNameformSize ) { DWORD dwError = 0; PVDIR_SCHEMA_INSTANCE pSchema = NULL; dwError = VmDirAllocateMemory( sizeof(VDIR_SCHEMA_INSTANCE), (PVOID*)&pSchema); BAIL_ON_VMDIR_ERROR(dwError); dwError = VmDirAllocateMemory( sizeof(VDIR_SCHEMA_OC_DESC) * dwOCSize, (PVOID*)&pSchema->ocs.pOCSortName); BAIL_ON_VMDIR_ERROR(dwError); pSchema->ocs.usNumOCs = dwOCSize; dwError = VmDirAllocateMemory( sizeof(VDIR_SCHEMA_AT_DESC) * dwATSize, (PVOID*)&pSchema->ats.pATSortName); BAIL_ON_VMDIR_ERROR(dwError); pSchema->ats.usNumATs = dwATSize; if (dwContentSize > 0) { dwError = VmDirAllocateMemory( sizeof(VDIR_SCHEMA_CR_DESC) * dwContentSize, (PVOID*)&pSchema->contentRules.pContentSortName); BAIL_ON_VMDIR_ERROR(dwError); } pSchema->contentRules.usNumContents = dwContentSize; if (dwStructureSize > 0) { dwError = VmDirAllocateMemory( sizeof(VDIR_SCHEMA_SR_DESC) * dwStructureSize, (PVOID*)&pSchema->structureRules.pStructureSortRuleID); BAIL_ON_VMDIR_ERROR(dwError); } pSchema->structureRules.usNumStructures = dwStructureSize; if (dwNameformSize > 0) { dwError = VmDirAllocateMemory( sizeof(VDIR_SCHEMA_NF_DESC) * dwNameformSize, (PVOID*)&pSchema->nameForms.pNameFormSortName); BAIL_ON_VMDIR_ERROR(dwError); } pSchema->nameForms.usNumNameForms = dwNameformSize; dwError = VmDirAllocateMutex(&(pSchema->mutex)); BAIL_ON_VMDIR_ERROR(dwError); *ppSchema = pSchema; cleanup: return dwError; error: if ( pSchema ) { VdirSchemaInstanceFree( pSchema ); } goto cleanup; }
/* * convert schema definition string to descriptor */ static DWORD _VmDirSchemaEntryToInstance( PVDIR_ENTRY pEntry, PVDIR_SCHEMA_INSTANCE* ppSchema ) { DWORD dwError = 0; DWORD dwCnt = 0; PVDIR_SCHEMA_INSTANCE pSchema = NULL; VDIR_ATTRIBUTE* pAttr = NULL; VDIR_ATTRIBUTE* pATAttr = NULL; VDIR_ATTRIBUTE* pOCAttr = NULL; VDIR_ATTRIBUTE* pContentRuleAttr = NULL; VDIR_ATTRIBUTE* pStructureRuleAttr = NULL; VDIR_ATTRIBUTE* pNameformAttr = NULL; for (pAttr = pEntry->attrs; pAttr; pAttr = pAttr->next) { if (VmDirStringCompareA(pAttr->pATDesc->pszName, VDIR_ATTRIBUTE_OBJECT_CLASSES, FALSE) == 0) { pOCAttr = pAttr; } if (VmDirStringCompareA(pAttr->pATDesc->pszName, VDIR_ATTRIBUTE_ATTRIBUTE_TYPES, FALSE) == 0) { pATAttr = pAttr; } if (VmDirStringCompareA(pAttr->pATDesc->pszName, VDIR_ATTRIBUTE_DIT_CONTENTRULES, FALSE) == 0) { pContentRuleAttr = pAttr; } if (VmDirStringCompareA(pAttr->pATDesc->pszName, VDIR_ATTRIBUTE_DIT_STRUCTURERULES, FALSE) == 0) { pStructureRuleAttr = pAttr; } if (VmDirStringCompareA(pAttr->pATDesc->pszName, VDIR_ATTRIBUTE_NAMEFORMS, FALSE) == 0) { pNameformAttr = pAttr; } } if (!pATAttr || !pOCAttr) { dwError = ERROR_INVALID_SCHEMA; BAIL_ON_VMDIR_ERROR(dwError); } dwError = VdirSchemaInstanceAllocate( &pSchema, pATAttr->numVals, pOCAttr->numVals, pContentRuleAttr ? pContentRuleAttr->numVals : 0, pStructureRuleAttr ? pStructureRuleAttr->numVals : 0, pNameformAttr ? pNameformAttr->numVals : 0 ); BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt=0; dwCnt < pATAttr->numVals; dwCnt++) { dwError = VmDirSchemaParseStrToATDesc( pATAttr->vals[dwCnt].lberbv.bv_val, pSchema->ats.pATSortName+dwCnt); BAIL_ON_VMDIR_ERROR(dwError); } for (dwCnt=0; dwCnt < pOCAttr->numVals; dwCnt++) { dwError = VmDirSchemaParseStrToOCDesc( pOCAttr->vals[dwCnt].lberbv.bv_val, pSchema->ocs.pOCSortName+dwCnt); BAIL_ON_VMDIR_ERROR(dwError); } if (pContentRuleAttr) { for (dwCnt=0; dwCnt < pContentRuleAttr->numVals; dwCnt++) { dwError = VmDirSchemaParseStrToContentDesc( pContentRuleAttr->vals[dwCnt].lberbv.bv_val, pSchema->contentRules.pContentSortName+dwCnt); BAIL_ON_VMDIR_ERROR(dwError); } } if (pStructureRuleAttr) { for (dwCnt=0; dwCnt < pStructureRuleAttr->numVals; dwCnt++) { dwError = VmDirSchemaParseStrToStructureDesc( pStructureRuleAttr->vals[dwCnt].lberbv.bv_val, pSchema->structureRules.pStructureSortRuleID+dwCnt); BAIL_ON_VMDIR_ERROR(dwError); } } if (pNameformAttr) { for (dwCnt=0; dwCnt < pNameformAttr->numVals; dwCnt++) { dwError = VmDirSchemaParseStrToNameformDesc( pNameformAttr->vals[dwCnt].lberbv.bv_val, pSchema->nameForms.pNameFormSortName + dwCnt); BAIL_ON_VMDIR_ERROR(dwError); } } *ppSchema = pSchema; cleanup: return dwError; error: if (pSchema) { VdirSchemaInstanceFree(pSchema); } *ppSchema = NULL; goto cleanup; }
/* * merge current and patch schema * 1. if new schema defined in patch, copy them over to current schema * 2. if both current and patch schema have schema definition, use value from patch schema * * The output is merged into pCurrentEntry. */ static DWORD VmDirSchemaPatchMerge( PVDIR_ENTRY pCurrentEntry, PVDIR_ENTRY pPatchEntry ) { DWORD dwError = 0; PVDIR_SCHEMA_INSTANCE pPatchSchema = NULL; PVDIR_ATTRIBUTE pAttr = NULL; USHORT usCnt = 0; dwError = _VmDirSchemaEntryToInstance( pPatchEntry, &pPatchSchema); BAIL_ON_VMDIR_ERROR(dwError); pAttr = VmDirEntryFindAttribute( VDIR_ATTRIBUTE_ATTRIBUTE_TYPES, pCurrentEntry ); assert( pAttr ); _VmDirSchemaNormalizeAttrValue( pAttr ); for (usCnt = 0; usCnt < pPatchSchema->ats.usNumATs; usCnt++) { PVDIR_SCHEMA_AT_DESC pATDesc = NULL; dwError = VmDirSchemaAttrNameToDescriptor( pCurrentEntry->pSchemaCtx, pPatchSchema->ats.pATSortName[ usCnt ].pszName, &pATDesc); if ( dwError == ERROR_NO_SUCH_ATTRIBUTE ) { dwError = VmDirEntryAddSingleValueStrAttribute( pCurrentEntry, VDIR_ATTRIBUTE_ATTRIBUTE_TYPES, pPatchSchema->ats.pATSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, add - %s", VDIR_SAFE_STRING(pPatchSchema->ats.pATSortName[ usCnt ].pszDefinition)); } else { dwError = _VmDirSchemaAttrReplaceValue( pAttr, pPatchSchema->ats.pATSortName[ usCnt ].pszName, pPatchSchema->ats.pATSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); } } pAttr = VmDirEntryFindAttribute( VDIR_ATTRIBUTE_OBJECT_CLASSES, pCurrentEntry ); assert( pAttr ); _VmDirSchemaNormalizeAttrValue( pAttr ); for (usCnt = 0; usCnt < pPatchSchema->ocs.usNumOCs; usCnt++) { PVDIR_SCHEMA_OC_DESC pOCDesc = NULL; dwError = VmDirSchemaOCNameToDescriptor( pCurrentEntry->pSchemaCtx, pPatchSchema->ocs.pOCSortName[ usCnt ].pszName, &pOCDesc); if ( dwError == ERROR_NO_SUCH_OBJECTCLASS ) { dwError = VmDirEntryAddSingleValueStrAttribute( pCurrentEntry, VDIR_ATTRIBUTE_OBJECT_CLASSES, pPatchSchema->ocs.pOCSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, add - %s", VDIR_SAFE_STRING(pPatchSchema->ocs.pOCSortName[ usCnt ].pszDefinition)); } else { dwError = _VmDirSchemaAttrReplaceValue( pAttr, pPatchSchema->ocs.pOCSortName[ usCnt ].pszName, pPatchSchema->ocs.pOCSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); } } pAttr = VmDirEntryFindAttribute( VDIR_ATTRIBUTE_DIT_CONTENTRULES, pCurrentEntry ); assert ( pAttr ); _VmDirSchemaNormalizeAttrValue( pAttr ); for (usCnt = 0; pAttr && usCnt < pPatchSchema->contentRules.usNumContents; usCnt++) { PVDIR_SCHEMA_CR_DESC pCRDesc = NULL; dwError = VmDirSchemaCRNameToDescriptor( pCurrentEntry->pSchemaCtx, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszName, &pCRDesc); if ( dwError == ERROR_NO_SUCH_DITCONTENTRULES ) { dwError = VmDirEntryAddSingleValueStrAttribute( pCurrentEntry, VDIR_ATTRIBUTE_DIT_CONTENTRULES, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); VMDIR_LOG_INFO( VMDIR_LOG_MASK_ALL, "Merge schema, add - %s", VDIR_SAFE_STRING(pPatchSchema->contentRules.pContentSortName[ usCnt ].pszDefinition)); } else { dwError = _VmDirSchemaAttrReplaceValue( pAttr, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszName, pPatchSchema->contentRules.pContentSortName[ usCnt ].pszDefinition); BAIL_ON_VMDIR_ERROR(dwError); } } cleanup: if ( pPatchSchema ) { VdirSchemaInstanceFree(pPatchSchema); } return dwError; error: goto cleanup; }
/* * This function is only for testing purpose. * It call load and verify to validate schema definition integrity. */ DWORD UnitTestSchemaInstanceInit( PSTR* ppszDescs, DWORD dwDescsSize, PVDIR_SCHEMA_INSTANCE* ppSchema ) { DWORD dwError = 0; DWORD dwCnt = 0; DWORD dwIdx = 0; USHORT dwATSize = 0; USHORT dwOCSize = 0; USHORT dwCRSize = 0; USHORT dwSRSize = 0; USHORT dwNFSize = 0; PVDIR_SCHEMA_INSTANCE pSchema = NULL; PSTR pszTmp = NULL; qsort(ppszDescs, dwDescsSize, sizeof(*ppszDescs), schemaInitPPSTRCmp); for (dwCnt=0; dwCnt < dwDescsSize; dwCnt++) { if (IS_ATTRIBUTETYPES_TAG(ppszDescs[dwCnt])) { dwATSize++; } else if (IS_OBJECTCLASSES_TAG(ppszDescs[dwCnt])) { dwOCSize++; } else if (IS_CONTENTRULES_TAG(ppszDescs[dwCnt])) { dwCRSize++; } else if (IS_STRUCTURERULES_TAG(ppszDescs[dwCnt])) { dwSRSize++; } else if (IS_NAMEFORM_TAG(ppszDescs[dwCnt])) { dwNFSize++; } } dwError = VdirSchemaInstanceAllocate(&pSchema, dwATSize, dwOCSize, dwCRSize, dwSRSize, dwNFSize); BAIL_ON_VMDIR_ERROR(dwError); for (dwCnt=0, dwIdx = 0; dwCnt < dwDescsSize; dwCnt++) { if (IS_ATTRIBUTETYPES_TAG(ppszDescs[dwCnt])) { dwError = VmDirSchemaParseStrToATDesc( ppszDescs[dwCnt], pSchema->ats.pATSortName+dwIdx); BAIL_ON_VMDIR_ERROR(dwError); dwIdx++; } } for (dwCnt=0, dwIdx = 0; dwCnt < dwDescsSize ; dwCnt++) { if (IS_OBJECTCLASSES_TAG(ppszDescs[dwCnt])) { dwError = VmDirSchemaParseStrToOCDesc( ppszDescs[dwCnt], pSchema->ocs.pOCSortName+dwIdx); BAIL_ON_VMDIR_ERROR(dwError); dwIdx++; } } for (dwCnt=0, dwIdx = 0; dwCnt < dwDescsSize ; dwCnt++) { if (IS_CONTENTRULES_TAG(ppszDescs[dwCnt])) { dwError = VmDirSchemaParseStrToContentDesc( ppszDescs[dwCnt], pSchema->contentRules.pContentSortName+dwIdx); BAIL_ON_VMDIR_ERROR(dwError); dwIdx++; } } for (dwCnt=0, dwIdx = 0; dwCnt < dwDescsSize ; dwCnt++) { if (IS_STRUCTURERULES_TAG(ppszDescs[dwCnt])) { dwError = VmDirSchemaParseStrToStructureDesc( ppszDescs[dwCnt], pSchema->structureRules.pStructureSortRuleID+dwIdx); BAIL_ON_VMDIR_ERROR(dwError); dwIdx++; } } for (dwCnt=0, dwIdx = 0; dwCnt < dwDescsSize ; dwCnt++) { if (IS_NAMEFORM_TAG(ppszDescs[dwCnt])) { dwError = VmDirSchemaParseStrToNameformDesc( ppszDescs[dwCnt], pSchema->nameForms.pNameFormSortName + dwIdx); BAIL_ON_VMDIR_ERROR(dwError); dwIdx++; } } #ifdef LDAP_DEBUG for (dwCnt = 0; dwCnt < dwOCSize; dwCnt ++) { VMDIR_SAFE_FREE_MEMORY(pszTmp); VdirSchemaVerifyOCDescPrint( pSchema->ocs.pOCSortName+dwCnt, &pszTmp); printf("%s\n", VDIR_SAFE_STRING(pszTmp)); } for (dwCnt = 0; dwCnt < dwATSize; dwCnt ++) { VMDIR_SAFE_FREE_MEMORY(pszTmp); VdirSchemaVerifyATDescPrint( pSchema->ats.pATSortName+dwCnt, &pszTmp); printf("%s\n", VDIR_SAFE_STRING(pszTmp)); } #endif dwError = VmDirSchemaLoadInstance(pSchema); BAIL_ON_VMDIR_ERROR(dwError); if (! VmDirSchemaVerifyIntegrity(pSchema)) { dwError = ERROR_INVALID_SCHEMA; BAIL_ON_VMDIR_ERROR(dwError); } *ppSchema = pSchema; cleanup: VMDIR_SAFE_FREE_MEMORY(pszTmp); return dwError; error: if (pSchema) { VdirSchemaInstanceFree(pSchema); } *ppSchema = NULL; goto cleanup; }