xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-modify.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: slapd-modify.c,v 1.3 2021/08/14 16:15:03 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: slapd-modify.c,v 1.3 2021/08/14 16:15:03 christos Exp $");
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 
25 #include "ac/stdlib.h"
26 
27 #include "ac/ctype.h"
28 #include "ac/param.h"
29 #include "ac/socket.h"
30 #include "ac/string.h"
31 #include "ac/unistd.h"
32 #include "ac/wait.h"
33 
34 #include "ldap.h"
35 #include "lutil.h"
36 
37 #include "slapd-common.h"
38 
39 #define LOOPS	100
40 
41 static void
42 do_modify( struct tester_conn_args *config, char *entry,
43 		char *attr, char *value, int friendly );
44 
45 
46 static void
usage(char * name,int opt)47 usage( char *name, int opt )
48 {
49 	if ( opt ) {
50 		fprintf( stderr, "%s: unable to handle option \'%c\'\n\n",
51 			name, opt );
52 	}
53 
54 	fprintf( stderr, "usage: %s " TESTER_COMMON_HELP
55 		"-a <attr:val> "
56 		"-e <entry> "
57 		"[-F]\n",
58 		name );
59 	exit( EXIT_FAILURE );
60 }
61 
62 int
main(int argc,char ** argv)63 main( int argc, char **argv )
64 {
65 	int		i;
66 	char		*entry = NULL;
67 	char		*ava = NULL;
68 	char		*value = NULL;
69 	int		friendly = 0;
70 	struct tester_conn_args	*config;
71 
72 	config = tester_init( "slapd-modify", TESTER_MODIFY );
73 
74 	while ( ( i = getopt( argc, argv, TESTER_COMMON_OPTS "a:e:F" ) ) != EOF )
75 	{
76 		switch ( i ) {
77 		case 'F':
78 			friendly++;
79 			break;
80 
81 		case 'i':
82 			/* ignored (!) by now */
83 			break;
84 
85 		case 'e':		/* entry to modify */
86 			entry = optarg;
87 			break;
88 
89 		case 'a':
90 			ava = optarg;
91 			break;
92 
93 		default:
94 			if ( tester_config_opt( config, i, optarg ) == LDAP_SUCCESS ) {
95 				break;
96 			}
97 			usage( argv[0], i );
98 			break;
99 		}
100 	}
101 
102 	if (( entry == NULL ) || ( ava == NULL ))
103 		usage( argv[0], 0 );
104 
105 	if ( *entry == '\0' ) {
106 
107 		fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
108 				argv[0] );
109 		exit( EXIT_FAILURE );
110 
111 	}
112 	if ( *ava  == '\0' ) {
113 		fprintf( stderr, "%s: invalid EMPTY AVA.\n",
114 				argv[0] );
115 		exit( EXIT_FAILURE );
116 	}
117 
118 	if ( !( value = strchr( ava, ':' ))) {
119 		fprintf( stderr, "%s: invalid AVA.\n",
120 				argv[0] );
121 		exit( EXIT_FAILURE );
122 	}
123 	*value++ = '\0';
124 	while ( *value && isspace( (unsigned char) *value ))
125 		value++;
126 
127 	tester_config_finish( config );
128 
129 	for ( i = 0; i < config->outerloops; i++ ) {
130 		do_modify( config, entry, ava, value, friendly );
131 	}
132 
133 	exit( EXIT_SUCCESS );
134 }
135 
136 
137 static void
do_modify(struct tester_conn_args * config,char * entry,char * attr,char * value,int friendly)138 do_modify( struct tester_conn_args *config,
139 	char *entry, char* attr, char* value, int friendly )
140 {
141 	LDAP	*ld = NULL;
142 	int  	i = 0, do_retry = config->retries;
143 	int     rc = LDAP_SUCCESS;
144 
145 	struct ldapmod mod;
146 	struct ldapmod *mods[2];
147 	char *values[2];
148 
149 	values[0] = value;
150 	values[1] = NULL;
151 	mod.mod_op = LDAP_MOD_ADD;
152 	mod.mod_type = attr;
153 	mod.mod_values = values;
154 	mods[0] = &mod;
155 	mods[1] = NULL;
156 
157 retry:;
158 	if ( ld == NULL ) {
159 		tester_init_ld( &ld, config, 0 );
160 	}
161 
162 	if ( do_retry == config->retries ) {
163 		fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
164 			(long) pid, config->loops, entry );
165 	}
166 
167 	for ( ; i < config->loops; i++ ) {
168 		mod.mod_op = LDAP_MOD_ADD;
169 		rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
170 		if ( rc != LDAP_SUCCESS ) {
171 			tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
172 			switch ( rc ) {
173 			case LDAP_TYPE_OR_VALUE_EXISTS:
174 				/* NOTE: this likely means
175 				 * the second modify failed
176 				 * during the previous round... */
177 				if ( !friendly ) {
178 					goto done;
179 				}
180 				break;
181 
182 			case LDAP_BUSY:
183 			case LDAP_UNAVAILABLE:
184 				if ( do_retry > 0 ) {
185 					do_retry--;
186 					goto retry;
187 				}
188 				/* fall thru */
189 
190 			default:
191 				goto done;
192 			}
193 		}
194 
195 		mod.mod_op = LDAP_MOD_DELETE;
196 		rc = ldap_modify_ext_s( ld, entry, mods, NULL, NULL );
197 		if ( rc != LDAP_SUCCESS ) {
198 			tester_ldap_error( ld, "ldap_modify_ext_s", NULL );
199 			switch ( rc ) {
200 			case LDAP_NO_SUCH_ATTRIBUTE:
201 				/* NOTE: this likely means
202 				 * the first modify failed
203 				 * during the previous round... */
204 				if ( !friendly ) {
205 					goto done;
206 				}
207 				break;
208 
209 			case LDAP_BUSY:
210 			case LDAP_UNAVAILABLE:
211 				if ( do_retry > 0 ) {
212 					do_retry--;
213 					goto retry;
214 				}
215 				/* fall thru */
216 
217 			default:
218 				goto done;
219 			}
220 		}
221 
222 	}
223 
224 done:;
225 	fprintf( stderr, "  PID=%ld - Modify done (%d).\n", (long) pid, rc );
226 
227 	ldap_unbind_ext( ld, NULL, NULL );
228 }
229 
230 
231