source: trunk/sys/libcrypto/others/o_names.c @ 202

Last change on this file since 202 was 1, checked in by alain, 8 years ago

First import

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