Exemple #1
0
/*
 * 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;
}
Exemple #2
0
/*
 * 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;
}
Exemple #3
0
/*
 *    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;
}
Exemple #4
0
/*
 * 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;
}
Exemple #5
0
/*
 * 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;
}
Exemple #6
0
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;
}
Exemple #7
0
/*
 * 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;
}
Exemple #8
0
/*
 * 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;
}
Exemple #9
0
/*
 * 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;
}