mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 00:29:35 -05:00
ITS#4752 try to undo failed Modifies
This commit is contained in:
parent
c5b33893f0
commit
b06eeff43b
1 changed files with 150 additions and 93 deletions
|
|
@ -4528,6 +4528,33 @@ typedef struct delrec {
|
|||
int idx[1];
|
||||
} delrec;
|
||||
|
||||
static int
|
||||
config_modify_add( ConfigTable *ct, ConfigArgs *ca, AttributeDescription *ad,
|
||||
int i )
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (ad->ad_type->sat_flags & SLAP_AT_ORDERED &&
|
||||
ca->line[0] == '{' )
|
||||
{
|
||||
char *ptr = strchr( ca->line + 1, '}' );
|
||||
if ( ptr ) {
|
||||
char *next;
|
||||
|
||||
ca->valx = strtol( ca->line + 1, &next, 0 );
|
||||
if ( next == ca->line + 1 || next[ 0 ] != '}' ) {
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
ca->line = ptr+1;
|
||||
}
|
||||
}
|
||||
rc = config_parse_add( ct, ca, i );
|
||||
if ( rc ) {
|
||||
rc = LDAP_OTHER;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
||||
ConfigArgs *ca )
|
||||
|
|
@ -4535,7 +4562,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
|||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
Modifications *ml;
|
||||
Entry *e = ce->ce_entry;
|
||||
Attribute *save_attrs = e->e_attrs, *oc_at;
|
||||
Attribute *save_attrs = e->e_attrs, *oc_at, *s, *a;
|
||||
ConfigTable *ct;
|
||||
ConfigOCs **colst;
|
||||
int i, nocs;
|
||||
|
|
@ -4547,6 +4574,11 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
|||
|
||||
colst = count_ocs( oc_at, &nocs );
|
||||
|
||||
/* make sure add/del flags are clear; should always be true */
|
||||
for ( s = save_attrs; s; s = s->a_next ) {
|
||||
s->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL);
|
||||
}
|
||||
|
||||
e->e_attrs = attrs_dup( e->e_attrs );
|
||||
|
||||
init_config_argv( ca );
|
||||
|
|
@ -4569,7 +4601,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
|||
rc = LDAP_OTHER;
|
||||
snprintf(ca->msg, sizeof(ca->msg), "cannot delete %s",
|
||||
ml->sml_desc->ad_cname.bv_val );
|
||||
goto out;
|
||||
goto out_noop;
|
||||
}
|
||||
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
|
||||
vals = ml->sml_values;
|
||||
|
|
@ -4631,11 +4663,11 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
|||
rc = LDAP_OTHER;
|
||||
snprintf(ca->msg, sizeof(ca->msg), "cannot insert %s",
|
||||
ml->sml_desc->ad_cname.bv_val );
|
||||
goto out;
|
||||
goto out_noop;
|
||||
}
|
||||
}
|
||||
rc = check_vals( ct, ca, ml, 0 );
|
||||
if ( rc ) goto out;
|
||||
if ( rc ) goto out_noop;
|
||||
}
|
||||
}
|
||||
rc = modify_add_values(e, &ml->sml_mod,
|
||||
|
|
@ -4664,117 +4696,142 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
|
|||
if(rc != LDAP_SUCCESS) break;
|
||||
}
|
||||
|
||||
if(rc == LDAP_SUCCESS) {
|
||||
if ( rc == LDAP_SUCCESS) {
|
||||
/* check that the entry still obeys the schema */
|
||||
rc = entry_schema_check(op, e, NULL, 0, 0,
|
||||
&rs->sr_text, ca->msg, sizeof(ca->msg) );
|
||||
if ( rc ) goto out_noop;
|
||||
}
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
/* Basic syntax checks are OK. Do the actual settings. */
|
||||
for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
|
||||
ct = config_find_table( colst, nocs, ml->sml_desc );
|
||||
if ( !ct ) continue;
|
||||
/* Basic syntax checks are OK. Do the actual settings. */
|
||||
for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
|
||||
ct = config_find_table( colst, nocs, ml->sml_desc );
|
||||
if ( !ct ) continue;
|
||||
|
||||
switch (ml->sml_op) {
|
||||
case LDAP_MOD_DELETE:
|
||||
case LDAP_MOD_REPLACE: {
|
||||
BerVarray vals = NULL, nvals = NULL;
|
||||
Attribute *a;
|
||||
delrec *d = NULL;
|
||||
s = attr_find( save_attrs, ml->sml_desc );
|
||||
a = attr_find( e->e_attrs, ml->sml_desc );
|
||||
|
||||
a = attr_find( e->e_attrs, ml->sml_desc );
|
||||
switch (ml->sml_op) {
|
||||
case LDAP_MOD_DELETE:
|
||||
case LDAP_MOD_REPLACE: {
|
||||
BerVarray vals = NULL, nvals = NULL;
|
||||
delrec *d = NULL;
|
||||
|
||||
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
|
||||
vals = ml->sml_values;
|
||||
nvals = ml->sml_nvalues;
|
||||
ml->sml_values = NULL;
|
||||
ml->sml_nvalues = NULL;
|
||||
}
|
||||
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
|
||||
vals = ml->sml_values;
|
||||
nvals = ml->sml_nvalues;
|
||||
ml->sml_values = NULL;
|
||||
ml->sml_nvalues = NULL;
|
||||
}
|
||||
|
||||
if ( ml->sml_values )
|
||||
d = dels;
|
||||
if ( ml->sml_values )
|
||||
d = dels;
|
||||
|
||||
/* If we didn't delete the whole attribute */
|
||||
if ( ml->sml_values && a ) {
|
||||
struct berval *mvals;
|
||||
int j;
|
||||
/* If we didn't delete the whole attribute */
|
||||
if ( ml->sml_values && a ) {
|
||||
struct berval *mvals;
|
||||
int j;
|
||||
|
||||
if ( ml->sml_nvalues )
|
||||
mvals = ml->sml_nvalues;
|
||||
else
|
||||
mvals = ml->sml_values;
|
||||
if ( ml->sml_nvalues )
|
||||
mvals = ml->sml_nvalues;
|
||||
else
|
||||
mvals = ml->sml_values;
|
||||
|
||||
/* use the indexes we saved up above */
|
||||
for (i=0; i < d->nidx; i++) {
|
||||
struct berval bv = *mvals++;
|
||||
if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
|
||||
bv.bv_val[0] == '{' ) {
|
||||
ptr = strchr( bv.bv_val, '}' ) + 1;
|
||||
bv.bv_len -= ptr - bv.bv_val;
|
||||
bv.bv_val = ptr;
|
||||
}
|
||||
ca->line = bv.bv_val;
|
||||
ca->valx = d->idx[i];
|
||||
rc = config_del_vals( ct, ca );
|
||||
if ( rc != LDAP_SUCCESS ) break;
|
||||
for (j=i+1; j < d->nidx; j++)
|
||||
if ( d->idx[j] >d->idx[i] )
|
||||
d->idx[j]--;
|
||||
/* use the indexes we saved up above */
|
||||
for (i=0; i < d->nidx; i++) {
|
||||
struct berval bv = *mvals++;
|
||||
if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
|
||||
bv.bv_val[0] == '{' ) {
|
||||
ptr = strchr( bv.bv_val, '}' ) + 1;
|
||||
bv.bv_len -= ptr - bv.bv_val;
|
||||
bv.bv_val = ptr;
|
||||
}
|
||||
} else {
|
||||
ca->valx = -1;
|
||||
ca->line = NULL;
|
||||
ca->line = bv.bv_val;
|
||||
ca->valx = d->idx[i];
|
||||
rc = config_del_vals( ct, ca );
|
||||
if ( rc ) rc = LDAP_OTHER;
|
||||
if ( rc != LDAP_SUCCESS ) break;
|
||||
s->a_flags |= SLAP_ATTR_IXDEL;
|
||||
for (j=i+1; j < d->nidx; j++)
|
||||
if ( d->idx[j] >d->idx[i] )
|
||||
d->idx[j]--;
|
||||
}
|
||||
if ( ml->sml_values ) {
|
||||
d = d->next;
|
||||
ch_free( dels );
|
||||
dels = d;
|
||||
}
|
||||
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
|
||||
ml->sml_values = vals;
|
||||
ml->sml_nvalues = nvals;
|
||||
}
|
||||
if ( !vals || rc != LDAP_SUCCESS )
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU: LDAP_MOD_REPLACE && vals */
|
||||
|
||||
case LDAP_MOD_ADD:
|
||||
for (i=0; ml->sml_values[i].bv_val; i++) {
|
||||
ca->line = ml->sml_values[i].bv_val;
|
||||
ca->valx = -1;
|
||||
if ( ml->sml_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
|
||||
ca->line[0] == '{' )
|
||||
{
|
||||
ptr = strchr( ca->line + 1, '}' );
|
||||
if ( ptr ) {
|
||||
char *next;
|
||||
|
||||
ca->valx = strtol( ca->line + 1, &next, 0 );
|
||||
if ( next == ca->line + 1 || next[ 0 ] != '}' ) {
|
||||
rc = LDAP_OTHER;
|
||||
goto out;
|
||||
}
|
||||
ca->line = ptr+1;
|
||||
}
|
||||
}
|
||||
rc = config_parse_add( ct, ca, i );
|
||||
if ( rc ) {
|
||||
rc = LDAP_OTHER;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ca->valx = -1;
|
||||
ca->line = NULL;
|
||||
rc = config_del_vals( ct, ca );
|
||||
if ( rc ) rc = LDAP_OTHER;
|
||||
s->a_flags |= SLAP_ATTR_IXDEL;
|
||||
}
|
||||
if ( ml->sml_values ) {
|
||||
d = d->next;
|
||||
ch_free( dels );
|
||||
dels = d;
|
||||
}
|
||||
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
|
||||
ml->sml_values = vals;
|
||||
ml->sml_nvalues = nvals;
|
||||
}
|
||||
if ( !vals || rc != LDAP_SUCCESS )
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU: LDAP_MOD_REPLACE && vals */
|
||||
|
||||
case LDAP_MOD_ADD:
|
||||
for (i=0; ml->sml_values[i].bv_val; i++) {
|
||||
ca->line = ml->sml_values[i].bv_val;
|
||||
ca->valx = -1;
|
||||
rc = config_modify_add( ct, ca, ml->sml_desc, i );
|
||||
if ( rc )
|
||||
goto out;
|
||||
a->a_flags |= SLAP_ATTR_IXADD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
/* Undo for a failed operation */
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
for ( s = save_attrs; s; s = s->a_next ) {
|
||||
if ( s->a_flags & SLAP_ATTR_IXDEL ) {
|
||||
s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
|
||||
ct = config_find_table( colst, nocs, s->a_desc );
|
||||
a = attr_find( e->e_attrs, s->a_desc );
|
||||
if ( a ) {
|
||||
/* clear the flag so the add check below will skip it */
|
||||
a->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
|
||||
ca->valx = -1;
|
||||
ca->line = NULL;
|
||||
config_del_vals( ct, ca );
|
||||
}
|
||||
for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) {
|
||||
ca->line = s->a_vals[i].bv_val;
|
||||
ca->valx = -1;
|
||||
config_modify_add( ct, ca, s->a_desc, i );
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( a = e->e_attrs; a; a = a->a_next ) {
|
||||
if ( a->a_flags & SLAP_ATTR_IXADD ) {
|
||||
ct = config_find_table( colst, nocs, a->a_desc );
|
||||
ca->valx = -1;
|
||||
ca->line = NULL;
|
||||
config_del_vals( ct, ca );
|
||||
s = attr_find( save_attrs, a->a_desc );
|
||||
if ( s ) {
|
||||
s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
|
||||
for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) {
|
||||
ca->line = s->a_vals[i].bv_val;
|
||||
ca->valx = -1;
|
||||
config_modify_add( ct, ca, s->a_desc, i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ca->cleanup )
|
||||
ca->cleanup( ca );
|
||||
out_noop:
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
attrs_free( save_attrs );
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue