typedvar.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * @file typedvar.c
  8. * @brief Functions for accessing a pointer as an object of a given type.
  9. *
  10. * These functions represent a low-level API for accessing a typed variable.
  11. * They are used in the configuration system to examine and set fields in
  12. * configuration objects used by individual modules.
  13. *
  14. * Almost no code should call these directly.
  15. **/
  16. #include "orconfig.h"
  17. #include "lib/conf/conftypes.h"
  18. #include "lib/confmgt/type_defs.h"
  19. #include "lib/confmgt/typedvar.h"
  20. #include "lib/encoding/confline.h"
  21. #include "lib/log/escape.h"
  22. #include "lib/log/log.h"
  23. #include "lib/log/util_bug.h"
  24. #include "lib/malloc/malloc.h"
  25. #include "lib/string/util_string.h"
  26. #include "lib/confmgt/var_type_def_st.h"
  27. #include <stddef.h>
  28. #include <string.h>
  29. /**
  30. * Try to parse a string in <b>value</b> that encodes an object of the type
  31. * defined by <b>def</b>.
  32. *
  33. * On success, adjust the lvalue pointed to by <b>target</b> to hold that
  34. * value, and return 0. On failure, set *<b>errmsg</b> to a newly allocated
  35. * string holding an error message, and return -1.
  36. **/
  37. int
  38. typed_var_assign_ex(void *target, const char *value, char **errmsg,
  39. const var_type_def_t *def)
  40. {
  41. if (BUG(!def))
  42. return -1;
  43. // clear old value if needed.
  44. typed_var_free_ex(target, def);
  45. tor_assert(def->fns->parse);
  46. return def->fns->parse(target, value, errmsg, def->params);
  47. }
  48. /**
  49. * Try to parse a single line from the head of<b>line</b> that encodes an
  50. * object of the type defined in <b>def</b>. On success and failure, behave as
  51. * typed_var_assign_ex().
  52. *
  53. * All types for which keys are significant should use this function.
  54. *
  55. * Note that although multiple lines may be provided in <b>line</b>,
  56. * only the first one is handled by this function.
  57. **/
  58. int
  59. typed_var_kvassign_ex(void *target, const config_line_t *line,
  60. char **errmsg, const var_type_def_t *def)
  61. {
  62. if (BUG(!def))
  63. return -1;
  64. if (def->fns->kv_parse) {
  65. // We do _not_ free the old value here, since linelist options
  66. // sometimes have append semantics.
  67. return def->fns->kv_parse(target, line, errmsg, def->params);
  68. }
  69. return typed_var_assign_ex(target, line->value, errmsg, def);
  70. }
  71. /**
  72. * Release storage held by a variable in <b>target</b> of type defined by
  73. * <b>def</b>, and set <b>target</b> to a reasonable default.
  74. **/
  75. void
  76. typed_var_free_ex(void *target, const var_type_def_t *def)
  77. {
  78. if (BUG(!def))
  79. return;
  80. if (def->fns->clear) {
  81. def->fns->clear(target, def->params);
  82. }
  83. }
  84. /**
  85. * Encode a value of type <b>def</b> pointed to by <b>value</b>, and return
  86. * its result in a newly allocated string. The string may need to be escaped.
  87. *
  88. * Returns NULL if this option has a NULL value, or on internal error.
  89. **/
  90. char *
  91. typed_var_encode_ex(const void *value, const var_type_def_t *def)
  92. {
  93. if (BUG(!def))
  94. return NULL;
  95. tor_assert(def->fns->encode);
  96. return def->fns->encode(value, def->params);
  97. }
  98. /**
  99. * As typed_var_encode_ex(), but returns a newly allocated config_line_t
  100. * object. The provided <b>key</b> is used as the key of the lines, unless
  101. * the type is one (line a linelist) that encodes its own keys.
  102. *
  103. * This function may return a list of multiple lines.
  104. *
  105. * Returns NULL if there are no lines to encode, or on internal error.
  106. */
  107. config_line_t *
  108. typed_var_kvencode_ex(const char *key, const void *value,
  109. const var_type_def_t *def)
  110. {
  111. if (BUG(!def))
  112. return NULL;
  113. if (def->fns->kv_encode) {
  114. return def->fns->kv_encode(key, value, def->params);
  115. }
  116. char *encoded_value = typed_var_encode_ex(value, def);
  117. if (!encoded_value)
  118. return NULL;
  119. config_line_t *result = tor_malloc_zero(sizeof(config_line_t));
  120. result->key = tor_strdup(key);
  121. result->value = encoded_value;
  122. return result;
  123. }
  124. /**
  125. * Set <b>dest</b> to contain the same value as <b>src</b>. Both types
  126. * must be as defined by <b>def</b>.
  127. *
  128. * Return 0 on success, and -1 on failure.
  129. **/
  130. int
  131. typed_var_copy_ex(void *dest, const void *src, const var_type_def_t *def)
  132. {
  133. if (BUG(!def))
  134. return -1;
  135. if (def->fns->copy) {
  136. // If we have been provided a copy fuction, use it.
  137. return def->fns->copy(dest, src, def);
  138. }
  139. // Otherwise, encode 'src' and parse the result into 'def'.
  140. char *enc = typed_var_encode_ex(src, def);
  141. if (!enc) {
  142. typed_var_free_ex(dest, def);
  143. return 0;
  144. }
  145. char *err = NULL;
  146. int rv = typed_var_assign_ex(dest, enc, &err, def);
  147. if (BUG(rv < 0)) {
  148. log_warn(LD_BUG, "Encoded value %s was not parseable as a %s: %s",
  149. escaped(enc), def->name, err?err:"");
  150. }
  151. tor_free(err);
  152. tor_free(enc);
  153. return rv;
  154. }
  155. /**
  156. * Return true if <b>a</b> and <b>b</b> are semantically equivalent.
  157. * Both types must be as defined by <b>def</b>.
  158. **/
  159. bool
  160. typed_var_eq_ex(const void *a, const void *b, const var_type_def_t *def)
  161. {
  162. if (BUG(!def))
  163. return false;
  164. if (def->fns->eq) {
  165. // Use a provided eq function if we got one.
  166. return def->fns->eq(a, b, def->params);
  167. }
  168. // Otherwise, encode the values and compare them.
  169. char *enc_a = typed_var_encode_ex(a, def);
  170. char *enc_b = typed_var_encode_ex(b, def);
  171. bool eq = !strcmp_opt(enc_a,enc_b);
  172. tor_free(enc_a);
  173. tor_free(enc_b);
  174. return eq;
  175. }
  176. /**
  177. * Check whether <b>value</b> encodes a valid value according to the
  178. * type definition in <b>def</b>.
  179. */
  180. bool
  181. typed_var_ok_ex(const void *value, const var_type_def_t *def)
  182. {
  183. if (BUG(!def))
  184. return false;
  185. if (def->fns->ok)
  186. return def->fns->ok(value, def->params);
  187. return true;
  188. }
  189. /* =====
  190. * The functions below take a config_type_t instead of a var_type_def_t.
  191. * I'd like to deprecate them eventually and use var_type_def_t everywhere,
  192. * but for now they make migration easier.
  193. * ===== */
  194. /**
  195. * As typed_var_assign_ex(), but look up the definition of the configuration
  196. * type from a provided config_type_t enum.
  197. */
  198. int
  199. typed_var_assign(void *target, const char *value, char **errmsg,
  200. config_type_t type)
  201. {
  202. const var_type_def_t *def = lookup_type_def(type);
  203. return typed_var_assign_ex(target, value, errmsg, def);
  204. }
  205. /**
  206. * As typed_var_kvassign_ex(), but look up the definition of the configuration
  207. * type from a provided config_type_t enum.
  208. */
  209. int
  210. typed_var_kvassign(void *target, const config_line_t *line, char **errmsg,
  211. config_type_t type)
  212. {
  213. const var_type_def_t *def = lookup_type_def(type);
  214. return typed_var_kvassign_ex(target, line, errmsg, def);
  215. }
  216. /**
  217. * As typed_var_free_ex(), but look up the definition of the configuration
  218. * type from a provided config_type_t enum.
  219. */
  220. void
  221. typed_var_free(void *target, config_type_t type)
  222. {
  223. const var_type_def_t *def = lookup_type_def(type);
  224. return typed_var_free_ex(target, def);
  225. }
  226. /**
  227. * As typed_var_encode_ex(), but look up the definition of the configuration
  228. * type from a provided config_type_t enum.
  229. */
  230. char *
  231. typed_var_encode(const void *value, config_type_t type)
  232. {
  233. const var_type_def_t *def = lookup_type_def(type);
  234. return typed_var_encode_ex(value, def);
  235. }
  236. /**
  237. * As typed_var_kvencode_ex(), but look up the definition of the configuration
  238. * type from a provided config_type_t enum.
  239. */
  240. config_line_t *
  241. typed_var_kvencode(const char *key, const void *value, config_type_t type)
  242. {
  243. const var_type_def_t *def = lookup_type_def(type);
  244. return typed_var_kvencode_ex(key, value, def);
  245. }
  246. /**
  247. * As typed_var_copy_ex(), but look up the definition of the configuration type
  248. * from a provided config_type_t enum.
  249. */
  250. int
  251. typed_var_copy(void *dest, const void *src, config_type_t type)
  252. {
  253. const var_type_def_t *def = lookup_type_def(type);
  254. return typed_var_copy_ex(dest, src, def);
  255. }
  256. /**
  257. * As typed_var_eq_ex(), but look up the definition of the configuration type
  258. * from a provided config_type_t enum.
  259. */
  260. bool
  261. typed_var_eq(const void *a, const void *b, config_type_t type)
  262. {
  263. const var_type_def_t *def = lookup_type_def(type);
  264. return typed_var_eq_ex(a, b, def);
  265. }
  266. /**
  267. * As typed_var_ok_ex(), but look up the definition of the configuration type
  268. * from a provided config_type_t enum.
  269. */
  270. bool
  271. typed_var_ok(const void *value, config_type_t type)
  272. {
  273. const var_type_def_t *def = lookup_type_def(type);
  274. return typed_var_ok_ex(value, def);
  275. }