+/* Cleanup loose ends after Modify completes */
+static int
+bdb_cf_cleanup( ConfigArgs *c )
+{
+ struct bdb_info *bdb = c->be->be_private;
+ int rc = 0;
+
+ if ( bdb->bi_flags & BDB_UPD_CONFIG ) {
+ if ( bdb->bi_db_config ) {
+ int i;
+ FILE *f = fopen( bdb->bi_db_config_path, "w" );
+ if ( f ) {
+ for (i=0; bdb->bi_db_config[i].bv_val; i++)
+ fprintf( f, "%s\n", bdb->bi_db_config[i].bv_val );
+ fclose( f );
+ }
+ } else {
+ unlink( bdb->bi_db_config_path );
+ }
+ bdb->bi_flags ^= BDB_UPD_CONFIG;
+ }
+
+ if ( bdb->bi_flags & BDB_DEL_INDEX ) {
+ bdb_attr_flush( bdb );
+ bdb->bi_flags ^= BDB_DEL_INDEX;
+ }
+
+ if ( bdb->bi_flags & BDB_RE_OPEN ) {
+ bdb->bi_flags ^= BDB_RE_OPEN;
+ rc = c->be->bd_info->bi_db_close( c->be, &c->reply );
+ if ( rc == 0 )
+ rc = c->be->bd_info->bi_db_open( c->be, &c->reply );
+ /* If this fails, we need to restart */
+ if ( rc ) {
+ slapd_shutdown = 2;
+ snprintf( c->cr_msg, sizeof( c->cr_msg ),
+ "failed to reopen database, rc=%d", rc );
+ Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_cf_cleanup)
+ ": %s\n", c->cr_msg, 0, 0 );
+ rc = LDAP_OTHER;
+ }
+ }
+ return rc;
+}
+
+static int
+bdb_cf_gen( ConfigArgs *c )
+{
+ struct bdb_info *bdb = c->be->be_private;
+ int rc;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ rc = 0;
+ switch( c->type ) {
+ case BDB_MODE: {
+ char buf[64];
+ struct berval bv;
+ bv.bv_len = snprintf( buf, sizeof(buf), "0%o", bdb->bi_dbenv_mode );
+ if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
+ bv.bv_val = buf;
+ value_add_one( &c->rvalue_vals, &bv );
+ } else {
+ rc = 1;
+ }
+ } break;
+
+ case BDB_CHKPT:
+ if ( bdb->bi_txn_cp ) {
+ char buf[64];
+ struct berval bv;
+ bv.bv_len = snprintf( buf, sizeof(buf), "%d %d", bdb->bi_txn_cp_kbyte,
+ bdb->bi_txn_cp_min );
+ if ( bv.bv_len > 0 && bv.bv_len < sizeof(buf) ) {
+ bv.bv_val = buf;
+ value_add_one( &c->rvalue_vals, &bv );
+ } else {
+ rc = 1;
+ }
+ } else {
+ rc = 1;
+ }
+ break;
+
+ case BDB_CRYPTFILE:
+ if ( bdb->bi_db_crypt_file ) {
+ c->value_string = ch_strdup( bdb->bi_db_crypt_file );
+ } else {
+ rc = 1;
+ }
+ break;
+
+ /* If a crypt file has been set, its contents are copied here.
+ * But we don't want the key to be incorporated here.
+ */
+ case BDB_CRYPTKEY:
+ if ( !bdb->bi_db_crypt_file && !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
+ value_add_one( &c->rvalue_vals, &bdb->bi_db_crypt_key );
+ } else {
+ rc = 1;
+ }
+ break;
+
+ case BDB_DIRECTORY:
+ if ( bdb->bi_dbenv_home ) {
+ c->value_string = ch_strdup( bdb->bi_dbenv_home );
+ } else {
+ rc = 1;
+ }
+ break;
+
+ case BDB_CONFIG:
+ if ( !( bdb->bi_flags & BDB_IS_OPEN )
+ && !bdb->bi_db_config )
+ {
+ char buf[SLAP_TEXT_BUFLEN];
+ FILE *f = fopen( bdb->bi_db_config_path, "r" );
+ struct berval bv;
+
+ if ( f ) {
+ bdb->bi_flags |= BDB_HAS_CONFIG;
+ while ( fgets( buf, sizeof(buf), f )) {
+ ber_str2bv( buf, 0, 1, &bv );
+ if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\n' ) {
+ bv.bv_len--;
+ bv.bv_val[bv.bv_len] = '\0';
+ }
+ /* shouldn't need this, but ... */
+ if ( bv.bv_len > 0 && bv.bv_val[bv.bv_len-1] == '\r' ) {
+ bv.bv_len--;
+ bv.bv_val[bv.bv_len] = '\0';
+ }
+ ber_bvarray_add( &bdb->bi_db_config, &bv );
+ }
+ fclose( f );
+ }
+ }
+ if ( bdb->bi_db_config ) {
+ int i;
+ struct berval bv;
+
+ bv.bv_val = c->log;
+ for (i=0; !BER_BVISNULL(&bdb->bi_db_config[i]); i++) {
+ bv.bv_len = sprintf( bv.bv_val, "{%d}%s", i,
+ bdb->bi_db_config[i].bv_val );
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ }
+ if ( !c->rvalue_vals ) rc = 1;
+ break;
+
+ case BDB_NOSYNC:
+ if ( bdb->bi_dbenv_xflags & DB_TXN_NOSYNC )
+ c->value_int = 1;
+ break;
+
+ case BDB_CHECKSUM:
+ if ( bdb->bi_flags & BDB_CHKSUM )
+ c->value_int = 1;
+ break;
+
+ case BDB_INDEX:
+ bdb_attr_index_unparse( bdb, &c->rvalue_vals );
+ if ( !c->rvalue_vals ) rc = 1;
+ break;
+
+ case BDB_LOCKD:
+ rc = 1;
+ if ( bdb->bi_lock_detect != DB_LOCK_DEFAULT ) {
+ int i;
+ for (i=0; !BER_BVISNULL(&bdb_lockd[i].word); i++) {
+ if ( bdb->bi_lock_detect == bdb_lockd[i].mask ) {
+ value_add_one( &c->rvalue_vals, &bdb_lockd[i].word );
+ rc = 0;
+ break;
+ }
+ }
+ }
+ break;
+
+ case BDB_SSTACK:
+ c->value_int = bdb->bi_search_stack_depth;
+ break;
+
+ case BDB_PGSIZE: {
+ struct bdb_db_pgsize *ps;
+ char buf[SLAP_TEXT_BUFLEN];
+ struct berval bv;
+ int rc = 1;
+
+ bv.bv_val = buf;
+ for ( ps = bdb->bi_pagesizes; ps; ps = ps->bdp_next ) {
+ bv.bv_len = sprintf( buf, "%s %d", ps->bdp_name.bv_val,
+ ps->bdp_size / 1024 );
+ value_add_one( &c->rvalue_vals, &bv );
+ rc = 0;
+
+ }
+ break;
+ }
+ }
+ return rc;
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ rc = 0;
+ switch( c->type ) {
+ case BDB_MODE:
+#if 0
+ /* FIXME: does it make any sense to change the mode,
+ * if we don't exec a chmod()? */
+ bdb->bi_dbenv_mode = SLAPD_DEFAULT_DB_MODE;
+ break;
+#endif