]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/slapadd.c
add copyright heading (for replca management modifications)
[openldap] / servers / slapd / tools / slapadd.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * Modified by Jong Hyuk Choi
8  *
9  * Modifications provided under the terms of the following condition:
10  *
11  * Copyright (c) 2003 by International Business Machines, Inc.
12  *
13  * International Business Machines, Inc. (hereinafter called IBM) grants
14  * permission under its copyrights to use, copy, modify, and distribute this
15  * Software with or without fee, provided that the above copyright notice and
16  * all paragraphs of this notice appear in all copies, and that the name of IBM
17  * not be used in connection with the marketing of any product incorporating
18  * the Software or modifications thereof, without specific, written prior
19  * permission.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
22  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
24  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
25  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
26  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
27  */
28
29 #include "portable.h"
30
31 #include <stdio.h>
32
33 #include <ac/stdlib.h>
34
35 #include <ac/ctype.h>
36 #include <ac/string.h>
37 #include <ac/socket.h>
38 #include <ac/unistd.h>
39
40 #include <lber.h>
41 #include <ldif.h>
42 #include <lutil.h>
43
44 #include "slapcommon.h"
45
46 static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
47 static const struct berval slap_syncrepl_bvc = BER_BVC("syncreplxxx");
48 static const struct berval slap_syncrepl_cn_bvc = BER_BVC("cn=syncreplxxx");
49 static struct berval slap_syncrepl_bv = BER_BVNULL;
50 static struct berval slap_syncrepl_cn_bv = BER_BVNULL;
51
52 struct subentryinfo {
53         struct berval cn;
54         struct berval ndn;
55         struct berval rdn;
56         struct berval cookie;
57         LDAP_SLIST_ENTRY( subentryinfo ) sei_next;
58 };
59
60 int
61 main( int argc, char **argv )
62 {
63         char            *buf = NULL;
64         int         lineno;
65         int         lmax;
66         int                     rc = EXIT_SUCCESS;
67
68         const char *text;
69         char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
70         size_t textlen = sizeof textbuf;
71
72         struct berval csn;
73         struct berval maxcsn = { 0, NULL };
74         struct berval ldifcsn = { 0, NULL };
75         int match;
76         int     provider_subentry = 0;
77         struct subentryinfo *sei;
78         LDAP_SLIST_HEAD( consumer_subentry_slist, subentryinfo ) consumer_subentry;
79         Attribute *attr;
80         Entry *ctxcsn_e;
81         ID      ctxcsn_id;
82         struct berval   ctxcsn_ndn = { 0, NULL };
83         int ret;
84         struct berval bvtext;
85         int i;
86 #ifdef NEW_LOGGING
87         lutil_log_initialize(argc, argv );
88 #endif
89         slap_tool_init( "slapadd", SLAPADD, argc, argv );
90
91         LDAP_SLIST_INIT( &consumer_subentry );
92
93         if( !be->be_entry_open ||
94                 !be->be_entry_close ||
95                 !be->be_entry_put )
96         {
97                 fprintf( stderr, "%s: database doesn't support necessary operations.\n",
98                         progname );
99                 exit( EXIT_FAILURE );
100         }
101
102         lmax = 0;
103         lineno = 0;
104
105         if( be->be_entry_open( be, 1 ) != 0 ) {
106                 fprintf( stderr, "%s: could not open database.\n",
107                         progname );
108                 exit( EXIT_FAILURE );
109         }
110
111         while( ldif_read_record( ldiffp, &lineno, &buf, &lmax ) ) {
112                 Entry *e = str2entry( buf );
113
114                 /*
115                  * Initialize text buffer
116                  */
117                 bvtext.bv_len = textlen;
118                 bvtext.bv_val = textbuf;
119                 bvtext.bv_val[0] = '\0';
120
121                 if( e == NULL ) {
122                         fprintf( stderr, "%s: could not parse entry (line=%d)\n",
123                                 progname, lineno );
124                         rc = EXIT_FAILURE;
125                         if( continuemode ) continue;
126                         break;
127                 }
128
129                 /* make sure the DN is not empty */
130                 if( !e->e_nname.bv_len ) {
131                         fprintf( stderr, "%s: empty dn=\"%s\" (line=%d)\n",
132                                 progname, e->e_dn, lineno );
133                         rc = EXIT_FAILURE;
134                         entry_free( e );
135                         if( continuemode ) continue;
136                         break;
137                 }
138
139                 /* check backend */
140                 if( select_backend( &e->e_nname, is_entry_referral(e), nosubordinates )
141                         != be )
142                 {
143                         fprintf( stderr, "%s: line %d: "
144                                 "database (%s) not configured to hold \"%s\"\n",
145                                 progname, lineno,
146                                 be ? be->be_suffix[0].bv_val : "<none>",
147                                 e->e_dn );
148                         fprintf( stderr, "%s: line %d: "
149                                 "database (%s) not configured to hold \"%s\"\n",
150                                 progname, lineno,
151                                 be ? be->be_nsuffix[0].bv_val : "<none>",
152                                 e->e_ndn );
153                         rc = EXIT_FAILURE;
154                         entry_free( e );
155                         if( continuemode ) continue;
156                         break;
157                 }
158
159                 if( global_schemacheck ) {
160                         Attribute *sc = attr_find( e->e_attrs,
161                                 slap_schema.si_ad_structuralObjectClass );
162                         Attribute *oc = attr_find( e->e_attrs,
163                                 slap_schema.si_ad_objectClass );
164
165                         if( oc == NULL ) {
166                                 fprintf( stderr, "%s: dn=\"%s\" (line=%d): %s\n",
167                                         progname, e->e_dn, lineno,
168                                         "no objectClass attribute");
169                                 rc = EXIT_FAILURE;
170                                 entry_free( e );
171                                 if( continuemode ) continue;
172                                 break;
173                         }
174
175                         if( sc == NULL ) {
176                                 struct berval vals[2];
177
178                                 rc = structural_class( oc->a_vals, vals,
179                                         NULL, &text, textbuf, textlen );
180
181                                 if( rc != LDAP_SUCCESS ) {
182                                         fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n",
183                                                 progname, e->e_dn, lineno, rc, text );
184                                         rc = EXIT_FAILURE;
185                                         entry_free( e );
186                                         if( continuemode ) continue;
187                                         break;
188                                 }
189
190                                 vals[1].bv_len = 0;
191                                 vals[1].bv_val = NULL;
192
193                                 attr_merge( e, slap_schema.si_ad_structuralObjectClass,
194                                         vals, NULL /* FIXME */ );
195                         }
196
197                         /* check schema */
198                         rc = entry_schema_check( be, e, NULL, &text, textbuf, textlen );
199
200                         if( rc != LDAP_SUCCESS ) {
201                                 fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n",
202                                         progname, e->e_dn, lineno, rc, text );
203                                 rc = EXIT_FAILURE;
204                                 entry_free( e );
205                                 if( continuemode ) continue;
206                                 break;
207                         }
208                 }
209
210                 if ( SLAP_LASTMOD(be) ) {
211                         struct tm *ltm;
212                         time_t now = slap_get_time();
213                         char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ];
214                         struct berval vals[ 2 ];
215
216                         struct berval name, timestamp;
217
218                         struct berval nvals[ 2 ];
219                         struct berval nname;
220                         char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
221
222                         vals[1].bv_len = 0;
223                         vals[1].bv_val = NULL;
224
225                         nvals[1].bv_len = 0;
226                         nvals[1].bv_val = NULL;
227
228                         ltm = gmtime(&now);
229                         lutil_gentime( timebuf, sizeof(timebuf), ltm );
230
231                         csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), 0, 0 );
232                         csn.bv_val = csnbuf;
233
234                         timestamp.bv_val = timebuf;
235                         timestamp.bv_len = strlen(timebuf);
236
237                         if ( be->be_rootndn.bv_len == 0 ) {
238                                 name.bv_val = SLAPD_ANONYMOUS;
239                                 name.bv_len = sizeof(SLAPD_ANONYMOUS) - 1;
240                                 nname.bv_val = SLAPD_ANONYMOUS;
241                                 nname.bv_len = sizeof(SLAPD_ANONYMOUS) - 1;
242                         } else {
243                                 name = be->be_rootdn;
244                                 nname = be->be_rootndn;
245                         }
246
247                         if( attr_find( e->e_attrs, slap_schema.si_ad_entryUUID )
248                                 == NULL )
249                         {
250                                 vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) );
251                                 vals[0].bv_val = uuidbuf;
252                                 attr_merge_normalize_one( e,
253                                                         slap_schema.si_ad_entryUUID, vals, NULL );
254                         }
255
256                         if( attr_find( e->e_attrs, slap_schema.si_ad_creatorsName )
257                                 == NULL )
258                         {
259                                 vals[0] = name;
260                                 nvals[0] = nname;
261                                 attr_merge( e, slap_schema.si_ad_creatorsName, vals, nvals );
262                         }
263
264                         if( attr_find( e->e_attrs, slap_schema.si_ad_modifiersName )
265                                 == NULL )
266                         {
267                                 vals[0] = name;
268                                 nvals[0] = nname;
269                                 attr_merge( e, slap_schema.si_ad_modifiersName, vals, nvals );
270                         }
271
272                         if( attr_find( e->e_attrs, slap_schema.si_ad_createTimestamp )
273                                 == NULL )
274                         {
275                                 vals[0] = timestamp;
276                                 attr_merge( e, slap_schema.si_ad_createTimestamp, vals, NULL );
277                         }
278
279                         if( attr_find( e->e_attrs, slap_schema.si_ad_modifyTimestamp )
280                                 == NULL )
281                         {
282                                 vals[0] = timestamp;
283                                 attr_merge( e, slap_schema.si_ad_modifyTimestamp, vals, NULL );
284                         }
285
286                         if( attr_find( e->e_attrs, slap_schema.si_ad_entryCSN )
287                                 == NULL )
288                         {
289                                 vals[0] = csn;
290                                 attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL );
291                         }
292
293                         if ( !is_entry_syncProviderSubentry( e ) &&
294                                  !is_entry_syncConsumerSubentry( e ) &&
295                                  update_ctxcsn != SLAP_TOOL_CTXCSN_KEEP ) {
296                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN );
297                                 if ( maxcsn.bv_len != 0 ) {
298                                         value_match( &match, slap_schema.si_ad_entryCSN,
299                                                 slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
300                                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
301                                                 &maxcsn, &attr->a_nvals[0], &text );
302                                 } else {
303                                         match = -1;
304                                 }
305                                 if ( match < 0 ) {
306                                         if ( maxcsn.bv_val )
307                                                 ch_free( maxcsn.bv_val );
308                                         ber_dupbv( &maxcsn, &attr->a_nvals[0] );
309                                 }
310                         }
311                 }
312
313                 if ( update_ctxcsn == SLAP_TOOL_CTXCSN_KEEP ) {
314                         if ( is_entry_syncProviderSubentry( e )) { 
315                                 if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
316                                         fprintf( stderr, "%s: consumer and provider subentries "
317                                                                          "are both present\n", progname );
318                                         rc = EXIT_FAILURE;
319                                         entry_free( e );
320                                         sei = LDAP_SLIST_FIRST( &consumer_subentry );
321                                         while ( sei ) {
322                                                 ch_free( sei->cn.bv_val );
323                                                 ch_free( sei->ndn.bv_val );
324                                                 ch_free( sei->rdn.bv_val );
325                                                 ch_free( sei->cookie.bv_val );
326                                                 LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
327                                                 ch_free( sei );
328                                                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
329                                         }
330                                         break;
331                                 }
332                                 if ( provider_subentry ) {
333                                         fprintf( stderr, "%s: multiple provider subentries are "
334                                                         "present : add -w flag to refresh\n", progname );
335                                         rc = EXIT_FAILURE;
336                                         entry_free( e );
337                                         break;
338                                 }
339                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
340                                 if ( attr == NULL ) {
341                                         entry_free( e );
342                                         continue;
343                                 }
344                                 provider_subentry = 1;
345                                 ber_dupbv( &maxcsn, &attr->a_nvals[0] );
346                         } else if ( is_entry_syncConsumerSubentry( e )) {
347                                 if ( provider_subentry ) {
348                                         fprintf( stderr, "%s: consumer and provider subentries "
349                                                                          "are both present\n", progname );
350                                         rc = EXIT_FAILURE;
351                                         entry_free( e );
352                                         break;
353                                 }
354
355                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_cn );
356
357                                 if ( attr == NULL ) {
358                                         entry_free( e );
359                                         continue;
360                                 }
361
362                                 if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
363                                         LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
364                                                 value_match( &match, slap_schema.si_ad_cn,
365                                                         slap_schema.si_ad_cn->ad_type->sat_equality,
366                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
367                                                         &sei->cn, &attr->a_nvals[0], &text );
368                                         }
369                                         if ( !match ) {
370                                                 fprintf( stderr, "%s: multiple consumer subentries "
371                                                                 "have the same id : add -w flag to refresh\n",
372                                                                 progname );
373                                                 rc = EXIT_FAILURE;
374                                                 entry_free( e );
375                                                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
376                                                 while ( sei ) {
377                                                         ch_free( sei->cn.bv_val );
378                                                         ch_free( sei->ndn.bv_val );
379                                                         ch_free( sei->rdn.bv_val );
380                                                         ch_free( sei->cookie.bv_val );
381                                                         LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
382                                                         ch_free( sei );
383                                                         sei = LDAP_SLIST_FIRST( &consumer_subentry );
384                                                 }
385                                                 break;
386                                         }
387                                 }
388                                 sei = ch_calloc( 1, sizeof( struct subentryinfo ));
389                                 ber_dupbv( &sei->cn, &attr->a_nvals[0] );
390                                 ber_dupbv( &sei->ndn, &e->e_nname );
391                                 dnExtractRdn( &sei->ndn, &sei->rdn, NULL );
392                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_syncreplCookie );
393                                 if ( attr == NULL ) {
394                                         ch_free( sei->cn.bv_val );
395                                         ch_free( sei->ndn.bv_val );
396                                         ch_free( sei->rdn.bv_val );
397                                         ch_free( sei->cookie.bv_val );
398                                         ch_free( sei );
399                                         entry_free( e );
400                                         continue;
401                                 }
402                                 ber_dupbv( &sei->cookie, &attr->a_nvals[0] );
403                                 LDAP_SLIST_INSERT_HEAD( &consumer_subentry, sei, sei_next );
404                         }
405                 }
406
407                 if ( !is_entry_syncProviderSubentry( e ) &&
408                          !is_entry_syncConsumerSubentry( e )) {
409                         if (!dryrun) {
410                                 ID id = be->be_entry_put( be, e, &bvtext );
411                                 if( id == NOID ) {
412                                         fprintf( stderr, "%s: could not add entry dn=\"%s\" "
413                                                                          "(line=%d): %s\n", progname, e->e_dn,
414                                                                          lineno, bvtext.bv_val );
415                                         rc = EXIT_FAILURE;
416                                         entry_free( e );
417                                         if( continuemode ) continue;
418                                         break;
419                                 }
420         
421                                 if ( verbose ) {
422                                         fprintf( stderr, "added: \"%s\" (%08lx)\n",
423                                                 e->e_dn, (long) id );
424                                 }
425                         } else {
426                                 if ( verbose ) {
427                                         fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
428                                 }
429                         }
430                 }
431
432                 entry_free( e );
433         }
434
435         bvtext.bv_len = textlen;
436         bvtext.bv_val = textbuf;
437         bvtext.bv_val[0] = '\0';
438
439         if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
440                 maxcsn.bv_len = 0;
441                 maxcsn.bv_val = NULL;
442                 LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
443                         if ( maxcsn.bv_len != 0 ) {
444                                 value_match( &match, slap_schema.si_ad_syncreplCookie,
445                                         slap_schema.si_ad_syncreplCookie->ad_type->sat_ordering,
446                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
447                                         &maxcsn, &sei->cookie, &text );
448                         } else {
449                                 match = -1;
450                         }
451                         if ( match < 0 ) {
452                                 if ( maxcsn.bv_val )
453                                         ch_free( maxcsn.bv_val );
454                                 ber_dupbv( &maxcsn, &sei->cookie );
455                         }
456                 }
457         }
458
459         if ( SLAP_LASTMOD(be) && replica_promotion ) {
460                 if ( provider_subentry || update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
461                          !LDAP_SLIST_EMPTY( &consumer_subentry )) {
462                         build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
463                                                   (struct berval *)&slap_ldapsync_cn_bv, NULL );
464                         ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
465                 
466                         if ( ctxcsn_id == NOID ) {
467                                 ctxcsn_e = slap_create_context_csn_entry( be, &maxcsn );
468                                 if ( !dryrun ) {
469                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
470                                         if( ctxcsn_id == NOID ) {
471                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
472                                                                                  progname);
473                                                 rc = EXIT_FAILURE;
474                                         }
475                                         if ( verbose ) {
476                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
477                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
478                                         }
479                                 } else {
480                                         if ( verbose ) {
481                                                 fprintf( stderr, "(dry) added: \"%s\"\n", ctxcsn_e->e_dn );
482                                         }
483                                 }
484                                 entry_free( ctxcsn_e );
485                         } else {
486                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
487                                 if ( ret == LDAP_SUCCESS ) {
488                                         attr = attr_find( ctxcsn_e->e_attrs,
489                                                                                 slap_schema.si_ad_contextCSN );
490                                         AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
491                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
492                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
493                                         if ( !dryrun ) {
494                                                 ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
495                                                 if( ctxcsn_id == NOID ) {
496                                                         fprintf( stderr, "%s: could not modify ctxcsn "
497                                                                                          "subentry\n", progname);
498                                                         rc = EXIT_FAILURE;
499                                                 }
500                                                 if ( verbose ) {
501                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
502                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
503                                                 }
504                                         } else {
505                                                 if ( verbose ) {
506                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
507                                                                                          ctxcsn_e->e_dn );
508                                                 }
509                                         }
510                                 } else {
511                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
512                                                                          progname);
513                                         rc = EXIT_FAILURE;
514                                 }
515                         }
516                 } 
517         } else if ( SLAP_LASTMOD(be) && replica_demotion &&
518                                 ( update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
519                                 provider_subentry )) {
520
521                 ber_dupbv( &slap_syncrepl_bv, (struct berval *) &slap_syncrepl_bvc );
522                 ber_dupbv( &slap_syncrepl_cn_bv,
523                                         (struct berval *) &slap_syncrepl_cn_bvc );
524
525                 if ( replica_id_list == NULL ) {
526                         replica_id_list = ch_calloc( 2, sizeof( int ));
527                         replica_id_list[0] = 0;
528                         replica_id_list[1] = -1;
529                 }
530
531                 for ( i = 0; replica_id_list[i] > -1 ; i++ ) {
532                         slap_syncrepl_bv.bv_len = snprintf( slap_syncrepl_bv.bv_val,
533                                                                         slap_syncrepl_bvc.bv_len,
534                                                                         "syncrepl%d", replica_id_list[i] );
535                         slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
536                                                                                 slap_syncrepl_cn_bvc.bv_len,
537                                                                                 "cn=syncrepl%d", replica_id_list[i] );
538                         build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
539                                                   (struct berval *)&slap_syncrepl_cn_bv, NULL );
540                         ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
541
542                         if ( ctxcsn_id == NOID ) {
543                                 ctxcsn_e = slap_create_syncrepl_entry( be, &maxcsn,
544                                                                                                 &slap_syncrepl_cn_bv,
545                                                                                                 &slap_syncrepl_bv );
546                                 if ( !dryrun ) {
547                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
548                                         if( ctxcsn_id == NOID ) {
549                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
550                                                                                  progname);
551                                                 rc = EXIT_FAILURE;
552                                         }
553                                         if ( verbose ) {
554                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
555                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
556                                         }
557                                 } else {
558                                         if ( verbose ) {
559                                                 fprintf( stderr, "(dry) added: \"%s\"\n",
560                                                                                         ctxcsn_e->e_dn );
561                                         }
562                                 }
563                                 entry_free( ctxcsn_e );
564                         } else {
565                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
566                                 if ( ret == LDAP_SUCCESS ) {
567                                         attr = attr_find( ctxcsn_e->e_attrs,
568                                                                           slap_schema.si_ad_syncreplCookie );
569                                         AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
570                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
571                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
572                                         if ( !dryrun ) {
573                                                 ctxcsn_id = be->be_entry_modify( be,
574                                                                                         ctxcsn_e, &bvtext );
575                                                 if( ctxcsn_id == NOID ) {
576                                                         fprintf( stderr, "%s: could not modify ctxcsn "
577                                                                                          "subentry\n", progname);
578                                                         rc = EXIT_FAILURE;
579                                                 }
580                                                 if ( verbose ) {
581                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
582                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
583                                                 }
584                                         } else {
585                                                 if ( verbose ) {
586                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
587                                                                                          ctxcsn_e->e_dn );
588                                                 }
589                                         }
590                                 } else {
591                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
592                                                                          progname);
593                                         rc = EXIT_FAILURE;
594                                 }
595                         }
596                 }
597                 
598                 if ( slap_syncrepl_bv.bv_val ) {
599                         ch_free( slap_syncrepl_bv.bv_val );
600                 }
601                 if ( slap_syncrepl_cn_bv.bv_val ) {
602                         ch_free( slap_syncrepl_cn_bv.bv_val );
603                 }
604         } else if ( SLAP_LASTMOD(be) && replica_demotion &&
605                                 !LDAP_SLIST_EMPTY( &consumer_subentry )) {
606
607                 LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
608                         ctxcsn_id = be->be_dn2id_get( be, &sei->ndn );
609
610                         if ( ctxcsn_id == NOID ) {
611                                 ctxcsn_e = slap_create_syncrepl_entry( be, &sei->cookie,
612                                                                                                 &sei->rdn, &sei->cn );
613                                 if ( !dryrun ) {
614                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
615                                         if( ctxcsn_id == NOID ) {
616                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
617                                                                                  progname);
618                                                 rc = EXIT_FAILURE;
619                                         }
620                                         if ( verbose ) {
621                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
622                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
623                                         }
624                                 } else {
625                                         if ( verbose ) {
626                                                 fprintf( stderr, "(dry) added: \"%s\"\n",
627                                                                                         ctxcsn_e->e_dn );
628                                         }
629                                 }
630                                 entry_free( ctxcsn_e );
631                         } else {
632                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
633                                 if ( ret == LDAP_SUCCESS ) {
634                                         attr = attr_find( ctxcsn_e->e_attrs,
635                                                                           slap_schema.si_ad_syncreplCookie );
636                                         AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
637                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
638                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
639                                         if ( !dryrun ) {
640                                                 ctxcsn_id = be->be_entry_modify( be,
641                                                                                         ctxcsn_e, &bvtext );
642                                                 if( ctxcsn_id == NOID ) {
643                                                         fprintf( stderr, "%s: could not modify ctxcsn "
644                                                                                          "subentry\n", progname);
645                                                         rc = EXIT_FAILURE;
646                                                 }
647                                                 if ( verbose ) {
648                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
649                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
650                                                 }
651                                         } else {
652                                                 if ( verbose ) {
653                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
654                                                                                          ctxcsn_e->e_dn );
655                                                 }
656                                         }
657                                 } else {
658                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
659                                                                          progname);
660                                         rc = EXIT_FAILURE;
661                                 }
662                         }
663                 }
664                 
665                 if ( slap_syncrepl_bv.bv_val ) {
666                         ch_free( slap_syncrepl_bv.bv_val );
667                 }
668                 if ( slap_syncrepl_cn_bv.bv_val ) {
669                         ch_free( slap_syncrepl_cn_bv.bv_val );
670                 }
671         }
672
673         sei = LDAP_SLIST_FIRST( &consumer_subentry );
674         while ( sei ) {
675                 ch_free( sei->cn.bv_val );
676                 ch_free( sei->ndn.bv_val );
677                 ch_free( sei->rdn.bv_val );
678                 ch_free( sei->cookie.bv_val );
679                 LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
680                 ch_free( sei );
681                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
682         }
683
684         ch_free( buf );
685
686         if( be->be_entry_close( be )) rc = EXIT_FAILURE;
687
688         if( be->be_sync ) {
689                 be->be_sync( be );
690         }
691
692         slap_tool_destroy();
693         return rc;
694 }