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