Move config_line_t functions from confparse.c into common.

I'm doing this to storagedir to used config_line_t.
This commit is contained in:
Nick Mathewson
2017-03-31 10:24:38 -04:00
parent 321c1c453e
commit c2947dbb86
6 changed files with 233 additions and 206 deletions
+185
View File
@@ -0,0 +1,185 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "compat.h"
#include "confline.h"
#include "torlog.h"
#include "util.h"
/** 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);
}
}
/** Return a newly allocated deep copy of the lines in <b>inp</b>. */
config_line_t *
config_lines_dup(const config_line_t *inp)
{
return config_lines_dup_and_filter(inp, NULL);
}
/** Return a newly allocated deep copy of the lines in <b>inp</b>,
* but only the ones that match <b>key</b>. */
config_line_t *
config_lines_dup_and_filter(const config_line_t *inp,
const char *key)
{
config_line_t *result = NULL;
config_line_t **next_out = &result;
while (inp) {
if (key && strcasecmpstart(inp->key, key)) {
inp = inp->next;
continue;
}
*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 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;
}
+45
View File
@@ -0,0 +1,45 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONFLINE_H
#define TOR_CONFLINE_H
/** Ordinary configuration line. */
#define CONFIG_LINE_NORMAL 0
/** Appends to previous configuration for the same option, even if we
* would ordinary replace it. */
#define CONFIG_LINE_APPEND 1
/* Removes all previous configuration for an option. */
#define CONFIG_LINE_CLEAR 2
/** A linked list of lines in a config file, or elsewhere */
typedef struct config_line_t {
char *key;
char *value;
struct config_line_t *next;
/** What special treatment (if any) does this line require? */
unsigned int command:2;
/** If true, subsequent assignments to this linelist should replace
* it, not extend it. Set only on the first item in a linelist in an
* or_options_t. */
unsigned int fragile:1;
} config_line_t;
void config_line_append(config_line_t **lst,
const char *key, const char *val);
config_line_t *config_lines_dup(const config_line_t *inp);
config_line_t *config_lines_dup_and_filter(const config_line_t *inp,
const char *key);
const config_line_t *config_line_find(const config_line_t *lines,
const char *key);
int config_lines_eq(config_line_t *a, config_line_t *b);
int config_count_key(const config_line_t *a, const char *key);
int config_get_lines(const char *string, config_line_t **result, int extended);
void config_free_lines(config_line_t *front);
#endif
+2
View File
@@ -84,6 +84,7 @@ LIBOR_A_SRC = \
src/common/compat.c \
src/common/compat_threads.c \
src/common/compat_time.c \
src/common/confline.c \
src/common/container.c \
src/common/log.c \
src/common/memarea.c \
@@ -144,6 +145,7 @@ COMMONHEADERS = \
src/common/compat_openssl.h \
src/common/compat_threads.h \
src/common/compat_time.h \
src/common/confline.h \
src/common/container.h \
src/common/crypto.h \
src/common/crypto_curve25519.h \
-176
View File
@@ -31,8 +31,6 @@ static int config_parse_msec_interval(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
static void config_reset(const config_format_t *fmt, void *options,
const config_var_t *var, int use_defaults);
static config_line_t *config_lines_dup_and_filter(const config_line_t *inp,
const char *key);
/** Allocate an empty configuration object of a given format type. */
void *
@@ -80,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. */
@@ -633,36 +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)
{
return config_lines_dup_and_filter(inp, NULL);
}
/** Return a newly allocated deep copy of the lines in <b>inp</b>,
* but only the ones that match <b>key</b>. */
static config_line_t *
config_lines_dup_and_filter(const config_line_t *inp,
const char *key)
{
config_line_t *result = NULL;
config_line_t **next_out = &result;
while (inp) {
if (key && strcasecmpstart(inp->key, key)) {
inp = inp->next;
continue;
}
*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
@@ -1028,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.
*/
-9
View File
@@ -103,14 +103,7 @@ typedef struct config_format_t {
#define CAL_WARN_DEPRECATIONS (1u<<2)
void *config_new(const config_format_t *fmt);
void config_line_append(config_line_t **lst,
const char *key, const char *val);
config_line_t *config_lines_dup(const config_line_t *inp);
const config_line_t *config_line_find(const config_line_t *lines,
const char *key);
void config_free(const config_format_t *fmt, void *options);
int config_lines_eq(config_line_t *a, config_line_t *b);
int config_count_key(const config_line_t *a, const char *key);
config_line_t *config_get_assigned_option(const config_format_t *fmt,
const void *options, const char *key,
int escape_val);
@@ -132,8 +125,6 @@ const char *config_find_deprecation(const config_format_t *fmt,
const config_var_t *config_find_option(const config_format_t *fmt,
const char *key);
int config_get_lines(const char *string, config_line_t **result, int extended);
void config_free_lines(config_line_t *front);
const char *config_expand_abbrev(const config_format_t *fmt,
const char *option,
int command_line, int warn_obsolete);
+1 -21
View File
@@ -75,6 +75,7 @@
#include "address.h"
#include "compat_libevent.h"
#include "ht.h"
#include "confline.h"
#include "replaycache.h"
#include "crypto_curve25519.h"
#include "crypto_ed25519.h"
@@ -3529,27 +3530,6 @@ typedef struct port_cfg_t {
char unix_addr[FLEXIBLE_ARRAY_MEMBER];
} port_cfg_t;
/** Ordinary configuration line. */
#define CONFIG_LINE_NORMAL 0
/** Appends to previous configuration for the same option, even if we
* would ordinary replace it. */
#define CONFIG_LINE_APPEND 1
/* Removes all previous configuration for an option. */
#define CONFIG_LINE_CLEAR 2
/** A linked list of lines in a config file. */
typedef struct config_line_t {
char *key;
char *value;
struct config_line_t *next;
/** What special treatment (if any) does this line require? */
unsigned int command:2;
/** If true, subsequent assignments to this linelist should replace
* it, not extend it. Set only on the first item in a linelist in an
* or_options_t. */
unsigned int fragile:1;
} config_line_t;
typedef struct routerset_t routerset_t;
/** A magic value for the (Socks|OR|...)Port options below, telling Tor