]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-modify.c
7525f281a11c7534d1ed23eb5a6c1344675af305
[openldap] / tests / progs / slapd-modify.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2017 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
36 static void
37 do_modify( struct tester_conn_args *config, char *entry,
38                 char *attr, char *value, int friendly );
39
40
41 static void
42 usage( char *name, int opt )
43 {
44         if ( opt ) {
45                 fprintf( stderr, "%s: unable to handle option \'%c\'\n\n",
46                         name, opt );
47         }
48
49         fprintf( stderr, "usage: %s " TESTER_COMMON_HELP
50                 "-a <attr:val> "
51                 "-e <entry> "
52                 "[-F]\n",
53                 name );
54         exit( EXIT_FAILURE );
55 }
56
57 int
58 main( int argc, char **argv )
59 {
60         int             i;
61         char            *entry = NULL;
62         char            *ava = NULL;
63         char            *value = NULL;
64         int             friendly = 0;
65         struct tester_conn_args *config;
66
67         config = tester_init( "slapd-modify", TESTER_MODIFY );
68
69         while ( ( i = getopt( argc, argv, TESTER_COMMON_OPTS "a:e:F" ) ) != EOF )
70         {
71                 switch ( i ) {
72                 case 'F':
73                         friendly++;
74                         break;
75
76                 case 'i':
77                         /* ignored (!) by now */
78                         break;
79
80                 case 'e':               /* entry to modify */
81                         entry = strdup( optarg );
82                         break;
83
84                 case 'a':
85                         ava = strdup( optarg );
86                         break;
87
88                 default:
89                         if ( tester_config_opt( config, i, optarg ) == LDAP_SUCCESS ) {
90                                 break;
91                         }
92                         usage( argv[0], i );
93                         break;
94                 }
95         }
96
97         if (( entry == NULL ) || ( ava == NULL ))
98                 usage( argv[0], 0 );
99
100         if ( *entry == '\0' ) {
101
102                 fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
103                                 argv[0] );
104                 exit( EXIT_FAILURE );
105
106         }
107         if ( *ava  == '\0' ) {
108                 fprintf( stderr, "%s: invalid EMPTY AVA.\n",
109                                 argv[0] );
110                 exit( EXIT_FAILURE );
111         }
112         
113         if ( !( value = strchr( ava, ':' ))) {
114                 fprintf( stderr, "%s: invalid AVA.\n",
115                                 argv[0] );
116                 exit( EXIT_FAILURE );
117         }
118         *value++ = '\0'; 
119         while ( *value && isspace( (unsigned char) *value ))
120                 value++;
121
122         tester_config_finish( config );
123
124         for ( i = 0; i < config->outerloops; i++ ) {
125                 do_modify( config, entry, ava, value, friendly );
126         }
127
128         exit( EXIT_SUCCESS );
129 }
130
131
132 static void
133 do_modify( struct tester_conn_args *config,
134         char *entry, char* attr, char* value, int friendly )
135 {
136         LDAP    *ld = NULL;
137         int     i = 0, do_retry = config->retries;
138         int     rc = LDAP_SUCCESS;
139
140         struct ldapmod mod;
141         struct ldapmod *mods[2];
142         char *values[2];
143
144         values[0] = value;
145         values[1] = NULL;
146         mod.mod_op = LDAP_MOD_ADD;
147         mod.mod_type = attr;
148         mod.mod_values = values;
149         mods[0] = &mod;
150         mods[1] = NULL;
151
152 retry:;
153         tester_init_ld( &ld, config, 0 );
154
155         if ( do_retry == config->retries ) {
156                 fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
157                         (long) pid, config->loops, entry );
158         }
159
160         for ( ; i < config->loops; i++ ) {
161                 mod.mod_op = LDAP_MOD_ADD;
162                 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
163                 if ( rc != LDAP_SUCCESS ) {
164                         tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
165                         switch ( rc ) {
166                         case LDAP_TYPE_OR_VALUE_EXISTS:
167                                 /* NOTE: this likely means
168                                  * the second modify failed
169                                  * during the previous round... */
170                                 if ( !friendly ) {
171                                         goto done;
172                                 }
173                                 break;
174
175                         case LDAP_BUSY:
176                         case LDAP_UNAVAILABLE:
177                                 if ( do_retry > 0 ) {
178                                         do_retry--;
179                                         goto retry;
180                                 }
181                                 /* fall thru */
182
183                         default:
184                                 goto done;
185                         }
186                 }
187                 
188                 mod.mod_op = LDAP_MOD_DELETE;
189                 rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
190                 if ( rc != LDAP_SUCCESS ) {
191                         tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
192                         switch ( rc ) {
193                         case LDAP_NO_SUCH_ATTRIBUTE:
194                                 /* NOTE: this likely means
195                                  * the first modify failed
196                                  * during the previous round... */
197                                 if ( !friendly ) {
198                                         goto done;
199                                 }
200                                 break;
201
202                         case LDAP_BUSY:
203                         case LDAP_UNAVAILABLE:
204                                 if ( do_retry > 0 ) {
205                                         do_retry--;
206                                         goto retry;
207                                 }
208                                 /* fall thru */
209
210                         default:
211                                 goto done;
212                         }
213                 }
214
215         }
216
217 done:;
218         fprintf( stderr, "  PID=%ld - Modify done (%d).\n", (long) pid, rc );
219
220         ldap_unbind_ext( ld, NULL, NULL );
221 }
222
223