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 */
9 * @brief Functions for accessing a pointer as an object of a given type.
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.
15 * Almost no code should call these directly.
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"
30 #include "lib/confmgt/var_type_def_st.h"
36 * Try to parse a string in <b>value</b> that encodes an object of the type
37 * defined by <b>def</b>.
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.
44 typed_var_assign(void *target
, const char *value
, char **errmsg
,
45 const var_type_def_t
*def
)
48 return -1; // LCOV_EXCL_LINE
49 // clear old value if needed.
50 typed_var_free(target
, def
);
52 tor_assert(def
->fns
->parse
);
53 return def
->fns
->parse(target
, value
, errmsg
, def
->params
);
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
61 * All types for which keys are significant should use this function.
63 * Note that although multiple lines may be provided in <b>line</b>,
64 * only the first one is handled by this function.
67 typed_var_kvassign(void *target
, const config_line_t
*line
,
68 char **errmsg
, const var_type_def_t
*def
)
71 return -1; // LCOV_EXCL_LINE
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
);
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
);
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.
95 typed_var_free(void *target
, const var_type_def_t
*def
)
98 return; // LCOV_EXCL_LINE
99 if (def
->fns
->clear
) {
100 def
->fns
->clear(target
, def
->params
);
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.
108 * Returns NULL if this option has a NULL value, or on internal error.
111 typed_var_encode(const void *value
, const var_type_def_t
*def
)
114 return NULL
; // LCOV_EXCL_LINE
115 tor_assert(def
->fns
->encode
);
116 return def
->fns
->encode(value
, def
->params
);
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.
124 * This function may return a list of multiple lines.
126 * Returns NULL if there are no lines to encode, or on internal error.
129 typed_var_kvencode(const char *key
, const void *value
,
130 const var_type_def_t
*def
)
133 return NULL
; // LCOV_EXCL_LINE
134 if (def
->fns
->kv_encode
) {
135 return def
->fns
->kv_encode(key
, value
, def
->params
);
137 char *encoded_value
= typed_var_encode(value
, def
);
141 config_line_t
*result
= tor_malloc_zero(sizeof(config_line_t
));
142 result
->key
= tor_strdup(key
);
143 result
->value
= encoded_value
;
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>.
151 * Return 0 on success, and -1 on failure.
154 typed_var_copy(void *dest
, const void *src
, const var_type_def_t
*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
);
163 // Otherwise, encode 'src' and parse the result into 'def'.
164 char *enc
= typed_var_encode(src
, def
);
166 typed_var_free(dest
, def
);
170 int rv
= typed_var_assign(dest
, enc
, &err
, def
);
173 log_warn(LD_BUG
, "Encoded value %s was not parseable as a %s: %s",
174 escaped(enc
), def
->name
, err
?err
:"");
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>.
187 typed_var_eq(const void *a
, const void *b
, const var_type_def_t
*def
)
190 return false; // LCOV_EXCL_LINE
193 // Use a provided eq function if we got one.
194 return def
->fns
->eq(a
, b
, def
->params
);
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
);
207 * Check whether <b>value</b> encodes a valid value according to the
208 * type definition in <b>def</b>.
211 typed_var_ok(const void *value
, const var_type_def_t
*def
)
214 return false; // LCOV_EXCL_LINE
217 return def
->fns
->ok(value
, def
->params
);
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.
228 typed_var_mark_fragile(void *value
, const var_type_def_t
*def
)
231 return; // LCOV_EXCL_LINE
234 if (def
->fns
->mark_fragile
)
235 def
->fns
->mark_fragile(value
, def
->params
);