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