Tor  0.4.3.1-alpha-dev
typedvar.c
Go to the documentation of this file.
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-2020, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * @file typedvar.c
9  * @brief Functions for accessing a pointer as an object of a given type.
10  *
11  * These functions represent a low-level API for accessing a typed variable.
12  * They are used in the configuration system to examine and set fields in
13  * configuration objects used by individual modules.
14  *
15  * Almost no code should call these directly.
16  **/
17 
18 #include "orconfig.h"
19 #include "lib/conf/conftypes.h"
20 #include "lib/confmgt/type_defs.h"
21 #include "lib/confmgt/typedvar.h"
22 #include "lib/encoding/confline.h"
23 #include "lib/log/escape.h"
24 #include "lib/log/log.h"
25 #include "lib/log/util_bug.h"
26 #include "lib/malloc/malloc.h"
27 #include "lib/string/util_string.h"
28 
30 
31 #include <stddef.h>
32 #include <string.h>
33 
34 /**
35  * Try to parse a string in <b>value</b> that encodes an object of the type
36  * defined by <b>def</b>.
37  *
38  * On success, adjust the lvalue pointed to by <b>target</b> to hold that
39  * value, and return 0. On failure, set *<b>errmsg</b> to a newly allocated
40  * string holding an error message, and return -1.
41  **/
42 int
43 typed_var_assign(void *target, const char *value, char **errmsg,
44  const var_type_def_t *def)
45 {
46  if (BUG(!def))
47  return -1; // LCOV_EXCL_LINE
48  // clear old value if needed.
49  typed_var_free(target, def);
50 
51  tor_assert(def->fns->parse);
52  return def->fns->parse(target, value, errmsg, def->params);
53 }
54 
55 /**
56  * Try to parse a single line from the head of<b>line</b> that encodes an
57  * object of the type defined in <b>def</b>. On success and failure, behave as
58  * typed_var_assign().
59  *
60  * All types for which keys are significant should use this function.
61  *
62  * Note that although multiple lines may be provided in <b>line</b>,
63  * only the first one is handled by this function.
64  **/
65 int
66 typed_var_kvassign(void *target, const config_line_t *line,
67  char **errmsg, const var_type_def_t *def)
68 {
69  if (BUG(!def))
70  return -1; // LCOV_EXCL_LINE
71 
72  if (def->fns->kv_parse) {
73  // We do _not_ free the old value here, since linelist options
74  // sometimes have append semantics.
75  return def->fns->kv_parse(target, line, errmsg, def->params);
76  }
77 
78  return typed_var_assign(target, line->value, errmsg, def);
79 }
80 
81 /**
82  * Release storage held by a variable in <b>target</b> of type defined by
83  * <b>def</b>, and set <b>target</b> to a reasonable default.
84  **/
85 void
86 typed_var_free(void *target, const var_type_def_t *def)
87 {
88  if (BUG(!def))
89  return; // LCOV_EXCL_LINE
90  if (def->fns->clear) {
91  def->fns->clear(target, def->params);
92  }
93 }
94 
95 /**
96  * Encode a value of type <b>def</b> pointed to by <b>value</b>, and return
97  * its result in a newly allocated string. The string may need to be escaped.
98  *
99  * Returns NULL if this option has a NULL value, or on internal error.
100  **/
101 char *
102 typed_var_encode(const void *value, const var_type_def_t *def)
103 {
104  if (BUG(!def))
105  return NULL; // LCOV_EXCL_LINE
106  tor_assert(def->fns->encode);
107  return def->fns->encode(value, def->params);
108 }
109 
110 /**
111  * As typed_var_encode(), but returns a newly allocated config_line_t
112  * object. The provided <b>key</b> is used as the key of the lines, unless
113  * the type is one (line a linelist) that encodes its own keys.
114  *
115  * This function may return a list of multiple lines.
116  *
117  * Returns NULL if there are no lines to encode, or on internal error.
118  */
120 typed_var_kvencode(const char *key, const void *value,
121  const var_type_def_t *def)
122 {
123  if (BUG(!def))
124  return NULL; // LCOV_EXCL_LINE
125  if (def->fns->kv_encode) {
126  return def->fns->kv_encode(key, value, def->params);
127  }
128  char *encoded_value = typed_var_encode(value, def);
129  if (!encoded_value)
130  return NULL;
131 
132  config_line_t *result = tor_malloc_zero(sizeof(config_line_t));
133  result->key = tor_strdup(key);
134  result->value = encoded_value;
135  return result;
136 }
137 
138 /**
139  * Set <b>dest</b> to contain the same value as <b>src</b>. Both types
140  * must be as defined by <b>def</b>.
141  *
142  * Return 0 on success, and -1 on failure.
143  **/
144 int
145 typed_var_copy(void *dest, const void *src, const var_type_def_t *def)
146 {
147  if (BUG(!def))
148  return -1; // LCOV_EXCL_LINE
149  if (def->fns->copy) {
150  // If we have been provided a copy fuction, use it.
151  return def->fns->copy(dest, src, def);
152  }
153 
154  // Otherwise, encode 'src' and parse the result into 'def'.
155  char *enc = typed_var_encode(src, def);
156  if (!enc) {
157  typed_var_free(dest, def);
158  return 0;
159  }
160  char *err = NULL;
161  int rv = typed_var_assign(dest, enc, &err, def);
162  if (BUG(rv < 0)) {
163  // LCOV_EXCL_START
164  log_warn(LD_BUG, "Encoded value %s was not parseable as a %s: %s",
165  escaped(enc), def->name, err?err:"");
166  // LCOV_EXCL_STOP
167  }
168  tor_free(err);
169  tor_free(enc);
170  return rv;
171 }
172 
173 /**
174  * Return true if <b>a</b> and <b>b</b> are semantically equivalent.
175  * Both types must be as defined by <b>def</b>.
176  **/
177 bool
178 typed_var_eq(const void *a, const void *b, const var_type_def_t *def)
179 {
180  if (BUG(!def))
181  return false; // LCOV_EXCL_LINE
182 
183  if (def->fns->eq) {
184  // Use a provided eq function if we got one.
185  return def->fns->eq(a, b, def->params);
186  }
187 
188  // Otherwise, encode the values and compare them.
189  char *enc_a = typed_var_encode(a, def);
190  char *enc_b = typed_var_encode(b, def);
191  bool eq = !strcmp_opt(enc_a,enc_b);
192  tor_free(enc_a);
193  tor_free(enc_b);
194  return eq;
195 }
196 
197 /**
198  * Check whether <b>value</b> encodes a valid value according to the
199  * type definition in <b>def</b>.
200  */
201 bool
202 typed_var_ok(const void *value, const var_type_def_t *def)
203 {
204  if (BUG(!def))
205  return false; // LCOV_EXCL_LINE
206 
207  if (def->fns->ok)
208  return def->fns->ok(value, def->params);
209 
210  return true;
211 }
212 
213 /**
214  * Mark <b>value</b> -- a variable that ordinarily would be extended by
215  * assignment -- as "fragile", so that it will get replaced by the next
216  * assignment instead.
217  **/
218 void
219 typed_var_mark_fragile(void *value, const var_type_def_t *def)
220 {
221  if (BUG(!def)) {
222  return; // LCOV_EXCL_LINE
223  }
224 
225  if (def->fns->mark_fragile)
226  def->fns->mark_fragile(value, def->params);
227 }
int(* copy)(void *target, const void *value, const void *params)
bool typed_var_ok(const void *value, const var_type_def_t *def)
Definition: typedvar.c:202
char * typed_var_encode(const void *value, const var_type_def_t *def)
Definition: typedvar.c:102
Header for confline.c.
void(* mark_fragile)(void *value, const void *params)
int(* parse)(void *target, const char *value, char **errmsg, const void *params)
void typed_var_free(void *target, const var_type_def_t *def)
Definition: typedvar.c:86
void typed_var_mark_fragile(void *value, const var_type_def_t *def)
Definition: typedvar.c:219
struct config_line_t *(* kv_encode)(const char *key, const void *value, const void *params)
#define tor_assert(expr)
Definition: util_bug.h:102
bool typed_var_eq(const void *a, const void *b, const var_type_def_t *def)
Definition: typedvar.c:178
Structure declarations for typedvar type definitions.
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
int typed_var_assign(void *target, const char *value, char **errmsg, const var_type_def_t *def)
Definition: typedvar.c:43
Headers for util_malloc.c.
const struct var_type_fns_t * fns
void(* clear)(void *arg, const void *params)
Header for lib/confmgt/typedvar.c.
int typed_var_copy(void *dest, const void *src, const var_type_def_t *def)
Definition: typedvar.c:145
bool(* eq)(const void *a, const void *b, const void *params)
char *(* encode)(const void *value, const void *params)
Header for lib/confmgt/type_defs.c.
Types used to specify configurable options.
const char * escaped(const char *s)
Definition: escape.c:126
const char * name
const void * params
Header for escape.c.
int typed_var_kvassign(void *target, const config_line_t *line, char **errmsg, const var_type_def_t *def)
Definition: typedvar.c:66
int strcmp_opt(const char *s1, const char *s2)
Definition: util_string.c:188
Headers for log.c.
bool(* ok)(const void *value, const void *params)
Macros to manage assertions, fatal and non-fatal.
int(* kv_parse)(void *target, const struct config_line_t *line, char **errmsg, const void *params)
config_line_t * typed_var_kvencode(const char *key, const void *value, const var_type_def_t *def)
Definition: typedvar.c:120
#define LD_BUG
Definition: log.h:86