o_names.c 9.7 KB

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