mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-03-07 14:18:15 +08:00
ITS#4337 implement modrdn for back-config
This commit is contained in:
parent
fcc51c0497
commit
6020a6d81d
@ -114,7 +114,7 @@ relay_back_db_config(
|
||||
* where the overlay is instantiated by moving
|
||||
* around the "relay" directive, although this could
|
||||
* make slapd.conf a bit confusing. */
|
||||
if ( overlay_config( be, "rwm" ) ) {
|
||||
if ( overlay_config( be, "rwm", -1, NULL ) ) {
|
||||
Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
|
||||
"%s: line %d: unable to install "
|
||||
"rwm overlay "
|
||||
|
@ -530,13 +530,48 @@ BackendInfo* backend_info(const char *type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
backend_db_insert(
|
||||
BackendDB *be,
|
||||
int idx
|
||||
)
|
||||
{
|
||||
/* If idx < 0, just add to end of list */
|
||||
if ( idx < 0 ) {
|
||||
LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
|
||||
} else if ( idx == 0 ) {
|
||||
LDAP_STAILQ_INSERT_HEAD(&backendDB, be, be_next);
|
||||
} else {
|
||||
int i;
|
||||
BackendDB *b2;
|
||||
|
||||
b2 = LDAP_STAILQ_FIRST(&backendDB);
|
||||
idx--;
|
||||
for (i=0; i<idx; i++) {
|
||||
b2 = LDAP_STAILQ_NEXT(b2, be_next);
|
||||
}
|
||||
LDAP_STAILQ_INSERT_AFTER(&backendDB, b2, be, be_next);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
backend_db_move(
|
||||
BackendDB *be,
|
||||
int idx
|
||||
)
|
||||
{
|
||||
LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
|
||||
backend_db_insert(be, idx);
|
||||
}
|
||||
|
||||
BackendDB *
|
||||
backend_db_init(
|
||||
const char *type,
|
||||
BackendDB *be )
|
||||
BackendDB *b0,
|
||||
int idx )
|
||||
{
|
||||
BackendInfo *bi = backend_info(type);
|
||||
BackendDB *be = b0;
|
||||
int rc = 0;
|
||||
|
||||
if( bi == NULL ) {
|
||||
@ -549,8 +584,11 @@ backend_db_init(
|
||||
*/
|
||||
if ( !be ) {
|
||||
be = ch_calloc( 1, sizeof(Backend) );
|
||||
/* Just append */
|
||||
if ( idx >= nbackends )
|
||||
idx = -1;
|
||||
nbackends++;
|
||||
LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
|
||||
backend_db_insert( be, idx );
|
||||
}
|
||||
|
||||
be->bd_info = bi;
|
||||
@ -574,11 +612,16 @@ backend_db_init(
|
||||
|
||||
if ( rc != 0 ) {
|
||||
fprintf( stderr, "database init failed (%s)\n", type );
|
||||
nbackends--;
|
||||
return NULL;
|
||||
/* If we created and linked this be, remove it and free it */
|
||||
if ( !b0 ) {
|
||||
LDAP_STAILQ_REMOVE(&backendDB, be, slap_backend_db, be_next);
|
||||
ch_free( be );
|
||||
be = NULL;
|
||||
nbackends--;
|
||||
}
|
||||
} else {
|
||||
bi->bi_nDB++;
|
||||
}
|
||||
|
||||
bi->bi_nDB++;
|
||||
return( be );
|
||||
}
|
||||
|
||||
|
@ -956,7 +956,7 @@ glue_sub_attach()
|
||||
|
||||
/* If it's not already configured, set up the overlay */
|
||||
if ( !SLAP_GLUE_INSTANCE( be )) {
|
||||
rc = overlay_config( be, glue.on_bi.bi_type );
|
||||
rc = overlay_config( be, glue.on_bi.bi_type, -1, NULL );
|
||||
if ( rc )
|
||||
break;
|
||||
}
|
||||
|
@ -942,14 +942,77 @@ overlay_destroy_one( BackendDB *be, slap_overinst *on )
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
|
||||
int idx )
|
||||
{
|
||||
slap_overinfo *oi = (slap_overinfo *)be->bd_info;
|
||||
|
||||
if ( idx == -1 ) {
|
||||
on2->on_next = oi->oi_list;
|
||||
oi->oi_list = on2;
|
||||
} else {
|
||||
int i;
|
||||
slap_overinst *on, *otmp1 = NULL, *otmp2;
|
||||
|
||||
/* Since the list is in reverse order and is singly linked,
|
||||
* we reverse it to find the idx insertion point. Adding
|
||||
* on overlay at a specific point should be a pretty
|
||||
* infrequent occurrence.
|
||||
*/
|
||||
for ( on = oi->oi_list; on; on=otmp2 ) {
|
||||
otmp2 = on->on_next;
|
||||
on->on_next = otmp1;
|
||||
otmp1 = on;
|
||||
}
|
||||
oi->oi_list = NULL;
|
||||
/* advance to insertion point */
|
||||
for ( i=0, on = otmp1; i<idx; i++ ) {
|
||||
otmp1 = on->on_next;
|
||||
on->on_next = oi->oi_list;
|
||||
oi->oi_list = on;
|
||||
}
|
||||
/* insert */
|
||||
on2->on_next = oi->oi_list;
|
||||
oi->oi_list = on2;
|
||||
if ( otmp1 ) {
|
||||
*prev = &otmp1->on_next;
|
||||
/* replace remainder of list */
|
||||
for ( on=otmp1; on; on=otmp1 ) {
|
||||
otmp1 = on->on_next;
|
||||
on->on_next = oi->oi_list;
|
||||
oi->oi_list = on;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
overlay_move( BackendDB *be, slap_overinst *on, int idx )
|
||||
{
|
||||
slap_overinfo *oi = (slap_overinfo *)be->bd_info;
|
||||
slap_overinst **onp;
|
||||
|
||||
for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
|
||||
if ( *onp == on ) {
|
||||
*onp = on->on_next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
overlay_insert( be, on, &onp, idx );
|
||||
}
|
||||
|
||||
/* add an overlay to a particular backend. */
|
||||
int
|
||||
overlay_config( BackendDB *be, const char *ov )
|
||||
overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res )
|
||||
{
|
||||
slap_overinst *on = NULL, *on2 = NULL;
|
||||
slap_overinst *on = NULL, *on2 = NULL, **prev;
|
||||
slap_overinfo *oi = NULL;
|
||||
BackendInfo *bi = NULL;
|
||||
|
||||
if ( res )
|
||||
*res = NULL;
|
||||
|
||||
on = overlay_find( ov );
|
||||
if ( !on ) {
|
||||
Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
|
||||
@ -1049,28 +1112,44 @@ overlay_config( BackendDB *be, const char *ov )
|
||||
oi = be->bd_info->bi_private;
|
||||
}
|
||||
|
||||
/* Insert new overlay on head of list. Overlays are executed
|
||||
* in reverse of config order...
|
||||
/* Insert new overlay into list. By default overlays are
|
||||
* added to head of list and executed in LIFO order.
|
||||
*/
|
||||
on2 = ch_calloc( 1, sizeof(slap_overinst) );
|
||||
*on2 = *on;
|
||||
on2->on_info = oi;
|
||||
on2->on_next = oi->oi_list;
|
||||
oi->oi_list = on2;
|
||||
|
||||
prev = &oi->oi_list;
|
||||
/* Do we need to find the insertion point? */
|
||||
if ( idx >= 0 ) {
|
||||
int i;
|
||||
|
||||
/* count current overlays */
|
||||
for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
|
||||
|
||||
/* are we just appending a new one? */
|
||||
if ( idx >= i )
|
||||
idx = -1;
|
||||
}
|
||||
overlay_insert( be, on2, &prev, idx );
|
||||
|
||||
/* Any initialization needed? */
|
||||
if ( on->on_bi.bi_db_init ) {
|
||||
if ( on2->on_bi.bi_db_init ) {
|
||||
int rc;
|
||||
be->bd_info = (BackendInfo *)on2;
|
||||
rc = on2->on_bi.bi_db_init( be );
|
||||
be->bd_info = (BackendInfo *)oi;
|
||||
if ( rc ) {
|
||||
oi->oi_list = on2->on_next;
|
||||
*prev = on2->on_next;
|
||||
ch_free( on2 );
|
||||
on2 = NULL;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if ( res )
|
||||
*res = &on2->on_bi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1228,7 +1228,7 @@ config_generic(ConfigArgs *c) {
|
||||
} 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",
|
||||
@ -1934,26 +1934,21 @@ config_timelimit(ConfigArgs *c) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -3218,8 +3213,11 @@ config_ldif_resp( Operation *op, SlapReply *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;
|
||||
}
|
||||
sc->got_frontend++;
|
||||
}
|
||||
}
|
||||
/* Does the configDB exist? */
|
||||
@ -3246,6 +3244,7 @@ config_ldif_resp( Operation *op, SlapReply *rs )
|
||||
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",
|
||||
@ -3285,7 +3284,7 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
|
||||
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;
|
||||
@ -3421,7 +3420,7 @@ read_config(const char *fname, const char *dir) {
|
||||
int rc;
|
||||
|
||||
/* Setup the config backend */
|
||||
be = backend_db_init( "config", NULL );
|
||||
be = backend_db_init( "config", NULL, 0 );
|
||||
if ( !be )
|
||||
return 1;
|
||||
|
||||
@ -3654,12 +3653,177 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr )
|
||||
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;
|
||||
@ -3710,83 +3874,14 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
|
||||
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 **
|
||||
@ -3897,14 +3992,17 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
|
||||
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 );
|
||||
@ -3995,12 +4093,13 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
|
||||
* 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;
|
||||
@ -4027,12 +4126,24 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
ca->valx = i;
|
||||
rc = config_parse_add( ct, ca, i );
|
||||
if ( rc ) {
|
||||
rc = LDAP_OTHER;
|
||||
@ -4063,6 +4174,7 @@ ok:
|
||||
}
|
||||
}
|
||||
|
||||
ca->valx = ibase;
|
||||
ce = ch_calloc( 1, sizeof(CfEntryInfo) );
|
||||
ce->ce_parent = last;
|
||||
ce->ce_entry = entry_dup( e );
|
||||
@ -4071,6 +4183,7 @@ ok:
|
||||
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 ) {
|
||||
@ -4098,6 +4211,76 @@ done:
|
||||
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.
|
||||
*/
|
||||
@ -4122,17 +4305,27 @@ config_back_add( Operation *op, SlapReply *rs )
|
||||
* 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 };
|
||||
@ -4155,10 +4348,6 @@ config_back_add( Operation *op, SlapReply *rs )
|
||||
op->o_ndn = ndn;
|
||||
}
|
||||
|
||||
if ( renumber ) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
out2:;
|
||||
ldap_pvt_thread_pool_resume( &connection_pool );
|
||||
|
||||
@ -4521,6 +4710,8 @@ config_back_modrdn( Operation *op, SlapReply *rs )
|
||||
{
|
||||
CfBackInfo *cfb;
|
||||
CfEntryInfo *ce, *last;
|
||||
struct berval rdn;
|
||||
int ixold, ixnew;
|
||||
|
||||
cfb = (CfBackInfo *)op->o_bd->be_private;
|
||||
|
||||
@ -4555,10 +4746,153 @@ config_back_modrdn( Operation *op, SlapReply *rs )
|
||||
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 ) {
|
||||
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 );
|
||||
}
|
||||
} 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:
|
||||
|
@ -417,6 +417,7 @@ slap_modrdn2mods(
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
rs->sr_text = NULL;
|
||||
|
||||
/* Add new attribute values to the entry */
|
||||
for ( a_cnt = 0; new_rdn[a_cnt]; a_cnt++ ) {
|
||||
|
@ -1926,7 +1926,7 @@ pc_cf_gen( ConfigArgs *c )
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( !backend_db_init( c->argv[1], &cm->db )) {
|
||||
if ( !backend_db_init( c->argv[1], &cm->db, -1 )) {
|
||||
snprintf( c->msg, sizeof( c->msg ), "unknown backend type (arg #1)" );
|
||||
Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->msg, 0 );
|
||||
return( 1 );
|
||||
|
@ -699,7 +699,7 @@ static int translucent_db_init(BackendDB *be) {
|
||||
ov->db.be_private = NULL;
|
||||
ov->db.be_pcl_mutexp = &ov->db.be_pcl_mutex;
|
||||
|
||||
if ( !backend_db_init( "ldap", &ov->db )) {
|
||||
if ( !backend_db_init( "ldap", &ov->db, -1 )) {
|
||||
Debug( LDAP_DEBUG_CONFIG, "translucent: unable to open captive back-ldap\n", 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -323,7 +323,9 @@ LDAP_SLAPD_F (void) backend_destroy_one LDAP_P((BackendDB *bd, int dynamic));
|
||||
|
||||
LDAP_SLAPD_F (BackendInfo *) backend_info LDAP_P(( const char *type ));
|
||||
LDAP_SLAPD_F (BackendDB *) backend_db_init LDAP_P(( const char *type,
|
||||
BackendDB *be ));
|
||||
BackendDB *be, int idx ));
|
||||
LDAP_SLAPD_F (void) backend_db_insert LDAP_P((BackendDB *bd, int idx));
|
||||
LDAP_SLAPD_F (void) backend_db_move LDAP_P((BackendDB *bd, int idx));
|
||||
|
||||
LDAP_SLAPD_F (BackendDB *) select_backend LDAP_P((
|
||||
struct berval * dn,
|
||||
@ -411,7 +413,8 @@ LDAP_SLAPD_F (int) glue_sub_del( BackendDB *be );
|
||||
* backover.c
|
||||
*/
|
||||
LDAP_SLAPD_F (int) overlay_register LDAP_P(( slap_overinst *on ));
|
||||
LDAP_SLAPD_F (int) overlay_config LDAP_P(( BackendDB *be, const char *ov ));
|
||||
LDAP_SLAPD_F (int) overlay_config LDAP_P(( BackendDB *be, const char *ov,
|
||||
int idx, BackendInfo **res ));
|
||||
LDAP_SLAPD_F (void) overlay_destroy_one LDAP_P((
|
||||
BackendDB *be,
|
||||
slap_overinst *on ));
|
||||
@ -428,6 +431,10 @@ LDAP_SLAPD_F (int) overlay_op_walk LDAP_P((
|
||||
slap_operation_t which,
|
||||
slap_overinfo *oi,
|
||||
slap_overinst *on ));
|
||||
LDAP_SLAPD_F (void) overlay_insert LDAP_P((
|
||||
BackendDB *be, slap_overinst *on, slap_overinst ***prev, int idx ));
|
||||
LDAP_SLAPD_F (void) overlay_move LDAP_P((
|
||||
BackendDB *be, slap_overinst *on, int idx ));
|
||||
|
||||
/*
|
||||
* bconfig.c
|
||||
|
@ -935,7 +935,7 @@ int slapi_over_config( BackendDB *be )
|
||||
slapi_over_initialized = 1;
|
||||
}
|
||||
|
||||
return overlay_config( be, SLAPI_OVERLAY_NAME );
|
||||
return overlay_config( be, SLAPI_OVERLAY_NAME, -1, NULL );
|
||||
}
|
||||
|
||||
#endif /* LDAP_SLAPI */
|
||||
|
Loading…
Reference in New Issue
Block a user