aboutsummaryrefslogtreecommitdiff
path: root/src/or/confparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/confparse.c')
-rw-r--r--src/or/confparse.c191
1 files changed, 22 insertions, 169 deletions
diff --git a/src/or/confparse.c b/src/or/confparse.c
index efcf4f981e..abae7e33dc 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -1,7 +1,8 @@
+
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,6 +10,16 @@
*
* \brief Back-end for parsing and generating key-value files, used to
* implement the torrc file format and the state file.
+ *
+ * This module is used by config.c to parse and encode torrc
+ * configuration files, and by statefile.c to parse and encode the
+ * $DATADIR/state file.
+ *
+ * To use this module, its callers provide an instance of
+ * config_format_t to describe the mappings from a set of configuration
+ * options to a number of fields in a C structure. With this mapping,
+ * the functions here can convert back and forth between the C structure
+ * specified, and a linked list of key-value pairs.
*/
#include "or.h"
@@ -67,120 +78,6 @@ config_expand_abbrev(const config_format_t *fmt, const char *option,
return option;
}
-/** Helper: allocate a new configuration option mapping 'key' to 'val',
- * append it to *<b>lst</b>. */
-void
-config_line_append(config_line_t **lst,
- const char *key,
- const char *val)
-{
- config_line_t *newline;
-
- newline = tor_malloc_zero(sizeof(config_line_t));
- newline->key = tor_strdup(key);
- newline->value = tor_strdup(val);
- newline->next = NULL;
- while (*lst)
- lst = &((*lst)->next);
-
- (*lst) = newline;
-}
-
-/** Return the line in <b>lines</b> whose key is exactly <b>key</b>, or NULL
- * if no such key exists. For handling commandline-only options only; other
- * options should be looked up in the appropriate data structure. */
-const config_line_t *
-config_line_find(const config_line_t *lines,
- const char *key)
-{
- const config_line_t *cl;
- for (cl = lines; cl; cl = cl->next) {
- if (!strcmp(cl->key, key))
- return cl;
- }
- return NULL;
-}
-
-/** Helper: parse the config string and strdup into key/value
- * strings. Set *result to the list, or NULL if parsing the string
- * failed. Return 0 on success, -1 on failure. Warn and ignore any
- * misformatted lines.
- *
- * If <b>extended</b> is set, then treat keys beginning with / and with + as
- * indicating "clear" and "append" respectively. */
-int
-config_get_lines(const char *string, config_line_t **result, int extended)
-{
- config_line_t *list = NULL, **next;
- char *k, *v;
- const char *parse_err;
-
- next = &list;
- do {
- k = v = NULL;
- string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err);
- if (!string) {
- log_warn(LD_CONFIG, "Error while parsing configuration: %s",
- parse_err?parse_err:"<unknown>");
- config_free_lines(list);
- tor_free(k);
- tor_free(v);
- return -1;
- }
- if (k && v) {
- unsigned command = CONFIG_LINE_NORMAL;
- if (extended) {
- if (k[0] == '+') {
- char *k_new = tor_strdup(k+1);
- tor_free(k);
- k = k_new;
- command = CONFIG_LINE_APPEND;
- } else if (k[0] == '/') {
- char *k_new = tor_strdup(k+1);
- tor_free(k);
- k = k_new;
- tor_free(v);
- v = tor_strdup("");
- command = CONFIG_LINE_CLEAR;
- }
- }
- /* This list can get long, so we keep a pointer to the end of it
- * rather than using config_line_append over and over and getting
- * n^2 performance. */
- *next = tor_malloc_zero(sizeof(config_line_t));
- (*next)->key = k;
- (*next)->value = v;
- (*next)->next = NULL;
- (*next)->command = command;
- next = &((*next)->next);
- } else {
- tor_free(k);
- tor_free(v);
- }
- } while (*string);
-
- *result = list;
- return 0;
-}
-
-/**
- * Free all the configuration lines on the linked list <b>front</b>.
- */
-void
-config_free_lines(config_line_t *front)
-{
- config_line_t *tmp;
-
- while (front) {
- tmp = front;
- front = tmp->next;
-
- tor_free(tmp->key);
- tor_free(tmp->value);
- tor_free(tmp);
- }
-}
-
/** If <b>key</b> is a deprecated configuration option, return the message
* 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. */
@@ -620,23 +517,6 @@ config_value_needs_escape(const char *value)
return 0;
}
-/** Return a newly allocated deep copy of the lines in <b>inp</b>. */
-config_line_t *
-config_lines_dup(const config_line_t *inp)
-{
- config_line_t *result = NULL;
- config_line_t **next_out = &result;
- while (inp) {
- *next_out = tor_malloc_zero(sizeof(config_line_t));
- (*next_out)->key = tor_strdup(inp->key);
- (*next_out)->value = tor_strdup(inp->value);
- inp = inp->next;
- next_out = &((*next_out)->next);
- }
- (*next_out) = NULL;
- return result;
-}
-
/** Return newly allocated line or lines corresponding to <b>key</b> in the
* configuration <b>options</b>. If <b>escape_val</b> is true and a
* value needs to be quoted before it's put in a config file, quote and
@@ -753,11 +633,11 @@ config_get_assigned_option(const config_format_t *fmt, const void *options,
tor_free(result);
return NULL;
case CONFIG_TYPE_LINELIST_S:
- log_warn(LD_CONFIG,
- "Can't return context-sensitive '%s' on its own", key);
tor_free(result->key);
tor_free(result);
- return NULL;
+ result = config_lines_dup_and_filter(*(const config_line_t **)value,
+ key);
+ break;
case CONFIG_TYPE_LINELIST:
case CONFIG_TYPE_LINELIST_V:
tor_free(result->key);
@@ -1002,36 +882,6 @@ config_free(const config_format_t *fmt, void *options)
tor_free(options);
}
-/** Return true iff a and b contain identical keys and values in identical
- * order. */
-int
-config_lines_eq(config_line_t *a, config_line_t *b)
-{
- while (a && b) {
- if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
- return 0;
- a = a->next;
- b = b->next;
- }
- if (a || b)
- return 0;
- return 1;
-}
-
-/** Return the number of lines in <b>a</b> whose key is <b>key</b>. */
-int
-config_count_key(const config_line_t *a, const char *key)
-{
- int n = 0;
- while (a) {
- if (!strcasecmp(a->key, key)) {
- ++n;
- }
- a = a->next;
- }
- return n;
-}
-
/** Return true iff the option <b>name</b> has the same value in <b>o1</b>
* and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
*/
@@ -1148,6 +998,11 @@ config_dump(const config_format_t *fmt, const void *default_options,
config_get_assigned_option(fmt, options, fmt->vars[i].name, 1);
for (; line; line = line->next) {
+ if (!strcmpstart(line->key, "__")) {
+ /* This check detects "hidden" variables inside LINELIST_V structures.
+ */
+ continue;
+ }
smartlist_add_asprintf(elements, "%s%s %s\n",
comment_option ? "# " : "",
line->key, line->value);
@@ -1213,6 +1068,8 @@ static struct unit_table_t memory_units[] = {
{ "gbits", 1<<27 },
{ "gbit", 1<<27 },
{ "tb", U64_LITERAL(1)<<40 },
+ { "tbyte", U64_LITERAL(1)<<40 },
+ { "tbytes", U64_LITERAL(1)<<40 },
{ "terabyte", U64_LITERAL(1)<<40 },
{ "terabytes", U64_LITERAL(1)<<40 },
{ "terabits", U64_LITERAL(1)<<37 },
@@ -1333,8 +1190,6 @@ config_parse_msec_interval(const char *s, int *ok)
{
uint64_t r;
r = config_parse_units(s, time_msec_units, ok);
- if (!ok)
- return -1;
if (r > INT_MAX) {
log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
*ok = 0;
@@ -1352,8 +1207,6 @@ config_parse_interval(const char *s, int *ok)
{
uint64_t r;
r = config_parse_units(s, time_units, ok);
- if (!ok)
- return -1;
if (r > INT_MAX) {
log_warn(LD_CONFIG, "Interval '%s' is too long", s);
*ok = 0;