summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/objects/o_names.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/objects/o_names.c')
-rw-r--r--src/lib/libcrypto/objects/o_names.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/src/lib/libcrypto/objects/o_names.c b/src/lib/libcrypto/objects/o_names.c
new file mode 100644
index 0000000000..b4453b4a98
--- /dev/null
+++ b/src/lib/libcrypto/objects/o_names.c
@@ -0,0 +1,364 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <openssl/lhash.h>
6#include <openssl/objects.h>
7#include <openssl/safestack.h>
8#include <openssl/e_os2.h>
9
10/* Later versions of DEC C has started to add lnkage information to certain
11 * functions, which makes it tricky to use them as values to regular function
12 * pointers. One way is to define a macro that takes care of casting them
13 * correctly.
14 */
15#ifdef OPENSSL_SYS_VMS_DECC
16# define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp
17#else
18# define OPENSSL_strcmp strcmp
19#endif
20
21/* I use the ex_data stuff to manage the identifiers for the obj_name_types
22 * that applications may define. I only really use the free function field.
23 */
24static LHASH *names_lh=NULL;
25static int names_type_num=OBJ_NAME_TYPE_NUM;
26
27typedef struct name_funcs_st
28 {
29 unsigned long (*hash_func)(const char *name);
30 int (*cmp_func)(const char *a,const char *b);
31 void (*free_func)(const char *, int, const char *);
32 } NAME_FUNCS;
33
34DECLARE_STACK_OF(NAME_FUNCS)
35IMPLEMENT_STACK_OF(NAME_FUNCS)
36
37static STACK_OF(NAME_FUNCS) *name_funcs_stack;
38
39/* The LHASH callbacks now use the raw "void *" prototypes and do per-variable
40 * casting in the functions. This prevents function pointer casting without the
41 * need for macro-generated wrapper functions. */
42
43/* static unsigned long obj_name_hash(OBJ_NAME *a); */
44static unsigned long obj_name_hash(const void *a_void);
45/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
46static int obj_name_cmp(const void *a_void,const void *b_void);
47
48int OBJ_NAME_init(void)
49 {
50 if (names_lh != NULL) return(1);
51 MemCheck_off();
52 names_lh=lh_new(obj_name_hash, obj_name_cmp);
53 MemCheck_on();
54 return(names_lh != NULL);
55 }
56
57int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
58 int (*cmp_func)(const char *, const char *),
59 void (*free_func)(const char *, int, const char *))
60 {
61 int ret;
62 int i;
63 NAME_FUNCS *name_funcs;
64
65 if (name_funcs_stack == NULL)
66 {
67 MemCheck_off();
68 name_funcs_stack=sk_NAME_FUNCS_new_null();
69 MemCheck_on();
70 }
71 if ((name_funcs_stack == NULL))
72 {
73 /* ERROR */
74 return(0);
75 }
76 ret=names_type_num;
77 names_type_num++;
78 for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++)
79 {
80 MemCheck_off();
81 name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS));
82 MemCheck_on();
83 if (!name_funcs) return(0);
84 name_funcs->hash_func = lh_strhash;
85 name_funcs->cmp_func = OPENSSL_strcmp;
86 name_funcs->free_func = 0; /* NULL is often declared to
87 * ((void *)0), which according
88 * to Compaq C is not really
89 * compatible with a function
90 * pointer. -- Richard Levitte*/
91 MemCheck_off();
92 sk_NAME_FUNCS_push(name_funcs_stack,name_funcs);
93 MemCheck_on();
94 }
95 name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
96 if (hash_func != NULL)
97 name_funcs->hash_func = hash_func;
98 if (cmp_func != NULL)
99 name_funcs->cmp_func = cmp_func;
100 if (free_func != NULL)
101 name_funcs->free_func = free_func;
102 return(ret);
103 }
104
105/* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */
106static int obj_name_cmp(const void *a_void, const void *b_void)
107 {
108 int ret;
109 OBJ_NAME *a = (OBJ_NAME *)a_void;
110 OBJ_NAME *b = (OBJ_NAME *)b_void;
111
112 ret=a->type-b->type;
113 if (ret == 0)
114 {
115 if ((name_funcs_stack != NULL)
116 && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
117 {
118 ret=sk_NAME_FUNCS_value(name_funcs_stack,
119 a->type)->cmp_func(a->name,b->name);
120 }
121 else
122 ret=strcmp(a->name,b->name);
123 }
124 return(ret);
125 }
126
127/* static unsigned long obj_name_hash(OBJ_NAME *a) */
128static unsigned long obj_name_hash(const void *a_void)
129 {
130 unsigned long ret;
131 OBJ_NAME *a = (OBJ_NAME *)a_void;
132
133 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
134 {
135 ret=sk_NAME_FUNCS_value(name_funcs_stack,
136 a->type)->hash_func(a->name);
137 }
138 else
139 {
140 ret=lh_strhash(a->name);
141 }
142 ret^=a->type;
143 return(ret);
144 }
145
146const char *OBJ_NAME_get(const char *name, int type)
147 {
148 OBJ_NAME on,*ret;
149 int num=0,alias;
150
151 if (name == NULL) return(NULL);
152 if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
153
154 alias=type&OBJ_NAME_ALIAS;
155 type&= ~OBJ_NAME_ALIAS;
156
157 on.name=name;
158 on.type=type;
159
160 for (;;)
161 {
162 ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
163 if (ret == NULL) return(NULL);
164 if ((ret->alias) && !alias)
165 {
166 if (++num > 10) return(NULL);
167 on.name=ret->data;
168 }
169 else
170 {
171 return(ret->data);
172 }
173 }
174 }
175
176int OBJ_NAME_add(const char *name, int type, const char *data)
177 {
178 OBJ_NAME *onp,*ret;
179 int alias;
180
181 if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
182
183 alias=type&OBJ_NAME_ALIAS;
184 type&= ~OBJ_NAME_ALIAS;
185
186 onp=(OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));
187 if (onp == NULL)
188 {
189 /* ERROR */
190 return(0);
191 }
192
193 onp->name=name;
194 onp->alias=alias;
195 onp->type=type;
196 onp->data=data;
197
198 ret=(OBJ_NAME *)lh_insert(names_lh,onp);
199 if (ret != NULL)
200 {
201 /* free things */
202 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
203 {
204 /* XXX: I'm not sure I understand why the free
205 * function should get three arguments...
206 * -- Richard Levitte
207 */
208 sk_NAME_FUNCS_value(name_funcs_stack,
209 ret->type)->free_func(ret->name,ret->type,ret->data);
210 }
211 OPENSSL_free(ret);
212 }
213 else
214 {
215 if (lh_error(names_lh))
216 {
217 /* ERROR */
218 return(0);
219 }
220 }
221 return(1);
222 }
223
224int OBJ_NAME_remove(const char *name, int type)
225 {
226 OBJ_NAME on,*ret;
227
228 if (names_lh == NULL) return(0);
229
230 type&= ~OBJ_NAME_ALIAS;
231 on.name=name;
232 on.type=type;
233 ret=(OBJ_NAME *)lh_delete(names_lh,&on);
234 if (ret != NULL)
235 {
236 /* free things */
237 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
238 {
239 /* XXX: I'm not sure I understand why the free
240 * function should get three arguments...
241 * -- Richard Levitte
242 */
243 sk_NAME_FUNCS_value(name_funcs_stack,
244 ret->type)->free_func(ret->name,ret->type,ret->data);
245 }
246 OPENSSL_free(ret);
247 return(1);
248 }
249 else
250 return(0);
251 }
252
253struct doall
254 {
255 int type;
256 void (*fn)(const OBJ_NAME *,void *arg);
257 void *arg;
258 };
259
260static void do_all_fn(const OBJ_NAME *name,struct doall *d)
261 {
262 if(name->type == d->type)
263 d->fn(name,d->arg);
264 }
265
266static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *)
267
268void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg)
269 {
270 struct doall d;
271
272 d.type=type;
273 d.fn=fn;
274 d.arg=arg;
275
276 lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d);
277 }
278
279struct doall_sorted
280 {
281 int type;
282 int n;
283 const OBJ_NAME **names;
284 };
285
286static void do_all_sorted_fn(const OBJ_NAME *name,void *d_)
287 {
288 struct doall_sorted *d=d_;
289
290 if(name->type != d->type)
291 return;
292
293 d->names[d->n++]=name;
294 }
295
296static int do_all_sorted_cmp(const void *n1_,const void *n2_)
297 {
298 const OBJ_NAME * const *n1=n1_;
299 const OBJ_NAME * const *n2=n2_;
300
301 return strcmp((*n1)->name,(*n2)->name);
302 }
303
304void OBJ_NAME_do_all_sorted(int type,void (*fn)(const OBJ_NAME *,void *arg),
305 void *arg)
306 {
307 struct doall_sorted d;
308 int n;
309
310 d.type=type;
311 d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names);
312 d.n=0;
313 OBJ_NAME_do_all(type,do_all_sorted_fn,&d);
314
315 qsort((void *)d.names,d.n,sizeof *d.names,do_all_sorted_cmp);
316
317 for(n=0 ; n < d.n ; ++n)
318 fn(d.names[n],arg);
319
320 OPENSSL_free((void *)d.names);
321 }
322
323static int free_type;
324
325static void names_lh_free(OBJ_NAME *onp)
326{
327 if(onp == NULL)
328 return;
329
330 if ((free_type < 0) || (free_type == onp->type))
331 {
332 OBJ_NAME_remove(onp->name,onp->type);
333 }
334 }
335
336static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *)
337
338static void name_funcs_free(NAME_FUNCS *ptr)
339 {
340 OPENSSL_free(ptr);
341 }
342
343void OBJ_NAME_cleanup(int type)
344 {
345 unsigned long down_load;
346
347 if (names_lh == NULL) return;
348
349 free_type=type;
350 down_load=names_lh->down_load;
351 names_lh->down_load=0;
352
353 lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
354 if (type < 0)
355 {
356 lh_free(names_lh);
357 sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
358 names_lh=NULL;
359 name_funcs_stack = NULL;
360 }
361 else
362 names_lh->down_load=down_load;
363 }
364