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