]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ext.c
multiple precision with BIGNUM/gmp/ulong
[openldap] / servers / slapd / slapi / slapi_ext.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003-2004 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 the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* (C) Copyright PADL Software Pty Ltd. 2003
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that this notice is preserved
18  * and that due credit is given to PADL Software Pty Ltd. This software
19  * is provided ``as is'' without express or implied warranty.
20  */
21 /* ACKNOWLEDGEMENTS:
22  * This work was initially developed by Luke Howard for inclusion
23  * in OpenLDAP Software.
24  */
25
26 #include "portable.h"
27
28 #include <ac/string.h>
29 #include <ac/stdarg.h>
30 #include <ac/ctype.h>
31 #include <ac/unistd.h>
32
33 #include <slap.h>
34 #include <slapi.h>
35
36 #ifdef LDAP_SLAPI
37 /*
38  * Object extensions
39  *
40  * We only support two types -- connection and operation extensions.
41  * Define more types in slapi.h
42  */
43
44 /* global state */
45 struct slapi_registered_extension_set {
46         ldap_pvt_thread_mutex_t mutex;
47         struct slapi_registered_extension {
48                 int active;
49                 int count;
50                 slapi_extension_constructor_fnptr *constructors;
51                 slapi_extension_destructor_fnptr *destructors;
52         } extensions[SLAPI_X_EXT_MAX];
53 } registered_extensions;
54
55 /* per-object state */
56 struct slapi_extension_block {
57         void **extensions;
58 };
59
60 static int get_extension_block(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
61 {
62         switch ((slapi_extension_t) objecttype) {
63         case SLAPI_X_EXT_CONNECTION:
64                 *eblock = ((Connection *)object)->c_extensions;
65                 *parent = NULL;
66                 break;  
67         case SLAPI_X_EXT_OPERATION:
68                 *eblock = ((Operation *)object)->o_extensions;
69                 *parent = ((Operation *)object)->o_conn;
70                 break;  
71         default:
72                 return -1;
73                 break;
74         }
75
76         if ( *eblock == NULL ) {
77                 return -1;
78         }
79
80         return 0;
81 }
82
83 static int map_extension_type(const char *objectname, slapi_extension_t *type)
84 {
85         if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) {
86                 *type = SLAPI_X_EXT_CONNECTION;
87         } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) {
88                 *type = SLAPI_X_EXT_OPERATION;
89         } else {
90                 return -1;
91         }
92
93         return 0;
94 }
95
96 static void new_extension(struct slapi_extension_block *eblock,
97         int objecttype, void *object, void *parent,
98         int extensionhandle )
99 {
100         slapi_extension_constructor_fnptr constructor;
101
102         assert( objecttype < SLAPI_X_EXT_MAX );
103         assert( extensionhandle < registered_extensions.extensions[objecttype].count );
104
105         assert( registered_extensions.extensions[objecttype].constructors != NULL );
106         constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
107
108         assert( eblock->extensions[extensionhandle] == NULL );
109
110         if ( constructor != NULL ) {
111                 eblock->extensions[extensionhandle] = (*constructor)( object, parent );
112         } else {
113                 eblock->extensions[extensionhandle] = NULL;
114         }
115 }
116
117 static void free_extension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
118 {
119         slapi_extension_destructor_fnptr destructor;
120
121         assert( objecttype < SLAPI_X_EXT_MAX );
122         assert( extensionhandle < registered_extensions.extensions[objecttype].count );
123
124         if ( eblock->extensions[extensionhandle] != NULL ) {
125                 assert( registered_extensions.extensions[objecttype].destructors != NULL );
126                 destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle];
127                 if ( destructor != NULL ) {
128                         (*destructor)( eblock->extensions[extensionhandle], object, parent );
129                 }
130                 eblock->extensions[extensionhandle] = NULL;
131         }
132 }
133 #endif /* LDAP_SLAPI */
134
135 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
136 {
137 #ifdef LDAP_SLAPI
138         struct slapi_extension_block *eblock;
139         void *parent;
140
141         if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
142                 return NULL;
143         }
144
145         if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
146                 return eblock->extensions[extensionhandle];
147         }
148
149         return NULL;
150 #else
151         return NULL;
152 #endif /* LDAP_SLAPI */
153 }
154
155 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
156 {
157 #ifdef LDAP_SLAPI
158         struct slapi_extension_block *eblock;
159         void *parent;
160
161         if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
162                 return;
163         }
164
165         if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
166                 /* free the old one */
167                 free_extension( eblock, objecttype, object, parent, extensionhandle );
168
169                 /* constructed by caller */
170                 eblock->extensions[extensionhandle] = extension;
171         }
172 #endif /* LDAP_SLAPI */
173 }
174
175 int slapi_register_object_extension(
176         const char *pluginname,
177         const char *objectname,
178         slapi_extension_constructor_fnptr constructor,
179         slapi_extension_destructor_fnptr destructor,
180         int *objecttype,
181         int *extensionhandle)
182 {
183 #ifdef LDAP_SLAPI
184         int rc;
185         slapi_extension_t type;
186         struct slapi_registered_extension *re;
187
188         ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
189
190         rc = map_extension_type( objectname, &type );
191         if ( rc != 0 ) {
192                 ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
193                 return rc;
194         }
195
196         *objecttype = (int)type;
197
198         re = &registered_extensions.extensions[*objecttype];
199
200         *extensionhandle = re->count;
201
202         if ( re->active ) {
203                 /* can't add new extensions after objects have been created */
204                 ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
205                 return -1;
206         }
207
208         re->count++;
209
210         if ( re->constructors == NULL ) {
211                 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
212                         sizeof( slapi_extension_constructor_fnptr ) );
213         } else {
214                 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
215                         re->count * sizeof( slapi_extension_constructor_fnptr ) );
216         }
217         re->constructors[*extensionhandle] = constructor;
218
219         if ( re->destructors == NULL ) {
220                 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
221                         sizeof( slapi_extension_destructor_fnptr ) );
222         } else {
223                 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
224                         re->count * sizeof( slapi_extension_destructor_fnptr ) );
225         }
226         re->destructors[*extensionhandle] = destructor;
227
228         ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
229
230         return 0;
231 #else
232         return -1;
233 #endif /* LDAP_SLAPI */
234 }
235
236 int slapi_int_create_object_extensions(int objecttype, void *object)
237 {
238 #ifdef LDAP_SLAPI
239         int i, rc;
240         struct slapi_extension_block *eblock;
241         void **peblock;
242         void *parent;
243
244         switch ((slapi_extension_t) objecttype) {
245         case SLAPI_X_EXT_CONNECTION:
246                 peblock = &(((Connection *)object)->c_extensions);
247                 parent = NULL;
248                 break;  
249         case SLAPI_X_EXT_OPERATION:
250                 peblock = &(((Operation *)object)->o_extensions);
251                 parent = ((Operation *)object)->o_conn;
252                 break;
253         default:
254                 return -1;
255                 break;
256         }
257
258         *peblock = NULL;
259
260         ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
261         if ( registered_extensions.extensions[objecttype].active == 0 ) {
262                 /*
263                  * once we've created some extensions, no new extensions can
264                  * be registered.
265                  */
266                 registered_extensions.extensions[objecttype].active = 1;
267         }
268         ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
269
270         eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
271
272         if ( registered_extensions.extensions[objecttype].count ) {
273                 eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) );
274                 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
275                         new_extension( eblock, objecttype, object, parent, i );
276                 }
277         } else {
278                 eblock->extensions = NULL;
279         }
280
281         *peblock = eblock;
282
283         return 0;
284 #else
285         return -1;
286 #endif
287 }
288
289 int slapi_int_free_object_extensions(int objecttype, void *object)
290 {
291 #ifdef LDAP_SLAPI
292         int i, rc;
293         struct slapi_extension_block *eblock;
294         void **peblock;
295         void *parent;
296
297         switch ((slapi_extension_t) objecttype) {
298         case SLAPI_X_EXT_CONNECTION:
299                 peblock = &(((Connection *)object)->c_extensions);
300                 parent = NULL;
301                 break;  
302         case SLAPI_X_EXT_OPERATION:
303                 peblock = &(((Operation *)object)->o_extensions);
304                 parent = ((Operation *)object)->o_conn;
305                 break;  
306         default:
307                 return -1;
308                 break;
309         }
310
311         eblock = (struct slapi_extension_block *)*peblock;
312
313         if ( eblock->extensions != NULL ) {
314                 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
315                         free_extension( eblock, objecttype, object, parent, i );
316                 }
317
318                 slapi_ch_free( (void **)&eblock->extensions );
319         }
320
321         slapi_ch_free( peblock );
322
323         return 0;
324 #else
325         return -1;
326 #endif
327 }
328
329 /* for reusable object types */
330 int slapi_int_clear_object_extensions(int objecttype, void *object)
331 {
332 #ifdef LDAP_SLAPI
333         int i, rc;
334         struct slapi_extension_block *eblock;
335         void *parent;
336
337         if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
338                 return -1;
339         }
340
341         if ( eblock->extensions == NULL ) {
342                 /* no extensions */
343                 return 0;
344         }
345
346         for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
347                 free_extension( eblock, objecttype, object, parent, i );
348         }
349
350         for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
351                 new_extension( eblock, objecttype, object, parent, i );
352         }
353
354         return 0;
355 #else
356         return -1;
357 #endif
358 }
359
360 int slapi_int_init_object_extensions(void)
361 {
362 #ifdef LDAP_SLAPI
363         memset( &registered_extensions, 0, sizeof( registered_extensions ) );
364
365         if ( ldap_pvt_thread_mutex_init( &registered_extensions.mutex ) != 0 ) {
366                 return -1;
367         }
368
369         return 0;
370 #else
371         return -1;
372 #endif
373 }