]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9227 syncrepl: don't delete non-replicated attrs
authorHoward Chu <hyc@openldap.org>
Fri, 8 May 2020 15:22:44 +0000 (16:22 +0100)
committerHoward Chu <hyc@openldap.org>
Fri, 8 May 2020 15:23:44 +0000 (16:23 +0100)
servers/slapd/syncrepl.c

index 1d32e4a2f4ee7b51e6641ea9337bc3ddaa093f06..9d338e5a48e7dd1312c3fe416c65445e26d18a0c 100644 (file)
@@ -3546,6 +3546,7 @@ static int syncrepl_dsee_schema()
  * operational attributes from the entry, and do a regular ModDN.
  */
 typedef struct dninfo {
+       syncinfo_t *si;
        Entry *new_entry;
        struct berval dn;
        struct berval ndn;
@@ -3767,6 +3768,7 @@ syncrepl_entry(
        op->o_callback = &cb;
        cb.sc_response = dn_callback;
        cb.sc_private = &dni;
+       dni.si = si;
        dni.new_entry = entry;
        dni.modlist = modlist;
        dni.syncstate = syncstate;
@@ -5122,6 +5124,37 @@ void syncrepl_diff_entry( Operation *op, Attribute *old, Attribute *new,
        *ml = NULL;
 }
 
+/* shallow copy attrs, excluding non-replicated attrs */
+static Attribute *
+attrs_exdup( Operation *op, dninfo *dni, Attribute *attrs )
+{
+       int i;
+       Attribute *tmp, *anew;
+
+       if ( attrs == NULL ) return NULL;
+
+       /* count attrs */
+       for ( tmp = attrs,i=0; tmp; tmp=tmp->a_next ) i++;
+
+       anew = op->o_tmpalloc( i * sizeof(Attribute), op->o_tmpmemctx );
+       for ( tmp = anew; attrs; attrs=attrs->a_next ) {
+               if ( dni->si->si_anlist && !ad_inlist( attrs->a_desc, dni->si->si_anlist ))
+                       continue;
+               if ( dni->si->si_exanlist && ad_inlist( attrs->a_desc, dni->si->si_exanlist ))
+                       continue;
+               *tmp = *attrs;
+               tmp->a_next = tmp+1;
+               tmp++;
+       }
+       if ( tmp == anew ) {
+               /* excluded everything */
+               op->o_tmpfree( anew, op->o_tmpmemctx );
+               return NULL;
+       }
+       tmp[-1].a_next = NULL;
+       return anew;
+}
+
 static int
 dn_callback(
        Operation*      op,
@@ -5263,9 +5296,11 @@ dn_callback(
                                } else
 #endif
                                {
-                                       syncrepl_diff_entry( op, rs->sr_entry->e_attrs,
+                                       Attribute *old = attrs_exdup( op, dni, rs->sr_entry->e_attrs );
+                                       syncrepl_diff_entry( op, old,
                                                dni->new_entry->e_attrs, &dni->mods, dni->modlist,
                                                is_ctx );
+                                       op->o_tmpfree( old, op->o_tmpmemctx );
                                }
                        }
                }