Entry * monitor_entry_stub( struct berval *pdn, struct berval *pndn, struct berval *rdn, ObjectClass *oc, struct berval *create, struct berval *modify ) { monitor_info_t *mi; AttributeDescription *nad = NULL; Entry *e; struct berval nat; char *ptr; const char *text; int rc; mi = ( monitor_info_t * )be_monitor->be_private; nat = *rdn; ptr = strchr( nat.bv_val, '=' ); nat.bv_len = ptr - nat.bv_val; rc = slap_bv2ad( &nat, &nad, &text ); if ( rc ) return NULL; e = entry_alloc(); if ( e ) { struct berval nrdn; rdnNormalize( 0, NULL, NULL, rdn, &nrdn, NULL ); build_new_dn( &e->e_name, pdn, rdn, NULL ); build_new_dn( &e->e_nname, pndn, &nrdn, NULL ); ber_memfree( nrdn.bv_val ); nat.bv_val = ptr + 1; nat.bv_len = rdn->bv_len - ( nat.bv_val - rdn->bv_val ); attr_merge_normalize_one( e, slap_schema.si_ad_objectClass, &oc->soc_cname, NULL ); attr_merge_normalize_one( e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL ); attr_merge_normalize_one( e, nad, &nat, NULL ); attr_merge_one( e, slap_schema.si_ad_creatorsName, &mi->mi_creatorsName, &mi->mi_ncreatorsName ); attr_merge_one( e, slap_schema.si_ad_modifiersName, &mi->mi_creatorsName, &mi->mi_ncreatorsName ); attr_merge_normalize_one( e, slap_schema.si_ad_createTimestamp, create ? create : &mi->mi_startTime, NULL ); attr_merge_normalize_one( e, slap_schema.si_ad_modifyTimestamp, modify ? modify : &mi->mi_startTime, NULL ); } return e; }
void glue_parent(Operation *op) { Operation nop = *op; slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct berval ndn = BER_BVNULL; Attribute *a; Entry *e; struct berval pdn; dnParent( &op->o_req_ndn, &pdn ); ber_dupbv_x( &ndn, &pdn, op->o_tmpmemctx ); Debug(LDAP_DEBUG_TRACE, "=> glue_parent: fabricating glue for <%s>\n", ndn.bv_val, 0, 0); e = entry_alloc(); e->e_id = NOID; ber_dupbv(&e->e_name, &ndn); ber_dupbv(&e->e_nname, &ndn); a = attr_alloc( slap_schema.si_ad_objectClass ); a->a_numvals = 2; a->a_vals = ch_malloc(sizeof(struct berval) * 3); ber_dupbv(&a->a_vals[0], &glue[0]); ber_dupbv(&a->a_vals[1], &glue[1]); ber_dupbv(&a->a_vals[2], &glue[2]); a->a_nvals = a->a_vals; a->a_next = e->e_attrs; e->e_attrs = a; a = attr_alloc( slap_schema.si_ad_structuralObjectClass ); a->a_numvals = 1; a->a_vals = ch_malloc(sizeof(struct berval) * 2); ber_dupbv(&a->a_vals[0], &glue[1]); ber_dupbv(&a->a_vals[1], &glue[2]); a->a_nvals = a->a_vals; a->a_next = e->e_attrs; e->e_attrs = a; nop.o_req_dn = ndn; nop.o_req_ndn = ndn; nop.ora_e = e; nop.o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; syncrepl_add_glue(&nop, e); nop.o_bd->bd_info = (BackendInfo *) on; op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); return; }
int hash_map_add(struct hash_map_t *self_p, long key, void *value_p) { ASSERTN(self_p != NULL, EINVAL); ASSERTN(value_p != NULL, EINVAL); int hash; struct hash_map_bucket_t *bucket_p; struct hash_map_entry_t *entry_p; /* Hash key. */ hash = self_p->hash(key); hash %= self_p->buckets_max; bucket_p = &self_p->buckets_p[hash]; /* Is the key already in map? */ if (bucket_p->list_p != NULL) { entry_p = bucket_p->list_p; while (entry_p != NULL) { if (entry_p->key == key) { entry_p->value_p = value_p; return (0); } entry_p = entry_p->next_p; } } /* Allocate new entry. */ entry_p = entry_alloc(self_p); if (entry_p == NULL) { return (-ENOMEM); } /* Initiate entry.*/ entry_p->key = key; entry_p->value_p = value_p; /* Insert in list. */ entry_p->next_p = bucket_p->list_p; bucket_p->list_p = entry_p; return (0); }
Entry* ndb_tool_entry_get( BackendDB *be, ID id ) { NdbArgs NA; int rc; char text[1024]; Operation op = {0}; Opheader ohdr = {0}; assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); NA.txn = myNdb->startTransaction(); if ( !NA.txn ) { snprintf( text, sizeof(text), "start_transaction failed: %s (%d)", myNdb->getNdbError().message, myNdb->getNdbError().code ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(ndb_tool_entry_get) ": %s\n", text, 0, 0 ); return NULL; } NA.e = entry_alloc(); NA.e->e_id = id; ber_dupbv( &NA.e->e_name, &myDn ); dnNormalize( 0, NULL, NULL, &NA.e->e_name, &NA.e->e_nname, NULL ); op.o_hdr = &ohdr; op.o_bd = be; op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; NA.ndb = myNdb; NA.ocs = myOcList; rc = ndb_entry_get_data( &op, &NA, 0 ); if ( rc ) { entry_free( NA.e ); NA.e = NULL; } NA.txn->close(); return NA.e; }
/********************************************************************************* * The contents of this file are subject to the Common Public Attribution * License Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.openemm.org/cpal1.html. The License is based on the Mozilla * Public License Version 1.1 but Sections 14 and 15 have been added to cover * use of software over a computer network and provide for limited attribution * for the Original Developer. In addition, Exhibit A has been modified to be * consistent with Exhibit B. * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is OpenEMM. * The Original Developer is the Initial Developer. * The Initial Developer of the Original Code is AGNITAS AG. All portions of * the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights * Reserved. * * Contributor(s): AGNITAS AG. ********************************************************************************/ # include <stdlib.h> # include <unistd.h> # include <fcntl.h> # include <string.h> # include <dirent.h> # include <errno.h> # include <sys/types.h> # include <sys/stat.h> # include "qctrl.h" entry_t * entry_alloc (const char *fname, int match) /*{{{*/ { entry_t *e; if (e = (entry_t *) malloc (sizeof (entry_t))) { e -> fname = NULL; e -> match = match; e -> next = NULL; if (fname && (! (e -> fname = strdup (fname)))) e = entry_free (e); } return e; }/*}}}*/ entry_t * entry_free (entry_t *e) /*{{{*/ { if (e) { if (e -> fname) free (e -> fname); free (e); } return NULL; }/*}}}*/ entry_t * entry_free_all (entry_t *e) /*{{{*/ { entry_t *tmp; while (tmp = e) { e = e -> next; entry_free (tmp); } return NULL; }/*}}}*/ static bool_t iswhitespace (const char ch) /*{{{*/ { return ((ch == ' ') || (ch == '\t')) ? true : false; }/*}}}*/ qf_t * qf_alloc (const buffer_t *src) /*{{{*/ { qf_t *q; char *temp; int size; char *ptr; q = NULL; if (temp = malloc (src -> length + 1)) { memcpy (temp, src -> buffer, src -> length); temp[src -> length] = '\0'; size = 0; if (q = (qf_t *) malloc (sizeof (qf_t))) { q -> content = NULL; q -> count = 0; q -> idx = 0; for (ptr = temp; ptr; ) { if (q -> count >= size) { size += (size ? size : 32); if (! (q -> content = (char **) realloc (q -> content, (size + 1) * sizeof (char *)))) break; } if (*ptr) { q -> content[q -> count++] = ptr; while (ptr = strchr (ptr, '\n')) if ((! *(ptr + 1)) || (! iswhitespace (*(ptr + 1)))) break; else ++ptr; } if (ptr) if (*ptr) *ptr++ = '\0'; else ptr = NULL; } if (ptr) { if (q -> content) free (q -> content); free (q); q = NULL; } else { q -> content[q -> count] = NULL; if (q -> count) temp = NULL; } } if (temp) free (temp); } return q; }/*}}}*/ qf_t * qf_free (qf_t *q) /*{{{*/ { if (q) { if (q -> content) { if (q -> content[0]) free (q -> content[0]); free (q -> content); } free (q); } return NULL; }/*}}}*/ const char * qf_first (qf_t *q, char ch) /*{{{*/ { q -> idx = 0; return qf_next (q, ch); }/*}}}*/ const char * qf_next (qf_t *q, char ch) /*{{{*/ { while (q -> idx < q -> count) if (q -> content[q -> idx][0] == ch) return q -> content[q -> idx++]; else if (q -> content[q -> idx][0] == '.') q -> idx = q -> count; else q -> idx++; return NULL; }/*}}}*/ int qf_count (qf_t *q, char ch) /*{{{*/ { int n; int cnt; for (n = 0, cnt = 0; n < q -> count; ++n) if ((! ch) || (q -> content[n][0] == ch)) ++cnt; return cnt; }/*}}}*/ queue_t * queue_scan (const char *path, int (*filter) (void *, queue_t *, const char *), void *data) /*{{{*/ { queue_t *q; DIR *dp; q = NULL; if (dp = opendir (path)) { if (q = (queue_t *) malloc (sizeof (queue_t))) { bool_t st; entry_t *prv, *tmp; struct dirent *ent; int n; strcpy (q -> path, path); strcpy (q -> fbuf, q -> path); for (q -> fptr = q -> fbuf; *(q -> fptr); q -> fptr++) ; *(q -> fptr++) = '/'; q -> qf = NULL; q -> ent = NULL; st = true; prv = NULL; while (st && (ent = readdir (dp))) { n = 0; if ((! filter) || (n = (*filter) (data, q, ent -> d_name))) if (tmp = entry_alloc (ent -> d_name, n)) { if (prv) prv -> next = tmp; else q -> ent = tmp; prv = tmp; } else st = false; } if (! st) q = queue_free (q); } closedir (dp); } return q; }/*}}}*/
/*..........................................................................*/ static QHsm *Entry_ctor(raid5_entry_t *rentry) { Entry *me; Entry *entry; /* allocate the memory */ me = entry = entry_alloc(); Q_ASSERT(me != NULL); QS_OBJ_DICTIONARY(entry); /* QS_OBJ_DICTIONARY(entry->x); */ QS_SIG_DICTIONARY(DIR_REQUEST_SIG, me); QS_SIG_DICTIONARY(DIR_UPDATE_SIG, me); QS_SIG_DICTIONARY(DIR_INSERT_SIG, me); /* adding free list */ list_add_tail(&me->entry, &rentry->free); /* call QHsm */ QHsm_ctor(&me->super, (QStateHandler)&Entry_initial); return &me->super; }
static int bdb_db_open( BackendDB *be, ConfigReply *cr ) { int rc, i; struct bdb_info *bdb = (struct bdb_info *) be->be_private; struct stat stat1, stat2; u_int32_t flags; char path[MAXPATHLEN]; char *dbhome; Entry *e = NULL; int do_recover = 0, do_alock_recover = 0; int alockt, quick = 0; int do_retry = 1; if ( be->be_suffix == NULL ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": need suffix.\n", 1, 0, 0 ); return -1; } Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(bdb_db_open) ": \"%s\"\n", be->be_suffix[0].bv_val, 0, 0 ); /* Check existence of dbenv_home. Any error means trouble */ rc = stat( bdb->bi_dbenv_home, &stat1 ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "cannot access database directory \"%s\" (%d).\n", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, errno ); return -1; } /* Perform database use arbitration/recovery logic */ alockt = (slapMode & SLAP_TOOL_READONLY) ? ALOCK_LOCKED : ALOCK_UNIQUE; if ( slapMode & SLAP_TOOL_QUICK ) { alockt |= ALOCK_NOSAVE; quick = 1; } rc = alock_open( &bdb->bi_alock_info, "slapd", bdb->bi_dbenv_home, alockt ); /* alockt is TRUE if the existing environment was created in Quick mode */ alockt = (rc & ALOCK_NOSAVE) ? 1 : 0; rc &= ~ALOCK_NOSAVE; if( rc == ALOCK_RECOVER ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "unclean shutdown detected; attempting recovery.\n", be->be_suffix[0].bv_val, 0, 0 ); do_alock_recover = 1; do_recover = DB_RECOVER; } else if( rc == ALOCK_BUSY ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "database already in use.\n", be->be_suffix[0].bv_val, 0, 0 ); return -1; } else if( rc != ALOCK_CLEAN ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "alock package is unstable.\n", be->be_suffix[0].bv_val, 0, 0 ); return -1; } if ( rc == ALOCK_CLEAN ) be->be_flags |= SLAP_DBFLAG_CLEAN; /* * The DB_CONFIG file may have changed. If so, recover the * database so that new settings are put into effect. Also * note the possible absence of DB_CONFIG in the log. */ if( stat( bdb->bi_db_config_path, &stat1 ) == 0 ) { if ( !do_recover ) { char *ptr = lutil_strcopy(path, bdb->bi_dbenv_home); *ptr++ = LDAP_DIRSEP[0]; strcpy( ptr, "__db.001" ); if( stat( path, &stat2 ) == 0 ) { if( stat2.st_mtime < stat1.st_mtime ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix \"%s\" has changed.\n", be->be_suffix[0].bv_val, 0, 0 ); if ( quick ) { Debug( LDAP_DEBUG_ANY, "Cannot use Quick mode; perform manual recovery first.\n", 0, 0, 0 ); slapMode ^= SLAP_TOOL_QUICK; rc = -1; goto fail; } else { Debug( LDAP_DEBUG_ANY, "Performing database recovery to activate new settings.\n", 0, 0, 0 ); } do_recover = DB_RECOVER; } } } } else { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": warning - no DB_CONFIG file found " "in directory %s: (%d).\n" "Expect poor performance for suffix \"%s\".\n", bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val ); } /* Always let slapcat run, regardless of environment state. * This can be used to cause a cache flush after an unclean * shutdown. */ if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "recovery skipped in read-only mode. " "Run manual recovery if errors are encountered.\n", be->be_suffix[0].bv_val, 0, 0 ); do_recover = 0; do_alock_recover = 0; quick = alockt; } /* An existing environment in Quick mode has nothing to recover. */ if ( alockt && do_recover ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "cannot recover, database must be reinitialized.\n", be->be_suffix[0].bv_val, 0, 0 ); rc = -1; goto fail; } rc = db_env_create( &bdb->bi_dbenv, 0 ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "db_env_create failed: %s (%d).\n", be->be_suffix[0].bv_val, db_strerror(rc), rc ); goto fail; } #ifdef HAVE_EBCDIC strcpy( path, bdb->bi_dbenv_home ); __atoe( path ); dbhome = path; #else dbhome = bdb->bi_dbenv_home; #endif /* If existing environment is clean but doesn't support * currently requested modes, remove it. */ if ( !do_recover && ( alockt ^ quick )) { shm_retry: rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE ); if ( rc ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "dbenv remove failed: %s (%d).\n", be->be_suffix[0].bv_val, db_strerror(rc), rc ); bdb->bi_dbenv = NULL; goto fail; } rc = db_env_create( &bdb->bi_dbenv, 0 ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "db_env_create failed: %s (%d).\n", be->be_suffix[0].bv_val, db_strerror(rc), rc ); goto fail; } } bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val ); bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall ); bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect ); if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { rc = bdb->bi_dbenv->set_encrypt( bdb->bi_dbenv, bdb->bi_db_crypt_key.bv_val, DB_ENCRYPT_AES ); if ( rc ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "dbenv set_encrypt failed: %s (%d).\n", be->be_suffix[0].bv_val, db_strerror(rc), rc ); goto fail; } } /* One long-lived TXN per thread, two TXNs per write op */ bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 ); if( bdb->bi_dbenv_xflags != 0 ) { rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv, bdb->bi_dbenv_xflags, 1); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "dbenv_set_flags failed: %s (%d).\n", be->be_suffix[0].bv_val, db_strerror(rc), rc ); goto fail; } } #define BDB_TXN_FLAGS (DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN) Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "dbenv_open(%s).\n", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, 0); flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD; if ( !quick ) flags |= BDB_TXN_FLAGS; /* If a key was set, use shared memory for the BDB environment */ if ( bdb->bi_shm_key ) { bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key ); flags |= DB_SYSTEM_MEM; } rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome, flags | do_recover, bdb->bi_dbenv_mode ); if ( rc ) { /* Regular open failed, probably a missing shm environment. * Start over, do a recovery. */ if ( !do_recover && bdb->bi_shm_key && do_retry ) { bdb->bi_dbenv->close( bdb->bi_dbenv, 0 ); rc = db_env_create( &bdb->bi_dbenv, 0 ); if( rc == 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": " "shared memory env open failed, assuming stale env.\n", be->be_suffix[0].bv_val, 0, 0 ); do_retry = 0; goto shm_retry; } } Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\" cannot be %s, err %d. " "Restore from backup!\n", be->be_suffix[0].bv_val, do_recover ? "recovered" : "opened", rc ); goto fail; } if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": database \"%s\": alock_recover failed\n", be->be_suffix[0].bv_val, 0, 0 ); rc = -1; goto fail; } #ifdef SLAP_ZONE_ALLOC if ( bdb->bi_cache.c_maxsize ) { bdb->bi_cache.c_zctx = slap_zn_mem_create( SLAP_ZONE_INITSIZE, SLAP_ZONE_MAXSIZE, SLAP_ZONE_DELTA, SLAP_ZONE_SIZE); } #endif /* dncache defaults to 0 == unlimited * must be >= entrycache */ if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) { bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize; } if ( bdb->bi_idl_cache_max_size ) { bdb->bi_idl_tree = NULL; bdb->bi_idl_cache_size = 0; } flags = DB_THREAD | bdb->bi_db_opflags; #ifdef DB_AUTO_COMMIT if ( !quick ) flags |= DB_AUTO_COMMIT; #endif bdb->bi_databases = (struct bdb_db_info **) ch_malloc( BDB_INDICES * sizeof(struct bdb_db_info *) ); /* open (and create) main database */ for( i = 0; bdbi_databases[i].name.bv_val; i++ ) { struct bdb_db_info *db; db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info)); rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 ); if( rc != 0 ) { snprintf(cr->msg, sizeof(cr->msg), "database \"%s\": db_create(%s) failed: %s (%d).", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, db_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 ); goto fail; } if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) { rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT ); if ( rc ) { snprintf(cr->msg, sizeof(cr->msg), "database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, db_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 ); goto fail; } } if( bdb->bi_flags & BDB_CHKSUM ) { rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM ); if ( rc ) { snprintf(cr->msg, sizeof(cr->msg), "database \"%s\": db set_flags(DB_CHKSUM)(%s) failed: %s (%d).", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, db_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 ); goto fail; } } rc = bdb_db_findsize( bdb, (struct berval *)&bdbi_databases[i].name ); if( i == BDB_ID2ENTRY ) { if ( !rc ) rc = BDB_ID2ENTRY_PAGESIZE; rc = db->bdi_db->set_pagesize( db->bdi_db, rc ); if ( slapMode & SLAP_TOOL_MODE ) db->bdi_db->mpf->set_priority( db->bdi_db->mpf, DB_PRIORITY_VERY_LOW ); if ( slapMode & SLAP_TOOL_READMAIN ) { flags |= DB_RDONLY; } else { flags |= DB_CREATE; } } else { /* Use FS default size if not configured */ if ( rc ) rc = db->bdi_db->set_pagesize( db->bdi_db, rc ); rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT ); #ifndef BDB_HIER if ( slapMode & SLAP_TOOL_READONLY ) { flags |= DB_RDONLY; } else { flags |= DB_CREATE; } #else rc = db->bdi_db->set_dup_compare( db->bdi_db, bdb_dup_compare ); if ( slapMode & (SLAP_TOOL_READONLY|SLAP_TOOL_READMAIN) ) { flags |= DB_RDONLY; } else { flags |= DB_CREATE; } #endif } #ifdef HAVE_EBCDIC strcpy( path, bdbi_databases[i].file ); __atoe( path ); rc = DB_OPEN( db->bdi_db, path, /* bdbi_databases[i].name, */ NULL, bdbi_databases[i].type, bdbi_databases[i].flags | flags, bdb->bi_dbenv_mode ); #else rc = DB_OPEN( db->bdi_db, bdbi_databases[i].file, /* bdbi_databases[i].name, */ NULL, bdbi_databases[i].type, bdbi_databases[i].flags | flags, bdb->bi_dbenv_mode ); #endif if ( rc != 0 ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "db_open(%s/%s) failed: %s (%d).", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, bdbi_databases[i].file, db_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 ); db->bdi_db->close( db->bdi_db, 0 ); goto fail; } flags &= ~(DB_CREATE | DB_RDONLY); db->bdi_name = bdbi_databases[i].name; bdb->bi_databases[i] = db; } bdb->bi_databases[i] = NULL; bdb->bi_ndatabases = i; /* get nextid */ rc = bdb_last_id( be, NULL ); if( rc != 0 ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "last_id(%s) failed: %s (%d).", be->be_suffix[0].bv_val, bdb->bi_dbenv_home, db_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open) ": %s\n", cr->msg, 0, 0 ); goto fail; } if ( !quick ) { TXN_BEGIN(bdb->bi_dbenv, NULL, &bdb->bi_cache.c_txn, DB_READ_COMMITTED | DB_TXN_NOWAIT); } entry_prealloc( bdb->bi_cache.c_maxsize ); attr_prealloc( bdb->bi_cache.c_maxsize * 20 ); /* setup for empty-DN contexts */ if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) { rc = bdb_id2entry( be, NULL, 0, &e ); } if ( !e ) { struct berval gluebv = BER_BVC("glue"); Operation op = {0}; Opheader ohdr = {0}; e = entry_alloc(); e->e_id = 0; ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv ); ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv ); attr_merge_one( e, slap_schema.si_ad_objectClass, &gluebv, NULL ); attr_merge_one( e, slap_schema.si_ad_structuralObjectClass, &gluebv, NULL ); op.o_hdr = &ohdr; op.o_bd = be; op.ora_e = e; op.o_dn = be->be_rootdn; op.o_ndn = be->be_rootndn; slap_add_opattrs( &op, NULL, NULL, 0, 0 ); } e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END; e->e_private = &bdb->bi_cache.c_dntree; bdb->bi_cache.c_dntree.bei_e = e; /* monitor setup */ rc = bdb_monitor_db_open( be ); if ( rc != 0 ) { goto fail; } bdb->bi_flags |= BDB_IS_OPEN; return 0; fail: bdb_db_close( be, NULL ); return rc; }
/* Duplicates an entry using a single malloc. Saves CPU time, increases * heap usage because a single large malloc is harder to satisfy than * lots of small ones, and the freed space isn't as easily reusable. * * Probably not worth using this function. */ Entry *entry_dup_bv( Entry *e ) { ber_len_t len; int nattrs, nvals; Entry *ret; struct berval *bvl; char *ptr; Attribute *src, *dst; ret = entry_alloc(); entry_partsize(e, &len, &nattrs, &nvals, 1); ret->e_id = e->e_id; ret->e_attrs = attrs_alloc( nattrs ); ret->e_ocflags = e->e_ocflags; ret->e_bv.bv_len = len + nvals * sizeof(struct berval); ret->e_bv.bv_val = ch_malloc( ret->e_bv.bv_len ); bvl = (struct berval *)ret->e_bv.bv_val; ptr = (char *)(bvl + nvals); ret->e_name.bv_len = e->e_name.bv_len; ret->e_name.bv_val = ptr; AC_MEMCPY( ptr, e->e_name.bv_val, e->e_name.bv_len ); ptr += e->e_name.bv_len; *ptr++ = '\0'; ret->e_nname.bv_len = e->e_nname.bv_len; ret->e_nname.bv_val = ptr; AC_MEMCPY( ptr, e->e_nname.bv_val, e->e_nname.bv_len ); ptr += e->e_name.bv_len; *ptr++ = '\0'; dst = ret->e_attrs; for (src = e->e_attrs; src; src=src->a_next,dst=dst->a_next ) { int i; dst->a_desc = src->a_desc; dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; dst->a_vals = bvl; dst->a_numvals = src->a_numvals; for ( i=0; src->a_vals[i].bv_val; i++ ) { bvl->bv_len = src->a_vals[i].bv_len; bvl->bv_val = ptr; AC_MEMCPY( ptr, src->a_vals[i].bv_val, bvl->bv_len ); ptr += bvl->bv_len; *ptr++ = '\0'; bvl++; } BER_BVZERO(bvl); bvl++; if ( src->a_vals != src->a_nvals ) { dst->a_nvals = bvl; for ( i=0; src->a_nvals[i].bv_val; i++ ) { bvl->bv_len = src->a_nvals[i].bv_len; bvl->bv_val = ptr; AC_MEMCPY( ptr, src->a_nvals[i].bv_val, bvl->bv_len ); ptr += bvl->bv_len; *ptr++ = '\0'; bvl++; } BER_BVZERO(bvl); bvl++; } } return ret; }
/* * Store some statistics for a statement. */ static void pgss_store(const char *query, double total_time, uint64 rows, const BufferUsage *bufusage) { pgssHashKey key; double usage; pgssEntry *entry; Assert(query != NULL); /* Safety check... */ if (!pgss || !pgss_hash) return; /* Set up key for hashtable search */ key.userid = GetUserId(); key.dbid = MyDatabaseId; key.encoding = GetDatabaseEncoding(); key.query_len = strlen(query); if (key.query_len >= pgss->query_size) key.query_len = pg_encoding_mbcliplen(key.encoding, query, key.query_len, pgss->query_size - 1); key.query_ptr = query; usage = USAGE_EXEC(duration); /* Lookup the hash table entry with shared lock. */ LWLockAcquire(pgss->lock, LW_SHARED); entry = (pgssEntry *) hash_search(pgss_hash, &key, HASH_FIND, NULL); if (!entry) { /* Must acquire exclusive lock to add a new entry. */ LWLockRelease(pgss->lock); LWLockAcquire(pgss->lock, LW_EXCLUSIVE); entry = entry_alloc(&key); } /* Grab the spinlock while updating the counters. */ { volatile pgssEntry *e = (volatile pgssEntry *) entry; SpinLockAcquire(&e->mutex); e->counters.calls += 1; e->counters.total_time += total_time; e->counters.rows += rows; e->counters.shared_blks_hit += bufusage->shared_blks_hit; e->counters.shared_blks_read += bufusage->shared_blks_read; e->counters.shared_blks_written += bufusage->shared_blks_written; e->counters.local_blks_hit += bufusage->local_blks_hit; e->counters.local_blks_read += bufusage->local_blks_read; e->counters.local_blks_written += bufusage->local_blks_written; e->counters.temp_blks_read += bufusage->temp_blks_read; e->counters.temp_blks_written += bufusage->temp_blks_written; e->counters.usage += usage; SpinLockRelease(&e->mutex); } LWLockRelease(pgss->lock); }
Entry * str2entry2( char *s, int checkvals ) { int rc; Entry *e; struct berval *type, *vals, *nvals; char *freeval; AttributeDescription *ad, *ad_prev; const char *text; char *next; int attr_cnt; int i, lines; Attribute ahead, *atail; /* * LDIF is used as the string format. * An entry looks like this: * * dn: <dn>\n * [<attr>:[:] <value>\n] * [<tab><continuedvalue>\n]* * ... * * If a double colon is used after a type, it means the * following value is encoded as a base 64 string. This * happens if the value contains a non-printing character * or newline. */ Debug( LDAP_DEBUG_TRACE, "=> str2entry: \"%s\"\n", s ? s : "NULL" ); e = entry_alloc(); if( e == NULL ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (entry allocation failed)\n" ); return( NULL ); } /* initialize entry */ e->e_id = NOID; /* dn + attributes */ atail = &ahead; ahead.a_next = NULL; ad = NULL; ad_prev = NULL; attr_cnt = 0; next = s; lines = ldif_countlines( s ); type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines ); vals = type+lines+1; nvals = vals+lines+1; freeval = (char *)(nvals+lines+1); i = -1; /* parse into individual values, record DN */ while ( (s = ldif_getline( &next )) != NULL ) { int freev; if ( *s == '\n' || *s == '\0' ) { break; } i++; if (i >= lines) { Debug( LDAP_DEBUG_TRACE, "<= str2entry ran past end of entry\n" ); goto fail; } rc = ldif_parse_line2( s, type+i, vals+i, &freev ); freeval[i] = freev; if ( rc ) { Debug( LDAP_DEBUG_TRACE, "<= str2entry NULL (parse_line)\n" ); continue; } if ( bvcasematch( &type[i], &dn_bv ) ) { if ( e->e_dn != NULL ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has multiple DNs \"%s\" and \"%s\"\n", (long) e->e_id, e->e_dn, vals[i].bv_val ); goto fail; } rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has invalid DN \"%s\"\n", (long) e->e_id, vals[i].bv_val ); goto fail; } if ( freeval[i] ) free( vals[i].bv_val ); vals[i].bv_val = NULL; i--; continue; } } lines = i+1; /* check to make sure there was a dn: line */ if ( BER_BVISNULL( &e->e_name )) { Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", (long) e->e_id ); goto fail; } /* Make sure all attributes with multiple values are contiguous */ if ( checkvals ) { int j, k; struct berval bv; int fv; for (i=0; i<lines; i++) { for ( j=i+1; j<lines; j++ ) { if ( bvcasematch( type+i, type+j )) { /* out of order, move intervening attributes down */ if ( j != i+1 ) { bv = vals[j]; fv = freeval[j]; for ( k=j; k>i; k-- ) { type[k] = type[k-1]; vals[k] = vals[k-1]; freeval[k] = freeval[k-1]; } k++; type[k] = type[i]; vals[k] = bv; freeval[k] = fv; } i++; } } } } if ( lines > 0 ) { for ( i=0; i<=lines; i++ ) { ad_prev = ad; if ( !ad || ( i<lines && !bvcasematch( type+i, &ad->ad_cname ))) { ad = NULL; rc = slap_bv2ad( type+i, &ad, &text ); if( rc != LDAP_SUCCESS ) { int wtool = ( slapMode & (SLAP_TOOL_MODE|SLAP_TOOL_READONLY) ) == SLAP_TOOL_MODE; Debug( wtool ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text ); if( wtool ) { goto fail; } rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= str2entry: slap_str2undef_ad(%s): %s\n", type[i].bv_val, text ); goto fail; } } /* require ';binary' when appropriate (ITS#5071) */ if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " "needs ';binary' transfer as per syntax %s\n", ad->ad_cname.bv_val, 0, ad->ad_type->sat_syntax->ssyn_oid ); goto fail; } } if (( ad_prev && ad != ad_prev ) || ( i == lines )) { int j, k; atail->a_next = attr_alloc( NULL ); atail = atail->a_next; atail->a_flags = 0; atail->a_numvals = attr_cnt; atail->a_desc = ad_prev; atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); if( ad_prev->ad_type->sat_equality && ad_prev->ad_type->sat_equality->smr_normalize ) atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); else atail->a_nvals = NULL; k = i - attr_cnt; for ( j=0; j<attr_cnt; j++ ) { if ( freeval[k] ) atail->a_vals[j] = vals[k]; else ber_dupbv( atail->a_vals+j, &vals[k] ); vals[k].bv_val = NULL; if ( atail->a_nvals ) { atail->a_nvals[j] = nvals[k]; nvals[k].bv_val = NULL; } k++; } BER_BVZERO( &atail->a_vals[j] ); if ( atail->a_nvals ) { BER_BVZERO( &atail->a_nvals[j] ); } else { atail->a_nvals = atail->a_vals; } attr_cnt = 0; /* FIXME: we only need this when migrating from an unsorted DB */ if ( atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL ); if ( rc == LDAP_SUCCESS ) { atail->a_flags |= SLAP_ATTR_SORTED_VALS; } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s value #%d provided more than once\n", atail->a_desc->ad_cname.bv_val, j ); goto fail; } } if ( i == lines ) break; } if ( BER_BVISNULL( &vals[i] ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " "no value\n", ad->ad_cname.bv_val, attr_cnt ); goto fail; } if ( ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad, ad->ad_type->sat_equality, &vals[i], &nvals[i], NULL ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (smr_normalize %s %d)\n", ad->ad_cname.bv_val, rc ); goto fail; } } attr_cnt++; } } free( type ); atail->a_next = NULL; e->e_attrs = ahead.a_next; Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long) e ); return( e ); fail: for ( i=0; i<lines; i++ ) { if ( freeval[i] ) free( vals[i].bv_val ); free( nvals[i].bv_val ); } free( type ); entry_free( e ); return NULL; }
static int translucent_pwmod(Operation *op, SlapReply *rs) { SlapReply nrs = { REP_RESULT }; Operation nop; slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; translucent_info *ov = on->on_bi.bi_private; Entry *e = NULL, *re = NULL; BackendDB *db; int rc = 0; slap_callback cb = { 0 }; if (!ov->pwmod_local) { rs->sr_err = LDAP_CONSTRAINT_VIOLATION, rs->sr_text = "attempt to modify password in local database"; return rs->sr_err; } /* ** fetch entry from the captive backend; ** if it did not exist, fail; ** release it, if captive backend supports this; ** */ db = op->o_bd; op->o_bd = &ov->db; ov->db.be_acl = op->o_bd->be_acl; rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re); if(rc != LDAP_SUCCESS || re == NULL ) { send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT, "attempt to modify nonexistent local record"); return(rs->sr_err); } op->o_bd = db; /* ** fetch entry from local backend; ** if it exists: ** return CONTINUE; */ op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e); op->o_bd->bd_info = (BackendInfo *) on; if(e && rc == LDAP_SUCCESS) { if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else { entry_free(re); } } op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; be_entry_release_r(op, e); op->o_bd->bd_info = (BackendInfo *) on; return SLAP_CB_CONTINUE; } /* don't leak remote entry copy */ if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else { entry_free(re); } } /* ** glue_parent() for this Entry; ** call bi_op_add() in local backend; ** */ e = entry_alloc(); ber_dupbv( &e->e_name, &op->o_req_dn ); ber_dupbv( &e->e_nname, &op->o_req_ndn ); e->e_attrs = NULL; nop = *op; nop.o_tag = LDAP_REQ_ADD; cb.sc_response = slap_null_cb; nop.oq_add.rs_e = e; glue_parent(&nop); nop.o_callback = &cb; rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs); if ( nop.ora_e == e ) { entry_free( e ); } if ( rc == LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } return rc; }
static int translucent_modify(Operation *op, SlapReply *rs) { SlapReply nrs = { REP_RESULT }; slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; translucent_info *ov = on->on_bi.bi_private; Entry *e = NULL, *re = NULL; Attribute *a, *ax; Modifications *m, **mm; BackendDB *db; int del, rc, erc = 0; slap_callback cb = { 0 }; Debug(LDAP_DEBUG_TRACE, "==> translucent_modify: %s\n", op->o_req_dn.bv_val, 0, 0); if(ov->defer_db_open) { send_ldap_error(op, rs, LDAP_UNAVAILABLE, "remote DB not available"); return(rs->sr_err); } /* ** fetch entry from the captive backend; ** if it did not exist, fail; ** release it, if captive backend supports this; ** */ db = op->o_bd; op->o_bd = &ov->db; ov->db.be_acl = op->o_bd->be_acl; rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re); op->o_bd = db; if(rc != LDAP_SUCCESS || re == NULL ) { send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT, "attempt to modify nonexistent local record"); return(rs->sr_err); } /* ** fetch entry from local backend; ** if it exists: ** foreach Modification: ** if attr not present in local: ** if Mod == LDAP_MOD_DELETE: ** if remote attr not present, return NO_SUCH; ** if remote attr present, drop this Mod; ** else force this Mod to LDAP_MOD_ADD; ** return CONTINUE; ** */ op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e); op->o_bd->bd_info = (BackendInfo *) on; if(e && rc == LDAP_SUCCESS) { Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: found local entry\n", 0, 0, 0); for(mm = &op->orm_modlist; *mm; ) { m = *mm; for(a = e->e_attrs; a; a = a->a_next) if(a->a_desc == m->sml_desc) break; if(a) { mm = &m->sml_next; continue; /* found local attr */ } if(m->sml_op == LDAP_MOD_DELETE) { for(a = re->e_attrs; a; a = a->a_next) if(a->a_desc == m->sml_desc) break; /* not found remote attr */ if(!a) { erc = LDAP_NO_SUCH_ATTRIBUTE; goto release; } if(ov->strict) { erc = LDAP_CONSTRAINT_VIOLATION; goto release; } Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: silently dropping delete: %s\n", m->sml_desc->ad_cname.bv_val, 0, 0); *mm = m->sml_next; m->sml_next = NULL; slap_mods_free(m, 1); continue; } m->sml_op = LDAP_MOD_ADD; mm = &m->sml_next; } erc = SLAP_CB_CONTINUE; release: if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else entry_free(re); } op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; be_entry_release_r(op, e); op->o_bd->bd_info = (BackendInfo *) on; if(erc == SLAP_CB_CONTINUE) { return(erc); } else if(erc) { send_ldap_error(op, rs, erc, "attempt to delete nonexistent attribute"); return(erc); } } /* don't leak remote entry copy */ if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else entry_free(re); } /* ** foreach Modification: ** if MOD_ADD or MOD_REPLACE, add Attribute; ** if no Modifications were suitable: ** if strict, throw CONSTRAINT_VIOLATION; ** else, return early SUCCESS; ** fabricate Entry with new Attribute chain; ** glue_parent() for this Entry; ** call bi_op_add() in local backend; ** */ Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: fabricating local add\n", 0, 0, 0); a = NULL; for(del = 0, ax = NULL, m = op->orm_modlist; m; m = m->sml_next) { Attribute atmp; if(((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_ADD) && ((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)) { Debug(LDAP_DEBUG_ANY, "=> translucent_modify: silently dropped modification(%d): %s\n", m->sml_op, m->sml_desc->ad_cname.bv_val, 0); if((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) del++; continue; } atmp.a_desc = m->sml_desc; atmp.a_vals = m->sml_values; atmp.a_nvals = m->sml_nvalues ? m->sml_nvalues : atmp.a_vals; atmp.a_numvals = m->sml_numvals; atmp.a_flags = 0; a = attr_dup( &atmp ); a->a_next = ax; ax = a; } if(del && ov->strict) { attrs_free( a ); send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to delete attributes from local database"); return(rs->sr_err); } if(!ax) { if(ov->strict) { send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "modification contained other than ADD or REPLACE"); return(rs->sr_err); } /* rs->sr_text = "no valid modification found"; */ rs->sr_err = LDAP_SUCCESS; send_ldap_result(op, rs); return(rs->sr_err); } e = entry_alloc(); ber_dupbv( &e->e_name, &op->o_req_dn ); ber_dupbv( &e->e_nname, &op->o_req_ndn ); e->e_attrs = a; op->o_tag = LDAP_REQ_ADD; cb.sc_response = translucent_tag_cb; cb.sc_private = op->orm_modlist; op->oq_add.rs_e = e; glue_parent(op); cb.sc_next = op->o_callback; op->o_callback = &cb; rc = on->on_info->oi_orig->bi_op_add(op, &nrs); if ( op->ora_e == e ) entry_free( e ); op->o_callback = cb.sc_next; return(rc); }
/* return 0 IFF we can retrieve the entry with ndn */ int ldap_back_entry_get( Operation *op, struct berval *ndn, ObjectClass *oc, AttributeDescription *at, int rw, Entry **ent ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = NULL; int rc, do_not_cache; ber_tag_t tag; struct berval bdn; LDAPMessage *result = NULL, *e = NULL; char *attr[3], **attrp = NULL; char *filter = NULL; SlapReply rs; int do_retry = 1; LDAPControl **ctrls = NULL; *ent = NULL; /* Tell getconn this is a privileged op */ do_not_cache = op->o_do_not_cache; tag = op->o_tag; /* do not cache */ op->o_do_not_cache = 1; /* ldap_back_entry_get() is an entry lookup, so it does not need * to know what the entry is being looked up for */ op->o_tag = LDAP_REQ_SEARCH; rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND ); op->o_do_not_cache = do_not_cache; op->o_tag = tag; if ( !rc ) { return rs.sr_err; } if ( at ) { attrp = attr; if ( oc && at != slap_schema.si_ad_objectClass ) { attr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val; attr[1] = at->ad_cname.bv_val; attr[2] = NULL; } else { attr[0] = at->ad_cname.bv_val; attr[1] = NULL; } } if ( oc ) { char *ptr; filter = op->o_tmpalloc( STRLENOF( "(objectClass=" ")" ) + oc->soc_cname.bv_len + 1, op->o_tmpmemctx ); ptr = lutil_strcopy( filter, "(objectClass=" ); ptr = lutil_strcopy( ptr, oc->soc_cname.bv_val ); *ptr++ = ')'; *ptr++ = '\0'; } retry: ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, &rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { goto cleanup; } /* TODO: timeout? */ rc = ldap_pvt_search_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter, attrp, LDAP_DEREF_NEVER, ctrls, NULL, NULL, LDAP_NO_LIMIT, 0, &result ); if ( rc != LDAP_SUCCESS ) { if ( rc == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, &rs, &ctrls ); goto retry; } } goto cleanup; } e = ldap_first_entry( lc->lc_ld, result ); if ( e == NULL ) { /* the entry exists, but it doesn't match the filter? */ goto cleanup; } *ent = entry_alloc(); if ( *ent == NULL ) { rc = LDAP_NO_MEMORY; goto cleanup; } rc = ldap_build_entry( op, e, *ent, &bdn ); if ( rc != LDAP_SUCCESS ) { entry_free( *ent ); *ent = NULL; } cleanup: (void)ldap_back_controls_free( op, &rs, &ctrls ); if ( result ) { ldap_msgfree( result ); } if ( filter ) { op->o_tmpfree( filter, op->o_tmpmemctx ); } if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
static int parse_dir (inode_build_t * grand_parent_inode, inode_build_t * parent_inode, char * parent_path) { int err; DIR * parent_dir = NULL; while (1) { parent_dir = opendir (parent_path); if (!parent_dir) { err = errno; break; } while (1) { struct dirent * ent = readdir (parent_dir); if (!ent) { err = errno; break; } char * name = ent->d_name; entry_build_t * child_ent = entry_alloc (parent_inode, name); if (!child_ent) { err = -1; break; } char * child_path = malloc (strlen (parent_path) + 1 + strlen (name) + 1); strcpy (child_path, parent_path); strcat (child_path, "/"); strcat (child_path, name); if (!strcmp (name, ".")) { printf ("Pseudo: %s\n", child_path); child_ent->inode = parent_inode; } else if (!strcmp (name, "..")) { printf ("Pseudo: %s\n", child_path); if (grand_parent_inode) child_ent->inode = grand_parent_inode; else child_ent->inode = parent_inode; /* self for root */ } else { inode_build_t * child_inode = inode_alloc (parent_inode, child_path); if (!child_inode) { err = -1; break; } child_ent->inode = child_inode; struct stat child_stat; err = lstat (child_path, &child_stat); if (err) { err = errno; break; } if (S_ISREG (child_stat.st_mode)) { printf ("File: %s\n", child_path); child_inode->flags = INODE_FILE; child_inode->size = child_stat.st_size; } else if (S_ISDIR (child_stat.st_mode)) { printf ("Dir: %s\n", child_path); child_inode->flags = INODE_DIR; err = parse_dir (parent_inode, child_inode, child_path); if (err) break; } else { assert (0); } } if (child_path) free (child_path); } if (err != 0) { perror ("Read directory"); } break; } if (parent_dir) closedir (parent_dir); return err; }
int schema_info( Entry **entry, const char **text ) { AttributeDescription *ad_structuralObjectClass = slap_schema.si_ad_structuralObjectClass; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_createTimestamp = slap_schema.si_ad_createTimestamp; AttributeDescription *ad_modifyTimestamp = slap_schema.si_ad_modifyTimestamp; Entry *e; struct berval vals[5]; struct berval nvals[5]; e = entry_alloc(); if( e == NULL ) { /* Out of memory, do something about it */ Debug( LDAP_DEBUG_ANY, "schema_info: entry_alloc failed - out of memory.\n", 0, 0, 0 ); *text = "out of memory"; return LDAP_OTHER; } e->e_attrs = NULL; /* backend-specific schema info should be created by the * backend itself */ ber_dupbv( &e->e_name, &frontendDB->be_schemadn ); ber_dupbv( &e->e_nname, &frontendDB->be_schemandn ); e->e_private = NULL; BER_BVSTR( &vals[0], "subentry" ); if( attr_merge_one( e, ad_structuralObjectClass, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } BER_BVSTR( &vals[0], "top" ); BER_BVSTR( &vals[1], "subentry" ); BER_BVSTR( &vals[2], "subschema" ); BER_BVSTR( &vals[3], "extensibleObject" ); BER_BVZERO( &vals[4] ); if ( attr_merge( e, ad_objectClass, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } { int rc; AttributeDescription *desc = NULL; struct berval rdn = frontendDB->be_schemadn; vals[0].bv_val = ber_bvchr( &rdn, '=' ); if( vals[0].bv_val == NULL ) { *text = "improperly configured subschema subentry"; return LDAP_OTHER; } vals[0].bv_val++; vals[0].bv_len = rdn.bv_len - (vals[0].bv_val - rdn.bv_val); rdn.bv_len -= vals[0].bv_len + 1; rc = slap_bv2ad( &rdn, &desc, text ); if( rc != LDAP_SUCCESS ) { entry_free( e ); *text = "improperly configured subschema subentry"; return LDAP_OTHER; } nvals[0].bv_val = ber_bvchr( &frontendDB->be_schemandn, '=' ); assert( nvals[0].bv_val != NULL ); nvals[0].bv_val++; nvals[0].bv_len = frontendDB->be_schemandn.bv_len - (nvals[0].bv_val - frontendDB->be_schemandn.bv_val); if ( attr_merge_one( e, desc, vals, nvals ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } } { char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; /* * According to RFC 4512: Servers SHOULD maintain the 'creatorsName', 'createTimestamp', 'modifiersName', and 'modifyTimestamp' attributes for all entries of the DIT. * to be conservative, we declare schema created * AND modified at server startup time ... */ vals[0].bv_val = timebuf; vals[0].bv_len = sizeof( timebuf ); slap_timestamp( &starttime, vals ); if( attr_merge_one( e, ad_createTimestamp, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } if( attr_merge_one( e, ad_modifyTimestamp, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } } if ( syn_schema_info( e ) || mr_schema_info( e ) || mru_schema_info( e ) || at_schema_info( e ) || oc_schema_info( e ) || cr_schema_info( e ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } *entry = e; return LDAP_SUCCESS; }
/* * shmem_startup hook: allocate or attach to shared memory, * then load any pre-existing statistics from file. */ static void pgss_shmem_startup(void) { bool found; HASHCTL info; FILE *file; uint32 header; int32 num; int32 i; int query_size; int buffer_size; char *buffer = NULL; if (prev_shmem_startup_hook) prev_shmem_startup_hook(); /* reset in case this is a restart within the postmaster */ pgss = NULL; pgss_hash = NULL; /* * Create or attach to the shared memory state, including hash table */ LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); pgss = ShmemInitStruct("pg_stat_statements", sizeof(pgssSharedState), &found); if (!found) { /* First time through ... */ pgss->lock = LWLockAssign(); pgss->query_size = pgstat_track_activity_query_size; } /* Be sure everyone agrees on the hash table entry size */ query_size = pgss->query_size; memset(&info, 0, sizeof(info)); info.keysize = sizeof(pgssHashKey); info.entrysize = offsetof(pgssEntry, query) +query_size; info.hash = pgss_hash_fn; info.match = pgss_match_fn; pgss_hash = ShmemInitHash("pg_stat_statements hash", pgss_max, pgss_max, &info, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE); LWLockRelease(AddinShmemInitLock); /* * If we're in the postmaster (or a standalone backend...), set up a shmem * exit hook to dump the statistics to disk. */ if (!IsUnderPostmaster) on_shmem_exit(pgss_shmem_shutdown, (Datum) 0); /* * Attempt to load old statistics from the dump file, if this is the first * time through and we weren't told not to. */ if (found || !pgss_save) return; /* * Note: we don't bother with locks here, because there should be no other * processes running when this code is reached. */ file = AllocateFile(PGSS_DUMP_FILE, PG_BINARY_R); if (file == NULL) { if (errno == ENOENT) return; /* ignore not-found error */ goto error; } buffer_size = query_size; buffer = (char *) palloc(buffer_size); if (fread(&header, sizeof(uint32), 1, file) != 1 || header != PGSS_FILE_HEADER || fread(&num, sizeof(int32), 1, file) != 1) goto error; for (i = 0; i < num; i++) { pgssEntry temp; pgssEntry *entry; if (fread(&temp, offsetof(pgssEntry, mutex), 1, file) != 1) goto error; /* Encoding is the only field we can easily sanity-check */ if (!PG_VALID_BE_ENCODING(temp.key.encoding)) goto error; /* Previous incarnation might have had a larger query_size */ if (temp.key.query_len >= buffer_size) { buffer = (char *) repalloc(buffer, temp.key.query_len + 1); buffer_size = temp.key.query_len + 1; } if (fread(buffer, 1, temp.key.query_len, file) != temp.key.query_len) goto error; buffer[temp.key.query_len] = '\0'; /* Clip to available length if needed */ if (temp.key.query_len >= query_size) temp.key.query_len = pg_encoding_mbcliplen(temp.key.encoding, buffer, temp.key.query_len, query_size - 1); temp.key.query_ptr = buffer; /* make the hashtable entry (discards old entries if too many) */ entry = entry_alloc(&temp.key); /* copy in the actual stats */ entry->counters = temp.counters; } pfree(buffer); FreeFile(file); return; error: ereport(LOG, (errcode_for_file_access(), errmsg("could not read pg_stat_statement file \"%s\": %m", PGSS_DUMP_FILE))); if (buffer) pfree(buffer); if (file) FreeFile(file); /* If possible, throw away the bogus file; ignore any error */ unlink(PGSS_DUMP_FILE); }
int entry_decode(EntryHeader *eh, Entry **e) #endif { int i, j, nattrs, nvals ALLOW_UNUSED; int rc; Attribute *a; Entry *x; const char *text; AttributeDescription *ad; unsigned char *ptr = (unsigned char *)eh->bv.bv_val; BerVarray bptr; nattrs = eh->nattrs; nvals = eh->nvals; x = entry_alloc(); x->e_attrs = attrs_alloc( nattrs ); ptr = (unsigned char *)eh->data; i = entry_getlen(&ptr); x->e_name.bv_val = (char *) ptr; x->e_name.bv_len = i; ptr += i+1; i = entry_getlen(&ptr); x->e_nname.bv_val = (char *) ptr; x->e_nname.bv_len = i; ptr += i+1; Debug( LDAP_DEBUG_TRACE, "entry_decode: \"%s\"\n", x->e_dn ); x->e_bv = eh->bv; a = x->e_attrs; bptr = (BerVarray)eh->bv.bv_val; while ((i = entry_getlen(&ptr))) { struct berval bv; bv.bv_len = i; bv.bv_val = (char *) ptr; ad = NULL; rc = slap_bv2ad( &bv, &ad, &text ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "<= entry_decode: str2ad(%s): %s\n", ptr, text ); rc = slap_bv2undef_ad( &bv, &ad, &text, 0 ); if( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= entry_decode: slap_str2undef_ad(%s): %s\n", ptr, text ); return rc; } } ptr += i + 1; a->a_desc = ad; a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; j = entry_getlen(&ptr); a->a_numvals = j; a->a_vals = bptr; while (j) { i = entry_getlen(&ptr); bptr->bv_len = i; bptr->bv_val = (char *)ptr; ptr += i+1; bptr++; j--; } bptr->bv_val = NULL; bptr->bv_len = 0; bptr++; j = entry_getlen(&ptr); if (j) { a->a_nvals = bptr; while (j) { i = entry_getlen(&ptr); bptr->bv_len = i; bptr->bv_val = (char *)ptr; ptr += i+1; bptr++; j--; } bptr->bv_val = NULL; bptr->bv_len = 0; bptr++; } else { a->a_nvals = a->a_vals; } /* FIXME: This is redundant once a sorted entry is saved into the DB */ if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL ); if ( rc == LDAP_SUCCESS ) { a->a_flags |= SLAP_ATTR_SORTED_VALS; } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { /* should never happen */ Debug( LDAP_DEBUG_ANY, "entry_decode: attributeType %s value #%d provided more than once\n", a->a_desc->ad_cname.bv_val, j ); return rc; } } a = a->a_next; nattrs--; if ( !nattrs ) break; } Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n", x->e_dn ); *e = x; return 0; }
/* * Read the entries specified in fname and merge the attributes * to the user defined baseObject entry. Note that if we find any errors * what so ever, we will discard the entire entries, print an * error message and return. */ static int read_baseObject( BackendDB *be, const char *fname ) { backsql_info *bi = (backsql_info *)be->be_private; LDIFFP *fp; int rc = 0, lmax = 0, ldifrc; unsigned long lineno = 0; char *buf = NULL; assert( fname != NULL ); fp = ldif_open( fname, "r" ); if ( fp == NULL ) { Debug( LDAP_DEBUG_ANY, "could not open back-sql baseObject " "attr file \"%s\" - absolute path?\n", fname, 0, 0 ); perror( fname ); return LDAP_OTHER; } bi->sql_baseObject = entry_alloc(); if ( bi->sql_baseObject == NULL ) { Debug( LDAP_DEBUG_ANY, "read_baseObject_file: entry_alloc failed", 0, 0, 0 ); ldif_close( fp ); return LDAP_NO_MEMORY; } bi->sql_baseObject->e_name = be->be_suffix[0]; bi->sql_baseObject->e_nname = be->be_nsuffix[0]; bi->sql_baseObject->e_attrs = NULL; while (( ldifrc = ldif_read_record( fp, &lineno, &buf, &lmax )) > 0 ) { Entry *e = str2entry( buf ); Attribute *a; if( e == NULL ) { fprintf( stderr, "back-sql baseObject: " "could not parse entry (line=%lu)\n", lineno ); rc = LDAP_OTHER; break; } /* make sure the DN is the database's suffix */ if ( !be_issuffix( be, &e->e_nname ) ) { fprintf( stderr, "back-sql: invalid baseObject - " "dn=\"%s\" (line=%lu)\n", e->e_name.bv_val, lineno ); entry_free( e ); rc = LDAP_OTHER; break; } /* * we found a valid entry, so walk thru all the attributes in the * entry, and add each attribute type and description to baseObject */ for ( a = e->e_attrs; a != NULL; a = a->a_next ) { if ( attr_merge( bi->sql_baseObject, a->a_desc, a->a_vals, ( a->a_nvals == a->a_vals ) ? NULL : a->a_nvals ) ) { rc = LDAP_OTHER; break; } } entry_free( e ); if ( rc ) { break; } } if ( ldifrc < 0 ) rc = LDAP_OTHER; if ( rc ) { entry_free( bi->sql_baseObject ); bi->sql_baseObject = NULL; } ch_free( buf ); ldif_close( fp ); Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n", fname, 0, 0 ); return rc; }
Entry * entry_dup( Entry *e ) { return entry_dup2( entry_alloc(), e ); }