~ubuntu-branches/ubuntu/precise/openssl098/precise

« back to all changes in this revision

Viewing changes to crypto/objects/o_names.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2011-03-23 19:50:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110323195031-6h9crj4bymhhr8b8
Tags: upstream-0.9.8o
ImportĀ upstreamĀ versionĀ 0.9.8o

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
static LHASH *names_lh=NULL;
 
26
static int names_type_num=OBJ_NAME_TYPE_NUM;
 
27
 
 
28
typedef 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
 
 
35
DECLARE_STACK_OF(NAME_FUNCS)
 
36
IMPLEMENT_STACK_OF(NAME_FUNCS)
 
37
 
 
38
static 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); */
 
45
static unsigned long obj_name_hash(const void *a_void);
 
46
/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
 
47
static int obj_name_cmp(const void *a_void,const void *b_void);
 
48
 
 
49
int 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
 
 
58
int 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) */
 
111
static 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) */
 
133
static 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
 
 
151
const 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
 
 
181
int 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
 
 
229
int 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
 
 
258
struct doall
 
259
        {
 
260
        int type;
 
261
        void (*fn)(const OBJ_NAME *,void *arg);
 
262
        void *arg;
 
263
        };
 
264
 
 
265
static 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
 
 
271
static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *)
 
272
 
 
273
void 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
 
 
284
struct doall_sorted
 
285
        {
 
286
        int type;
 
287
        int n;
 
288
        const OBJ_NAME **names;
 
289
        };
 
290
 
 
291
static 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
 
 
301
static 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
 
 
309
void 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
 
 
328
static int free_type;
 
329
 
 
330
static 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
 
 
341
static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *)
 
342
 
 
343
static void name_funcs_free(NAME_FUNCS *ptr)
 
344
        {
 
345
        OPENSSL_free(ptr);
 
346
        }
 
347
 
 
348
void 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