]> git.sur5r.net Git - openldap/blob - servers/slapd/slapadd.c
fix ACL who logging
[openldap] / servers / slapd / slapadd.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 The OpenLDAP Foundation.
5  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
6  * Portions Copyright 2003 IBM Corporation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Kurt Zeilenga for inclusion
19  * in OpenLDAP Software.  Additional signficant contributors include
20  *    Jong Hyuk Choi
21  *    Pierangelo Masarati
22  */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27
28 #include <ac/stdlib.h>
29
30 #include <ac/ctype.h>
31 #include <ac/string.h>
32 #include <ac/socket.h>
33 #include <ac/unistd.h>
34
35 #include <lber.h>
36 #include <ldif.h>
37 #include <lutil.h>
38
39 #include "slapcommon.h"
40
41 static char csnbuf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
42 static const struct berval slap_syncrepl_bvc = BER_BVC("syncreplxxx");
43 static const struct berval slap_syncrepl_cn_bvc = BER_BVC("cn=syncreplxxx");
44 static struct berval slap_syncrepl_bv = BER_BVNULL;
45 static struct berval slap_syncrepl_cn_bv = BER_BVNULL;
46
47 struct subentryinfo {
48         struct berval cn;
49         struct berval ndn;
50         struct berval rdn;
51         struct berval cookie;
52         LDAP_SLIST_ENTRY( subentryinfo ) sei_next;
53 };
54
55 int
56 slapadd( int argc, char **argv )
57 {
58         char            *buf = NULL;
59         int         lineno;
60         int         lmax;
61         int                     rc = EXIT_SUCCESS;
62
63         const char *text;
64         char textbuf[SLAP_TEXT_BUFLEN] = { '\0' };
65         size_t textlen = sizeof textbuf;
66         const char *progname = "slapadd";
67
68         struct berval csn;
69         struct berval maxcsn = BER_BVNULL;
70         struct berval ldifcsn = BER_BVNULL;
71         int match;
72         int     provider_subentry = 0;
73         struct subentryinfo *sei;
74         LDAP_SLIST_HEAD( consumer_subentry_slist, subentryinfo ) consumer_subentry;
75         Attribute *attr;
76         Entry *ctxcsn_e;
77         ID      ctxcsn_id;
78         struct berval   ctxcsn_ndn = BER_BVNULL;
79         int ret;
80         struct berval bvtext;
81         int i;
82         struct berval mc;
83         struct sync_cookie sc;
84 #ifdef NEW_LOGGING
85         lutil_log_initialize(argc, argv );
86 #endif
87         slap_tool_init( progname, SLAPADD, argc, argv );
88
89         LDAP_SLIST_INIT( &consumer_subentry );
90
91         if( !be->be_entry_open ||
92                 !be->be_entry_close ||
93                 !be->be_entry_put )
94         {
95                 fprintf( stderr, "%s: database doesn't support necessary operations.\n",
96                         progname );
97                 if ( !dryrun ) {
98                         exit( EXIT_FAILURE );
99                 }
100         }
101
102         lmax = 0;
103         lineno = 0;
104
105         if( !dryrun && 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 ( dryrun ) {
314                         if ( verbose ) {
315                                 fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
316                         }
317                         goto done;
318                 }
319
320                 if ( update_ctxcsn == SLAP_TOOL_CTXCSN_KEEP &&
321                         ( replica_promotion || replica_demotion )) {
322                         if ( is_entry_syncProviderSubentry( e )) { 
323                                 if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
324                                         fprintf( stderr, "%s: consumer and provider subentries "
325                                                                          "are both present\n", progname );
326                                         rc = EXIT_FAILURE;
327                                         entry_free( e );
328                                         sei = LDAP_SLIST_FIRST( &consumer_subentry );
329                                         while ( sei ) {
330                                                 ch_free( sei->cn.bv_val );
331                                                 ch_free( sei->ndn.bv_val );
332                                                 ch_free( sei->rdn.bv_val );
333                                                 ch_free( sei->cookie.bv_val );
334                                                 LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
335                                                 ch_free( sei );
336                                                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
337                                         }
338                                         break;
339                                 }
340                                 if ( provider_subentry ) {
341                                         fprintf( stderr, "%s: multiple provider subentries are "
342                                                         "present : add -w flag to refresh\n", progname );
343                                         rc = EXIT_FAILURE;
344                                         entry_free( e );
345                                         break;
346                                 }
347                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
348                                 if ( attr == NULL ) {
349                                         entry_free( e );
350                                         continue;
351                                 }
352                                 provider_subentry = 1;
353                                 ber_dupbv( &maxcsn, &attr->a_nvals[0] );
354                         } else if ( is_entry_syncConsumerSubentry( e )) {
355                                 if ( provider_subentry ) {
356                                         fprintf( stderr, "%s: consumer and provider subentries "
357                                                                          "are both present\n", progname );
358                                         rc = EXIT_FAILURE;
359                                         entry_free( e );
360                                         break;
361                                 }
362
363                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_cn );
364
365                                 if ( attr == NULL ) {
366                                         entry_free( e );
367                                         continue;
368                                 }
369
370                                 if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
371                                         LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
372                                                 value_match( &match, slap_schema.si_ad_cn,
373                                                         slap_schema.si_ad_cn->ad_type->sat_equality,
374                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
375                                                         &sei->cn, &attr->a_nvals[0], &text );
376                                         }
377                                         if ( !match ) {
378                                                 fprintf( stderr, "%s: multiple consumer subentries "
379                                                                 "have the same id : add -w flag to refresh\n",
380                                                                 progname );
381                                                 rc = EXIT_FAILURE;
382                                                 entry_free( e );
383                                                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
384                                                 while ( sei ) {
385                                                         ch_free( sei->cn.bv_val );
386                                                         ch_free( sei->ndn.bv_val );
387                                                         ch_free( sei->rdn.bv_val );
388                                                         ch_free( sei->cookie.bv_val );
389                                                         LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
390                                                         ch_free( sei );
391                                                         sei = LDAP_SLIST_FIRST( &consumer_subentry );
392                                                 }
393                                                 break;
394                                         }
395                                 }
396                                 sei = ch_calloc( 1, sizeof( struct subentryinfo ));
397                                 ber_dupbv( &sei->cn, &attr->a_nvals[0] );
398                                 ber_dupbv( &sei->ndn, &e->e_nname );
399                                 dnExtractRdn( &sei->ndn, &sei->rdn, NULL );
400                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_syncreplCookie );
401                                 if ( attr == NULL ) {
402                                         ch_free( sei->cn.bv_val );
403                                         ch_free( sei->ndn.bv_val );
404                                         ch_free( sei->rdn.bv_val );
405                                         ch_free( sei->cookie.bv_val );
406                                         ch_free( sei );
407                                         entry_free( e );
408                                         continue;
409                                 }
410                                 ber_dupbv( &sei->cookie, &attr->a_nvals[0] );
411                                 LDAP_SLIST_INSERT_HEAD( &consumer_subentry, sei, sei_next );
412                         }
413                 }
414
415                 if (( !is_entry_syncProviderSubentry( e ) &&
416                                  !is_entry_syncConsumerSubentry( e )) ||
417                                  ( !replica_promotion && !replica_demotion ))
418                 {
419                         /* dryrun moved earlier */
420                         assert( !dryrun );
421
422                         if (!dryrun) {
423                                 ID id = be->be_entry_put( be, e, &bvtext );
424                                 if( id == NOID ) {
425                                         fprintf( stderr, "%s: could not add entry dn=\"%s\" "
426                                                                          "(line=%d): %s\n", progname, e->e_dn,
427                                                                          lineno, bvtext.bv_val );
428                                         rc = EXIT_FAILURE;
429                                         entry_free( e );
430                                         if( continuemode ) continue;
431                                         break;
432                                 }
433         
434                                 if ( verbose ) {
435                                         fprintf( stderr, "added: \"%s\" (%08lx)\n",
436                                                 e->e_dn, (long) id );
437                                 }
438                         } else {
439                                 if ( verbose ) {
440                                         fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
441                                 }
442                         }
443                 }
444
445 done:;
446                 entry_free( e );
447         }
448
449         bvtext.bv_len = textlen;
450         bvtext.bv_val = textbuf;
451         bvtext.bv_val[0] = '\0';
452
453         if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
454                 maxcsn.bv_len = 0;
455                 maxcsn.bv_val = NULL;
456                 LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
457                         sc.octet_str = &sei->cookie;
458                         slap_parse_sync_cookie( &sc );
459                         if ( maxcsn.bv_len != 0 ) {
460                                 value_match( &match, slap_schema.si_ad_syncreplCookie,
461                                         slap_schema.si_ad_syncreplCookie->ad_type->sat_ordering,
462                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
463                                         &maxcsn, &sc.ctxcsn[0], &text );
464                         } else {
465                                 match = -1;
466                         }
467                         if ( match < 0 ) {
468                                 if ( maxcsn.bv_val )
469                                         ch_free( maxcsn.bv_val );
470                                 ber_dupbv( &maxcsn, &sc.ctxcsn[0] );
471                         }
472                         sc.octet_str = NULL;
473                         slap_sync_cookie_free( &sc, 0 );
474                 }
475         }
476
477         slap_compose_sync_cookie( NULL, &mc, &maxcsn, -1, -1 );
478
479         if ( SLAP_LASTMOD(be) && replica_promotion ) {
480                 if ( provider_subentry || update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
481                          !LDAP_SLIST_EMPTY( &consumer_subentry )) {
482                         build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
483                                                   (struct berval *)&slap_ldapsync_cn_bv, NULL );
484                         ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
485                 
486                         if ( ctxcsn_id == NOID ) {
487                                 ctxcsn_e = slap_create_context_csn_entry( be, &maxcsn );
488                                 
489                                 /* dryrun moved earlier */
490                                 assert( !dryrun );
491
492                                 if ( !dryrun ) {
493                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
494                                         if( ctxcsn_id == NOID ) {
495                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
496                                                                                  progname);
497                                                 rc = EXIT_FAILURE;
498                                         }
499                                         if ( verbose ) {
500                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
501                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
502                                         }
503                                 } else {
504                                         if ( verbose ) {
505                                                 fprintf( stderr, "(dry) added: \"%s\"\n", ctxcsn_e->e_dn );
506                                         }
507                                 }
508                                 entry_free( ctxcsn_e );
509                         } else {
510                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
511                                 if ( ret == LDAP_SUCCESS ) {
512                                         attr = attr_find( ctxcsn_e->e_attrs,
513                                                                                 slap_schema.si_ad_contextCSN );
514                                         AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
515                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
516                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
517                                 
518                                         /* dryrun moved earlier */
519                                         assert( !dryrun );
520
521                                         if ( !dryrun ) {
522                                                 ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
523                                                 if( ctxcsn_id == NOID ) {
524                                                         fprintf( stderr, "%s: could not modify ctxcsn "
525                                                                                          "subentry\n", progname);
526                                                         rc = EXIT_FAILURE;
527                                                 }
528                                                 if ( verbose ) {
529                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
530                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
531                                                 }
532                                         } else {
533                                                 if ( verbose ) {
534                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
535                                                                                          ctxcsn_e->e_dn );
536                                                 }
537                                         }
538                                 } else {
539                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
540                                                                          progname);
541                                         rc = EXIT_FAILURE;
542                                 }
543                         }
544                 } 
545         } else if ( SLAP_LASTMOD(be) && replica_demotion &&
546                                 ( update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
547                                 provider_subentry )) {
548
549                 ber_dupbv( &slap_syncrepl_bv, (struct berval *) &slap_syncrepl_bvc );
550                 ber_dupbv( &slap_syncrepl_cn_bv,
551                                         (struct berval *) &slap_syncrepl_cn_bvc );
552
553                 if ( replica_id_list == NULL ) {
554                         replica_id_list = ch_calloc( 2, sizeof( int ));
555                         replica_id_list[0] = 0;
556                         replica_id_list[1] = -1;
557                 }
558
559                 for ( i = 0; replica_id_list[i] > -1 ; i++ ) {
560                         slap_syncrepl_bv.bv_len = snprintf( slap_syncrepl_bv.bv_val,
561                                                                         slap_syncrepl_bvc.bv_len+1,
562                                                                         "syncrepl%d", replica_id_list[i] );
563                         slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
564                                                                                 slap_syncrepl_cn_bvc.bv_len+1,
565                                                                                 "cn=syncrepl%d", replica_id_list[i] );
566                         build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
567                                                   (struct berval *)&slap_syncrepl_cn_bv, NULL );
568                         ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
569
570                         if ( ctxcsn_id == NOID ) {
571                                 ctxcsn_e = slap_create_syncrepl_entry( be, &mc,
572                                                 &slap_syncrepl_cn_bv,
573                                                 &slap_syncrepl_bv );
574
575                                 /* dryrun moved earlier */
576                                 assert( !dryrun );
577
578                                 if ( !dryrun ) {
579                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
580                                         if( ctxcsn_id == NOID ) {
581                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
582                                                                                  progname);
583                                                 rc = EXIT_FAILURE;
584                                         }
585                                         if ( verbose ) {
586                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
587                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
588                                         }
589                                 } else {
590                                         if ( verbose ) {
591                                                 fprintf( stderr, "(dry) added: \"%s\"\n",
592                                                                                         ctxcsn_e->e_dn );
593                                         }
594                                 }
595                                 entry_free( ctxcsn_e );
596                         } else {
597                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
598                                 if ( ret == LDAP_SUCCESS ) {
599                                         attr = attr_find( ctxcsn_e->e_attrs,
600                                                                           slap_schema.si_ad_syncreplCookie );
601                                         AC_MEMCPY( attr->a_vals[0].bv_val, mc.bv_val, mc.bv_len );
602                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
603                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
604                                 
605                                         /* dryrun moved earlier */
606                                         assert( !dryrun );
607
608                                         if ( !dryrun ) {
609                                                 ctxcsn_id = be->be_entry_modify( be,
610                                                                                         ctxcsn_e, &bvtext );
611                                                 if( ctxcsn_id == NOID ) {
612                                                         fprintf( stderr, "%s: could not modify ctxcsn "
613                                                                                          "subentry\n", progname);
614                                                         rc = EXIT_FAILURE;
615                                                 }
616                                                 if ( verbose ) {
617                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
618                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
619                                                 }
620                                         } else {
621                                                 if ( verbose ) {
622                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
623                                                                                          ctxcsn_e->e_dn );
624                                                 }
625                                         }
626                                 } else {
627                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
628                                                                          progname);
629                                         rc = EXIT_FAILURE;
630                                 }
631                         }
632                 }
633                 
634                 if ( slap_syncrepl_bv.bv_val ) {
635                         ch_free( slap_syncrepl_bv.bv_val );
636                 }
637                 if ( slap_syncrepl_cn_bv.bv_val ) {
638                         ch_free( slap_syncrepl_cn_bv.bv_val );
639                 }
640         } else if ( SLAP_LASTMOD(be) && replica_demotion &&
641                                 !LDAP_SLIST_EMPTY( &consumer_subentry )) {
642
643                 LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
644                         ctxcsn_id = be->be_dn2id_get( be, &sei->ndn );
645
646                         if ( ctxcsn_id == NOID ) {
647                                 ctxcsn_e = slap_create_syncrepl_entry( be, &sei->cookie,
648                                                 &sei->rdn, &sei->cn );
649
650                                 /* dryrun moved earlier */
651                                 assert( !dryrun );
652
653                                 if ( !dryrun ) {
654                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
655                                         if( ctxcsn_id == NOID ) {
656                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
657                                                                                  progname);
658                                                 rc = EXIT_FAILURE;
659                                         }
660                                         if ( verbose ) {
661                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
662                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
663                                         }
664                                 } else {
665                                         if ( verbose ) {
666                                                 fprintf( stderr, "(dry) added: \"%s\"\n",
667                                                                                         ctxcsn_e->e_dn );
668                                         }
669                                 }
670                                 entry_free( ctxcsn_e );
671                         } else {
672                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
673                                 if ( ret == LDAP_SUCCESS ) {
674                                         attr = attr_find( ctxcsn_e->e_attrs,
675                                                                           slap_schema.si_ad_syncreplCookie );
676                                         AC_MEMCPY( attr->a_vals[0].bv_val, sei->cookie.bv_val, sei->cookie.bv_len );
677                                         attr->a_vals[0].bv_val[sei->cookie.bv_len] = '\0';
678                                         attr->a_vals[0].bv_len = sei->cookie.bv_len;
679                                         
680                                         /* dryrun moved earlier */
681                                         assert( !dryrun );
682
683                                         if ( !dryrun ) {
684                                                 ctxcsn_id = be->be_entry_modify( be,
685                                                                                         ctxcsn_e, &bvtext );
686                                                 if( ctxcsn_id == NOID ) {
687                                                         fprintf( stderr, "%s: could not modify ctxcsn "
688                                                                                          "subentry\n", progname);
689                                                         rc = EXIT_FAILURE;
690                                                 }
691                                                 if ( verbose ) {
692                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
693                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
694                                                 }
695                                         } else {
696                                                 if ( verbose ) {
697                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
698                                                                                          ctxcsn_e->e_dn );
699                                                 }
700                                         }
701                                 } else {
702                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
703                                                                          progname);
704                                         rc = EXIT_FAILURE;
705                                 }
706                         }
707                 }
708                 
709                 if ( slap_syncrepl_bv.bv_val ) {
710                         ch_free( slap_syncrepl_bv.bv_val );
711                 }
712                 if ( slap_syncrepl_cn_bv.bv_val ) {
713                         ch_free( slap_syncrepl_cn_bv.bv_val );
714                 }
715         }
716
717         sei = LDAP_SLIST_FIRST( &consumer_subentry );
718         while ( sei ) {
719                 ch_free( sei->cn.bv_val );
720                 ch_free( sei->ndn.bv_val );
721                 ch_free( sei->rdn.bv_val );
722                 ch_free( sei->cookie.bv_val );
723                 LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
724                 ch_free( sei );
725                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
726         }
727
728         ch_free( buf );
729
730         if ( !dryrun ) {
731                 if( be->be_entry_close( be ) ) {
732                         rc = EXIT_FAILURE;
733                 }
734
735                 if( be->be_sync ) {
736                         be->be_sync( be );
737                 }
738         }
739
740         slap_tool_destroy();
741         return rc;
742 }