Add a config_mgr_t type to wrap config_format_t

Remember that our goal in the present refactoring is to allow each
subsystem to declare its own configuration structure and
variables.  To do this, each module will get its own
config_format_t, and so we'll want a different structure that wraps
several config_format_t objects.  This is a "config_mgr_t".
This commit is contained in:
Nick Mathewson 2019-07-19 06:45:54 -04:00
parent c32d485942
commit e8dc513bd0
9 changed files with 327 additions and 189 deletions

View File

@ -843,7 +843,7 @@ static void config_maybe_load_geoip_files_(const or_options_t *options,
static int options_validate_cb(void *old_options, void *options, static int options_validate_cb(void *old_options, void *options,
void *default_options, void *default_options,
int from_setconf, char **msg); int from_setconf, char **msg);
static void options_free_cb(void *options); static void options_free_cb(const config_mgr_t *, void *options);
static void cleanup_protocol_warning_severity_level(void); static void cleanup_protocol_warning_severity_level(void);
static void set_protocol_warning_severity_level(int warning_severity); static void set_protocol_warning_severity_level(int warning_severity);
@ -851,7 +851,7 @@ static void set_protocol_warning_severity_level(int warning_severity);
#define OR_OPTIONS_MAGIC 9090909 #define OR_OPTIONS_MAGIC 9090909
/** Configuration format for or_options_t. */ /** Configuration format for or_options_t. */
STATIC const config_format_t options_format = { static const config_format_t options_format = {
sizeof(or_options_t), sizeof(or_options_t),
{ {
"or_options_t", "or_options_t",
@ -895,6 +895,19 @@ static int in_option_validation = 0;
/* True iff we've initialized libevent */ /* True iff we've initialized libevent */
static int libevent_initialized = 0; static int libevent_initialized = 0;
/* A global configuration manager to handle all configuration objects. */
static config_mgr_t *options_mgr = NULL;
/** Return the global configuration manager object for torrc options. */
STATIC const config_mgr_t *
get_options_mgr(void)
{
if (PREDICT_UNLIKELY(options_mgr == NULL)) {
options_mgr = config_mgr_new(&options_format);
}
return options_mgr;
}
/** Return the contents of our frontpage string, or NULL if not configured. */ /** Return the contents of our frontpage string, or NULL if not configured. */
MOCK_IMPL(const char*, MOCK_IMPL(const char*,
get_dirportfrontpage, (void)) get_dirportfrontpage, (void))
@ -977,14 +990,14 @@ set_options(or_options_t *new_val, char **msg)
if (old_options && old_options != global_options) { if (old_options && old_options != global_options) {
elements = smartlist_new(); elements = smartlist_new();
for (i=0; options_format.vars[i].member.name; ++i) { for (i=0; options_format.vars[i].member.name; ++i) {
const config_var_t *var = &options_format.vars[i]; const config_var_t *var = &options_format.vars[i]; // XXXX 29211
const char *var_name = var->member.name; const char *var_name = var->member.name;
if (config_var_is_contained(var)) { if (config_var_is_contained(var)) {
/* something else will check this var, or it doesn't need checking */ /* something else will check this var, or it doesn't need checking */
continue; continue;
} }
if (!config_is_same(&options_format, new_val, old_options, var_name)) { if (!config_is_same(get_options_mgr(), new_val, old_options, var_name)) {
line = config_get_assigned_option(&options_format, new_val, line = config_get_assigned_option(get_options_mgr(), new_val,
var_name, 1); var_name, 1);
if (line) { if (line) {
@ -1046,7 +1059,7 @@ or_options_free_(or_options_t *options)
tor_free(options->command_arg); tor_free(options->command_arg);
tor_free(options->master_key_fname); tor_free(options->master_key_fname);
config_free_lines(options->MyFamily); config_free_lines(options->MyFamily);
config_free(&options_format, options); config_free(get_options_mgr(), options);
} }
/** Release all memory and resources held by global configuration structures. /** Release all memory and resources held by global configuration structures.
@ -1080,6 +1093,8 @@ config_free_all(void)
have_parsed_cmdline = 0; have_parsed_cmdline = 0;
libevent_initialized = 0; libevent_initialized = 0;
config_mgr_free(options_mgr);
} }
/** Make <b>address</b> -- a piece of information related to our operation as /** Make <b>address</b> -- a piece of information related to our operation as
@ -2547,7 +2562,7 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
param = tor_malloc_zero(sizeof(config_line_t)); param = tor_malloc_zero(sizeof(config_line_t));
param->key = is_cmdline ? tor_strdup(argv[i]) : param->key = is_cmdline ? tor_strdup(argv[i]) :
tor_strdup(config_expand_abbrev(&options_format, s, 1, 1)); tor_strdup(config_expand_abbrev(get_options_mgr(), s, 1, 1));
param->value = arg; param->value = arg;
param->command = command; param->command = command;
param->next = NULL; param->next = NULL;
@ -2573,7 +2588,7 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
int int
option_is_recognized(const char *key) option_is_recognized(const char *key)
{ {
const config_var_t *var = config_find_option(&options_format, key); const config_var_t *var = config_find_option(get_options_mgr(), key);
return (var != NULL); return (var != NULL);
} }
@ -2582,7 +2597,7 @@ option_is_recognized(const char *key)
const char * const char *
option_get_canonical_name(const char *key) option_get_canonical_name(const char *key)
{ {
const config_var_t *var = config_find_option(&options_format, key); const config_var_t *var = config_find_option(get_options_mgr(), key);
return var ? var->member.name : NULL; return var ? var->member.name : NULL;
} }
@ -2591,7 +2606,7 @@ option_get_canonical_name(const char *key)
config_line_t * config_line_t *
option_get_assignment(const or_options_t *options, const char *key) option_get_assignment(const or_options_t *options, const char *key)
{ {
return config_get_assigned_option(&options_format, options, key, 1); return config_get_assigned_option(get_options_mgr(), options, key, 1);
} }
/** Try assigning <b>list</b> to the global options. You do this by duping /** Try assigning <b>list</b> to the global options. You do this by duping
@ -2607,9 +2622,9 @@ setopt_err_t
options_trial_assign(config_line_t *list, unsigned flags, char **msg) options_trial_assign(config_line_t *list, unsigned flags, char **msg)
{ {
int r; int r;
or_options_t *trial_options = config_dup(&options_format, get_options()); or_options_t *trial_options = config_dup(get_options_mgr(), get_options());
if ((r=config_assign(&options_format, trial_options, if ((r=config_assign(get_options_mgr(), trial_options,
list, flags, msg)) < 0) { list, flags, msg)) < 0) {
or_options_free(trial_options); or_options_free(trial_options);
return r; return r;
@ -2992,7 +3007,7 @@ is_local_addr, (const tor_addr_t *addr))
or_options_t * or_options_t *
options_new(void) options_new(void)
{ {
return config_new(&options_format); return config_new(get_options_mgr());
} }
/** Set <b>options</b> to hold reasonable defaults for most options. /** Set <b>options</b> to hold reasonable defaults for most options.
@ -3000,10 +3015,10 @@ options_new(void)
void void
options_init(or_options_t *options) options_init(or_options_t *options)
{ {
config_init(&options_format, options); config_init(get_options_mgr(), options);
config_line_t *dflts = get_options_defaults(); config_line_t *dflts = get_options_defaults();
char *msg=NULL; char *msg=NULL;
if (config_assign(&options_format, options, dflts, if (config_assign(get_options_mgr(), options, dflts,
CAL_WARN_DEPRECATIONS, &msg)<0) { CAL_WARN_DEPRECATIONS, &msg)<0) {
log_err(LD_BUG, "Unable to set default options: %s", msg); log_err(LD_BUG, "Unable to set default options: %s", msg);
tor_free(msg); tor_free(msg);
@ -3040,7 +3055,7 @@ options_dump(const or_options_t *options, int how_to_dump)
return NULL; return NULL;
} }
return config_dump(&options_format, use_defaults, options, minimal, 0); return config_dump(get_options_mgr(), use_defaults, options, minimal, 0);
} }
/** Return 0 if every element of sl is a string holding a decimal /** Return 0 if every element of sl is a string holding a decimal
@ -3174,8 +3189,9 @@ options_validate_cb(void *old_options, void *options, void *default_options,
/** Callback to free an or_options_t */ /** Callback to free an or_options_t */
static void static void
options_free_cb(void *options) options_free_cb(const config_mgr_t *mgr, void *options)
{ {
(void)mgr;
or_options_free_(options); or_options_free_(options);
} }
@ -4435,7 +4451,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
STMT_BEGIN \ STMT_BEGIN \
if (!options->TestingTorNetwork && \ if (!options->TestingTorNetwork && \
!options->UsingTestNetworkDefaults_ && \ !options->UsingTestNetworkDefaults_ && \
!config_is_same(&options_format,options, \ !config_is_same(get_options_mgr(),options, \
default_options,#arg)) { \ default_options,#arg)) { \
REJECT(#arg " may only be changed in testing Tor " \ REJECT(#arg " may only be changed in testing Tor " \
"networks!"); \ "networks!"); \
@ -5431,7 +5447,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
err = SETOPT_ERR_PARSE; err = SETOPT_ERR_PARSE;
goto err; goto err;
} }
retval = config_assign(&options_format, newoptions, cl, retval = config_assign(get_options_mgr(), newoptions, cl,
CAL_WARN_DEPRECATIONS, msg); CAL_WARN_DEPRECATIONS, msg);
config_free_lines(cl); config_free_lines(cl);
if (retval < 0) { if (retval < 0) {
@ -5439,15 +5455,15 @@ options_init_from_string(const char *cf_defaults, const char *cf,
goto err; goto err;
} }
if (i==0) if (i==0)
newdefaultoptions = config_dup(&options_format, newoptions); newdefaultoptions = config_dup(get_options_mgr(), newoptions);
} }
if (newdefaultoptions == NULL) { if (newdefaultoptions == NULL) {
newdefaultoptions = config_dup(&options_format, global_default_options); newdefaultoptions = config_dup(get_options_mgr(), global_default_options);
} }
/* Go through command-line variables too */ /* Go through command-line variables too */
retval = config_assign(&options_format, newoptions, retval = config_assign(get_options_mgr(), newoptions,
global_cmdline_options, CAL_WARN_DEPRECATIONS, msg); global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
if (retval < 0) { if (retval < 0) {
err = SETOPT_ERR_PARSE; err = SETOPT_ERR_PARSE;

View File

@ -247,9 +247,8 @@ int options_any_client_port_set(const or_options_t *options);
#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7) #define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7)
STATIC int options_act(const or_options_t *old_options); STATIC int options_act(const or_options_t *old_options);
#ifdef TOR_UNIT_TESTS struct config_mgr_t;
extern const struct config_format_t options_format; STATIC const struct config_mgr_t *get_options_mgr(void);
#endif
STATIC port_cfg_t *port_cfg_new(size_t namelen); STATIC port_cfg_t *port_cfg_new(size_t namelen);
#define port_cfg_free(port) \ #define port_cfg_free(port) \

View File

@ -37,13 +37,44 @@
#include "lib/string/printf.h" #include "lib/string/printf.h"
#include "lib/string/util_string.h" #include "lib/string/util_string.h"
static void config_reset(const config_format_t *fmt, void *options, static void config_reset(const config_mgr_t *fmt, void *options,
const config_var_t *var, int use_defaults); const config_var_t *var, int use_defaults);
struct config_mgr_t {
/** The 'top-level' configuration format. This one is used for legacy
* options that have not yet been assigned to different sub-modules.
*
* (NOTE: for now, this is the only config_format_t that a config_mgr_t
* contains. A subsequent commit will add more. XXXX)
*/
const config_format_t *toplevel;
};
/** Create a new config_mgr_t to manage a set of configuration objects to be
* wrapped under <b>toplevel_fmt</b>. */
config_mgr_t *
config_mgr_new(const config_format_t *toplevel_fmt)
{
config_mgr_t *mgr = tor_malloc_zero(sizeof(config_mgr_t));
mgr->toplevel = toplevel_fmt;
return mgr;
}
/** Release all storage held in <b>mgr</b> */
void
config_mgr_free_(config_mgr_t *mgr)
{
if (!mgr)
return;
memset(mgr, 0, sizeof(*mgr));
tor_free(mgr);
}
/** Allocate an empty configuration object of a given format type. */ /** Allocate an empty configuration object of a given format type. */
void * void *
config_new(const config_format_t *fmt) config_new(const config_mgr_t *mgr)
{ {
const config_format_t *fmt = mgr->toplevel;
void *opts = tor_malloc_zero(fmt->size); void *opts = tor_malloc_zero(fmt->size);
struct_set_magic(opts, &fmt->magic); struct_set_magic(opts, &fmt->magic);
CONFIG_CHECK(fmt, opts); CONFIG_CHECK(fmt, opts);
@ -60,9 +91,10 @@ config_new(const config_format_t *fmt)
* apply abbreviations that work for the config file and the command line. * apply abbreviations that work for the config file and the command line.
* If <b>warn_obsolete</b> is set, warn about deprecated names. */ * If <b>warn_obsolete</b> is set, warn about deprecated names. */
const char * const char *
config_expand_abbrev(const config_format_t *fmt, const char *option, config_expand_abbrev(const config_mgr_t *mgr, const char *option,
int command_line, int warn_obsolete) int command_line, int warn_obsolete)
{ {
const config_format_t *fmt = mgr->toplevel;
int i; int i;
if (! fmt->abbrevs) if (! fmt->abbrevs)
return option; return option;
@ -90,8 +122,9 @@ config_expand_abbrev(const config_format_t *fmt, const char *option,
* explaining why it is deprecated (which may be an empty string). Return NULL * explaining why it is deprecated (which may be an empty string). Return NULL
* if it is not deprecated. The <b>key</b> field must be fully expanded. */ * if it is not deprecated. The <b>key</b> field must be fully expanded. */
const char * const char *
config_find_deprecation(const config_format_t *fmt, const char *key) config_find_deprecation(const config_mgr_t *mgr, const char *key)
{ {
const config_format_t *fmt = mgr->toplevel;
if (BUG(fmt == NULL) || BUG(key == NULL)) if (BUG(fmt == NULL) || BUG(key == NULL))
return NULL; // LCOV_EXCL_LINE return NULL; // LCOV_EXCL_LINE
if (fmt->deprecations == NULL) if (fmt->deprecations == NULL)
@ -112,8 +145,9 @@ config_find_deprecation(const config_format_t *fmt, const char *key)
* NULL. * NULL.
*/ */
const config_var_t * const config_var_t *
config_find_option(const config_format_t *fmt, const char *key) config_find_option(const config_mgr_t *mgr, const char *key)
{ {
const config_format_t *fmt = mgr->toplevel;
int i; int i;
size_t keylen = strlen(key); size_t keylen = strlen(key);
if (!keylen) if (!keylen)
@ -139,8 +173,9 @@ config_find_option(const config_format_t *fmt, const char *key)
/** Return the number of option entries in <b>fmt</b>. */ /** Return the number of option entries in <b>fmt</b>. */
static int static int
config_count_options(const config_format_t *fmt) config_count_options(const config_mgr_t *mgr)
{ {
const config_format_t *fmt = mgr->toplevel;
int i; int i;
for (i=0; fmt->vars[i].member.name; ++i) for (i=0; fmt->vars[i].member.name; ++i)
; ;
@ -175,14 +210,15 @@ config_var_is_contained(const config_var_t *var)
* Called from config_assign_line() and option_reset(). * Called from config_assign_line() and option_reset().
*/ */
static int static int
config_assign_value(const config_format_t *fmt, void *options, config_assign_value(const config_mgr_t *mgr, void *options,
config_line_t *c, char **msg) config_line_t *c, char **msg)
{ {
const config_var_t *var; const config_var_t *var;
const config_format_t *fmt = mgr->toplevel;
CONFIG_CHECK(fmt, options); CONFIG_CHECK(fmt, options);
var = config_find_option(fmt, c->key); var = config_find_option(mgr, c->key);
tor_assert(var); tor_assert(var);
tor_assert(!strcmp(c->key, var->member.name)); tor_assert(!strcmp(c->key, var->member.name));
@ -192,9 +228,11 @@ config_assign_value(const config_format_t *fmt, void *options,
/** Mark every linelist in <b>options</b> "fragile", so that fresh assignments /** Mark every linelist in <b>options</b> "fragile", so that fresh assignments
* to it will replace old ones. */ * to it will replace old ones. */
static void static void
config_mark_lists_fragile(const config_format_t *fmt, void *options) config_mark_lists_fragile(const config_mgr_t *mgr, void *options)
{ {
int i; int i;
const config_format_t *fmt = mgr->toplevel;
tor_assert(fmt); tor_assert(fmt);
tor_assert(options); tor_assert(options);
@ -224,10 +262,11 @@ warn_deprecated_option(const char *what, const char *why)
* Called from config_assign(). * Called from config_assign().
*/ */
static int static int
config_assign_line(const config_format_t *fmt, void *options, config_assign_line(const config_mgr_t *mgr, void *options,
config_line_t *c, unsigned flags, config_line_t *c, unsigned flags,
bitarray_t *options_seen, char **msg) bitarray_t *options_seen, char **msg)
{ {
const config_format_t *fmt = mgr->toplevel;
const unsigned use_defaults = flags & CAL_USE_DEFAULTS; const unsigned use_defaults = flags & CAL_USE_DEFAULTS;
const unsigned clear_first = flags & CAL_CLEAR_FIRST; const unsigned clear_first = flags & CAL_CLEAR_FIRST;
const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS; const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS;
@ -235,7 +274,7 @@ config_assign_line(const config_format_t *fmt, void *options,
CONFIG_CHECK(fmt, options); CONFIG_CHECK(fmt, options);
var = config_find_option(fmt, c->key); var = config_find_option(mgr, c->key);
if (!var) { if (!var) {
if (fmt->extra) { if (fmt->extra) {
void *lvalue = STRUCT_VAR_P(options, fmt->extra->offset); void *lvalue = STRUCT_VAR_P(options, fmt->extra->offset);
@ -258,7 +297,7 @@ config_assign_line(const config_format_t *fmt, void *options,
const char *deprecation_msg; const char *deprecation_msg;
if (warn_deprecations && if (warn_deprecations &&
(deprecation_msg = config_find_deprecation(fmt, var->member.name))) { (deprecation_msg = config_find_deprecation(mgr, var->member.name))) {
warn_deprecated_option(var->member.name, deprecation_msg); warn_deprecated_option(var->member.name, deprecation_msg);
} }
@ -271,14 +310,14 @@ config_assign_line(const config_format_t *fmt, void *options,
log_warn(LD_CONFIG, log_warn(LD_CONFIG,
"Linelist option '%s' has no value. Skipping.", c->key); "Linelist option '%s' has no value. Skipping.", c->key);
} else { /* not already cleared */ } else { /* not already cleared */
config_reset(fmt, options, var, use_defaults); config_reset(mgr, options, var, use_defaults);
} }
} }
return 0; return 0;
} else if (c->command == CONFIG_LINE_CLEAR && !clear_first) { } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
// XXXX This is unreachable, since a CLEAR line always has an // XXXX This is unreachable, since a CLEAR line always has an
// XXXX empty value. // XXXX empty value.
config_reset(fmt, options, var, use_defaults); // LCOV_EXCL_LINE config_reset(mgr, options, var, use_defaults); // LCOV_EXCL_LINE
} }
if (options_seen && ! config_var_is_cumulative(var)) { if (options_seen && ! config_var_is_cumulative(var)) {
@ -292,7 +331,7 @@ config_assign_line(const config_format_t *fmt, void *options,
bitarray_set(options_seen, var_index); bitarray_set(options_seen, var_index);
} }
if (config_assign_value(fmt, options, c, msg) < 0) if (config_assign_value(mgr, options, c, msg) < 0)
return -2; return -2;
return 0; return 0;
} }
@ -300,18 +339,19 @@ config_assign_line(const config_format_t *fmt, void *options,
/** Restore the option named <b>key</b> in options to its default value. /** Restore the option named <b>key</b> in options to its default value.
* Called from config_assign(). */ * Called from config_assign(). */
STATIC void STATIC void
config_reset_line(const config_format_t *fmt, void *options, config_reset_line(const config_mgr_t *mgr, void *options,
const char *key, int use_defaults) const char *key, int use_defaults)
{ {
const config_format_t *fmt = mgr->toplevel;
const config_var_t *var; const config_var_t *var;
CONFIG_CHECK(fmt, options); CONFIG_CHECK(fmt, options);
var = config_find_option(fmt, key); var = config_find_option(mgr, key);
if (!var) if (!var)
return; /* give error on next pass. */ return; /* give error on next pass. */
config_reset(fmt, options, var, use_defaults); config_reset(mgr, options, var, use_defaults);
} }
/** Return true iff value needs to be quoted and escaped to be used in /** Return true iff value needs to be quoted and escaped to be used in
@ -345,16 +385,18 @@ config_value_needs_escape(const char *value)
* value needs to be quoted before it's put in a config file, quote and * value needs to be quoted before it's put in a config file, quote and
* escape that value. Return NULL if no such key exists. */ * escape that value. Return NULL if no such key exists. */
config_line_t * config_line_t *
config_get_assigned_option(const config_format_t *fmt, const void *options, config_get_assigned_option(const config_mgr_t *mgr, const void *options,
const char *key, int escape_val) const char *key, int escape_val)
{ {
const config_var_t *var; const config_var_t *var;
config_line_t *result; config_line_t *result;
const config_format_t *fmt = mgr->toplevel;
tor_assert(options && key); tor_assert(options && key);
CONFIG_CHECK(fmt, options); CONFIG_CHECK(fmt, options);
var = config_find_option(fmt, key); var = config_find_option(mgr, key);
if (!var) { if (!var) {
log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key); log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
return NULL; return NULL;
@ -432,12 +474,13 @@ options_trial_assign() calls config_assign(1, 1)
returns. returns.
*/ */
int int
config_assign(const config_format_t *fmt, void *options, config_line_t *list, config_assign(const config_mgr_t *mgr, void *options, config_line_t *list,
unsigned config_assign_flags, char **msg) unsigned config_assign_flags, char **msg)
{ {
config_line_t *p; config_line_t *p;
bitarray_t *options_seen; bitarray_t *options_seen;
const int n_options = config_count_options(fmt); const config_format_t *fmt = mgr->toplevel;
const int n_options = config_count_options(mgr);
const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST; const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST;
const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS; const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS;
@ -445,7 +488,7 @@ config_assign(const config_format_t *fmt, void *options, config_line_t *list,
/* pass 1: normalize keys */ /* pass 1: normalize keys */
for (p = list; p; p = p->next) { for (p = list; p; p = p->next) {
const char *full = config_expand_abbrev(fmt, p->key, 0, 1); const char *full = config_expand_abbrev(mgr, p->key, 0, 1);
if (strcmp(full,p->key)) { if (strcmp(full,p->key)) {
tor_free(p->key); tor_free(p->key);
p->key = tor_strdup(full); p->key = tor_strdup(full);
@ -456,14 +499,14 @@ config_assign(const config_format_t *fmt, void *options, config_line_t *list,
* mentioned config options, and maybe set to their defaults. */ * mentioned config options, and maybe set to their defaults. */
if (clear_first) { if (clear_first) {
for (p = list; p; p = p->next) for (p = list; p; p = p->next)
config_reset_line(fmt, options, p->key, use_defaults); config_reset_line(mgr, options, p->key, use_defaults);
} }
options_seen = bitarray_init_zero(n_options); options_seen = bitarray_init_zero(n_options);
/* pass 3: assign. */ /* pass 3: assign. */
while (list) { while (list) {
int r; int r;
if ((r=config_assign_line(fmt, options, list, config_assign_flags, if ((r=config_assign_line(mgr, options, list, config_assign_flags,
options_seen, msg))) { options_seen, msg))) {
bitarray_free(options_seen); bitarray_free(options_seen);
return r; return r;
@ -475,7 +518,7 @@ config_assign(const config_format_t *fmt, void *options, config_line_t *list,
/** Now we're done assigning a group of options to the configuration. /** Now we're done assigning a group of options to the configuration.
* Subsequent group assignments should _replace_ linelists, not extend * Subsequent group assignments should _replace_ linelists, not extend
* them. */ * them. */
config_mark_lists_fragile(fmt, options); config_mark_lists_fragile(mgr, options);
return 0; return 0;
} }
@ -483,12 +526,9 @@ config_assign(const config_format_t *fmt, void *options, config_line_t *list,
/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent. /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
* Called from config_reset() and config_free(). */ * Called from config_reset() and config_free(). */
static void static void
config_clear(const config_format_t *fmt, void *options, config_clear(void *options,
const config_var_t *var) const config_var_t *var)
{ {
(void)fmt; /* unused */
struct_var_free(options, &var->member); struct_var_free(options, &var->member);
} }
@ -496,20 +536,21 @@ config_clear(const config_format_t *fmt, void *options,
* <b>use_defaults</b>, set it to its default value. * <b>use_defaults</b>, set it to its default value.
* Called by config_init() and option_reset_line() and option_assign_line(). */ * Called by config_init() and option_reset_line() and option_assign_line(). */
static void static void
config_reset(const config_format_t *fmt, void *options, config_reset(const config_mgr_t *mgr, void *options,
const config_var_t *var, int use_defaults) const config_var_t *var, int use_defaults)
{ {
const config_format_t *fmt = mgr->toplevel;
config_line_t *c; config_line_t *c;
char *msg = NULL; char *msg = NULL;
CONFIG_CHECK(fmt, options); CONFIG_CHECK(fmt, options);
config_clear(fmt, options, var); /* clear it first */ config_clear(options, var); /* clear it first */
if (!use_defaults) if (!use_defaults)
return; /* all done */ return; /* all done */
if (var->initvalue) { if (var->initvalue) {
c = tor_malloc_zero(sizeof(config_line_t)); c = tor_malloc_zero(sizeof(config_line_t));
c->key = tor_strdup(var->member.name); c->key = tor_strdup(var->member.name);
c->value = tor_strdup(var->initvalue); c->value = tor_strdup(var->initvalue);
if (config_assign_value(fmt, options, c, &msg) < 0) { if (config_assign_value(mgr, options, c, &msg) < 0) {
// LCOV_EXCL_START // LCOV_EXCL_START
log_warn(LD_BUG, "Failed to assign default: %s", msg); log_warn(LD_BUG, "Failed to assign default: %s", msg);
tor_free(msg); /* if this happens it's a bug */ tor_free(msg); /* if this happens it's a bug */
@ -521,9 +562,10 @@ config_reset(const config_format_t *fmt, void *options,
/** Release storage held by <b>options</b>. */ /** Release storage held by <b>options</b>. */
void void
config_free_(const config_format_t *fmt, void *options) config_free_(const config_mgr_t *mgr, void *options)
{ {
int i; int i;
const config_format_t *fmt = mgr->toplevel;
if (!options) if (!options)
return; return;
@ -531,7 +573,7 @@ config_free_(const config_format_t *fmt, void *options)
tor_assert(fmt); tor_assert(fmt);
for (i=0; fmt->vars[i].member.name; ++i) for (i=0; fmt->vars[i].member.name; ++i)
config_clear(fmt, options, &(fmt->vars[i])); config_clear(options, &(fmt->vars[i]));
if (fmt->extra) { if (fmt->extra) {
config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->offset); config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->offset);
@ -545,14 +587,15 @@ config_free_(const config_format_t *fmt, void *options)
* and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options. * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
*/ */
int int
config_is_same(const config_format_t *fmt, config_is_same(const config_mgr_t *mgr,
const void *o1, const void *o2, const void *o1, const void *o2,
const char *name) const char *name)
{ {
const config_format_t *fmt = mgr->toplevel;
CONFIG_CHECK(fmt, o1); CONFIG_CHECK(fmt, o1);
CONFIG_CHECK(fmt, o2); CONFIG_CHECK(fmt, o2);
const config_var_t *var = config_find_option(fmt, name); const config_var_t *var = config_find_option(mgr, name);
if (!var) { if (!var) {
return true; return true;
} }
@ -562,12 +605,13 @@ config_is_same(const config_format_t *fmt,
/** Copy storage held by <b>old</b> into a new or_options_t and return it. */ /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
void * void *
config_dup(const config_format_t *fmt, const void *old) config_dup(const config_mgr_t *mgr, const void *old)
{ {
const config_format_t *fmt = mgr->toplevel;
void *newopts; void *newopts;
int i; int i;
newopts = config_new(fmt); newopts = config_new(mgr);
for (i=0; fmt->vars[i].member.name; ++i) { for (i=0; fmt->vars[i].member.name; ++i) {
if (config_var_is_contained(&fmt->vars[i])) { if (config_var_is_contained(&fmt->vars[i])) {
// Something else will copy this option, or it doesn't need copying. // Something else will copy this option, or it doesn't need copying.
@ -586,9 +630,10 @@ config_dup(const config_format_t *fmt, const void *old)
/** Set all vars in the configuration object <b>options</b> to their default /** Set all vars in the configuration object <b>options</b> to their default
* values. */ * values. */
void void
config_init(const config_format_t *fmt, void *options) config_init(const config_mgr_t *mgr, void *options)
{ {
int i; int i;
const config_format_t *fmt = mgr->toplevel;
const config_var_t *var; const config_var_t *var;
CONFIG_CHECK(fmt, options); CONFIG_CHECK(fmt, options);
@ -596,7 +641,7 @@ config_init(const config_format_t *fmt, void *options)
var = &fmt->vars[i]; var = &fmt->vars[i];
if (!var->initvalue) if (!var->initvalue)
continue; /* defaults to NULL or 0 */ continue; /* defaults to NULL or 0 */
config_reset(fmt, options, var, 1); config_reset(mgr, options, var, 1);
} }
} }
@ -605,11 +650,12 @@ config_init(const config_format_t *fmt, void *options)
* Else, if comment_defaults, write default values as comments. * Else, if comment_defaults, write default values as comments.
*/ */
char * char *
config_dump(const config_format_t *fmt, const void *default_options, config_dump(const config_mgr_t *mgr, const void *default_options,
const void *options, int minimal, const void *options, int minimal,
int comment_defaults) int comment_defaults)
{ {
smartlist_t *elements; smartlist_t *elements;
const config_format_t *fmt = mgr->toplevel;
const void *defaults = default_options; const void *defaults = default_options;
void *defaults_tmp = NULL; void *defaults_tmp = NULL;
config_line_t *line, *assigned; config_line_t *line, *assigned;
@ -618,8 +664,8 @@ config_dump(const config_format_t *fmt, const void *default_options,
char *msg = NULL; char *msg = NULL;
if (defaults == NULL) { if (defaults == NULL) {
defaults = defaults_tmp = config_new(fmt); defaults = defaults_tmp = config_new(mgr);
config_init(fmt, defaults_tmp); config_init(mgr, defaults_tmp);
} }
/* XXX use a 1 here so we don't add a new log line while dumping */ /* XXX use a 1 here so we don't add a new log line while dumping */
@ -643,15 +689,15 @@ config_dump(const config_format_t *fmt, const void *default_options,
/* Don't save 'hidden' control variables. */ /* Don't save 'hidden' control variables. */
if (fmt->vars[i].flags & CVFLAG_NODUMP) if (fmt->vars[i].flags & CVFLAG_NODUMP)
continue; continue;
if (minimal && config_is_same(fmt, options, defaults, if (minimal && config_is_same(mgr, options, defaults,
fmt->vars[i].member.name)) fmt->vars[i].member.name))
continue; continue;
else if (comment_defaults && else if (comment_defaults &&
config_is_same(fmt, options, defaults, fmt->vars[i].member.name)) config_is_same(mgr, options, defaults, fmt->vars[i].member.name))
comment_option = 1; comment_option = 1;
line = assigned = line = assigned =
config_get_assigned_option(fmt, options, fmt->vars[i].member.name, 1); config_get_assigned_option(mgr, options, fmt->vars[i].member.name, 1);
for (; line; line = line->next) { for (; line; line = line->next) {
if (!strcmpstart(line->key, "__")) { if (!strcmpstart(line->key, "__")) {
@ -677,7 +723,7 @@ config_dump(const config_format_t *fmt, const void *default_options,
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements); smartlist_free(elements);
if (defaults_tmp) { if (defaults_tmp) {
fmt->free_fn(defaults_tmp); fmt->free_fn(mgr, defaults_tmp);
} }
return result; return result;
} }
@ -687,8 +733,9 @@ config_dump(const config_format_t *fmt, const void *default_options,
* Return false otherwise. Log errors at level <b>severity</b>. * Return false otherwise. Log errors at level <b>severity</b>.
*/ */
bool bool
config_check_ok(const config_format_t *fmt, const void *options, int severity) config_check_ok(const config_mgr_t *mgr, const void *options, int severity)
{ {
const config_format_t *fmt = mgr->toplevel;
bool all_ok = true; bool all_ok = true;
for (int i=0; fmt->vars[i].member.name; ++i) { for (int i=0; fmt->vars[i].member.name; ++i) {
if (!struct_var_ok(options, &fmt->vars[i].member)) { if (!struct_var_ok(options, &fmt->vars[i].member)) {

View File

@ -39,8 +39,10 @@ typedef struct config_deprecation_t {
* of arguments. */ * of arguments. */
typedef int (*validate_fn_t)(void*,void*,void*,int,char**); typedef int (*validate_fn_t)(void*,void*,void*,int,char**);
struct config_mgr_t;
/** Callback to free a configuration object. */ /** Callback to free a configuration object. */
typedef void (*free_cfg_fn_t)(void*); typedef void (*free_cfg_fn_t)(const struct config_mgr_t *mgr, void*);
/** Information on the keys, value types, key-to-struct-member mappings, /** Information on the keys, value types, key-to-struct-member mappings,
* variable descriptions, validation functions, and abbreviations for a * variable descriptions, validation functions, and abbreviations for a
@ -61,6 +63,19 @@ typedef struct config_format_t {
const struct_member_t *extra; const struct_member_t *extra;
} config_format_t; } config_format_t;
/**
* A collection of config_format_t objects to describe several objects
* that are all configured with the same configuration file.
*
* (NOTE: for now, this only handles a single config_format_t.)
**/
typedef struct config_mgr_t config_mgr_t;
config_mgr_t *config_mgr_new(const config_format_t *toplevel_fmt);
void config_mgr_free_(config_mgr_t *mgr);
#define config_mgr_free(mgr) \
FREE_AND_NULL(config_mgr_t, config_mgr_free_, (mgr))
/** Macro: assert that <b>cfg</b> has the right magic field for format /** Macro: assert that <b>cfg</b> has the right magic field for format
* <b>fmt</b>. */ * <b>fmt</b>. */
#define CONFIG_CHECK(fmt, cfg) STMT_BEGIN \ #define CONFIG_CHECK(fmt, cfg) STMT_BEGIN \
@ -72,34 +87,34 @@ typedef struct config_format_t {
#define CAL_CLEAR_FIRST (1u<<1) #define CAL_CLEAR_FIRST (1u<<1)
#define CAL_WARN_DEPRECATIONS (1u<<2) #define CAL_WARN_DEPRECATIONS (1u<<2)
void *config_new(const config_format_t *fmt); void *config_new(const config_mgr_t *fmt);
void config_free_(const config_format_t *fmt, void *options); void config_free_(const config_mgr_t *fmt, void *options);
#define config_free(fmt, options) do { \ #define config_free(mgr, options) do { \
config_free_((fmt), (options)); \ config_free_((mgr), (options)); \
(options) = NULL; \ (options) = NULL; \
} while (0) } while (0)
struct config_line_t *config_get_assigned_option(const config_format_t *fmt, struct config_line_t *config_get_assigned_option(const config_mgr_t *mgr,
const void *options, const char *key, const void *options, const char *key,
int escape_val); int escape_val);
int config_is_same(const config_format_t *fmt, int config_is_same(const config_mgr_t *fmt,
const void *o1, const void *o2, const void *o1, const void *o2,
const char *name); const char *name);
void config_init(const config_format_t *fmt, void *options); void config_init(const config_mgr_t *mgr, void *options);
void *config_dup(const config_format_t *fmt, const void *old); void *config_dup(const config_mgr_t *mgr, const void *old);
char *config_dump(const config_format_t *fmt, const void *default_options, char *config_dump(const config_mgr_t *mgr, const void *default_options,
const void *options, int minimal, const void *options, int minimal,
int comment_defaults); int comment_defaults);
bool config_check_ok(const config_format_t *fmt, const void *options, bool config_check_ok(const config_mgr_t *mgr, const void *options,
int severity); int severity);
int config_assign(const config_format_t *fmt, void *options, int config_assign(const config_mgr_t *mgr, void *options,
struct config_line_t *list, struct config_line_t *list,
unsigned flags, char **msg); unsigned flags, char **msg);
const char *config_find_deprecation(const config_format_t *fmt, const char *config_find_deprecation(const config_mgr_t *mgr,
const char *key); const char *key);
const config_var_t *config_find_option(const config_format_t *fmt, const config_var_t *config_find_option(const config_mgr_t *mgr,
const char *key); const char *key);
const char *config_expand_abbrev(const config_format_t *fmt, const char *config_expand_abbrev(const config_mgr_t *mgr,
const char *option, const char *option,
int command_line, int warn_obsolete); int command_line, int warn_obsolete);
void warn_deprecated_option(const char *what, const char *why); void warn_deprecated_option(const char *what, const char *why);
@ -117,7 +132,7 @@ bool config_var_is_contained(const config_var_t *var);
#define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt) #define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt)
#ifdef CONFPARSE_PRIVATE #ifdef CONFPARSE_PRIVATE
STATIC void config_reset_line(const config_format_t *fmt, void *options, STATIC void config_reset_line(const config_mgr_t *mgr, void *options,
const char *key, int use_defaults); const char *key, int use_defaults);
#endif #endif

View File

@ -145,7 +145,7 @@ static int or_state_validate_cb(void *old_options, void *options,
void *default_options, void *default_options,
int from_setconf, char **msg); int from_setconf, char **msg);
static void or_state_free_cb(void *state); static void or_state_free_cb(const config_mgr_t *mgr, void *state);
/** Magic value for or_state_t. */ /** Magic value for or_state_t. */
#define OR_STATE_MAGIC 0x57A73f57 #define OR_STATE_MAGIC 0x57A73f57
@ -174,6 +174,19 @@ static const config_format_t state_format = {
&state_extra_var, &state_extra_var,
}; };
/* A global configuration manager for state-file objects */
static config_mgr_t *state_mgr = NULL;
/** Return the configuration manager for state-file objects. */
static const config_mgr_t *
get_state_mgr(void)
{
if (PREDICT_UNLIKELY(state_mgr == NULL)) {
state_mgr = config_mgr_new(&state_format);
}
return state_mgr;
}
/** Persistent serialized state. */ /** Persistent serialized state. */
static or_state_t *global_state = NULL; static or_state_t *global_state = NULL;
@ -269,8 +282,9 @@ or_state_validate_cb(void *old_state, void *state, void *default_state,
} }
static void static void
or_state_free_cb(void *state) or_state_free_cb(const config_mgr_t *mgr, void *state)
{ {
(void)mgr;
or_state_free_(state); or_state_free_(state);
} }
@ -298,7 +312,7 @@ or_state_set(or_state_t *new_state)
char *err = NULL; char *err = NULL;
int ret = 0; int ret = 0;
tor_assert(new_state); tor_assert(new_state);
config_free(&state_format, global_state); config_free(get_state_mgr(), global_state);
global_state = new_state; global_state = new_state;
if (entry_guards_parse_state(global_state, 1, &err)<0) { if (entry_guards_parse_state(global_state, 1, &err)<0) {
log_warn(LD_GENERAL,"%s",err); log_warn(LD_GENERAL,"%s",err);
@ -363,7 +377,7 @@ or_state_new(void)
{ {
or_state_t *new_state = tor_malloc_zero(sizeof(or_state_t)); or_state_t *new_state = tor_malloc_zero(sizeof(or_state_t));
new_state->magic_ = OR_STATE_MAGIC; new_state->magic_ = OR_STATE_MAGIC;
config_init(&state_format, new_state); config_init(get_state_mgr(), new_state);
return new_state; return new_state;
} }
@ -404,7 +418,7 @@ or_state_load(void)
int assign_retval; int assign_retval;
if (config_get_lines(contents, &lines, 0)<0) if (config_get_lines(contents, &lines, 0)<0)
goto done; goto done;
assign_retval = config_assign(&state_format, new_state, assign_retval = config_assign(get_state_mgr(), new_state,
lines, 0, &errmsg); lines, 0, &errmsg);
config_free_lines(lines); config_free_lines(lines);
if (assign_retval<0) if (assign_retval<0)
@ -431,7 +445,7 @@ or_state_load(void)
or_state_save_broken(fname); or_state_save_broken(fname);
tor_free(contents); tor_free(contents);
config_free(&state_format, new_state); config_free(get_state_mgr(), new_state);
new_state = or_state_new(); new_state = or_state_new();
} else if (contents) { } else if (contents) {
@ -464,7 +478,7 @@ or_state_load(void)
tor_free(fname); tor_free(fname);
tor_free(contents); tor_free(contents);
if (new_state) if (new_state)
config_free(&state_format, new_state); config_free(get_state_mgr(), new_state);
return r; return r;
} }
@ -517,7 +531,7 @@ or_state_save(time_t now)
tor_free(global_state->TorVersion); tor_free(global_state->TorVersion);
tor_asprintf(&global_state->TorVersion, "Tor %s", get_version()); tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
state = config_dump(&state_format, NULL, global_state, 1, 0); state = config_dump(get_state_mgr(), NULL, global_state, 1, 0);
format_local_iso_time(tbuf, now); format_local_iso_time(tbuf, now);
tor_asprintf(&contents, tor_asprintf(&contents,
"# Tor state file last generated on %s local time\n" "# Tor state file last generated on %s local time\n"
@ -727,7 +741,7 @@ or_state_free_(or_state_t *state)
if (!state) if (!state)
return; return;
config_free(&state_format, state); config_free(get_state_mgr(), state);
} }
void void
@ -735,4 +749,5 @@ or_state_free_all(void)
{ {
or_state_free(global_state); or_state_free(global_state);
global_state = NULL; global_state = NULL;
config_mgr_free(state_mgr);
} }

View File

@ -62,7 +62,7 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
static int static int
disk_state_validate_cb(void *old_state, void *state, void *default_state, disk_state_validate_cb(void *old_state, void *state, void *default_state,
int from_setconf, char **msg); int from_setconf, char **msg);
static void disk_state_free_cb(void *); static void disk_state_free_cb(const config_mgr_t *mgr, void *);
/* Array of variables that are saved to disk as a persistent state. */ /* Array of variables that are saved to disk as a persistent state. */
static const config_var_t state_vars[] = { static const config_var_t state_vars[] = {
@ -103,6 +103,19 @@ static const config_format_t state_format = {
&state_extra_var, &state_extra_var,
}; };
/* Global configuration manager for the shared-random state file */
static config_mgr_t *shared_random_state_mgr = NULL;
/** Return the configuration manager for the shared-random state file. */
static const config_mgr_t *
get_srs_mgr(void)
{
if (PREDICT_UNLIKELY(shared_random_state_mgr == NULL)) {
shared_random_state_mgr = config_mgr_new(&state_format);
}
return shared_random_state_mgr;
}
static void state_query_del_(sr_state_object_t obj_type, void *data); static void state_query_del_(sr_state_object_t obj_type, void *data);
/* Return a string representation of a protocol phase. */ /* Return a string representation of a protocol phase. */
@ -264,7 +277,7 @@ disk_state_free_(sr_disk_state_t *state)
if (state == NULL) { if (state == NULL) {
return; return;
} }
config_free(&state_format, state); config_free(get_srs_mgr(), state);
} }
/* Allocate a new disk state, initialize it and return it. */ /* Allocate a new disk state, initialize it and return it. */
@ -280,7 +293,7 @@ disk_state_new(time_t now)
new_state->ValidAfter = now; new_state->ValidAfter = now;
/* Init config format. */ /* Init config format. */
config_init(&state_format, new_state); config_init(get_srs_mgr(), new_state);
return new_state; return new_state;
} }
@ -349,8 +362,9 @@ disk_state_validate_cb(void *old_state, void *state, void *default_state,
} }
static void static void
disk_state_free_cb(void *state) disk_state_free_cb(const config_mgr_t *mgr, void *state)
{ {
(void)mgr;
disk_state_free_(state); disk_state_free_(state);
} }
@ -683,7 +697,7 @@ disk_state_load_from_disk_impl(const char *fname)
} }
disk_state = disk_state_new(time(NULL)); disk_state = disk_state_new(time(NULL));
config_assign(&state_format, disk_state, lines, 0, &errmsg); config_assign(get_srs_mgr(), disk_state, lines, 0, &errmsg);
config_free_lines(lines); config_free_lines(lines);
if (errmsg) { if (errmsg) {
log_warn(LD_DIR, "SR: Reading state error: %s", errmsg); log_warn(LD_DIR, "SR: Reading state error: %s", errmsg);
@ -736,7 +750,7 @@ disk_state_save_to_disk(void)
/* Make sure that our disk state is up to date with our memory state /* Make sure that our disk state is up to date with our memory state
* before saving it to disk. */ * before saving it to disk. */
disk_state_update(); disk_state_update();
state = config_dump(&state_format, NULL, sr_disk_state, 0, 0); state = config_dump(get_srs_mgr(), NULL, sr_disk_state, 0, 0);
format_local_iso_time(tbuf, now); format_local_iso_time(tbuf, now);
tor_asprintf(&content, tor_asprintf(&content,
"# Tor shared random state file last generated on %s " "# Tor shared random state file last generated on %s "
@ -1278,6 +1292,7 @@ sr_state_free_all(void)
/* Nullify our global state. */ /* Nullify our global state. */
sr_state = NULL; sr_state = NULL;
sr_disk_state = NULL; sr_disk_state = NULL;
config_mgr_free(shared_random_state_mgr);
} }
/* Save our current state in memory to disk. */ /* Save our current state in memory to disk. */

View File

@ -119,7 +119,7 @@ test_validate_cb(void *old_options, void *options, void *default_options,
return 0; return 0;
} }
static void test_free_cb(void *options); static void test_free_cb(const config_mgr_t *mgr, void *options);
#define TEST_MAGIC 0x1337 #define TEST_MAGIC 0x1337
@ -139,12 +139,12 @@ static const config_format_t test_fmt = {
}; };
static void static void
test_free_cb(void *options) test_free_cb(const config_mgr_t *mgr, void *options)
{ {
if (!options) if (!options)
return; return;
config_free(&test_fmt, options); config_free(mgr, options);
} }
/* Make sure that config_init sets everything to the right defaults. */ /* Make sure that config_init sets everything to the right defaults. */
@ -152,8 +152,9 @@ static void
test_confparse_init(void *arg) test_confparse_init(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
config_init(&test_fmt, tst); test_struct_t *tst = config_new(mgr);
config_init(mgr, tst);
// Make sure that options are initialized right. */ // Make sure that options are initialized right. */
tt_uint_op(tst->magic, OP_EQ, TEST_MAGIC); tt_uint_op(tst->magic, OP_EQ, TEST_MAGIC);
@ -178,7 +179,8 @@ test_confparse_init(void *arg)
tt_int_op(tst->hidden_int, OP_EQ, 0); tt_int_op(tst->hidden_int, OP_EQ, 0);
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_mgr_free(mgr);
} }
static const char simple_settings[] = static const char simple_settings[] =
@ -207,18 +209,18 @@ static const char simple_settings[] =
/* Return a configuration object set up from simple_settings above. */ /* Return a configuration object set up from simple_settings above. */
static test_struct_t * static test_struct_t *
get_simple_config(void) get_simple_config(const config_mgr_t *mgr)
{ {
test_struct_t *result = NULL; test_struct_t *result = NULL;
test_struct_t *tst = config_new(&test_fmt); test_struct_t *tst = config_new(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines(simple_settings, &lines, 0); int r = config_get_lines(simple_settings, &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
@ -227,7 +229,7 @@ get_simple_config(void)
done: done:
tor_free(msg); tor_free(msg);
config_free_lines(lines); config_free_lines(lines);
config_free(&test_fmt, tst); config_free(mgr, tst);
return result; return result;
} }
@ -236,7 +238,8 @@ static void
test_confparse_assign_simple(void *arg) test_confparse_assign_simple(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = get_simple_config(); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
tt_str_op(tst->s, OP_EQ, "this is a"); tt_str_op(tst->s, OP_EQ, "this is a");
tt_str_op(tst->fn, OP_EQ, "/simple/test of the"); tt_str_op(tst->fn, OP_EQ, "/simple/test of the");
@ -284,10 +287,11 @@ test_confparse_assign_simple(void *arg)
tt_str_op(tst->mixed_hidden_lines->next->value, OP_EQ, "ABC"); tt_str_op(tst->mixed_hidden_lines->next->value, OP_EQ, "ABC");
tt_assert(!tst->mixed_hidden_lines->next->next); tt_assert(!tst->mixed_hidden_lines->next->next);
tt_assert(config_check_ok(&test_fmt, tst, LOG_ERR)); tt_assert(config_check_ok(mgr, tst, LOG_ERR));
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_mgr_free(mgr);
} }
/* Try to assign to an obsolete option, and make sure we get a warning. */ /* Try to assign to an obsolete option, and make sure we get a warning. */
@ -295,26 +299,28 @@ static void
test_confparse_assign_obsolete(void *arg) test_confparse_assign_obsolete(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines("obsolete option here", int r = config_get_lines("obsolete option here",
&lines, 0); &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
setup_capture_of_logs(LOG_WARN); setup_capture_of_logs(LOG_WARN);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
expect_single_log_msg_containing("Skipping obsolete configuration option"); expect_single_log_msg_containing("Skipping obsolete configuration option");
done: done:
teardown_capture_of_logs(); teardown_capture_of_logs();
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
/* Try to assign to an deprecated option, and make sure we get a warning /* Try to assign to an deprecated option, and make sure we get a warning
@ -323,30 +329,32 @@ static void
test_confparse_assign_deprecated(void *arg) test_confparse_assign_deprecated(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines("deprecated_int 7", int r = config_get_lines("deprecated_int 7",
&lines, 0); &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
setup_capture_of_logs(LOG_WARN); setup_capture_of_logs(LOG_WARN);
r = config_assign(&test_fmt, tst, lines, CAL_WARN_DEPRECATIONS, &msg); r = config_assign(mgr, tst, lines, CAL_WARN_DEPRECATIONS, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
expect_single_log_msg_containing("This integer is deprecated."); expect_single_log_msg_containing("This integer is deprecated.");
tt_int_op(tst->deprecated_int, OP_EQ, 7); tt_int_op(tst->deprecated_int, OP_EQ, 7);
tt_assert(config_check_ok(&test_fmt, tst, LOG_ERR)); tt_assert(config_check_ok(mgr, tst, LOG_ERR));
done: done:
teardown_capture_of_logs(); teardown_capture_of_logs();
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
/* Try to re-assign an option name that has been depreacted in favor of /* Try to re-assign an option name that has been depreacted in favor of
@ -355,16 +363,17 @@ static void
test_confparse_assign_replaced(void *arg) test_confparse_assign_replaced(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines("float 1000\n", &lines, 0); int r = config_get_lines("float 1000\n", &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
setup_capture_of_logs(LOG_WARN); setup_capture_of_logs(LOG_WARN);
r = config_assign(&test_fmt, tst, lines, CAL_WARN_DEPRECATIONS, &msg); r = config_assign(mgr, tst, lines, CAL_WARN_DEPRECATIONS, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
expect_single_log_msg_containing("use 'dbl' instead."); expect_single_log_msg_containing("use 'dbl' instead.");
@ -374,9 +383,10 @@ test_confparse_assign_replaced(void *arg)
done: done:
teardown_capture_of_logs(); teardown_capture_of_logs();
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
/* Try to set a linelist value with no option. */ /* Try to set a linelist value with no option. */
@ -384,25 +394,27 @@ static void
test_confparse_assign_emptystring(void *arg) test_confparse_assign_emptystring(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines("lines\n", &lines, 0); int r = config_get_lines("lines\n", &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
setup_capture_of_logs(LOG_WARN); setup_capture_of_logs(LOG_WARN);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
expect_single_log_msg_containing("has no value"); expect_single_log_msg_containing("has no value");
done: done:
teardown_capture_of_logs(); teardown_capture_of_logs();
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
/* Try to set a the same option twice; make sure we get a warning. */ /* Try to set a the same option twice; make sure we get a warning. */
@ -410,26 +422,28 @@ static void
test_confparse_assign_twice(void *arg) test_confparse_assign_twice(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines("pos 10\n" int r = config_get_lines("pos 10\n"
"pos 99\n", &lines, 0); "pos 99\n", &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
setup_capture_of_logs(LOG_WARN); setup_capture_of_logs(LOG_WARN);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
expect_single_log_msg_containing("used more than once"); expect_single_log_msg_containing("used more than once");
done: done:
teardown_capture_of_logs(); teardown_capture_of_logs();
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
typedef struct badval_test_t { typedef struct badval_test_t {
@ -443,16 +457,17 @@ static void
test_confparse_assign_badval(void *arg) test_confparse_assign_badval(void *arg)
{ {
const badval_test_t *bt = arg; const badval_test_t *bt = arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
config_init(&test_fmt, tst); config_init(mgr, tst);
int r = config_get_lines(bt->cfg, &lines, 0); int r = config_get_lines(bt->cfg, &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
setup_capture_of_logs(LOG_WARN); setup_capture_of_logs(LOG_WARN);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_LT, 0); tt_int_op(r, OP_LT, 0);
tt_ptr_op(msg, OP_NE, NULL); tt_ptr_op(msg, OP_NE, NULL);
if (! strstr(msg, bt->expect_msg)) { if (! strstr(msg, bt->expect_msg)) {
@ -461,9 +476,10 @@ test_confparse_assign_badval(void *arg)
done: done:
teardown_capture_of_logs(); teardown_capture_of_logs();
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
/* Various arguments for badval test. /* Various arguments for badval test.
@ -495,11 +511,12 @@ static void
test_confparse_dump(void *arg) test_confparse_dump(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = get_simple_config(); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
char *dumped = NULL; char *dumped = NULL;
/* Minimal version. */ /* Minimal version. */
dumped = config_dump(&test_fmt, NULL, tst, 1, 0); dumped = config_dump(mgr, NULL, tst, 1, 0);
tt_str_op(dumped, OP_EQ, tt_str_op(dumped, OP_EQ,
"s this is a\n" "s this is a\n"
"fn /simple/test of the\n" "fn /simple/test of the\n"
@ -524,7 +541,7 @@ test_confparse_dump(void *arg)
/* Maximal */ /* Maximal */
tor_free(dumped); tor_free(dumped);
dumped = config_dump(&test_fmt, NULL, tst, 0, 0); dumped = config_dump(mgr, NULL, tst, 0, 0);
tt_str_op(dumped, OP_EQ, tt_str_op(dumped, OP_EQ,
"s this is a\n" "s this is a\n"
"fn /simple/test of the\n" "fn /simple/test of the\n"
@ -550,7 +567,7 @@ test_confparse_dump(void *arg)
/* commented */ /* commented */
tor_free(dumped); tor_free(dumped);
dumped = config_dump(&test_fmt, NULL, tst, 0, 1); dumped = config_dump(mgr, NULL, tst, 0, 1);
tt_str_op(dumped, OP_EQ, tt_str_op(dumped, OP_EQ,
"s this is a\n" "s this is a\n"
"fn /simple/test of the\n" "fn /simple/test of the\n"
@ -575,8 +592,9 @@ test_confparse_dump(void *arg)
"VisibleLineB ABC\n"); "VisibleLineB ABC\n");
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
tor_free(dumped); tor_free(dumped);
config_mgr_free(mgr);
} }
/* Try confparse_reset_line(), and make sure it behaves correctly */ /* Try confparse_reset_line(), and make sure it behaves correctly */
@ -584,16 +602,18 @@ static void
test_confparse_reset(void *arg) test_confparse_reset(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = get_simple_config(); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_reset_line(&test_fmt, tst, "interval", 0); config_reset_line(mgr, tst, "interval", 0);
tt_int_op(tst->interval, OP_EQ, 0); tt_int_op(tst->interval, OP_EQ, 0);
config_reset_line(&test_fmt, tst, "interval", 1); config_reset_line(mgr, tst, "interval", 1);
tt_int_op(tst->interval, OP_EQ, 10); tt_int_op(tst->interval, OP_EQ, 10);
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_mgr_free(mgr);
} }
/* Try setting options a second time on a config object, and make sure /* Try setting options a second time on a config object, and make sure
@ -602,7 +622,8 @@ static void
test_confparse_reassign(void *arg) test_confparse_reassign(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = get_simple_config(); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL, *rs = NULL; char *msg = NULL, *rs = NULL;
@ -613,7 +634,7 @@ test_confparse_reassign(void *arg)
"csv 14,15\n" "csv 14,15\n"
"routerset 127.0.0.1\n", "routerset 127.0.0.1\n",
&lines, 0); &lines, 0);
r = config_assign(&test_fmt, tst,lines, 0, &msg); r = config_assign(mgr, tst,lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
@ -633,7 +654,7 @@ test_confparse_reassign(void *arg)
tt_str_op(rs, OP_EQ, "127.0.0.1"); tt_str_op(rs, OP_EQ, "127.0.0.1");
// Try again with the CLEAR_FIRST and USE_DEFAULTS flags // Try again with the CLEAR_FIRST and USE_DEFAULTS flags
r = config_assign(&test_fmt, tst, lines, r = config_assign(mgr, tst, lines,
CAL_CLEAR_FIRST|CAL_USE_DEFAULTS, &msg); CAL_CLEAR_FIRST|CAL_USE_DEFAULTS, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
@ -644,10 +665,11 @@ test_confparse_reassign(void *arg)
tt_int_op(tst->i, OP_EQ, 12); tt_int_op(tst->i, OP_EQ, 12);
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
tor_free(rs); tor_free(rs);
config_mgr_free(mgr);
} }
/* Try setting options a second time on a config object, using the +foo /* Try setting options a second time on a config object, using the +foo
@ -656,7 +678,8 @@ static void
test_confparse_reassign_extend(void *arg) test_confparse_reassign_extend(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = get_simple_config(); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL; char *msg = NULL;
@ -664,7 +687,7 @@ test_confparse_reassign_extend(void *arg)
"+lines 13\n", "+lines 13\n",
&lines, 1); // allow extended format. &lines, 1); // allow extended format.
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&test_fmt, tst,lines, 0, &msg); r = config_assign(mgr, tst,lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
@ -684,27 +707,28 @@ test_confparse_reassign_extend(void *arg)
"/lines\n", "/lines\n",
&lines, 1); // allow extended format. &lines, 1); // allow extended format.
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
tt_assert(tst->lines == NULL); tt_assert(tst->lines == NULL);
config_free_lines(lines); config_free_lines(lines);
config_free(&test_fmt, tst); config_free(mgr, tst);
tst = get_simple_config(); tst = get_simple_config(mgr);
r = config_get_lines( r = config_get_lines(
"/lines away!\n", "/lines away!\n",
&lines, 1); // allow extended format. &lines, 1); // allow extended format.
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&test_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
tt_assert(tst->lines == NULL); tt_assert(tst->lines == NULL);
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
tor_free(msg); tor_free(msg);
config_mgr_free(mgr);
} }
/* Test out confparse_get_assigned(). */ /* Test out confparse_get_assigned(). */
@ -712,30 +736,32 @@ static void
test_confparse_get_assigned(void *arg) test_confparse_get_assigned(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = get_simple_config();
config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = get_simple_config(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
lines = config_get_assigned_option(&test_fmt, tst, "I", 1); lines = config_get_assigned_option(mgr, tst, "I", 1);
tt_assert(lines); tt_assert(lines);
tt_str_op(lines->key, OP_EQ, "i"); tt_str_op(lines->key, OP_EQ, "i");
tt_str_op(lines->value, OP_EQ, "3"); tt_str_op(lines->value, OP_EQ, "3");
tt_assert(lines->next == NULL); tt_assert(lines->next == NULL);
config_free_lines(lines); config_free_lines(lines);
lines = config_get_assigned_option(&test_fmt, tst, "s", 1); lines = config_get_assigned_option(mgr, tst, "s", 1);
tt_assert(lines); tt_assert(lines);
tt_str_op(lines->key, OP_EQ, "s"); tt_str_op(lines->key, OP_EQ, "s");
tt_str_op(lines->value, OP_EQ, "this is a"); tt_str_op(lines->value, OP_EQ, "this is a");
tt_assert(lines->next == NULL); tt_assert(lines->next == NULL);
config_free_lines(lines); config_free_lines(lines);
lines = config_get_assigned_option(&test_fmt, tst, "obsolete", 1); lines = config_get_assigned_option(mgr, tst, "obsolete", 1);
tt_assert(!lines); tt_assert(!lines);
lines = config_get_assigned_option(&test_fmt, tst, "nonesuch", 1); lines = config_get_assigned_option(mgr, tst, "nonesuch", 1);
tt_assert(!lines); tt_assert(!lines);
lines = config_get_assigned_option(&test_fmt, tst, "mixedlines", 1); lines = config_get_assigned_option(mgr, tst, "mixedlines", 1);
tt_assert(lines); tt_assert(lines);
tt_str_op(lines->key, OP_EQ, "LineTypeA"); tt_str_op(lines->key, OP_EQ, "LineTypeA");
tt_str_op(lines->value, OP_EQ, "i d"); tt_str_op(lines->value, OP_EQ, "i d");
@ -745,7 +771,7 @@ test_confparse_get_assigned(void *arg)
tt_assert(lines->next->next == NULL); tt_assert(lines->next->next == NULL);
config_free_lines(lines); config_free_lines(lines);
lines = config_get_assigned_option(&test_fmt, tst, "linetypeb", 1); lines = config_get_assigned_option(mgr, tst, "linetypeb", 1);
tt_assert(lines); tt_assert(lines);
tt_str_op(lines->key, OP_EQ, "LineTypeB"); tt_str_op(lines->key, OP_EQ, "LineTypeB");
tt_str_op(lines->value, OP_EQ, "i c"); tt_str_op(lines->value, OP_EQ, "i c");
@ -754,7 +780,7 @@ test_confparse_get_assigned(void *arg)
tor_free(tst->s); tor_free(tst->s);
tst->s = tor_strdup("Hello\nWorld"); tst->s = tor_strdup("Hello\nWorld");
lines = config_get_assigned_option(&test_fmt, tst, "s", 1); lines = config_get_assigned_option(mgr, tst, "s", 1);
tt_assert(lines); tt_assert(lines);
tt_str_op(lines->key, OP_EQ, "s"); tt_str_op(lines->key, OP_EQ, "s");
tt_str_op(lines->value, OP_EQ, "\"Hello\\nWorld\""); tt_str_op(lines->value, OP_EQ, "\"Hello\\nWorld\"");
@ -762,8 +788,9 @@ test_confparse_get_assigned(void *arg)
config_free_lines(lines); config_free_lines(lines);
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_free_lines(lines); config_free_lines(lines);
config_mgr_free(mgr);
} }
/* Another variant, which accepts and stores unrecognized lines.*/ /* Another variant, which accepts and stores unrecognized lines.*/
@ -796,24 +823,25 @@ static void
test_confparse_extra_lines(void *arg) test_confparse_extra_lines(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&etest_fmt); config_mgr_t *mgr = config_mgr_new(&etest_fmt);
test_struct_t *tst = config_new(mgr);
config_line_t *lines = NULL; config_line_t *lines = NULL;
char *msg = NULL, *dump = NULL; char *msg = NULL, *dump = NULL;
config_init(&etest_fmt, tst); config_init(mgr, tst);
int r = config_get_lines( int r = config_get_lines(
"unknotty addita\n" "unknotty addita\n"
"pos 99\n" "pos 99\n"
"wombat knish\n", &lines, 0); "wombat knish\n", &lines, 0);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&etest_fmt, tst, lines, 0, &msg); r = config_assign(mgr, tst, lines, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL); tt_ptr_op(msg, OP_EQ, NULL);
tt_assert(tst->extra_lines); tt_assert(tst->extra_lines);
dump = config_dump(&etest_fmt, NULL, tst, 1, 0); dump = config_dump(mgr, NULL, tst, 1, 0);
tt_str_op(dump, OP_EQ, tt_str_op(dump, OP_EQ,
"pos 99\n" "pos 99\n"
"unknotty addita\n" "unknotty addita\n"
@ -823,7 +851,8 @@ test_confparse_extra_lines(void *arg)
tor_free(msg); tor_free(msg);
tor_free(dump); tor_free(dump);
config_free_lines(lines); config_free_lines(lines);
config_free(&etest_fmt, tst); config_free(mgr, tst);
config_mgr_free(mgr);
} }
static void static void
@ -889,12 +918,14 @@ static void
test_confparse_check_ok_fail(void *arg) test_confparse_check_ok_fail(void *arg)
{ {
(void)arg; (void)arg;
test_struct_t *tst = config_new(&test_fmt); config_mgr_t *mgr = config_mgr_new(&test_fmt);
test_struct_t *tst = config_new(mgr);
tst->pos = -10; tst->pos = -10;
tt_assert(! config_check_ok(&test_fmt, tst, LOG_INFO)); tt_assert(! config_check_ok(mgr, tst, LOG_INFO));
done: done:
config_free(&test_fmt, tst); config_free(mgr, tst);
config_mgr_free(mgr);
} }
#define CONFPARSE_TEST(name, flags) \ #define CONFPARSE_TEST(name, flags) \

View File

@ -295,7 +295,7 @@ helper_parse_options(const char *conf)
if (ret != 0) { if (ret != 0) {
goto done; goto done;
} }
ret = config_assign(&options_format, opt, line, 0, &msg); ret = config_assign(get_options_mgr(), opt, line, 0, &msg);
if (ret != 0) { if (ret != 0) {
goto done; goto done;
} }

View File

@ -96,7 +96,7 @@ clear_log_messages(void)
opt->command = CMD_RUN_TOR; \ opt->command = CMD_RUN_TOR; \
options_init(opt); \ options_init(opt); \
\ \
dflt = config_dup(&options_format, opt); \ dflt = config_dup(get_options_mgr(), opt); \
clear_log_messages(); \ clear_log_messages(); \
} while (0) } while (0)
@ -196,7 +196,7 @@ test_options_validate_impl(const char *configuration,
if (r) if (r)
goto done; goto done;
r = config_assign(&options_format, opt, cl, 0, &msg); r = config_assign(get_options_mgr(), opt, cl, 0, &msg);
if (phase == PH_ASSIGN) { if (phase == PH_ASSIGN) {
if (test_options_checkmsgs(configuration, expect_errmsg, if (test_options_checkmsgs(configuration, expect_errmsg,
expect_log_severity, expect_log_severity,
@ -304,7 +304,7 @@ test_have_enough_mem_for_dircache(void *arg)
r = config_get_lines(configuration, &cl, 1); r = config_get_lines(configuration, &cl, 1);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&options_format, opt, cl, 0, &msg); r = config_assign(get_options_mgr(), opt, cl, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
/* 300 MB RAM available, DirCache enabled */ /* 300 MB RAM available, DirCache enabled */
@ -327,7 +327,7 @@ test_have_enough_mem_for_dircache(void *arg)
r = config_get_lines(configuration, &cl, 1); r = config_get_lines(configuration, &cl, 1);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&options_format, opt, cl, 0, &msg); r = config_assign(get_options_mgr(), opt, cl, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
/* 300 MB RAM available, DirCache enabled, Bridge */ /* 300 MB RAM available, DirCache enabled, Bridge */
@ -350,7 +350,7 @@ test_have_enough_mem_for_dircache(void *arg)
r = config_get_lines(configuration, &cl, 1); r = config_get_lines(configuration, &cl, 1);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
r = config_assign(&options_format, opt, cl, 0, &msg); r = config_assign(get_options_mgr(), opt, cl, 0, &msg);
tt_int_op(r, OP_EQ, 0); tt_int_op(r, OP_EQ, 0);
/* 200 MB RAM available, DirCache disabled */ /* 200 MB RAM available, DirCache disabled */
@ -438,7 +438,7 @@ get_options_test_data(const char *conf)
rv = config_get_lines(conf, &cl, 1); rv = config_get_lines(conf, &cl, 1);
tt_int_op(rv, OP_EQ, 0); tt_int_op(rv, OP_EQ, 0);
rv = config_assign(&options_format, result->opt, cl, 0, &msg); rv = config_assign(get_options_mgr(), result->opt, cl, 0, &msg);
if (msg) { if (msg) {
/* Display the parse error message by comparing it with an empty string */ /* Display the parse error message by comparing it with an empty string */
tt_str_op(msg, OP_EQ, ""); tt_str_op(msg, OP_EQ, "");
@ -449,7 +449,7 @@ get_options_test_data(const char *conf)
result->opt->TokenBucketRefillInterval = 1; result->opt->TokenBucketRefillInterval = 1;
rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1); rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1);
tt_int_op(rv, OP_EQ, 0); tt_int_op(rv, OP_EQ, 0);
rv = config_assign(&options_format, result->def_opt, cl, 0, &msg); rv = config_assign(get_options_mgr(), result->def_opt, cl, 0, &msg);
if (msg) { if (msg) {
/* Display the parse error message by comparing it with an empty string */ /* Display the parse error message by comparing it with an empty string */
tt_str_op(msg, OP_EQ, ""); tt_str_op(msg, OP_EQ, "");