#include "config.h"
-static struct berval config_rdn = BER_BVC("cn=config");
-static struct berval schema_rdn = BER_BVC("cn=schema");
+#define CONFIG_RDN "cn=config"
+#define SCHEMA_RDN "cn=schema"
+
+static struct berval config_rdn = BER_BVC(CONFIG_RDN);
+static struct berval schema_rdn = BER_BVC(SCHEMA_RDN);
extern int slap_DN_strict; /* dn.c */
int cb_use_ldif;
} CfBackInfo;
+static CfBackInfo cfBackInfo;
+
static char *passwd_salt;
static char *logfileName;
#ifdef SLAP_AUTH_REWRITE
/* Private state */
static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
- *cfAd_include;
+ *cfAd_include, *cfAd_attr, *cfAd_oc, *cfAd_om;
static ConfigFile *cfn;
static Avlnode *CfOcTree;
+/* System schema state */
+extern AttributeType *at_sys_tail; /* at.c */
+extern ObjectClass *oc_sys_tail; /* oc.c */
+extern OidMacro *om_sys_tail; /* oidm.c */
+static AttributeType *cf_at_tail;
+static ObjectClass *cf_oc_tail;
+static OidMacro *cf_om_tail;
+
static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
SlapReply *rs, int *renumber, Operation *op );
+static int config_check_schema( CfBackInfo *cfb );
+
static ConfigDriver config_fname;
static ConfigDriver config_cfdir;
static ConfigDriver config_generic;
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "attribute", "attribute", 2, 0, STRLENOF( "attribute" ),
- ARG_PAREN|ARG_MAGIC|CFG_ATTR|ARG_NO_DELETE|ARG_NO_INSERT,
+ ARG_PAREN|ARG_MAGIC|CFG_ATTR,
&config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' "
"DESC 'OpenLDAP attributeTypes' "
"EQUALITY caseIgnoreMatch "
ARG_MAGIC|CFG_MONITORING|ARG_DB|ARG_ON_OFF, &config_generic,
"( OLcfgDbAt:0.18 NAME 'olcMonitoring' "
"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
- { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC|ARG_NO_DELETE|ARG_NO_INSERT,
+ { "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC,
&config_generic, "( OLcfgGlAt:32 NAME 'olcObjectClasses' "
"DESC 'OpenLDAP object classes' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
NULL, NULL },
- { "objectidentifier", NULL, 0, 0, 0, ARG_MAGIC|CFG_OID,
+ { "objectidentifier", "name> <oid", 3, 3, 0, ARG_MAGIC|CFG_OID,
&config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
static int
config_generic(ConfigArgs *c) {
- char *p;
int i;
if ( c->op == SLAP_CONFIG_EMIT ) {
}
break;
+ case CFG_OC: {
+ CfEntryInfo *ce = c->ca_entry->e_private;
+ /* can't modify the hardcoded schema */
+ if ( ce->ce_parent->ce_type == Cft_Global )
+ return 1;
+ }
+ cfn = c->private;
+ if ( c->valx < 0 ) {
+ ObjectClass *oc;
+
+ for( oc = cfn->c_oc_head; oc; oc_next( &oc )) {
+ oc_delete( oc );
+ if ( oc == cfn->c_oc_tail )
+ break;
+ }
+ cfn->c_oc_head = cfn->c_oc_tail = NULL;
+ } else {
+ ObjectClass *oc, *prev = NULL;
+ int i;
+
+ for ( i=0, oc=cfn->c_oc_head; i<c->valx; i++) {
+ prev = oc;
+ oc_next( &oc );
+ }
+ oc_delete( oc );
+ if ( cfn->c_oc_tail == oc ) {
+ cfn->c_oc_tail = prev;
+ }
+ if ( cfn->c_oc_head == oc ) {
+ oc_next( &oc );
+ cfn->c_oc_head = oc;
+ }
+ }
+ break;
+
+ case CFG_ATTR: {
+ CfEntryInfo *ce = c->ca_entry->e_private;
+ /* can't modify the hardcoded schema */
+ if ( ce->ce_parent->ce_type == Cft_Global )
+ return 1;
+ }
+ cfn = c->private;
+ if ( c->valx < 0 ) {
+ AttributeType *at;
+
+ for( at = cfn->c_at_head; at; at_next( &at )) {
+ at_delete( at );
+ if ( at == cfn->c_at_tail )
+ break;
+ }
+ cfn->c_at_head = cfn->c_at_tail = NULL;
+ } else {
+ AttributeType *at, *prev = NULL;
+ int i;
+
+ for ( i=0, at=cfn->c_at_head; i<c->valx; i++) {
+ prev = at;
+ at_next( &at );
+ }
+ at_delete( at );
+ if ( cfn->c_at_tail == at ) {
+ cfn->c_at_tail = prev;
+ }
+ if ( cfn->c_at_head == at ) {
+ at_next( &at );
+ cfn->c_at_head = at;
+ }
+ }
+ break;
+
case CFG_LIMITS:
/* FIXME: there is no limits_free function */
case CFG_ATOPT:
/* FIXME: there is no way to remove attributes added by
a DSE file */
case CFG_OID:
- case CFG_OC:
case CFG_DIT:
- case CFG_ATTR:
case CFG_MODPATH:
default:
rc = 1;
return rc;
}
- p = strchr(c->line,'(' /*')'*/);
-
switch(c->type) {
case CFG_BACKEND:
if(!(c->bi = backend_info(c->argv[1]))) {
} else if ( !strcasecmp( c->argv[1], "frontend" )) {
c->be = frontendDB;
} else {
- c->be = backend_db_init(c->argv[1], NULL);
+ c->be = backend_db_init(c->argv[1], NULL, c->valx);
if ( !c->be ) {
snprintf( c->msg, sizeof( c->msg ), "<%s> failed init", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
case CFG_OID: {
OidMacro *om;
- if(parse_oidm(c->fname, c->lineno, c->argc, c->argv, 1, &om))
+ if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
+ cfn = c->private;
+ if(parse_oidm(c, 1, &om))
return(1);
if (!cfn->c_om_head) cfn->c_om_head = om;
cfn->c_om_tail = om;
break;
case CFG_OC: {
- ObjectClass *oc;
+ ObjectClass *oc, *prev;
- if(parse_oc(c->fname, c->lineno, p, c->argv, &oc)) return(1);
+ if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
+ cfn = c->private;
+ if ( c->valx < 0 ) {
+ prev = cfn->c_oc_tail;
+ } else {
+ prev = NULL;
+ /* If adding anything after the first, prev is easy */
+ if ( c->valx ) {
+ int i;
+ for (i=0, oc = cfn->c_oc_head; i<c->valx; i++) {
+ prev = oc;
+ oc_next( &oc );
+ }
+ } else
+ /* If adding the first, and head exists, find its prev */
+ if (cfn->c_oc_head) {
+ for ( oc_start( &oc ); oc != cfn->c_oc_head; ) {
+ prev = oc;
+ oc_next( &oc );
+ }
+ }
+ /* else prev is NULL, append to end of global list */
+ }
+ if(parse_oc(c, &oc, prev)) return(1);
if (!cfn->c_oc_head) cfn->c_oc_head = oc;
- cfn->c_oc_tail = oc;
+ if (cfn->c_oc_tail == prev) cfn->c_oc_tail = oc;
}
break;
- case CFG_DIT: {
- ContentRule *cr;
+ case CFG_ATTR: {
+ AttributeType *at, *prev;
- if(parse_cr(c->fname, c->lineno, p, c->argv, &cr)) return(1);
- if (!cfn->c_cr_head) cfn->c_cr_head = cr;
- cfn->c_cr_tail = cr;
+ if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
+ cfn = c->private;
+ if ( c->valx < 0 ) {
+ prev = cfn->c_at_tail;
+ } else {
+ prev = NULL;
+ /* If adding anything after the first, prev is easy */
+ if ( c->valx ) {
+ int i;
+ for (i=0, at = cfn->c_at_head; i<c->valx; i++) {
+ prev = at;
+ at_next( &at );
+ }
+ } else
+ /* If adding the first, and head exists, find its prev */
+ if (cfn->c_at_head) {
+ for ( at_start( &at ); at != cfn->c_at_head; ) {
+ prev = at;
+ at_next( &at );
+ }
+ }
+ /* else prev is NULL, append to end of global list */
+ }
+ if(parse_at(c, &at, prev)) return(1);
+ if (!cfn->c_at_head) cfn->c_at_head = at;
+ if (cfn->c_at_tail == prev) cfn->c_at_tail = at;
}
break;
- case CFG_ATTR: {
- AttributeType *at;
+ case CFG_DIT: {
+ ContentRule *cr;
- if(parse_at(c->fname, c->lineno, p, c->argv, &at)) return(1);
- if (!cfn->c_at_head) cfn->c_at_head = at;
- cfn->c_at_tail = at;
+ if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
+ cfn = c->private;
+ if(parse_cr(c, &cr)) return(1);
+ if (!cfn->c_cr_head) cfn->c_cr_head = cr;
+ cfn->c_cr_tail = cr;
}
break;
break;
case CFG_ROOTDSE:
- if(read_root_dse_file(c->argv[1])) {
+ if(root_dse_read_file(c->argv[1])) {
snprintf( c->msg, sizeof( c->msg ), "<%s> could not read file", c->argv[0] );
Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
c->log, c->msg, c->argv[1] );
{
struct berval bv;
ber_str2bv( c->argv[1], 0, 1, &bv );
+ if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
+ cfn = c->private;
ber_bvarray_add( &cfn->c_dseFiles, &bv );
}
break;
ber_str2bv(ptr, 0, 1, &bv);
ber_bvarray_add( &modcur->mp_loads, &bv );
}
+ /* Check for any new hardcoded schema */
+ if ( c->op == LDAP_MOD_ADD && CONFIG_ONLINE_ADD( c )) {
+ config_check_schema( &cfBackInfo );
+ }
break;
case CFG_MODPATH:
static int
config_overlay(ConfigArgs *c) {
- slap_overinfo *oi;
if (c->op == SLAP_CONFIG_EMIT) {
return 1;
} else if ( c->op == LDAP_MOD_DELETE ) {
assert(0);
}
- if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1])) {
+ if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1],
+ c->valx, &c->bi)) {
/* log error */
Debug( LDAP_DEBUG_ANY,
"%s: (optional) %s overlay \"%s\" configuration failed.\n",
c->log, c->be == frontendDB ? "global " : "", &c->argv[1][1]);
return 1;
- } else if(overlay_config(c->be, c->argv[1])) {
+ } else if(overlay_config(c->be, c->argv[1], c->valx, &c->bi)) {
return(1);
}
- /* Setup context for subsequent config directives.
- * The newly added overlay is at the head of the list.
- */
- oi = (slap_overinfo *)c->be->bd_info;
- c->bi = &oi->oi_list->on_bi;
return(0);
}
free(pdn.bv_val);
free(ndn.bv_val);
} else if(tbe) {
- char *type = tbe->bd_info->bi_type;
+ BackendDB *b2 = tbe;
- if ( overlay_is_over( tbe ) ) {
- slap_overinfo *oi = (slap_overinfo *)tbe->bd_info->bi_private;
- type = oi->oi_orig->bi_type;
- }
+ /* Does tbe precede be? */
+ while (( b2 = LDAP_STAILQ_NEXT(b2, be_next )) && b2 && b2 != c->be );
- snprintf( c->msg, sizeof( c->msg ), "<%s> namingContext \"%s\" already served by "
- "a preceding %s database serving namingContext",
- c->argv[0], pdn.bv_val, type );
- Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
- c->log, c->msg, tbe->be_suffix[0].bv_val);
- free(pdn.bv_val);
- free(ndn.bv_val);
- return(1);
- } else if(pdn.bv_len == 0 && default_search_nbase.bv_len) {
+ if ( b2 ) {
+ char *type = tbe->bd_info->bi_type;
+
+ if ( overlay_is_over( tbe ) ) {
+ slap_overinfo *oi = (slap_overinfo *)tbe->bd_info->bi_private;
+ type = oi->oi_orig->bi_type;
+ }
+
+ snprintf( c->msg, sizeof( c->msg ), "<%s> namingContext \"%s\" "
+ "already served by a preceding %s database",
+ c->argv[0], pdn.bv_val, type );
+ Debug(LDAP_DEBUG_ANY, "%s: %s serving namingContext \"%s\"\n",
+ c->log, c->msg, tbe->be_suffix[0].bv_val);
+ free(pdn.bv_val);
+ free(ndn.bv_val);
+ return(1);
+ }
+ }
+ if(pdn.bv_len == 0 && default_search_nbase.bv_len) {
Debug(LDAP_DEBUG_ANY, "%s: suffix DN empty and default search "
"base provided \"%s\" (assuming okay)\n",
c->log, default_search_base.bv_val, 0);
fprintf( out, "Installed log subsystems:\n\n" );
for ( i = 0; !BER_BVISNULL( &loglevel_ops[ i ].word ); i++ ) {
- fprintf( out, "\t%-30s (%d)\n",
+ fprintf( out, "\t%-30s (%lu)\n",
loglevel_ops[ i ].word.bv_val,
loglevel_ops[ i ].mask );
}
}
for(i = 1; i < c->argc; i++) {
slap_ssf_t *tgt = NULL;
- char *src;
+ char *src = NULL;
for ( j=0; !BER_BVISNULL( &sec_keys[j].key ); j++ ) {
if(!strncasecmp(c->argv[i], sec_keys[j].key.bv_val,
sec_keys[j].key.bv_len)) {
typedef struct setup_cookie {
CfBackInfo *cfb;
ConfigArgs *ca;
+ Entry *frontend;
+ Entry *config;
+ int got_frontend;
+ int got_config;
} setup_cookie;
static int
setup_cookie *sc = op->o_callback->sc_private;
sc->cfb->cb_got_ldif = 1;
+ /* Does the frontend exist? */
+ if ( !sc->got_frontend ) {
+ if ( !strncmp( rs->sr_entry->e_nname.bv_val,
+ "olcDatabase", STRLENOF( "olcDatabase" ))) {
+ if ( strncmp( rs->sr_entry->e_nname.bv_val +
+ STRLENOF( "olcDatabase" ), "={-1}frontend",
+ STRLENOF( "={-1}frontend" ))) {
+ struct berval rdn;
+ int i = op->o_noop;
+ sc->ca->be = frontendDB;
+ sc->ca->bi = frontendDB->bd_info;
+ frontendDB->be_cf_ocs = &CFOC_FRONTEND;
+ rdn.bv_val = sc->ca->log;
+ rdn.bv_len = snprintf(rdn.bv_val, sizeof( sc->ca->log ),
+ "%s=" SLAP_X_ORDERED_FMT "%s",
+ cfAd_database->ad_cname.bv_val, -1,
+ sc->ca->bi->bi_type);
+ op->o_noop = 1;
+ sc->frontend = config_build_entry( op, rs,
+ sc->cfb->cb_root, sc->ca, &rdn, &CFOC_DATABASE,
+ sc->ca->be->be_cf_ocs );
+ op->o_noop = i;
+ sc->got_frontend++;
+ } else {
+ sc->got_frontend++;
+ goto ok;
+ }
+ }
+ }
+ /* Does the configDB exist? */
+ if ( sc->got_frontend && !sc->got_config &&
+ !strncmp( rs->sr_entry->e_nname.bv_val,
+ "olcDatabase", STRLENOF( "olcDatabase" ))) {
+ if ( strncmp( rs->sr_entry->e_nname.bv_val +
+ STRLENOF( "olcDatabase" ), "={0}config",
+ STRLENOF( "={0}config" ))) {
+ struct berval rdn;
+ int i = op->o_noop;
+ sc->ca->be = LDAP_STAILQ_FIRST( &backendDB );
+ sc->ca->bi = sc->ca->be->bd_info;
+ rdn.bv_val = sc->ca->log;
+ rdn.bv_len = snprintf(rdn.bv_val, sizeof( sc->ca->log ),
+ "%s=" SLAP_X_ORDERED_FMT "%s",
+ cfAd_database->ad_cname.bv_val, 0,
+ sc->ca->bi->bi_type);
+ op->o_noop = 1;
+ sc->config = config_build_entry( op, rs, sc->cfb->cb_root,
+ sc->ca, &rdn, &CFOC_DATABASE, sc->ca->be->be_cf_ocs );
+ op->o_noop = i;
+ }
+ sc->got_config++;
+ }
+
+ok:
rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL );
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n",
if ( !cfb->cb_db.bd_info )
return 0; /* FIXME: eventually this will be a fatal error */
- if ( backend_db_init( "ldif", &cfb->cb_db ) == NULL )
+ if ( backend_db_init( "ldif", &cfb->cb_db, -1 ) == NULL )
return 1;
cfb->cb_db.be_suffix = be->be_suffix;
sc.cfb = cfb;
sc.ca = &c;
cb.sc_private = ≻
+ sc.got_frontend = 0;
+ sc.got_config = 0;
+ sc.frontend = NULL;
+ sc.config = NULL;
op->o_bd = &cfb->cb_db;
/* Restore normal DN validation */
slap_DN_strict = prev_DN_strict;
+ op->o_tag = LDAP_REQ_ADD;
+ if ( rc == LDAP_SUCCESS && sc.frontend ) {
+ op->ora_e = sc.frontend;
+ rc = op->o_bd->be_add( op, &rs );
+ }
+ if ( rc == LDAP_SUCCESS && sc.config ) {
+ op->ora_e = sc.config;
+ rc = op->o_bd->be_add( op, &rs );
+ }
ldap_pvt_thread_pool_context_reset( thrctx );
}
int rc;
/* Setup the config backend */
- be = backend_db_init( "config", NULL );
+ be = backend_db_init( "config", NULL, 0 );
if ( !be )
return 1;
AttributeDescription *ad;
BerVarray vals;
- int i, rc = 0, sort = 0;
+ int i, rc = 0;
if ( isAttr ) {
a = ptr;
}
if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )) {
- sort = 1;
rc = ordered_value_sort( a, 1 );
if ( rc ) {
snprintf(ca->msg, sizeof( ca->msg ), "ordered_value_sort failed on attr %s\n",
}
for ( i=0; vals[i].bv_val; i++ ) {
ca->line = vals[i].bv_val;
- if ( sort ) {
+ if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) &&
+ ca->line[0] == '{' ) {
char *idx = strchr( ca->line, '}' );
if ( idx ) ca->line = idx+1;
}
return rc;
}
+static int
+config_rename_attr( SlapReply *rs, Entry *e, struct berval *rdn,
+ Attribute **at )
+{
+ struct berval rtype, rval;
+ Attribute *a;
+ AttributeDescription *ad = NULL;
+
+ dnRdn( &e->e_name, rdn );
+ rval.bv_val = strchr(rdn->bv_val, '=' ) + 1;
+ rval.bv_len = rdn->bv_len - (rval.bv_val - rdn->bv_val);
+ rtype.bv_val = rdn->bv_val;
+ rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
+
+ /* Find attr */
+ slap_bv2ad( &rtype, &ad, &rs->sr_text );
+ a = attr_find( e->e_attrs, ad );
+ if (!a ) return LDAP_NAMING_VIOLATION;
+ *at = a;
+
+ return 0;
+}
+
+static void
+config_rename_kids( CfEntryInfo *ce )
+{
+ CfEntryInfo *ce2;
+ struct berval rdn, nrdn;
+
+ for (ce2 = ce->ce_kids; ce2; ce2 = ce2->ce_sibs) {
+ dnRdn ( &ce2->ce_entry->e_name, &rdn );
+ dnRdn ( &ce2->ce_entry->e_nname, &nrdn );
+ free( ce2->ce_entry->e_name.bv_val );
+ free( ce2->ce_entry->e_nname.bv_val );
+ build_new_dn( &ce2->ce_entry->e_name, &ce->ce_entry->e_name,
+ &rdn, NULL );
+ build_new_dn( &ce2->ce_entry->e_nname, &ce->ce_entry->e_nname,
+ &nrdn, NULL );
+ config_rename_kids( ce2 );
+ }
+}
+
+static int
+config_rename_one( Operation *op, SlapReply *rs, Entry *e,
+ CfEntryInfo *parent, Attribute *a, struct berval *newrdn,
+ struct berval *nnewrdn, int use_ldif )
+{
+ char *ptr1;
+ int rc = 0;
+ struct berval odn, ondn;
+
+ odn = e->e_name;
+ ondn = e->e_nname;
+ build_new_dn( &e->e_name, &parent->ce_entry->e_name, newrdn, NULL );
+ build_new_dn( &e->e_nname, &parent->ce_entry->e_nname, nnewrdn, NULL );
+
+ /* Replace attr */
+ free( a->a_vals[0].bv_val );
+ ptr1 = strchr( newrdn->bv_val, '=' ) + 1;
+ a->a_vals[0].bv_len = newrdn->bv_len - (ptr1 - newrdn->bv_val);
+ a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 );
+ strcpy( a->a_vals[0].bv_val, ptr1 );
+
+ if ( a->a_nvals != a->a_vals ) {
+ free( a->a_nvals[0].bv_val );
+ ptr1 = strchr( nnewrdn->bv_val, '=' ) + 1;
+ a->a_nvals[0].bv_len = nnewrdn->bv_len - (ptr1 - nnewrdn->bv_val);
+ a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 );
+ strcpy( a->a_nvals[0].bv_val, ptr1 );
+ }
+ if ( use_ldif ) {
+ CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
+ BackendDB *be = op->o_bd;
+ slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+ struct berval dn, ndn, xdn, xndn;
+
+ op->o_bd = &cfb->cb_db;
+
+ /* Save current rootdn; use the underlying DB's rootdn */
+ dn = op->o_dn;
+ ndn = op->o_ndn;
+ xdn = op->o_req_dn;
+ xndn = op->o_req_ndn;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+ op->o_req_dn = odn;
+ op->o_req_ndn = ondn;
+
+ sc.sc_next = op->o_callback;
+ op->o_callback = ≻
+ op->orr_newrdn = *newrdn;
+ op->orr_nnewrdn = *nnewrdn;
+ op->orr_deleteoldrdn = 1;
+ op->orr_modlist = NULL;
+ slap_modrdn2mods( op, rs );
+ rc = op->o_bd->be_modrdn( op, rs );
+ slap_mods_free( op->orr_modlist, 1 );
+
+ op->o_bd = be;
+ op->o_callback = sc.sc_next;
+ op->o_dn = dn;
+ op->o_ndn = ndn;
+ op->o_req_dn = xdn;
+ op->o_req_ndn = xndn;
+ }
+ free( odn.bv_val );
+ free( ondn.bv_val );
+ if ( e->e_private )
+ config_rename_kids( e->e_private );
+ return rc;
+}
+
+static int
+config_renumber_one( Operation *op, SlapReply *rs, CfEntryInfo *parent,
+ Entry *e, int idx, int tailindex, int use_ldif )
+{
+ struct berval ival, newrdn, nnewrdn;
+ struct berval rdn;
+ Attribute *a;
+ char ibuf[32], *ptr1, *ptr2 = NULL;
+ int rc = 0;
+
+ rc = config_rename_attr( rs, e, &rdn, &a );
+ if ( rc ) return rc;
+
+ ival.bv_val = ibuf;
+ ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, idx );
+ if ( ival.bv_len >= sizeof( ibuf ) ) {
+ return LDAP_NAMING_VIOLATION;
+ }
+
+ newrdn.bv_len = rdn.bv_len + ival.bv_len;
+ newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
+
+ if ( tailindex ) {
+ ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
+ ptr1 = lutil_strcopy( ptr1, ival.bv_val );
+ } else {
+ int xlen;
+ ptr2 = ber_bvchr( &rdn, '}' );
+ if ( ptr2 ) {
+ ptr2++;
+ } else {
+ ptr2 = rdn.bv_val + a->a_desc->ad_cname.bv_len + 1;
+ }
+ xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
+ ptr1 = lutil_strncopy( newrdn.bv_val, a->a_desc->ad_cname.bv_val,
+ a->a_desc->ad_cname.bv_len );
+ *ptr1++ = '=';
+ ptr1 = lutil_strcopy( ptr1, ival.bv_val );
+ ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
+ *ptr1 = '\0';
+ }
+
+ /* Do the equivalent of ModRDN */
+ /* Replace DN / NDN */
+ newrdn.bv_len = ptr1 - newrdn.bv_val;
+ rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
+ rc = config_rename_one( op, rs, e, parent, a, &newrdn, &nnewrdn, use_ldif );
+
+ free( nnewrdn.bv_val );
+ free( newrdn.bv_val );
+ return rc;
+}
+
static int
check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
- SlapReply *rs, int *renum )
+ SlapReply *rs, int *renum, int *ibase )
{
CfEntryInfo *ce;
- int index = -1, gotindex = 0, nsibs;
+ int index = -1, gotindex = 0, nsibs, rc = 0;
int renumber = 0, tailindex = 0;
char *ptr1, *ptr2 = NULL;
struct berval rdn;
renumber = 1;
}
}
+ /* just make index = nsibs */
if ( !renumber ) {
- struct berval ival, newrdn, nnewrdn;
- struct berval rtype, rval;
- Attribute *a;
- AttributeDescription *ad = NULL;
- char ibuf[32];
- const char *text;
-
- rval.bv_val = strchr(rdn.bv_val, '=' ) + 1;
- rval.bv_len = rdn.bv_len - (rval.bv_val - rdn.bv_val);
- rtype.bv_val = rdn.bv_val;
- rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
-
- /* Find attr */
- slap_bv2ad( &rtype, &ad, &text );
- a = attr_find( e->e_attrs, ad );
- if (!a ) return LDAP_NAMING_VIOLATION;
-
- ival.bv_val = ibuf;
- ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, nsibs );
- if ( ival.bv_len >= sizeof( ibuf ) ) {
- return LDAP_NAMING_VIOLATION;
- }
-
- newrdn.bv_len = rdn.bv_len + ival.bv_len;
- newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
-
- if ( tailindex ) {
- ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
- ptr1 = lutil_strcopy( ptr1, ival.bv_val );
- } else {
- int xlen;
- if ( !gotindex ) {
- ptr2 = rval.bv_val;
- xlen = rval.bv_len;
- } else {
- xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
- }
- ptr1 = lutil_strncopy( newrdn.bv_val, rtype.bv_val,
- rtype.bv_len );
- *ptr1++ = '=';
- ptr1 = lutil_strcopy( ptr1, ival.bv_val );
- ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
- *ptr1 = '\0';
- }
-
- /* Do the equivalent of ModRDN */
- /* Replace DN / NDN */
- newrdn.bv_len = ptr1 - newrdn.bv_val;
- rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
- free( e->e_name.bv_val );
- build_new_dn( &e->e_name, &parent->ce_entry->e_name,
- &newrdn, NULL );
- free( e->e_nname.bv_val );
- build_new_dn( &e->e_nname, &parent->ce_entry->e_nname,
- &nnewrdn, NULL );
-
- /* Replace attr */
- free( a->a_vals[0].bv_val );
- ptr1 = strchr( newrdn.bv_val, '=' ) + 1;
- a->a_vals[0].bv_len = newrdn.bv_len - (ptr1 - newrdn.bv_val);
- a->a_vals[0].bv_val = ch_malloc( a->a_vals[0].bv_len + 1 );
- strcpy( a->a_vals[0].bv_val, ptr1 );
-
- if ( a->a_nvals != a->a_vals ) {
- free( a->a_nvals[0].bv_val );
- ptr1 = strchr( nnewrdn.bv_val, '=' ) + 1;
- a->a_nvals[0].bv_len = nnewrdn.bv_len - (ptr1 - nnewrdn.bv_val);
- a->a_nvals[0].bv_val = ch_malloc( a->a_nvals[0].bv_len + 1 );
- strcpy( a->a_nvals[0].bv_val, ptr1 );
- }
- free( nnewrdn.bv_val );
- free( newrdn.bv_val );
+ rc = config_renumber_one( NULL, rs, parent, e, index, tailindex, 0 );
}
}
+ if ( ibase ) *ibase = index;
if ( renum ) *renum = renumber;
- return 0;
+ return rc;
}
static ConfigOCs **
CfEntryInfo *ce, *last;
ConfigOCs **colst;
Attribute *a, *oc_at;
- int i, nocs, rc = 0;
+ int i, ibase = -1, nocs, rc = 0;
struct berval pdn;
ConfigTable *ct;
char *ptr;
- /* Make sure parent exists and entry does not */
+ /* Make sure parent exists and entry does not. But allow
+ * Databases and Overlays to be inserted.
+ */
ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
- if ( ce )
+ if ( ce && ce->ce_type != Cft_Database &&
+ ce->ce_type != Cft_Overlay )
return LDAP_ALREADY_EXISTS;
dnParent( &e->e_nname, &pdn );
* but only the other types support auto-renumbering of siblings.
*/
{
- int renumber = renum ? *renum : 0;
- rc = check_name_index( last, colst[0]->co_type, e, rs, renum );
+ rc = check_name_index( last, colst[0]->co_type, e, rs, renum,
+ &ibase );
if ( rc ) {
goto done;
}
- if ( renum && *renum && renumber == -1 ) {
+ if ( renum && *renum && colst[0]->co_type != Cft_Database &&
+ colst[0]->co_type != Cft_Overlay ) {
snprintf( ca->msg, sizeof( ca->msg ),
"operation requires sibling renumbering" );
rc = LDAP_UNWILLING_TO_PERFORM;
ct = config_find_table( colst, nocs, a->a_desc );
if ( !ct ) continue; /* user data? */
for (i=0; a->a_vals[i].bv_val; i++) {
+ char *iptr = NULL;
ca->line = a->a_vals[i].bv_val;
if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
ptr = strchr( ca->line, '}' );
- if ( ptr ) ca->line = ptr+1;
+ if ( ptr ) {
+ iptr = strchr( ca->line, '{' );
+ ca->line = ptr+1;
+ }
}
- ca->valx = i;
- rc = config_parse_add( ct, ca );
+ if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_SIB ) {
+ if ( iptr ) {
+ ca->valx = strtol( iptr+1, NULL, 0 );
+ } else {
+ ca->valx = -1;
+ }
+ } else {
+ ca->valx = i;
+ }
+ rc = config_parse_add( ct, ca, i );
if ( rc ) {
rc = LDAP_OTHER;
goto done;
}
}
+ ca->valx = ibase;
ce = ch_calloc( 1, sizeof(CfEntryInfo) );
ce->ce_parent = last;
ce->ce_entry = entry_dup( e );
ce->ce_be = ca->be;
ce->ce_bi = ca->bi;
ce->ce_private = ca->private;
+ ca->ca_entry = ce->ce_entry;
if ( !last ) {
cfb->cb_root = ce;
} else if ( last->ce_kids ) {
- CfEntryInfo *c2;
-
- for (c2=last->ce_kids; c2 && c2->ce_sibs; c2 = c2->ce_sibs);
+ CfEntryInfo *c2, **cprev;
- c2->ce_sibs = ce;
+ /* Advance to first of this type */
+ cprev = &last->ce_kids;
+ for ( c2 = *cprev; c2 && c2->ce_type != ce->ce_type; ) {
+ cprev = &c2->ce_sibs;
+ c2 = c2->ce_sibs;
+ }
+ /* Account for the (-1) frontendDB entry */
+ if ( ce->ce_type == Cft_Database ) {
+ if ( ca->be == frontendDB )
+ ibase = 0;
+ else if ( ibase != -1 )
+ ibase++;
+ }
+ /* Append */
+ if ( ibase < 0 ) {
+ for (c2 = *cprev; c2 && c2->ce_type == ce->ce_type;) {
+ cprev = &c2->ce_sibs;
+ c2 = c2->ce_sibs;
+ }
+ } else {
+ /* Insert */
+ int i;
+ for ( i=0; i<ibase; i++ ) {
+ c2 = *cprev;
+ cprev = &c2->ce_sibs;
+ }
+ }
+ ce->ce_sibs = *cprev;
+ *cprev = ce;
} else {
last->ce_kids = ce;
}
return rc;
}
+#define BIGTMP 10000
+static int
+config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce,
+ int base, int rebase, int max, int use_ldif )
+{
+ CfEntryInfo *ce2, *ce3, *cetmp = NULL, *cerem = NULL;
+ ConfigType etype = ce->ce_type;
+ int count = 0, rc = 0;
+
+ /* Reverse ce list */
+ for (ce2 = ce->ce_sibs;ce2;ce2 = ce3) {
+ if (ce2->ce_type != etype) {
+ cerem = ce2;
+ break;
+ }
+ ce3 = ce2->ce_sibs;
+ ce2->ce_sibs = cetmp;
+ cetmp = ce2;
+ count++;
+ if ( max && count >= max ) {
+ cerem = ce3;
+ break;
+ }
+ }
+
+ /* Move original to a temp name until increments are done */
+ if ( rebase ) {
+ ce->ce_entry->e_private = NULL;
+ rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+ base+BIGTMP, 0, use_ldif );
+ ce->ce_entry->e_private = ce;
+ }
+ /* start incrementing */
+ for (ce2=cetmp; ce2; ce2=ce3) {
+ ce3 = ce2->ce_sibs;
+ ce2->ce_sibs = cerem;
+ cerem = ce2;
+ if ( rc == 0 )
+ rc = config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
+ count+base, 0, use_ldif );
+ count--;
+ }
+ if ( rebase )
+ rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+ base, 0, use_ldif );
+ return rc;
+}
+
+static int
+config_rename_del( Operation *op, SlapReply *rs, CfEntryInfo *ce,
+ CfEntryInfo *ce2, int old, int use_ldif )
+{
+ int count = 0;
+
+ /* Renumber original to a temp value */
+ ce->ce_entry->e_private = NULL;
+ config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+ old+BIGTMP, 0, use_ldif );
+ ce->ce_entry->e_private = ce;
+
+ /* start decrementing */
+ for (; ce2 != ce; ce2=ce2->ce_sibs) {
+ config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
+ count+old, 0, use_ldif );
+ count++;
+ }
+ return config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
+ count+old, 0, use_ldif );
+}
+
/* Parse an LDAP entry into config directives, then store in underlying
* database.
*/
* 1) check for existence of entry
* 2) check for sibling renumbering
* 3) perform internal add
- * 4) store entry in underlying database
- * 5) perform any necessary renumbering
+ * 4) perform any necessary renumbering
+ * 5) store entry in underlying database
*/
- /* NOTE: by now we do not accept adds that require renumbering */
- renumber = -1;
rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op );
if ( rs->sr_err != LDAP_SUCCESS ) {
rs->sr_text = ca.msg;
goto out2;
}
+ if ( renumber ) {
+ CfEntryInfo *ce = ca.ca_entry->e_private;
+ req_add_s addr = op->oq_add;
+ op->o_tag = LDAP_REQ_MODRDN;
+ rs->sr_err = config_rename_add( op, rs, ce, ca.valx, 0, 0, cfb->cb_use_ldif );
+ op->o_tag = LDAP_REQ_ADD;
+ op->oq_add = addr;
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ goto out2;
+ }
+ }
+
if ( cfb->cb_use_ldif ) {
BackendDB *be = op->o_bd;
slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
op->o_ndn = ndn;
}
- if ( renumber ) {
- /* TODO */
- }
-
out2:;
ldap_pvt_thread_pool_resume( &connection_pool );
if(rc == LDAP_SUCCESS) {
/* check that the entry still obeys the schema */
- rc = entry_schema_check(op, e, NULL, 0,
+ rc = entry_schema_check(op, e, NULL, 0, 0,
&rs->sr_text, ca->msg, sizeof(ca->msg) );
}
if ( rc == LDAP_SUCCESS ) {
if ( rc ) rc = LDAP_OTHER;
}
if ( ml->sml_values ) {
+ d = d->next;
ch_free( dels );
- dels = d->next;
+ dels = d;
}
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
ml->sml_values = vals;
ca->line = ptr+1;
}
}
- rc = config_parse_add( ct, ca );
+ rc = config_parse_add( ct, ca, i );
if ( rc ) {
rc = LDAP_OTHER;
goto out;
{
CfBackInfo *cfb;
CfEntryInfo *ce, *last;
+ struct berval rdn;
+ int ixold, ixnew;
cfb = (CfBackInfo *)op->o_bd->be_private;
rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
goto out;
}
+
+ /* If newRDN == oldRDN, quietly succeed */
+ dnRdn( &op->o_req_ndn, &rdn );
+ if ( dn_match( &rdn, &op->orr_nnewrdn )) {
+ rs->sr_err = LDAP_SUCCESS;
+ goto out;
+ }
+
+ /* Current behavior, subject to change as needed:
+ *
+ * For backends and overlays, we only allow renumbering.
+ * For schema, we allow renaming with the same number.
+ * Otherwise, the op is not allowed.
+ */
+
+ if ( ce->ce_type == Cft_Schema ) {
+ char *ptr1, *ptr2;
+ int len;
+
+ /* Can't alter the main cn=schema entry */
+ if ( ce->ce_parent->ce_type == Cft_Global ) {
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "renaming not allowed for this entry";
+ goto out;
+ }
+
+ /* We could support this later if desired */
+ ptr1 = ber_bvchr( &rdn, '}' );
+ ptr2 = ber_bvchr( &op->orr_newrdn, '}' );
+ len = ptr1 - rdn.bv_val;
+ if ( len != ptr2 - op->orr_newrdn.bv_val ||
+ strncmp( rdn.bv_val, op->orr_newrdn.bv_val, len )) {
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "schema reordering not supported";
+ goto out;
+ }
+ } else if ( ce->ce_type == Cft_Database ||
+ ce->ce_type == Cft_Overlay ) {
+ char *ptr1, *ptr2, *iptr1, *iptr2;
+ int len1, len2;
+
+ iptr2 = ber_bvchr( &op->orr_newrdn, '=' ) + 1;
+ if ( *iptr2 != '{' ) {
+ rs->sr_err = LDAP_NAMING_VIOLATION;
+ rs->sr_text = "new ordering index is required";
+ goto out;
+ }
+ iptr2++;
+ iptr1 = ber_bvchr( &rdn, '{' ) + 1;
+ ptr1 = ber_bvchr( &rdn, '}' );
+ ptr2 = ber_bvchr( &op->orr_newrdn, '}' );
+ if ( !ptr2 ) {
+ rs->sr_err = LDAP_NAMING_VIOLATION;
+ rs->sr_text = "new ordering index is required";
+ goto out;
+ }
+
+ len1 = ptr1 - rdn.bv_val;
+ len2 = ptr2 - op->orr_newrdn.bv_val;
+
+ if ( rdn.bv_len - len1 != op->orr_newrdn.bv_len - len2 ||
+ strncmp( ptr1, ptr2, rdn.bv_len - len1 )) {
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "changing database/overlay type not allowed";
+ goto out;
+ }
+ ixold = strtol( iptr1, NULL, 0 );
+ ixnew = strtol( iptr2, &ptr1, 0 );
+ if ( ptr1 != ptr2 || ixold < 0 || ixnew < 0 ) {
+ rs->sr_err = LDAP_NAMING_VIOLATION;
+ goto out;
+ }
+ /* config DB is always 0, cannot be changed */
+ if ( ce->ce_type == Cft_Database && ( ixold == 0 || ixnew == 0 )) {
+ rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
+ goto out;
+ }
+ } else {
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "renaming not supported for this entry";
+ goto out;
+ }
+
ldap_pvt_thread_pool_pause( &connection_pool );
- rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
- rs->sr_text = "renaming not implemented yet within naming context";
+ if ( ce->ce_type == Cft_Schema ) {
+ req_modrdn_s modr = op->oq_modrdn;
+ struct berval rdn;
+ Attribute *a;
+ rs->sr_err = config_rename_attr( rs, ce->ce_entry, &rdn, &a );
+ if ( rs->sr_err == LDAP_SUCCESS ) {
+ rs->sr_err = config_rename_one( op, rs, ce->ce_entry,
+ ce->ce_parent, a, &op->orr_newrdn, &op->orr_nnewrdn,
+ cfb->cb_use_ldif );
+ }
+ op->oq_modrdn = modr;
+ } else {
+ CfEntryInfo *ce2, *cebase, **cprev, **cbprev, *ceold;
+ req_modrdn_s modr = op->oq_modrdn;
+ int i;
+
+ /* Advance to first of this type */
+ cprev = &ce->ce_parent->ce_kids;
+ for ( ce2 = *cprev; ce2 && ce2->ce_type != ce->ce_type; ) {
+ cprev = &ce2->ce_sibs;
+ ce2 = ce2->ce_sibs;
+ }
+ /* Skip the -1 entry */
+ if ( ce->ce_type == Cft_Database ) {
+ cprev = &ce2->ce_sibs;
+ ce2 = ce2->ce_sibs;
+ }
+ cebase = ce2;
+ cbprev = cprev;
+
+ /* Remove from old slot */
+ for ( ce2 = *cprev; ce2 && ce2 != ce; ce2 = ce2->ce_sibs )
+ cprev = &ce2->ce_sibs;
+ *cprev = ce->ce_sibs;
+ ceold = ce->ce_sibs;
+
+ /* Insert into new slot */
+ cprev = cbprev;
+ for ( i=0; i<ixnew; i++ ) {
+ ce2 = *cprev;
+ if ( !ce2 )
+ break;
+ cprev = &ce2->ce_sibs;
+ }
+ ce->ce_sibs = *cprev;
+ *cprev = ce;
+
+ ixnew = i;
+
+ /* NOTE: These should be encoded in the OC tables, not inline here */
+ if ( ce->ce_type == Cft_Database )
+ backend_db_move( ce->ce_be, ixnew );
+ else if ( ce->ce_type == Cft_Overlay )
+ overlay_move( ce->ce_be, (slap_overinst *)ce->ce_bi, ixnew );
+
+ if ( ixold < ixnew ) {
+ rs->sr_err = config_rename_del( op, rs, ce, ceold, ixold,
+ cfb->cb_use_ldif );
+ } else {
+ rs->sr_err = config_rename_add( op, rs, ce, ixnew, 1,
+ ixold - ixnew, cfb->cb_use_ldif );
+ }
+ op->oq_modrdn = modr;
+ }
ldap_pvt_thread_pool_resume( &connection_pool );
out:
}
oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
- rc = structural_class(oc_at->a_vals, &val, NULL, &text, c->msg,
- sizeof(c->msg));
- attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &val, NULL );
- if ( op ) {
+ rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->msg,
+ sizeof(c->msg), op->o_tmpmemctx );
+ attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
+ if ( !op->o_noop ) {
op->ora_e = e;
op->o_bd->be_add( op, rs );
if ( ( rs->sr_err != LDAP_SUCCESS )
}
#endif
+static int
+config_check_schema(CfBackInfo *cfb)
+{
+ struct berval schema_dn = BER_BVC(SCHEMA_RDN "," CONFIG_RDN);
+ ConfigArgs c = {0};
+ ConfigFile *cf = cfb->cb_config;
+ CfEntryInfo *ce, *last;
+ Entry *e;
+
+ /* If there's no root entry, we must be in the midst of converting */
+ if ( !cfb->cb_root )
+ return 0;
+
+ /* Make sure the main schema entry exists */
+ ce = config_find_base( cfb->cb_root, &schema_dn, &last );
+ if ( ce ) {
+ Attribute *a;
+ struct berval *bv;
+
+ e = ce->ce_entry;
+
+ /* Make sure it's up to date */
+ if ( cf_om_tail != om_sys_tail ) {
+ a = attr_find( e->e_attrs, cfAd_om );
+ if ( a ) {
+ if ( a->a_nvals != a->a_vals )
+ ber_bvarray_free( a->a_nvals );
+ ber_bvarray_free( a->a_vals );
+ a->a_vals = NULL;
+ a->a_nvals = NULL;
+ }
+ oidm_unparse( &bv, NULL, NULL, 1 );
+ attr_merge_normalize( e, cfAd_om, bv, NULL );
+ ber_bvarray_free( bv );
+ cf_om_tail = om_sys_tail;
+ }
+ if ( cf_at_tail != at_sys_tail ) {
+ a = attr_find( e->e_attrs, cfAd_attr );
+ if ( a ) {
+ if ( a->a_nvals != a->a_vals )
+ ber_bvarray_free( a->a_nvals );
+ ber_bvarray_free( a->a_vals );
+ a->a_vals = NULL;
+ a->a_nvals = NULL;
+ }
+ at_unparse( &bv, NULL, NULL, 1 );
+ attr_merge_normalize( e, cfAd_attr, bv, NULL );
+ ber_bvarray_free( bv );
+ cf_at_tail = at_sys_tail;
+ }
+ if ( cf_oc_tail != oc_sys_tail ) {
+ a = attr_find( e->e_attrs, cfAd_oc );
+ if ( a ) {
+ if ( a->a_nvals != a->a_vals )
+ ber_bvarray_free( a->a_nvals );
+ ber_bvarray_free( a->a_vals );
+ a->a_vals = NULL;
+ a->a_nvals = NULL;
+ }
+ oc_unparse( &bv, NULL, NULL, 1 );
+ attr_merge_normalize( e, cfAd_oc, bv, NULL );
+ ber_bvarray_free( bv );
+ cf_oc_tail = oc_sys_tail;
+ }
+ } else {
+ SlapReply rs = {REP_RESULT};
+ c.private = NULL;
+ e = config_build_entry( NULL, &rs, cfb->cb_root, &c, &schema_rdn,
+ &CFOC_SCHEMA, NULL );
+ if ( !e ) {
+ return -1;
+ }
+ ce = e->e_private;
+ ce->ce_private = cfb->cb_config;
+ cf_at_tail = at_sys_tail;
+ cf_oc_tail = oc_sys_tail;
+ cf_om_tail = om_sys_tail;
+ }
+ return 0;
+}
+
static const char *defacl[] = {
NULL, "to", "*", "by", "*", "none", NULL
};
parse_acl(be, "config_back_db_open", 0, 6, (char **)defacl, 0 );
}
- /* If we read the config from back-ldif, nothing to do here */
- if ( cfb->cb_got_ldif )
- return 0;
+ /* If we read the config from back-ldif, do some quick sanity checks */
+ if ( cfb->cb_got_ldif ) {
+ return config_check_schema( cfb );
+ }
- if ( cfb->cb_use_ldif ) {
- thrctx = ldap_pvt_thread_pool_context();
- op = (Operation *) &opbuf;
- connection_fake_init( &conn, op, thrctx );
+ thrctx = ldap_pvt_thread_pool_context();
+ op = (Operation *) &opbuf;
+ connection_fake_init( &conn, op, thrctx );
- op->o_tag = LDAP_REQ_ADD;
- op->o_callback = &cb;
- op->o_bd = &cfb->cb_db;
- op->o_dn = op->o_bd->be_rootdn;
- op->o_ndn = op->o_bd->be_rootndn;
- } else {
- op = NULL;
+ op->o_tag = LDAP_REQ_ADD;
+ op->o_callback = &cb;
+ op->o_bd = &cfb->cb_db;
+ op->o_dn = op->o_bd->be_rootdn;
+ op->o_ndn = op->o_bd->be_rootndn;
+
+ if ( !cfb->cb_use_ldif ) {
+ op->o_noop = 1;
}
/* create root of tree */
}
ce = e->e_private;
ce->ce_private = cfb->cb_config;
+ cf_at_tail = at_sys_tail;
+ cf_oc_tail = oc_sys_tail;
+ cf_om_tail = om_sys_tail;
/* Create schema nodes for included schema... */
if ( cfb->cb_config->c_kids ) {
backend_destroy_one( &cfb->cb_db, 0 );
}
- free( be->be_private );
-
loglevel_destroy();
return 0;
struct berval dn;
CfBackInfo *cfb;
- cfb = ch_calloc( 1, sizeof(CfBackInfo));
+ cfb = &cfBackInfo;
cfb->cb_config = ch_calloc( 1, sizeof(ConfigFile));
cfn = cfb->cb_config;
be->be_private = cfb;
char *name;
AttributeDescription **desc;
} ads[] = {
+ { "attribute", &cfAd_attr },
{ "backend", &cfAd_backend },
{ "database", &cfAd_database },
{ "include", &cfAd_include },
+ { "objectclass", &cfAd_oc },
+ { "objectidentifier", &cfAd_om },
{ "overlay", &cfAd_overlay },
{ NULL, NULL }
};
config_back_initialize( BackendInfo *bi )
{
ConfigTable *ct = config_back_cf_table;
+ ConfigArgs ca;
char *argv[4];
int i;
AttributeDescription *ad = NULL;
bi->bi_tool_entry_get = config_tool_entry_get;
bi->bi_tool_entry_put = config_tool_entry_put;
+ ca.argv = argv;
+ argv[ 0 ] = "slapd";
+ ca.argv = argv;
+ ca.argc = 3;
+ ca.fname = argv[0];
+
argv[3] = NULL;
for (i=0; OidMacros[i].name; i++ ) {
argv[1] = OidMacros[i].name;
argv[2] = OidMacros[i].oid;
- parse_oidm( "slapd", i, 3, argv, 0, NULL );
+ parse_oidm( &ca, 0, NULL );
}
bi->bi_cf_ocs = cf_ocs;