diff options
Diffstat (limited to 'ldap/servers/plugins/shared/utils.c')
-rw-r--r-- | ldap/servers/plugins/shared/utils.c | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/ldap/servers/plugins/shared/utils.c b/ldap/servers/plugins/shared/utils.c new file mode 100644 index 00000000..d5044b17 --- /dev/null +++ b/ldap/servers/plugins/shared/utils.c @@ -0,0 +1,467 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/*********************************************************************** +** NAME +** utils.c +** +** DESCRIPTION +** +** +** AUTHOR +** <rweltman@netscape.com> +** +***********************************************************************/ + + +/*********************************************************************** +** Includes +***********************************************************************/ + +#include "plugin-utils.h" + +static char *plugin_name = "utils"; + +/* + * Lock for updating a counter (global for all counters) + */ +static Slapi_Mutex *counter_lock = NULL; + +/* ------------------------------------------------------------ */ +/* + * op_error - Record (and report) an operational error. + */ +int +op_error(int internal_error) { + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, + "Internal error: %d\n", internal_error); + + return LDAP_OPERATIONS_ERROR; +} + +int initCounterLock() { + if ( NULL == counter_lock ) { + if ( !(counter_lock = slapi_new_mutex()) ) { + return 200; + } + } + return 0; +} + +/* ------------------------------------------------------------ */ +/* + * readPblockAndEntry - search for and read an entry + * Return: + * A pblock containing the entry, or NULL + */ +Slapi_PBlock * +readPblockAndEntry( const char *baseDN, const char *filter, + char *attrs[] ) { + int result = 0; + Slapi_PBlock *spb = NULL; + + BEGIN + int sres; + + /* Perform the search - the new pblock needs to be freed */ + spb = slapi_search_internal((char *)baseDN, LDAP_SCOPE_BASE, + (char *)filter, NULL, attrs, 0); + if ( !spb ) { + result = op_error(20); + break; + } + + if ( slapi_pblock_get( spb, SLAPI_PLUGIN_INTOP_RESULT, &sres ) ) { + result = op_error(21); + break; + } else if (sres) { + result = op_error(22); + break; + } + END + + return spb; +} + +/* ------------------------------------------------------------ */ +/* + * hasObjectClass - read an entry and check if it has a + * particular object class value + * Return: + * 1 - the entry contains the object class value + * 0 - the entry doesn't contain the object class value + */ +int +entryHasObjectClass(Slapi_PBlock *pb, Slapi_Entry *e, + const char *objectClass) { + Slapi_Attr *attr; + Slapi_Value *v; + const struct berval *bv; + int vhint; + + if ( slapi_entry_attr_find(e, "objectclass", &attr) ) { + return 0; /* no objectclass values! */ + } + + /* + * Check each of the object class values in turn. + */ + for ( vhint = slapi_attr_first_value( attr, &v ); + vhint != -1; + vhint = slapi_attr_next_value( attr, vhint, &v )) { + bv = slapi_value_get_berval(v); + if ( NULL != bv && NULL != bv->bv_val && + !strcasecmp(bv->bv_val, objectClass) ) { + return 1; + } + } + return 0; +} + +/* ------------------------------------------------------------ */ +/* + * dnHasObjectClass - read an entry if it has a particular object class + * Return: + * A pblock containing the entry, or NULL + */ +Slapi_PBlock * +dnHasObjectClass( const char *baseDN, const char *objectClass ) { + int result = 0; + Slapi_PBlock *spb = NULL; + + BEGIN + Slapi_Entry **entries; + char filter[1024]; + char *attrs[2]; + + /* Perform the search - the new pblock needs to be freed */ + attrs[0] = "objectclass"; + attrs[1] = NULL; + sprintf( filter, "objectclass=%s", objectClass ); + if ( !(spb = readPblockAndEntry( baseDN, filter, attrs) ) ) { + break; + } + + if ( slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, + &entries) ) { + result = op_error(23); + break; + } + /* + * Can only be one entry returned on a base search; just check + * the first one + */ + if ( !*entries ) { + /* Clean up */ + slapi_free_search_results_internal(spb); + slapi_pblock_destroy(spb); + spb = NULL; + } + END + + return spb; +} + +/* ------------------------------------------------------------ */ +/* + * dnHasAttribute - read an entry if it has a particular attribute + * Return: + * The entry, or NULL + */ +Slapi_PBlock * +dnHasAttribute( const char *baseDN, const char *attrName ) { + int result = 0; + Slapi_PBlock *spb = NULL; + + BEGIN + int sres; + Slapi_Entry **entries; + char filter[1024]; + char *attrs[2]; + + /* Perform the search - the new pblock needs to be freed */ + attrs[0] = (char *)attrName; + attrs[1] = NULL; + sprintf( filter, "%s=*", attrName ); + spb = slapi_search_internal((char *)baseDN, LDAP_SCOPE_BASE, + filter, NULL, attrs, 0); + if ( !spb ) { + result = op_error(20); + break; + } + + if ( slapi_pblock_get( spb, SLAPI_PLUGIN_INTOP_RESULT, &sres ) ) { + result = op_error(21); + break; + } else if (sres) { + result = op_error(22); + break; + } + + if ( slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, + &entries) ) { + result = op_error(23); + break; + } + /* + * Can only be one entry returned on a base search; just check + * the first one + */ + if ( !*entries ) { + /* Clean up */ + slapi_free_search_results_internal(spb); + slapi_pblock_destroy(spb); + spb = NULL; + } + END + + return spb; +} + +/* ------------------------------------------------------------ */ +/* + * setCounter - set the value of a counter + * + * Return: + * LDAP_SUCCESS - updated the attribute + * other - failure to update the count + */ +int +setCounter( Slapi_Entry *e, const char *attrName, int value ) { + int result = LDAP_SUCCESS; + Slapi_PBlock *modifySpb = NULL; + char strValue[16]; + char *strValues[2] = { NULL }; + LDAPMod mod; + LDAPMod *mods[2]; + int res; + + BEGIN + /* Store the updated value */ + strValues[0] = strValue; + sprintf( strValue, "%d", value ); + mod.mod_op = LDAP_MOD_REPLACE; + mod.mod_type = (char *)attrName; + mod.mod_values = strValues; + mods[0] = &mod; + mods[1] = NULL; + modifySpb = slapi_modify_internal( slapi_entry_get_dn(e), mods, + NULL, 1 ); + /* Check if the operation succeeded */ + if ( slapi_pblock_get( modifySpb, SLAPI_PLUGIN_INTOP_RESULT, + &res ) ) { + result = op_error(33); + break; + } else if (res) { + result = op_error(34); + break; + } + slapi_pblock_destroy(modifySpb); + END + return result; +} + +/* ------------------------------------------------------------ */ +/* + * updateCounter - read and increment/decrement the value of a counter + * + * Return: + * LDAP_SUCCESS - updated the attribute + * other - failure to update the count + */ +int +updateCounter( Slapi_Entry *e, const char *attrName, int increment ) { + int result = LDAP_SUCCESS; + Slapi_PBlock *modifySpb = NULL; + Slapi_Attr *attr; + int value = 0; + char strValue[16]; + char *strValues[2] = { NULL }; + LDAPMod mod; + LDAPMod *mods[2]; + int res; + + BEGIN + /* Lock the entry */ + slapi_lock_mutex(counter_lock); + /* Get the count attribute */ + if ( slapi_entry_attr_find(e, (char *)attrName, &attr) ) { + /* No count yet; that's OK */ + } else { + /* Get the first value for the attribute */ + Slapi_Value *v = NULL; + const struct berval *bv = NULL; + + if ( -1 == slapi_attr_first_value( attr, &v ) || NULL == v || + NULL == ( bv = slapi_value_get_berval(v)) || + NULL == bv->bv_val ) { + /* No values yet; that's OK, too */ + } else { + value = atoi( bv->bv_val ); + } + } + /* Add the increment */ + value += increment; + if ( value < 0 ) { + value = 0; + } + /* Store the updated value */ + strValues[0] = strValue; + sprintf( strValue, "%d", value ); + mod.mod_op = LDAP_MOD_REPLACE; + mod.mod_type = (char *)attrName; + mod.mod_values = strValues; + mods[0] = &mod; + mods[1] = NULL; + modifySpb = slapi_modify_internal( slapi_entry_get_dn(e), mods, + NULL, 1 ); + /* Check if the operation succeeded */ + if ( slapi_pblock_get( modifySpb, SLAPI_PLUGIN_INTOP_RESULT, + &res ) ) { + result = op_error(33); + break; + } else if (res) { + result = op_error(34); + break; + } + slapi_pblock_destroy(modifySpb); + /* Unlock the entry */ + slapi_unlock_mutex(counter_lock); +#ifdef DEBUG + slapi_log_error(SLAPI_LOG_PLUGIN, plugin_name, + "adjusted %s in %s by %d to %d\n", + attrName, slapi_entry_get_dn(e), increment, value); +#endif + + END + return result; +} + +/* ------------------------------------------------------------ */ +/* + * updateCounterByDN - read and increment/decrement the value of a counter + * + * Return: + * LDAP_SUCCESS - updated the attribute + * other - failure to update the count + */ +int +updateCounterByDN( const char *dn, const char *attrName, int increment ) { + int result = LDAP_SUCCESS; + Slapi_PBlock *spb = NULL; + Slapi_Entry **entries; + + BEGIN + char *attrs[2]; + int sres; + + /* Perform the search - the new pblock needs to be freed */ + attrs[0] = (char *)attrName; + attrs[1] = NULL; + spb = slapi_search_internal((char *)dn, LDAP_SCOPE_BASE, + "objectclass=*", NULL, attrs, 0); + if ( !spb ) { + result = op_error(20); + break; + } + + if ( slapi_pblock_get( spb, SLAPI_PLUGIN_INTOP_RESULT, &sres ) ) { + result = op_error(21); + break; + } else if (sres) { + result = op_error(22); + break; + } + + if ( slapi_pblock_get(spb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, + &entries) ) { + result = op_error(23); + break; + } + END + if ( 0 == result ) { + result = updateCounter( *entries, attrName, increment ); + } + if ( NULL != spb ) { + /* Clean up */ + slapi_free_search_results_internal(spb); + slapi_pblock_destroy(spb); + } + return result; +} + +/* + * Lock for accessing a cache (global for all caches) + */ +static Slapi_Mutex *cache_lock = NULL; + +DNLink *cacheInit() { + DNLink *root; + slapi_lock_mutex(cache_lock); + root = (DNLink *)malloc( sizeof(DNLink) ); + root->next = NULL; + root->data = NULL; + root->dn = (char *)malloc(1); + root->dn[0] = 0; + slapi_unlock_mutex(cache_lock); + return root; +} + +DNLink *cacheAdd( DNLink *root, char *dn, void *data ) { + if ( NULL == root ) { + return NULL; + } + slapi_lock_mutex(cache_lock); + for( ; root->next; root = root->next ) { + } + root->next = (DNLink *)malloc( sizeof(DNLink) ); + root = root->next; + root->dn = dn; + root->data = data; + root->next = NULL; + slapi_unlock_mutex(cache_lock); + return root; +} + +char *cacheRemove( DNLink *root, char *dn ) { + char *found = NULL; + DNLink *current = root; + DNLink *prev = NULL; + if ( NULL == root ) { + return NULL; + } + slapi_lock_mutex(cache_lock); + for( ; current; prev = current, current = current->next ) { + if ( !strcmp( current->dn, dn ) ) { + found = current->dn; + prev->next = current->next; + slapi_ch_free( (void **)¤t ); + break; + } + } + slapi_unlock_mutex(cache_lock); + return found; +} + +int cacheDelete( DNLink *root, char *dn ) { + char *found = cacheRemove( root, dn ); + if ( found ) { + slapi_ch_free( (void **)&found ); + return 0; + } else { + return 1; + } +} + +DNLink *cacheFind( DNLink *root, char *dn ) { + if ( NULL == root ) { + return NULL; + } + slapi_lock_mutex(cache_lock); + for( ; root && strcmp(dn, root->dn); root = root->next ) { + } + slapi_unlock_mutex(cache_lock); + return root; +} |