typedvar.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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>. If not NULL, <b>key</b> is the name of the option,
  32. * which may be used for logging.
  33. *
  34. * On success, adjust the lvalue pointed to by <b>target</b> to hold that
  35. * value, and return 0. On failure, set *<b>errmsg</b> to a newly allocated
  36. * string holding an error message, and return -1.
  37. **/
  38. int
  39. typed_var_assign(void *target, const char *value, char **errmsg,
  40. const var_type_def_t *def, const char *key)
  41. {
  42. if (BUG(!def))
  43. return -1; // LCOV_EXCL_LINE
  44. // clear old value if needed.
  45. typed_var_free(target, def);
  46. tor_assert(def->fns->parse);
  47. return def->fns->parse(target, value, errmsg, def->params, key);
  48. }
  49. /**
  50. * Try to parse a single line from the head of<b>line</b> that encodes an
  51. * object of the type defined in <b>def</b>. On success and failure, behave as
  52. * typed_var_assign().
  53. *
  54. * All types for which keys are significant should use this function.
  55. *
  56. * Note that although multiple lines may be provided in <b>line</b>,
  57. * only the first one is handled by this function.
  58. **/
  59. int
  60. typed_var_kvassign(void *target, const config_line_t *line,
  61. char **errmsg, const var_type_def_t *def)
  62. {
  63. if (BUG(!def))
  64. return -1; // LCOV_EXCL_LINE
  65. if (def->fns->kv_parse) {
  66. // We do _not_ free the old value here, since linelist options
  67. // sometimes have append semantics.
  68. return def->fns->kv_parse(target, line, errmsg, def->params);
  69. }
  70. return typed_var_assign(target, line->value, errmsg, def, line->key);
  71. }
  72. /**
  73. * Release storage held by a variable in <b>target</b> of type defined by
  74. * <b>def</b>, and set <b>target</b> to a reasonable default.
  75. **/
  76. void
  77. typed_var_free(void *target, const var_type_def_t *def)
  78. {
  79. if (BUG(!def))
  80. return; // LCOV_EXCL_LINE
  81. if (def->fns->clear) {
  82. def->fns->clear(target, def->params);
  83. }
  84. }
  85. /**
  86. * Encode a value of type <b>def</b> pointed to by <b>value</b>, and return
  87. * its result in a newly allocated string. The string may need to be escaped.
  88. *
  89. * Returns NULL if this option has a NULL value, or on internal error.
  90. **/
  91. char *
  92. typed_var_encode(const void *value, const var_type_def_t *def)
  93. {
  94. if (BUG(!def))
  95. return NULL; // LCOV_EXCL_LINE
  96. tor_assert(def->fns->encode);
  97. return def->fns->encode(value, def->params);
  98. }
  99. /**
  100. * As typed_var_encode(), but returns a newly allocated config_line_t
  101. * object. The provided <b>key</b> is used as the key of the lines, unless
  102. * the type is one (line a linelist) that encodes its own keys.
  103. *
  104. * This function may return a list of multiple lines.
  105. *
  106. * Returns NULL if there are no lines to encode, or on internal error.
  107. */
  108. config_line_t *
  109. typed_var_kvencode(const char *key, const void *value,
  110. const var_type_def_t *def)
  111. {
  112. if (BUG(!def))
  113. return NULL; // LCOV_EXCL_LINE
  114. if (def->fns->kv_encode) {
  115. return def->fns->kv_encode(key, value, def->params);
  116. }
  117. char *encoded_value = typed_var_encode(value, def);
  118. if (!encoded_value)
  119. return NULL;
  120. config_line_t *result = tor_malloc_zero(sizeof(config_line_t));
  121. result->key = tor_strdup(key);
  122. result->value = encoded_value;
  123. return result;
  124. }
  125. /**
  126. * Set <b>dest</b> to contain the same value as <b>src</b>. Both types
  127. * must be as defined by <b>def</b>.
  128. *
  129. * Return 0 on success, and -1 on failure.
  130. **/
  131. int
  132. typed_var_copy(void *dest, const void *src, const var_type_def_t *def)
  133. {
  134. if (BUG(!def))
  135. return -1; // LCOV_EXCL_LINE
  136. if (def->fns->copy) {
  137. // If we have been provided a copy fuction, use it.
  138. return def->fns->copy(dest, src, def);
  139. }
  140. // Otherwise, encode 'src' and parse the result into 'def'.
  141. char *enc = typed_var_encode(src, def);
  142. if (!enc) {
  143. typed_var_free(dest, def);
  144. return 0;
  145. }
  146. char *err = NULL;
  147. int rv = typed_var_assign(dest, enc, &err, def, NULL);
  148. if (BUG(rv < 0)) {
  149. // LCOV_EXCL_START
  150. log_warn(LD_BUG, "Encoded value %s was not parseable as a %s: %s",
  151. escaped(enc), def->name, err?err:"");
  152. // LCOV_EXCL_STOP
  153. }
  154. tor_free(err);
  155. tor_free(enc);
  156. return rv;
  157. }
  158. /**
  159. * Return true if <b>a</b> and <b>b</b> are semantically equivalent.
  160. * Both types must be as defined by <b>def</b>.
  161. **/
  162. bool
  163. typed_var_eq(const void *a, const void *b, const var_type_def_t *def)
  164. {
  165. if (BUG(!def))
  166. return false; // LCOV_EXCL_LINE
  167. if (def->fns->eq) {
  168. // Use a provided eq function if we got one.
  169. return def->fns->eq(a, b, def->params);
  170. }
  171. // Otherwise, encode the values and compare them.
  172. char *enc_a = typed_var_encode(a, def);
  173. char *enc_b = typed_var_encode(b, def);
  174. bool eq = !strcmp_opt(enc_a,enc_b);
  175. tor_free(enc_a);
  176. tor_free(enc_b);
  177. return eq;
  178. }
  179. /**
  180. * Check whether <b>value</b> encodes a valid value according to the
  181. * type definition in <b>def</b>.
  182. */
  183. bool
  184. typed_var_ok(const void *value, const var_type_def_t *def)
  185. {
  186. if (BUG(!def))
  187. return false; // LCOV_EXCL_LINE
  188. if (def->fns->ok)
  189. return def->fns->ok(value, def->params);
  190. return true;
  191. }
  192. /**
  193. * Mark <b>value</b> -- a variable that ordinarily would be extended by
  194. * assignment -- as "fragile", so that it will get replaced by the next
  195. * assignment instead.
  196. **/
  197. void
  198. typed_var_mark_fragile(void *value, const var_type_def_t *def)
  199. {
  200. if (BUG(!def)) {
  201. return; // LCOV_EXCL_LINE
  202. }
  203. if (def->fns->mark_fragile)
  204. def->fns->mark_fragile(value, def->params);
  205. }