]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-modify.c
cb416d861180984e3df3edaac42d4dcb98a21454
[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                         memset( optarg, '*', passwd.bv_len );
120                         break;
121
122                 case 'e':               /* entry to modify */
123                         entry = strdup( optarg );
124                         break;
125
126                 case 'a':
127                         ava = strdup( optarg );
128                         break;
129
130                 case 'l':               /* the number of loops */
131                         if ( lutil_atoi( &loops, optarg ) != 0 ) {
132                                 usage( argv[0] );
133                         }
134                         break;
135
136                 case 'L':               /* the number of outerloops */
137                         if ( lutil_atoi( &outerloops, optarg ) != 0 ) {
138                                 usage( argv[0] );
139                         }
140                         break;
141
142                 case 'r':               /* number of retries */
143                         if ( lutil_atoi( &retries, optarg ) != 0 ) {
144                                 usage( argv[0] );
145                         }
146                         break;
147
148                 case 't':               /* delay in seconds */
149                         if ( lutil_atoi( &delay, optarg ) != 0 ) {
150                                 usage( argv[0] );
151                         }
152                         break;
153
154                 default:
155                         usage( argv[0] );
156                         break;
157                 }
158         }
159
160         if (( entry == NULL ) || ( ava == NULL ) || ( port == -1 && uri == NULL ))
161                 usage( argv[0] );
162
163         if ( *entry == '\0' ) {
164
165                 fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
166                                 argv[0] );
167                 exit( EXIT_FAILURE );
168
169         }
170         if ( *ava  == '\0' ) {
171                 fprintf( stderr, "%s: invalid EMPTY AVA.\n",
172                                 argv[0] );
173                 exit( EXIT_FAILURE );
174         }
175         
176         if ( !( value = strchr( ava, ':' ))) {
177                 fprintf( stderr, "%s: invalid AVA.\n",
178                                 argv[0] );
179                 exit( EXIT_FAILURE );
180         }
181         *value++ = '\0'; 
182         while ( *value && isspace( (unsigned char) *value ))
183                 value++;
184
185         uri = tester_uri( uri, host, port );
186
187         for ( i = 0; i < outerloops; i++ ) {
188                 do_modify( uri, manager, &passwd, entry, ava, value,
189                                 loops, retries, delay, friendly, chaserefs );
190         }
191
192         exit( EXIT_SUCCESS );
193 }
194
195
196 static void
197 do_modify( char *uri, char *manager,
198         struct berval *passwd, char *entry, char* attr, char* value,
199         int maxloop, int maxretries, int delay, int friendly, int chaserefs )
200 {
201         LDAP    *ld = NULL;
202         int     i = 0, do_retry = maxretries;
203         pid_t   pid;
204         int     rc = LDAP_SUCCESS;
205
206         struct ldapmod mod;
207         struct ldapmod *mods[2];
208         char *values[2];
209         int version = LDAP_VERSION3;
210
211         pid = getpid();
212         
213         values[0] = value;
214         values[1] = NULL;
215         mod.mod_op = LDAP_MOD_ADD;
216         mod.mod_type = attr;
217         mod.mod_values = values;
218         mods[0] = &mod;
219         mods[1] = NULL;
220
221 retry:;
222         ldap_initialize( &ld, uri );
223         if ( ld == NULL ) {
224                 tester_perror( "ldap_initialize", NULL );
225                 exit( EXIT_FAILURE );
226         }
227
228         (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); 
229         (void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
230                 chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF );
231
232         if ( do_retry == maxretries ) {
233                 fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
234                         (long) pid, maxloop, entry );
235         }
236
237         rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL );
238         if ( rc != LDAP_SUCCESS ) {
239                 tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
240                 switch ( rc ) {
241                 case LDAP_BUSY:
242                 case LDAP_UNAVAILABLE:
243                         if ( do_retry > 0 ) {
244                                 do_retry--;
245                                 if ( delay > 0 ) {
246                                     sleep( delay );
247                                 }
248                                 goto retry;
249                         }
250                 /* fallthru */
251                 default:
252                         break;
253                 }
254                 exit( EXIT_FAILURE );
255         }
256
257         for ( ; i < maxloop; i++ ) {
258                 mod.mod_op = LDAP_MOD_ADD;
259                 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
260                 if ( rc != LDAP_SUCCESS ) {
261                         tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
262                         switch ( rc ) {
263                         case LDAP_TYPE_OR_VALUE_EXISTS:
264                                 /* NOTE: this likely means
265                                  * the second modify failed
266                                  * during the previous round... */
267                                 if ( !friendly ) {
268                                         goto done;
269                                 }
270                                 break;
271
272                         case LDAP_BUSY:
273                         case LDAP_UNAVAILABLE:
274                                 if ( do_retry > 0 ) {
275                                         do_retry--;
276                                         goto retry;
277                                 }
278                                 /* fall thru */
279
280                         default:
281                                 goto done;
282                         }
283                 }
284                 
285                 mod.mod_op = LDAP_MOD_DELETE;
286                 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
287                 if ( rc != LDAP_SUCCESS ) {
288                         tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
289                         switch ( rc ) {
290                         case LDAP_NO_SUCH_ATTRIBUTE:
291                                 /* NOTE: this likely means
292                                  * the first modify failed
293                                  * during the previous round... */
294                                 if ( !friendly ) {
295                                         goto done;
296                                 }
297                                 break;
298
299                         case LDAP_BUSY:
300                         case LDAP_UNAVAILABLE:
301                                 if ( do_retry > 0 ) {
302                                         do_retry--;
303                                         goto retry;
304                                 }
305                                 /* fall thru */
306
307                         default:
308                                 goto done;
309                         }
310                 }
311
312         }
313
314 done:;
315         fprintf( stderr, " PID=%ld - Modify done (%d).\n", (long) pid, rc );
316
317         ldap_unbind_ext( ld, NULL, NULL );
318 }
319
320