o_names.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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. return (0);
  193. }
  194. }
  195. return (1);
  196. }
  197. int OBJ_NAME_remove(const char *name, int type)
  198. {
  199. OBJ_NAME on, *ret;
  200. if (names_lh == NULL)
  201. return (0);
  202. type &= ~OBJ_NAME_ALIAS;
  203. on.name = name;
  204. on.type = type;
  205. ret = lh_OBJ_NAME_delete(names_lh, &on);
  206. if (ret != NULL) {
  207. /* free things */
  208. if ((name_funcs_stack != NULL)
  209. && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) {
  210. /*
  211. * XXX: I'm not sure I understand why the free function should
  212. * get three arguments... -- Richard Levitte
  213. */
  214. sk_NAME_FUNCS_value(name_funcs_stack,
  215. ret->type)->free_func(ret->name, ret->type,
  216. ret->data);
  217. }
  218. OPENSSL_free(ret);
  219. return (1);
  220. } else
  221. return (0);
  222. }
  223. struct doall {
  224. int type;
  225. void (*fn) (const OBJ_NAME *, void *arg);
  226. void *arg;
  227. };
  228. static void do_all_fn_doall_arg(const OBJ_NAME *name, struct doall *d)
  229. {
  230. if (name->type == d->type)
  231. d->fn(name, d->arg);
  232. }
  233. static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME, struct doall)
  234. void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg),
  235. void *arg)
  236. {
  237. struct doall d;
  238. d.type = type;
  239. d.fn = fn;
  240. d.arg = arg;
  241. lh_OBJ_NAME_doall_arg(names_lh, LHASH_DOALL_ARG_FN(do_all_fn),
  242. struct doall, &d);
  243. }
  244. struct doall_sorted {
  245. int type;
  246. int n;
  247. const OBJ_NAME **names;
  248. };
  249. static void do_all_sorted_fn(const OBJ_NAME *name, void *d_)
  250. {
  251. struct doall_sorted *d = d_;
  252. if (name->type != d->type)
  253. return;
  254. d->names[d->n++] = name;
  255. }
  256. static int do_all_sorted_cmp(const void *n1_, const void *n2_)
  257. {
  258. const OBJ_NAME *const *n1 = n1_;
  259. const OBJ_NAME *const *n2 = n2_;
  260. return strcmp((*n1)->name, (*n2)->name);
  261. }
  262. void OBJ_NAME_do_all_sorted(int type,
  263. void (*fn) (const OBJ_NAME *, void *arg),
  264. void *arg)
  265. {
  266. struct doall_sorted d;
  267. int n;
  268. d.type = type;
  269. d.names =
  270. OPENSSL_malloc(lh_OBJ_NAME_num_items(names_lh) * sizeof *d.names);
  271. d.n = 0;
  272. OBJ_NAME_do_all(type, do_all_sorted_fn, &d);
  273. qsort((void *)d.names, d.n, sizeof *d.names, do_all_sorted_cmp);
  274. for (n = 0; n < d.n; ++n)
  275. fn(d.names[n], arg);
  276. OPENSSL_free((void *)d.names);
  277. }
  278. static int free_type;
  279. static void names_lh_free_doall(OBJ_NAME *onp)
  280. {
  281. if (onp == NULL)
  282. return;
  283. if (free_type < 0 || free_type == onp->type)
  284. OBJ_NAME_remove(onp->name, onp->type);
  285. }
  286. static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME)
  287. static void name_funcs_free(NAME_FUNCS *ptr)
  288. {
  289. OPENSSL_free(ptr);
  290. }
  291. void OBJ_NAME_cleanup(int type)
  292. {
  293. unsigned long down_load;
  294. if (names_lh == NULL)
  295. return;
  296. free_type = type;
  297. down_load = lh_OBJ_NAME_down_load(names_lh);
  298. lh_OBJ_NAME_down_load(names_lh) = 0;
  299. lh_OBJ_NAME_doall(names_lh, LHASH_DOALL_FN(names_lh_free));
  300. if (type < 0) {
  301. lh_OBJ_NAME_free(names_lh);
  302. sk_NAME_FUNCS_pop_free(name_funcs_stack, name_funcs_free);
  303. names_lh = NULL;
  304. name_funcs_stack = NULL;
  305. } else
  306. lh_OBJ_NAME_down_load(names_lh) = down_load;
  307. }