]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-modrdn.c
allow selective handling of errors
[openldap] / tests / progs / slapd-modrdn.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2006 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This work was initially developed by Howard Chu, based in part
17  * on other OpenLDAP test tools, for inclusion in OpenLDAP Software.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdlib.h>
25
26 #include <ac/ctype.h>
27 #include <ac/param.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/unistd.h>
31 #include <ac/wait.h>
32
33 #include <ldap.h>
34 #include <lutil.h>
35
36 #include "slapd-common.h"
37
38 #define LOOPS   100
39 #define RETRIES 0
40
41 static void
42 do_modrdn( char *uri, char *manager, struct berval *passwd,
43                 char *entry, int maxloop, int maxretries, int delay,
44                 int friendly, int chaserefs );
45
46 static void
47 usage( char *name )
48 {
49         fprintf( stderr,
50                 "usage: %s "
51                 "-H <uri> | ([-h <host>] -p <port>) "
52                 "-D <manager> "
53                 "-w <passwd> "
54                 "-e <entry> "
55                 "[-i <ignore>] "
56                 "[-l <loops>] "
57                 "[-L <outerloops>] "
58                 "[-r <maxretries>] "
59                 "[-t <delay>] "
60                 "[-F] "
61                 "[-C]\n",
62                         name );
63         exit( EXIT_FAILURE );
64 }
65
66 int
67 main( int argc, char **argv )
68 {
69         int             i;
70         char            *uri = NULL;
71         char            *host = "localhost";
72         int             port = -1;
73         char            *manager = NULL;
74         struct berval   passwd = { 0, NULL };
75         char            *entry = NULL;
76         int             loops = LOOPS;
77         int             outerloops = 1;
78         int             retries = RETRIES;
79         int             delay = 0;
80         int             friendly = 0;
81         int             chaserefs = 0;
82
83         tester_init( "slapd-modrdn", TESTER_MODRDN );
84
85         while ( (i = getopt( argc, argv, "CFH:h:i:p:D:w:e:l:L:r:t:" )) != EOF ) {
86                 switch( i ) {
87                 case 'C':
88                         chaserefs++;
89                         break;
90
91                 case 'F':
92                         friendly++;
93                         break;
94
95                 case 'H':               /* the server uri */
96                         uri = strdup( optarg );
97                         break;
98
99                 case 'h':               /* the servers host */
100                         host = strdup( optarg );
101                         break;
102
103                 case 'i':
104                         /* ignored (!) by now */
105                         break;
106
107                 case 'p':               /* the servers port */
108                         if ( lutil_atoi( &port, optarg ) != 0 ) {
109                                 usage( argv[0] );
110                         }
111                         break;
112
113                 case 'D':               /* the servers manager */
114                         manager = strdup( optarg );
115                         break;
116
117                 case 'w':               /* the server managers password */
118                         passwd.bv_val = strdup( optarg );
119                         passwd.bv_len = strlen( optarg );
120                         break;
121
122                 case 'e':               /* entry to rename */
123                         entry = strdup( optarg );
124                         break;
125
126                 case 'l':               /* the number of loops */
127                         if ( lutil_atoi( &loops, optarg ) != 0 ) {
128                                 usage( argv[0] );
129                         }
130                         break;
131
132                 case 'L':               /* the number of outerloops */
133                         if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
134                                 usage( argv[0] );
135                         }
136                         break;
137
138                 case 'r':               /* the number of retries */
139                         if ( lutil_atoi( &retries, optarg ) != 0 ) {
140                                 usage( argv[0] );
141                         }
142                         break;
143
144                 case 't':               /* delay in seconds */
145                         if ( lutil_atoi( &delay, optarg ) != 0 ) {
146                                 usage( argv[0] );
147                         }
148                         break;
149
150                 default:
151                         usage( argv[0] );
152                         break;
153                 }
154         }
155
156         if (( entry == NULL ) || ( port == -1 && uri == NULL ))
157                 usage( argv[0] );
158
159         if ( *entry == '\0' ) {
160
161                 fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
162                                 argv[0] );
163                 exit( EXIT_FAILURE );
164
165         }
166
167         uri = tester_uri( uri, host, port );
168
169         for ( i = 0; i < outerloops; i++ ) {
170                 do_modrdn( uri, manager, &passwd, entry,
171                         loops, retries, delay, friendly, chaserefs );
172         }
173
174         exit( EXIT_SUCCESS );
175 }
176
177
178 static void
179 do_modrdn( char *uri, char *manager,
180         struct berval *passwd, char *entry, int maxloop, int maxretries,
181         int delay, int friendly, int chaserefs )
182 {
183         LDAP    *ld = NULL;
184         int     i = 0, do_retry = maxretries;
185         pid_t   pid;
186         char    *DNs[2];
187         char    *rdns[2];
188         int     rc = LDAP_SUCCESS;
189         char    *p1, *p2;
190         int     version = LDAP_VERSION3;
191
192         pid = getpid();
193         DNs[0] = entry;
194         DNs[1] = strdup( entry );
195
196         /* reverse the RDN, make new DN */
197         p1 = strchr( entry, '=' ) + 1;
198         p2 = strchr( p1, ',' );
199
200         *p2 = '\0';
201         rdns[1] = strdup( entry );
202         *p2-- = ',';
203
204         for (i = p1 - entry;p2 >= p1;)
205                 DNs[1][i++] = *p2--;
206         
207         DNs[1][i] = '\0';
208         rdns[0] = strdup( DNs[1] );
209         DNs[1][i] = ',';
210
211 retry:;
212         ldap_initialize( &ld, uri );
213         if ( ld == NULL ) {
214                 tester_perror( "ldap_initialize", NULL );
215                 exit( EXIT_FAILURE );
216         }
217
218         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 
219         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
220                 chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
221
222         if ( do_retry == maxretries ) {
223                 fprintf( stderr, "PID=%ld - Modrdn(%d): entry=\"%s\".\n",
224                         (long) pid, maxloop, entry );
225         }
226
227         rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
228         if ( rc != LDAP_SUCCESS ) {
229                 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
230                 switch ( rc ) {
231                 case LDAP_BUSY:
232                 case LDAP_UNAVAILABLE:
233                         if ( do_retry > 0 ) {
234                                 do_retry--;
235                                 if ( delay > 0) {
236                                     sleep( delay );
237                                 }
238                                 goto retry;
239                         }
240                 /* fallthru */
241                 default:
242                         break;
243                 }
244                 exit( EXIT_FAILURE );
245         }
246
247         for ( ; i < maxloop; i++ ) {
248                 rc = ldap_rename_s( ld, DNs[0], rdns[0], NULL, 0, NULL, NULL );
249                 if ( rc != LDAP_SUCCESS ) {
250                         tester_ldap_error( ld, "ldap_rename_s", NULL );
251                         switch ( rc ) {
252                         case LDAP_NO_SUCH_OBJECT:
253                                 /* NOTE: this likely means
254                                  * the second modrdn failed
255                                  * during the previous round... */
256                                 if ( !friendly ) {
257                                         goto done;
258                                 }
259                                 break;
260
261                         case LDAP_BUSY:
262                         case LDAP_UNAVAILABLE:
263                                 if ( do_retry > 0 ) {
264                                         do_retry--;
265                                         goto retry;
266                                 }
267                                 /* fall thru */
268
269                         default:
270                                 goto done;
271                         }
272                 }
273                 rc = ldap_rename_s( ld, DNs[1], rdns[1], NULL, 1, NULL, NULL );
274                 if ( rc != LDAP_SUCCESS ) {
275                         tester_ldap_error( ld, "ldap_rename_s", NULL );
276                         switch ( rc ) {
277                         case LDAP_NO_SUCH_OBJECT:
278                                 /* NOTE: this likely means
279                                  * the first modrdn failed
280                                  * during the previous round... */
281                                 if ( !friendly ) {
282                                         goto done;
283                                 }
284                                 break;
285
286                         case LDAP_BUSY:
287                         case LDAP_UNAVAILABLE:
288                                 if ( do_retry > 0 ) {
289                                         do_retry--;
290                                         goto retry;
291                                 }
292                                 /* fall thru */
293
294                         default:
295                                 goto done;
296                         }
297                 }
298         }
299
300 done:;
301         fprintf( stderr, " PID=%ld - Modrdn done (%d).\n", (long) pid, rc );
302
303         ldap_unbind_ext( ld, NULL, NULL );
304 }
305
306