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