o_names.c 8.1 KB

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