d9389a5e5a3a86721eb75fb519607c7e17c1932d
[openssl.git] / crypto / objects / o_names.c
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
9 /* I use the ex_data stuff to manage the identifiers for the obj_name_types
10  * that applications may define.  I only really use the free function field.
11  */
12 static LHASH *names_lh=NULL;
13 static int names_type_num=OBJ_NAME_TYPE_NUM;
14
15 typedef struct name_funcs_st
16         {
17         unsigned long (*hash_func)();
18         int (*cmp_func)();
19         void (*free_func)();
20         } NAME_FUNCS;
21
22 DECLARE_STACK_OF(NAME_FUNCS)
23 IMPLEMENT_STACK_OF(NAME_FUNCS)
24
25 static STACK_OF(NAME_FUNCS) *name_funcs_stack;
26
27 static unsigned long obj_name_hash(OBJ_NAME *a);
28 static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
29
30 int OBJ_NAME_init(void)
31         {
32         if (names_lh != NULL) return(1);
33         MemCheck_off();
34         names_lh=lh_new(obj_name_hash,obj_name_cmp);
35         MemCheck_on();
36         return(names_lh != NULL);
37         }
38
39 int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(),
40              void (*free_func)())
41         {
42         int ret;
43         int i;
44         NAME_FUNCS *name_funcs;
45
46         if (name_funcs_stack == NULL)
47                 {
48                 MemCheck_off();
49                 name_funcs_stack=sk_NAME_FUNCS_new_null();
50                 MemCheck_on();
51                 }
52         if ((name_funcs_stack == NULL))
53                 {
54                 /* ERROR */
55                 return(0);
56                 }
57         ret=names_type_num;
58         names_type_num++;
59         for (i=sk_NAME_FUNCS_num(name_funcs_stack); i<names_type_num; i++)
60                 {
61                 MemCheck_off();
62                 name_funcs = Malloc(sizeof(NAME_FUNCS));
63                 name_funcs->hash_func = lh_strhash;
64                 name_funcs->cmp_func = (int (*)())strcmp;
65                 name_funcs->free_func = 0; /* NULL is often declared to
66                                             * ((void *)0), which according
67                                             * to Compaq C is not really
68                                             * compatible with a function
69                                             * pointer.  -- Richard Levitte*/
70                 sk_NAME_FUNCS_push(name_funcs_stack,name_funcs);
71                 MemCheck_on();
72                 }
73         name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
74         if (hash_func != NULL)
75                 name_funcs->hash_func = hash_func;
76         if (cmp_func != NULL)
77                 name_funcs->cmp_func = cmp_func;
78         if (free_func != NULL)
79                 name_funcs->free_func = free_func;
80         return(ret);
81         }
82
83 static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b)
84         {
85         int ret;
86
87         ret=a->type-b->type;
88         if (ret == 0)
89                 {
90                 if ((name_funcs_stack != NULL)
91                         && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
92                         {
93                         ret=sk_NAME_FUNCS_value(name_funcs_stack,a->type)
94                                 ->cmp_func(a->name,b->name);
95                         }
96                 else
97                         ret=strcmp(a->name,b->name);
98                 }
99         return(ret);
100         }
101
102 static unsigned long obj_name_hash(OBJ_NAME *a)
103         {
104         unsigned long ret;
105
106         if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type))
107                 {
108                 ret=sk_NAME_FUNCS_value(name_funcs_stack,a->type)
109                         ->hash_func(a->name);
110                 }
111         else
112                 {
113                 ret=lh_strhash(a->name);
114                 }
115         ret^=a->type;
116         return(ret);
117         }
118
119 const char *OBJ_NAME_get(const char *name, int type)
120         {
121         OBJ_NAME on,*ret;
122         int num=0,alias;
123
124         if (name == NULL) return(NULL);
125         if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
126
127         alias=type&OBJ_NAME_ALIAS;
128         type&= ~OBJ_NAME_ALIAS;
129
130         on.name=name;
131         on.type=type;
132
133         for (;;)
134                 {
135                 ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
136                 if (ret == NULL) return(NULL);
137                 if ((ret->alias) && !alias)
138                         {
139                         if (++num > 10) return(NULL);
140                         on.name=ret->data;
141                         }
142                 else
143                         {
144                         return(ret->data);
145                         }
146                 }
147         }
148
149 int OBJ_NAME_add(const char *name, int type, const char *data)
150         {
151         OBJ_NAME *onp,*ret;
152         int alias;
153
154         if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
155
156         alias=type&OBJ_NAME_ALIAS;
157         type&= ~OBJ_NAME_ALIAS;
158
159         onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME));
160         if (onp == NULL)
161                 {
162                 /* ERROR */
163                 return(0);
164                 }
165
166         onp->name=name;
167         onp->alias=alias;
168         onp->type=type;
169         onp->data=data;
170
171         ret=(OBJ_NAME *)lh_insert(names_lh,onp);
172         if (ret != NULL)
173                 {
174                 /* free things */
175                 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
176                         {
177                         /* XXX: I'm not sure I understand why the free
178                          * function should get three arguments...
179                          * -- Richard Levitte
180                          */
181                         sk_NAME_FUNCS_value(name_funcs_stack,ret->type)
182                                 ->free_func(ret->name,ret->type,ret->data);
183                         }
184                 Free(ret);
185                 }
186         else
187                 {
188                 if (lh_error(names_lh))
189                         {
190                         /* ERROR */
191                         return(0);
192                         }
193                 }
194         return(1);
195         }
196
197 int OBJ_NAME_remove(const char *name, int type)
198         {
199         OBJ_NAME on,*ret;
200
201         if (names_lh == NULL) return(0);
202
203         type&= ~OBJ_NAME_ALIAS;
204         on.name=name;
205         on.type=type;
206         ret=(OBJ_NAME *)lh_delete(names_lh,&on);
207         if (ret != NULL)
208                 {
209                 /* free things */
210                 if ((name_funcs_stack != NULL) && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type))
211                         {
212                         /* XXX: I'm not sure I understand why the free
213                          * function should get three arguments...
214                          * -- Richard Levitte
215                          */
216                         sk_NAME_FUNCS_value(name_funcs_stack,ret->type)
217                                 ->free_func(ret->name,ret->type,ret->data);
218                         }
219                 Free(ret);
220                 return(1);
221                 }
222         else
223                 return(0);
224         }
225
226 static int free_type;
227
228 static void names_lh_free(OBJ_NAME *onp, int type)
229 {
230         if(onp == NULL)
231             return;
232
233         if ((free_type < 0) || (free_type == onp->type))
234                 {
235                 OBJ_NAME_remove(onp->name,onp->type);
236                 }
237         }
238
239 static void name_funcs_free(NAME_FUNCS *ptr)
240         {
241         Free(ptr);
242         }
243
244 void OBJ_NAME_cleanup(int type)
245         {
246         unsigned long down_load;
247
248         if (names_lh == NULL) return;
249
250         free_type=type;
251         down_load=names_lh->down_load;
252         names_lh->down_load=0;
253
254         lh_doall(names_lh,names_lh_free);
255         if (type < 0)
256                 {
257                 lh_free(names_lh);
258                 sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
259                 names_lh=NULL;
260                 name_funcs_stack = NULL;
261                 }
262         else
263                 names_lh->down_load=down_load;
264         }
265