]> git.sur5r.net Git - openldap/blob - servers/slapd/slapadd.c
reintroduce changes made in tools/slapadd.c v1.64 (looks like missing during code...
[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                         ( replica_promotion || replica_demotion )) {
313                         if ( is_entry_syncProviderSubentry( e )) { 
314                                 if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
315                                         fprintf( stderr, "%s: consumer and provider subentries "
316                                                                          "are both present\n", progname );
317                                         rc = EXIT_FAILURE;
318                                         entry_free( e );
319                                         sei = LDAP_SLIST_FIRST( &consumer_subentry );
320                                         while ( sei ) {
321                                                 ch_free( sei->cn.bv_val );
322                                                 ch_free( sei->ndn.bv_val );
323                                                 ch_free( sei->rdn.bv_val );
324                                                 ch_free( sei->cookie.bv_val );
325                                                 LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
326                                                 ch_free( sei );
327                                                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
328                                         }
329                                         break;
330                                 }
331                                 if ( provider_subentry ) {
332                                         fprintf( stderr, "%s: multiple provider subentries are "
333                                                         "present : add -w flag to refresh\n", progname );
334                                         rc = EXIT_FAILURE;
335                                         entry_free( e );
336                                         break;
337                                 }
338                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN );
339                                 if ( attr == NULL ) {
340                                         entry_free( e );
341                                         continue;
342                                 }
343                                 provider_subentry = 1;
344                                 ber_dupbv( &maxcsn, &attr->a_nvals[0] );
345                         } else if ( is_entry_syncConsumerSubentry( e )) {
346                                 if ( provider_subentry ) {
347                                         fprintf( stderr, "%s: consumer and provider subentries "
348                                                                          "are both present\n", progname );
349                                         rc = EXIT_FAILURE;
350                                         entry_free( e );
351                                         break;
352                                 }
353
354                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_cn );
355
356                                 if ( attr == NULL ) {
357                                         entry_free( e );
358                                         continue;
359                                 }
360
361                                 if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
362                                         LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
363                                                 value_match( &match, slap_schema.si_ad_cn,
364                                                         slap_schema.si_ad_cn->ad_type->sat_equality,
365                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
366                                                         &sei->cn, &attr->a_nvals[0], &text );
367                                         }
368                                         if ( !match ) {
369                                                 fprintf( stderr, "%s: multiple consumer subentries "
370                                                                 "have the same id : add -w flag to refresh\n",
371                                                                 progname );
372                                                 rc = EXIT_FAILURE;
373                                                 entry_free( e );
374                                                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
375                                                 while ( sei ) {
376                                                         ch_free( sei->cn.bv_val );
377                                                         ch_free( sei->ndn.bv_val );
378                                                         ch_free( sei->rdn.bv_val );
379                                                         ch_free( sei->cookie.bv_val );
380                                                         LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
381                                                         ch_free( sei );
382                                                         sei = LDAP_SLIST_FIRST( &consumer_subentry );
383                                                 }
384                                                 break;
385                                         }
386                                 }
387                                 sei = ch_calloc( 1, sizeof( struct subentryinfo ));
388                                 ber_dupbv( &sei->cn, &attr->a_nvals[0] );
389                                 ber_dupbv( &sei->ndn, &e->e_nname );
390                                 dnExtractRdn( &sei->ndn, &sei->rdn, NULL );
391                                 attr = attr_find( e->e_attrs, slap_schema.si_ad_syncreplCookie );
392                                 if ( attr == NULL ) {
393                                         ch_free( sei->cn.bv_val );
394                                         ch_free( sei->ndn.bv_val );
395                                         ch_free( sei->rdn.bv_val );
396                                         ch_free( sei->cookie.bv_val );
397                                         ch_free( sei );
398                                         entry_free( e );
399                                         continue;
400                                 }
401                                 ber_dupbv( &sei->cookie, &attr->a_nvals[0] );
402                                 LDAP_SLIST_INSERT_HEAD( &consumer_subentry, sei, sei_next );
403                         }
404                 }
405
406                 if (( !is_entry_syncProviderSubentry( e ) &&
407                          !is_entry_syncConsumerSubentry( e )) ||
408                          ( !replica_promotion && !replica_demotion )) {
409                         if (!dryrun) {
410                                 ID id = be->be_entry_put( be, e, &bvtext );
411                                 if( id == NOID ) {
412                                         fprintf( stderr, "%s: could not add entry dn=\"%s\" "
413                                                                          "(line=%d): %s\n", progname, e->e_dn,
414                                                                          lineno, bvtext.bv_val );
415                                         rc = EXIT_FAILURE;
416                                         entry_free( e );
417                                         if( continuemode ) continue;
418                                         break;
419                                 }
420         
421                                 if ( verbose ) {
422                                         fprintf( stderr, "added: \"%s\" (%08lx)\n",
423                                                 e->e_dn, (long) id );
424                                 }
425                         } else {
426                                 if ( verbose ) {
427                                         fprintf( stderr, "(dry) added: \"%s\"\n", e->e_dn );
428                                 }
429                         }
430                 }
431
432                 entry_free( e );
433         }
434
435         bvtext.bv_len = textlen;
436         bvtext.bv_val = textbuf;
437         bvtext.bv_val[0] = '\0';
438
439         if ( !LDAP_SLIST_EMPTY( &consumer_subentry )) {
440                 maxcsn.bv_len = 0;
441                 maxcsn.bv_val = NULL;
442                 LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
443                         sc.octet_str = &sei->cookie;
444                         slap_parse_sync_cookie( &sc );
445                         if ( maxcsn.bv_len != 0 ) {
446                                 value_match( &match, slap_schema.si_ad_syncreplCookie,
447                                         slap_schema.si_ad_syncreplCookie->ad_type->sat_ordering,
448                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
449                                         &maxcsn, &sc.ctxcsn[0], &text );
450                         } else {
451                                 match = -1;
452                         }
453                         if ( match < 0 ) {
454                                 if ( maxcsn.bv_val )
455                                         ch_free( maxcsn.bv_val );
456                                 ber_dupbv( &maxcsn, &sc.ctxcsn[0] );
457                         }
458                         sc.octet_str = NULL;
459                         slap_sync_cookie_free( &sc, 0 );
460                 }
461         }
462
463         slap_compose_sync_cookie( NULL, &mc, &maxcsn, -1, -1 );
464
465         if ( SLAP_LASTMOD(be) && replica_promotion ) {
466                 if ( provider_subentry || update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
467                          !LDAP_SLIST_EMPTY( &consumer_subentry )) {
468                         build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
469                                                   (struct berval *)&slap_ldapsync_cn_bv, NULL );
470                         ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
471                 
472                         if ( ctxcsn_id == NOID ) {
473                                 ctxcsn_e = slap_create_context_csn_entry( be, &maxcsn );
474                                 if ( !dryrun ) {
475                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
476                                         if( ctxcsn_id == NOID ) {
477                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
478                                                                                  progname);
479                                                 rc = EXIT_FAILURE;
480                                         }
481                                         if ( verbose ) {
482                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
483                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
484                                         }
485                                 } else {
486                                         if ( verbose ) {
487                                                 fprintf( stderr, "(dry) added: \"%s\"\n", ctxcsn_e->e_dn );
488                                         }
489                                 }
490                                 entry_free( ctxcsn_e );
491                         } else {
492                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
493                                 if ( ret == LDAP_SUCCESS ) {
494                                         attr = attr_find( ctxcsn_e->e_attrs,
495                                                                                 slap_schema.si_ad_contextCSN );
496                                         AC_MEMCPY( attr->a_vals[0].bv_val, maxcsn.bv_val, maxcsn.bv_len );
497                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
498                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
499                                         if ( !dryrun ) {
500                                                 ctxcsn_id = be->be_entry_modify( be, ctxcsn_e, &bvtext );
501                                                 if( ctxcsn_id == NOID ) {
502                                                         fprintf( stderr, "%s: could not modify ctxcsn "
503                                                                                          "subentry\n", progname);
504                                                         rc = EXIT_FAILURE;
505                                                 }
506                                                 if ( verbose ) {
507                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
508                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
509                                                 }
510                                         } else {
511                                                 if ( verbose ) {
512                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
513                                                                                          ctxcsn_e->e_dn );
514                                                 }
515                                         }
516                                 } else {
517                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
518                                                                          progname);
519                                         rc = EXIT_FAILURE;
520                                 }
521                         }
522                 } 
523         } else if ( SLAP_LASTMOD(be) && replica_demotion &&
524                                 ( update_ctxcsn == SLAP_TOOL_CTXCSN_BATCH ||
525                                 provider_subentry )) {
526
527                 ber_dupbv( &slap_syncrepl_bv, (struct berval *) &slap_syncrepl_bvc );
528                 ber_dupbv( &slap_syncrepl_cn_bv,
529                                         (struct berval *) &slap_syncrepl_cn_bvc );
530
531                 if ( replica_id_list == NULL ) {
532                         replica_id_list = ch_calloc( 2, sizeof( int ));
533                         replica_id_list[0] = 0;
534                         replica_id_list[1] = -1;
535                 }
536
537                 for ( i = 0; replica_id_list[i] > -1 ; i++ ) {
538                         slap_syncrepl_bv.bv_len = snprintf( slap_syncrepl_bv.bv_val,
539                                                                         slap_syncrepl_bvc.bv_len,
540                                                                         "syncrepl%d", replica_id_list[i] );
541                         slap_syncrepl_cn_bv.bv_len = snprintf( slap_syncrepl_cn_bv.bv_val,
542                                                                                 slap_syncrepl_cn_bvc.bv_len,
543                                                                                 "cn=syncrepl%d", replica_id_list[i] );
544                         build_new_dn( &ctxcsn_ndn, &be->be_nsuffix[0],
545                                                   (struct berval *)&slap_syncrepl_cn_bv, NULL );
546                         ctxcsn_id = be->be_dn2id_get( be, &ctxcsn_ndn );
547
548                         if ( ctxcsn_id == NOID ) {
549                                 ctxcsn_e = slap_create_syncrepl_entry( be, &mc,
550                                                                                                 &slap_syncrepl_cn_bv,
551                                                                                                 &slap_syncrepl_bv );
552                                 if ( !dryrun ) {
553                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
554                                         if( ctxcsn_id == NOID ) {
555                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
556                                                                                  progname);
557                                                 rc = EXIT_FAILURE;
558                                         }
559                                         if ( verbose ) {
560                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
561                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
562                                         }
563                                 } else {
564                                         if ( verbose ) {
565                                                 fprintf( stderr, "(dry) added: \"%s\"\n",
566                                                                                         ctxcsn_e->e_dn );
567                                         }
568                                 }
569                                 entry_free( ctxcsn_e );
570                         } else {
571                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
572                                 if ( ret == LDAP_SUCCESS ) {
573                                         attr = attr_find( ctxcsn_e->e_attrs,
574                                                                           slap_schema.si_ad_syncreplCookie );
575                                         AC_MEMCPY( attr->a_vals[0].bv_val, mc.bv_val, mc.bv_len );
576                                         attr->a_vals[0].bv_val[maxcsn.bv_len] = '\0';
577                                         attr->a_vals[0].bv_len = maxcsn.bv_len;
578                                         if ( !dryrun ) {
579                                                 ctxcsn_id = be->be_entry_modify( be,
580                                                                                         ctxcsn_e, &bvtext );
581                                                 if( ctxcsn_id == NOID ) {
582                                                         fprintf( stderr, "%s: could not modify ctxcsn "
583                                                                                          "subentry\n", progname);
584                                                         rc = EXIT_FAILURE;
585                                                 }
586                                                 if ( verbose ) {
587                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
588                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
589                                                 }
590                                         } else {
591                                                 if ( verbose ) {
592                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
593                                                                                          ctxcsn_e->e_dn );
594                                                 }
595                                         }
596                                 } else {
597                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
598                                                                          progname);
599                                         rc = EXIT_FAILURE;
600                                 }
601                         }
602                 }
603                 
604                 if ( slap_syncrepl_bv.bv_val ) {
605                         ch_free( slap_syncrepl_bv.bv_val );
606                 }
607                 if ( slap_syncrepl_cn_bv.bv_val ) {
608                         ch_free( slap_syncrepl_cn_bv.bv_val );
609                 }
610         } else if ( SLAP_LASTMOD(be) && replica_demotion &&
611                                 !LDAP_SLIST_EMPTY( &consumer_subentry )) {
612
613                 LDAP_SLIST_FOREACH( sei, &consumer_subentry, sei_next ) {
614                         ctxcsn_id = be->be_dn2id_get( be, &sei->ndn );
615
616                         if ( ctxcsn_id == NOID ) {
617                                 ctxcsn_e = slap_create_syncrepl_entry( be, &sei->cookie,
618                                                                                                 &sei->rdn, &sei->cn );
619                                 if ( !dryrun ) {
620                                         ctxcsn_id = be->be_entry_put( be, ctxcsn_e, &bvtext );
621                                         if( ctxcsn_id == NOID ) {
622                                                 fprintf( stderr, "%s: could not add ctxcsn subentry\n",
623                                                                                  progname);
624                                                 rc = EXIT_FAILURE;
625                                         }
626                                         if ( verbose ) {
627                                                 fprintf( stderr, "added: \"%s\" (%08lx)\n",
628                                                                                  ctxcsn_e->e_dn, (long) ctxcsn_id );
629                                         }
630                                 } else {
631                                         if ( verbose ) {
632                                                 fprintf( stderr, "(dry) added: \"%s\"\n",
633                                                                                         ctxcsn_e->e_dn );
634                                         }
635                                 }
636                                 entry_free( ctxcsn_e );
637                         } else {
638                                 ret = be->be_id2entry_get( be, ctxcsn_id, &ctxcsn_e );
639                                 if ( ret == LDAP_SUCCESS ) {
640                                         attr = attr_find( ctxcsn_e->e_attrs,
641                                                                           slap_schema.si_ad_syncreplCookie );
642                                         AC_MEMCPY( attr->a_vals[0].bv_val, sei->cookie.bv_val, sei->cookie.bv_len );
643                                         attr->a_vals[0].bv_val[sei->cookie.bv_len] = '\0';
644                                         attr->a_vals[0].bv_len = sei->cookie.bv_len;
645                                         if ( !dryrun ) {
646                                                 ctxcsn_id = be->be_entry_modify( be,
647                                                                                         ctxcsn_e, &bvtext );
648                                                 if( ctxcsn_id == NOID ) {
649                                                         fprintf( stderr, "%s: could not modify ctxcsn "
650                                                                                          "subentry\n", progname);
651                                                         rc = EXIT_FAILURE;
652                                                 }
653                                                 if ( verbose ) {
654                                                         fprintf( stderr, "modified: \"%s\" (%08lx)\n",
655                                                                                          ctxcsn_e->e_dn, (long) ctxcsn_id );
656                                                 }
657                                         } else {
658                                                 if ( verbose ) {
659                                                         fprintf( stderr, "(dry) modified: \"%s\"\n",
660                                                                                          ctxcsn_e->e_dn );
661                                                 }
662                                         }
663                                 } else {
664                                         fprintf( stderr, "%s: could not modify ctxcsn subentry\n",
665                                                                          progname);
666                                         rc = EXIT_FAILURE;
667                                 }
668                         }
669                 }
670                 
671                 if ( slap_syncrepl_bv.bv_val ) {
672                         ch_free( slap_syncrepl_bv.bv_val );
673                 }
674                 if ( slap_syncrepl_cn_bv.bv_val ) {
675                         ch_free( slap_syncrepl_cn_bv.bv_val );
676                 }
677         }
678
679         sei = LDAP_SLIST_FIRST( &consumer_subentry );
680         while ( sei ) {
681                 ch_free( sei->cn.bv_val );
682                 ch_free( sei->ndn.bv_val );
683                 ch_free( sei->rdn.bv_val );
684                 ch_free( sei->cookie.bv_val );
685                 LDAP_SLIST_REMOVE_HEAD( &consumer_subentry, sei_next );
686                 ch_free( sei );
687                 sei = LDAP_SLIST_FIRST( &consumer_subentry );
688         }
689
690         ch_free( buf );
691
692         if( be->be_entry_close( be )) rc = EXIT_FAILURE;
693
694         if( be->be_sync ) {
695                 be->be_sync( be );
696         }
697
698         slap_tool_destroy();
699         return rc;
700 }