]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-modify.c
allow selective handling of errors
[openldap] / tests / progs / slapd-modify.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
16 #include "portable.h"
17
18 #include <stdio.h>
19
20 #include <ac/stdlib.h>
21
22 #include <ac/ctype.h>
23 #include <ac/param.h>
24 #include <ac/socket.h>
25 #include <ac/string.h>
26 #include <ac/unistd.h>
27 #include <ac/wait.h>
28
29 #include <ldap.h>
30 #include <lutil.h>
31
32 #include "slapd-common.h"
33
34 #define LOOPS   100
35 #define RETRIES 0
36
37 static void
38 do_modify( char *uri, char *manager, struct berval *passwd,
39                 char *entry, char *attr, char *value, int maxloop,
40                 int maxretries, int delay, int friendly, int chaserefs );
41
42
43 static void
44 usage( char *name )
45 {
46         fprintf( stderr,
47                 "usage: %s "
48                 "-H <uri> | ([-h <host>] -p <port>) "
49                 "-D <manager> "
50                 "-w <passwd> "
51                 "-e <entry> "
52                 "[-i <ignore>] "
53                 "[-l <loops>] "
54                 "[-L <outerloops>] "
55                 "[-r <maxretries>] "
56                 "[-t <delay>] "
57                 "[-F] "
58                 "[-C]\n",
59                         name );
60         exit( EXIT_FAILURE );
61 }
62
63 int
64 main( int argc, char **argv )
65 {
66         int             i;
67         char            *uri = NULL;
68         char            *host = "localhost";
69         int             port = -1;
70         char            *manager = NULL;
71         struct berval   passwd = { 0, NULL };
72         char            *entry = NULL;
73         char            *ava = NULL;
74         char            *value = NULL;
75         int             loops = LOOPS;
76         int             outerloops = 1;
77         int             retries = RETRIES;
78         int             delay = 0;
79         int             friendly = 0;
80         int             chaserefs = 0;
81
82         tester_init( "slapd-modify", TESTER_MODIFY );
83
84         while ( (i = getopt( argc, argv, "CFH:h:i:p:D:w:e:a:l:L:r:t:" )) != EOF ) {
85                 switch ( i ) {
86                 case 'C':
87                         chaserefs++;
88                         break;
89
90                 case 'F':
91                         friendly++;
92                         break;
93
94                 case 'H':               /* the server uri */
95                         uri = strdup( optarg );
96                         break;
97
98                 case 'h':               /* the servers host */
99                         host = strdup( optarg );
100                         break;
101
102                 case 'i':
103                         /* ignored (!) by now */
104                         break;
105
106                 case 'p':               /* the servers port */
107                         if ( lutil_atoi( &port, optarg ) != 0 ) {
108                                 usage( argv[0] );
109                         }
110                         break;
111
112                 case 'D':               /* the servers manager */
113                         manager = strdup( optarg );
114                         break;
115
116                 case 'w':               /* the server managers password */
117                         passwd.bv_val = strdup( optarg );
118                         passwd.bv_len = strlen( optarg );
119                         break;
120
121                 case 'e':               /* entry to modify */
122                         entry = strdup( optarg );
123                         break;
124
125                 case 'a':
126                         ava = strdup( optarg );
127                         break;
128
129                 case 'l':               /* the number of loops */
130                         if ( lutil_atoi( &loops, optarg ) != 0 ) {
131                                 usage( argv[0] );
132                         }
133                         break;
134
135                 case 'L':               /* the number of outerloops */
136                         if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
137                                 usage( argv[0] );
138                         }
139                         break;
140
141                 case 'r':               /* number of retries */
142                         if ( lutil_atoi( &retries, optarg ) != 0 ) {
143                                 usage( argv[0] );
144                         }
145                         break;
146
147                 case 't':               /* delay in seconds */
148                         if ( lutil_atoi( &delay, optarg ) != 0 ) {
149                                 usage( argv[0] );
150                         }
151                         break;
152
153                 default:
154                         usage( argv[0] );
155                         break;
156                 }
157         }
158
159         if (( entry == NULL ) || ( ava == NULL ) || ( port == -1 && uri == NULL ))
160                 usage( argv[0] );
161
162         if ( *entry == '\0' ) {
163
164                 fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
165                                 argv[0] );
166                 exit( EXIT_FAILURE );
167
168         }
169         if ( *ava  == '\0' ) {
170                 fprintf( stderr, "%s: invalid EMPTY AVA.\n",
171                                 argv[0] );
172                 exit( EXIT_FAILURE );
173         }
174         
175         if ( !( value = strchr( ava, ':' ))) {
176                 fprintf( stderr, "%s: invalid AVA.\n",
177                                 argv[0] );
178                 exit( EXIT_FAILURE );
179         }
180         *value++ = '\0'; 
181         while ( *value && isspace( (unsigned char) *value ))
182                 value++;
183
184         uri = tester_uri( uri, host, port );
185
186         for ( i = 0; i < outerloops; i++ ) {
187                 do_modify( uri, manager, &passwd, entry, ava, value,
188                                 loops, retries, delay, friendly, chaserefs );
189         }
190
191         exit( EXIT_SUCCESS );
192 }
193
194
195 static void
196 do_modify( char *uri, char *manager,
197         struct berval *passwd, char *entry, char* attr, char* value,
198         int maxloop, int maxretries, int delay, int friendly, int chaserefs )
199 {
200         LDAP    *ld = NULL;
201         int     i = 0, do_retry = maxretries;
202         pid_t   pid;
203         int     rc = LDAP_SUCCESS;
204
205         struct ldapmod mod;
206         struct ldapmod *mods[2];
207         char *values[2];
208         int version = LDAP_VERSION3;
209
210         pid = getpid();
211         
212         values[0] = value;
213         values[1] = NULL;
214         mod.mod_op = LDAP_MOD_ADD;
215         mod.mod_type = attr;
216         mod.mod_values = values;
217         mods[0] = &mod;
218         mods[1] = NULL;
219
220 retry:;
221         ldap_initialize( &ld, uri );
222         if ( ld == NULL ) {
223                 tester_perror( "ldap_initialize", NULL );
224                 exit( EXIT_FAILURE );
225         }
226
227         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 
228         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
229                 chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
230
231         if ( do_retry == maxretries ) {
232                 fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
233                         (long) pid, maxloop, entry );
234         }
235
236         rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
237         if ( rc != LDAP_SUCCESS ) {
238                 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
239                 switch ( rc ) {
240                 case LDAP_BUSY:
241                 case LDAP_UNAVAILABLE:
242                         if ( do_retry > 0 ) {
243                                 do_retry--;
244                                 if ( delay > 0 ) {
245                                     sleep( delay );
246                                 }
247                                 goto retry;
248                         }
249                 /* fallthru */
250                 default:
251                         break;
252                 }
253                 exit( EXIT_FAILURE );
254         }
255
256         for ( ; i < maxloop; i++ ) {
257                 mod.mod_op = LDAP_MOD_ADD;
258                 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
259                 if ( rc != LDAP_SUCCESS ) {
260                         tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
261                         switch ( rc ) {
262                         case LDAP_TYPE_OR_VALUE_EXISTS:
263                                 /* NOTE: this likely means
264                                  * the second modify failed
265                                  * during the previous round... */
266                                 if ( !friendly ) {
267                                         goto done;
268                                 }
269                                 break;
270
271                         case LDAP_BUSY:
272                         case LDAP_UNAVAILABLE:
273                                 if ( do_retry > 0 ) {
274                                         do_retry--;
275                                         goto retry;
276                                 }
277                                 /* fall thru */
278
279                         default:
280                                 goto done;
281                         }
282                 }
283                 
284                 mod.mod_op = LDAP_MOD_DELETE;
285                 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
286                 if ( rc != LDAP_SUCCESS ) {
287                         tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
288                         switch ( rc ) {
289                         case LDAP_NO_SUCH_ATTRIBUTE:
290                                 /* NOTE: this likely means
291                                  * the first modify failed
292                                  * during the previous round... */
293                                 if ( !friendly ) {
294                                         goto done;
295                                 }
296                                 break;
297
298                         case LDAP_BUSY:
299                         case LDAP_UNAVAILABLE:
300                                 if ( do_retry > 0 ) {
301                                         do_retry--;
302                                         goto retry;
303                                 }
304                                 /* fall thru */
305
306                         default:
307                                 goto done;
308                         }
309                 }
310
311         }
312
313 done:;
314         fprintf( stderr, " PID=%ld - Modify done (%d).\n", (long) pid, rc );
315
316         ldap_unbind_ext( ld, NULL, NULL );
317 }
318
319