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