diff options
author | Nick Mathewson <nickm@torproject.org> | 2019-06-13 11:59:17 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2019-06-24 15:11:57 -0400 |
commit | 458da8a80d356a0c8015f025828cd1523838ecac (patch) | |
tree | 9045b6848c8584580b717a8539feefa35e65caaa | |
parent | 246599abb4dbfdb2f8ac073fc5b2059f602e8ed7 (diff) | |
download | tor-458da8a80d356a0c8015f025828cd1523838ecac.tar.gz tor-458da8a80d356a0c8015f025828cd1523838ecac.zip |
Move unit-parsing code to src/lib/confmgt
lib/confmgt is at a higher level than lib/conf, since it needs to
call down to logging and similar modules.
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/app/config/confparse.c | 194 | ||||
-rw-r--r-- | src/include.am | 1 | ||||
-rw-r--r-- | src/lib/confmgt/.may_include | 7 | ||||
-rw-r--r-- | src/lib/confmgt/include.am | 18 | ||||
-rw-r--r-- | src/lib/confmgt/unitparse.c | 202 | ||||
-rw-r--r-- | src/lib/confmgt/unitparse.h | 34 |
8 files changed, 267 insertions, 193 deletions
diff --git a/.gitignore b/.gitignore index 0865f981b1..77610b3193 100644 --- a/.gitignore +++ b/.gitignore @@ -162,6 +162,8 @@ uptime-*.json /src/lib/libtor-buf-testing.a /src/lib/libtor-compress.a /src/lib/libtor-compress-testing.a +/src/lib/libtor-confmgt.a +/src/lib/libtor-confmgt-testing.a /src/lib/libtor-container.a /src/lib/libtor-container-testing.a /src/lib/libtor-crypt-ops.a diff --git a/Makefile.am b/Makefile.am index df30e0b59a..0083608ce9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,7 @@ TOR_UTIL_LIBS = \ src/lib/libtor-math.a \ src/lib/libtor-meminfo.a \ src/lib/libtor-osinfo.a \ + src/lib/libtor-confmgt.a \ src/lib/libtor-log.a \ src/lib/libtor-lock.a \ src/lib/libtor-fdio.a \ @@ -88,6 +89,7 @@ TOR_UTIL_TESTING_LIBS = \ src/lib/libtor-meminfo-testing.a \ src/lib/libtor-osinfo-testing.a \ src/lib/libtor-term-testing.a \ + src/lib/libtor-confmgt-testing.a \ src/lib/libtor-log-testing.a \ src/lib/libtor-lock-testing.a \ src/lib/libtor-fdio-testing.a \ diff --git a/src/app/config/confparse.c b/src/app/config/confparse.c index 3bf14b378d..296e7c2a39 100644 --- a/src/app/config/confparse.c +++ b/src/app/config/confparse.c @@ -26,12 +26,10 @@ #include "app/config/confparse.h" #include "feature/nodelist/routerset.h" +#include "lib/confmgt/unitparse.h" #include "lib/container/bitarray.h" #include "lib/encoding/confline.h" -static uint64_t config_parse_memunit(const char *s, int *ok); -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); @@ -1014,193 +1012,3 @@ config_dump(const config_format_t *fmt, const void *default_options, } return result; } - -/** Mapping from a unit name to a multiplier for converting that unit into a - * base unit. Used by config_parse_unit. */ -struct unit_table_t { - const char *unit; /**< The name of the unit */ - uint64_t multiplier; /**< How many of the base unit appear in this unit */ -}; - -/** Table to map the names of memory units to the number of bytes they - * contain. */ -static struct unit_table_t memory_units[] = { - { "", 1 }, - { "b", 1<< 0 }, - { "byte", 1<< 0 }, - { "bytes", 1<< 0 }, - { "kb", 1<<10 }, - { "kbyte", 1<<10 }, - { "kbytes", 1<<10 }, - { "kilobyte", 1<<10 }, - { "kilobytes", 1<<10 }, - { "kilobits", 1<<7 }, - { "kilobit", 1<<7 }, - { "kbits", 1<<7 }, - { "kbit", 1<<7 }, - { "m", 1<<20 }, - { "mb", 1<<20 }, - { "mbyte", 1<<20 }, - { "mbytes", 1<<20 }, - { "megabyte", 1<<20 }, - { "megabytes", 1<<20 }, - { "megabits", 1<<17 }, - { "megabit", 1<<17 }, - { "mbits", 1<<17 }, - { "mbit", 1<<17 }, - { "gb", 1<<30 }, - { "gbyte", 1<<30 }, - { "gbytes", 1<<30 }, - { "gigabyte", 1<<30 }, - { "gigabytes", 1<<30 }, - { "gigabits", 1<<27 }, - { "gigabit", 1<<27 }, - { "gbits", 1<<27 }, - { "gbit", 1<<27 }, - { "tb", UINT64_C(1)<<40 }, - { "tbyte", UINT64_C(1)<<40 }, - { "tbytes", UINT64_C(1)<<40 }, - { "terabyte", UINT64_C(1)<<40 }, - { "terabytes", UINT64_C(1)<<40 }, - { "terabits", UINT64_C(1)<<37 }, - { "terabit", UINT64_C(1)<<37 }, - { "tbits", UINT64_C(1)<<37 }, - { "tbit", UINT64_C(1)<<37 }, - { NULL, 0 }, -}; - -/** Table to map the names of time units to the number of seconds they - * contain. */ -static struct unit_table_t time_units[] = { - { "", 1 }, - { "second", 1 }, - { "seconds", 1 }, - { "minute", 60 }, - { "minutes", 60 }, - { "hour", 60*60 }, - { "hours", 60*60 }, - { "day", 24*60*60 }, - { "days", 24*60*60 }, - { "week", 7*24*60*60 }, - { "weeks", 7*24*60*60 }, - { "month", 2629728, }, /* about 30.437 days */ - { "months", 2629728, }, - { NULL, 0 }, -}; - -/** Table to map the names of time units to the number of milliseconds - * they contain. */ -static struct unit_table_t time_msec_units[] = { - { "", 1 }, - { "msec", 1 }, - { "millisecond", 1 }, - { "milliseconds", 1 }, - { "second", 1000 }, - { "seconds", 1000 }, - { "minute", 60*1000 }, - { "minutes", 60*1000 }, - { "hour", 60*60*1000 }, - { "hours", 60*60*1000 }, - { "day", 24*60*60*1000 }, - { "days", 24*60*60*1000 }, - { "week", 7*24*60*60*1000 }, - { "weeks", 7*24*60*60*1000 }, - { NULL, 0 }, -}; - -/** Parse a string <b>val</b> containing a number, zero or more - * spaces, and an optional unit string. If the unit appears in the - * table <b>u</b>, then multiply the number by the unit multiplier. - * On success, set *<b>ok</b> to 1 and return this product. - * Otherwise, set *<b>ok</b> to 0. - */ -static uint64_t -config_parse_units(const char *val, struct unit_table_t *u, int *ok) -{ - uint64_t v = 0; - double d = 0; - int use_float = 0; - char *cp; - - tor_assert(ok); - - v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp); - if (!*ok || (cp && *cp == '.')) { - d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp); - if (!*ok) - goto done; - use_float = 1; - } - - if (!cp) { - *ok = 1; - v = use_float ? ((uint64_t)d) : v; - goto done; - } - - cp = (char*) eat_whitespace(cp); - - for ( ;u->unit;++u) { - if (!strcasecmp(u->unit, cp)) { - if (use_float) - v = (uint64_t)(u->multiplier * d); - else - v *= u->multiplier; - *ok = 1; - goto done; - } - } - log_warn(LD_CONFIG, "Unknown unit '%s'.", cp); - *ok = 0; - done: - - if (*ok) - return v; - else - return 0; -} - -/** Parse a string in the format "number unit", where unit is a unit of - * information (byte, KB, M, etc). On success, set *<b>ok</b> to true - * and return the number of bytes specified. Otherwise, set - * *<b>ok</b> to false and return 0. */ -static uint64_t -config_parse_memunit(const char *s, int *ok) -{ - uint64_t u = config_parse_units(s, memory_units, ok); - return u; -} - -/** Parse a string in the format "number unit", where unit is a unit of - * time in milliseconds. On success, set *<b>ok</b> to true and return - * the number of milliseconds in the provided interval. Otherwise, set - * *<b>ok</b> to 0 and return -1. */ -static int -config_parse_msec_interval(const char *s, int *ok) -{ - uint64_t r; - r = config_parse_units(s, time_msec_units, ok); - if (r > INT_MAX) { - log_warn(LD_CONFIG, "Msec interval '%s' is too long", s); - *ok = 0; - return -1; - } - return (int)r; -} - -/** Parse a string in the format "number unit", where unit is a unit of time. - * On success, set *<b>ok</b> to true and return the number of seconds in - * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1. - */ -static int -config_parse_interval(const char *s, int *ok) -{ - uint64_t r; - r = config_parse_units(s, time_units, ok); - if (r > INT_MAX) { - log_warn(LD_CONFIG, "Interval '%s' is too long", s); - *ok = 0; - return -1; - } - return (int)r; -} diff --git a/src/include.am b/src/include.am index ab1983b3cd..065bdc31cb 100644 --- a/src/include.am +++ b/src/include.am @@ -6,6 +6,7 @@ include src/lib/cc/include.am include src/lib/ctime/include.am include src/lib/compress/include.am include src/lib/conf/include.am +include src/lib/confmgt/include.am include src/lib/container/include.am include src/lib/crypt_ops/include.am include src/lib/defs/include.am diff --git a/src/lib/confmgt/.may_include b/src/lib/confmgt/.may_include new file mode 100644 index 0000000000..640acf3770 --- /dev/null +++ b/src/lib/confmgt/.may_include @@ -0,0 +1,7 @@ +orconfig.h +lib/cc/*.h +lib/conf/*.h +lib/confmgt/*.h +lib/log/*.h +lib/malloc/*.h +lib/string/*.h diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am new file mode 100644 index 0000000000..729e6147ff --- /dev/null +++ b/src/lib/confmgt/include.am @@ -0,0 +1,18 @@ +noinst_LIBRARIES += src/lib/libtor-confmgt.a + +if UNITTESTS_ENABLED +noinst_LIBRARIES += src/lib/libtor-confmgt-testing.a +endif + +# ADD_C_FILE: INSERT SOURCES HERE. +src_lib_libtor_confmgt_a_SOURCES = \ + src/lib/confmgt/unitparse.c + +src_lib_libtor_confmgt_testing_a_SOURCES = \ + $(src_lib_libtor_confmgt_a_SOURCES) +src_lib_libtor_confmgt_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) +src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) + +# ADD_C_FILE: INSERT HEADERS HERE. +noinst_HEADERS += \ + src/lib/confmgt/unitparse.h diff --git a/src/lib/confmgt/unitparse.c b/src/lib/confmgt/unitparse.c new file mode 100644 index 0000000000..906195259d --- /dev/null +++ b/src/lib/confmgt/unitparse.c @@ -0,0 +1,202 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file unitparse.c + * @brief Functions for parsing values with units from a configuration file. + **/ + +#include "orconfig.h" +#include "lib/confmgt/unitparse.h" +#include "lib/log/log.h" +#include "lib/log/util_bug.h" +#include "lib/string/parse_int.h" +#include "lib/string/util_string.h" + +#include <string.h> + +/** Table to map the names of memory units to the number of bytes they + * contain. */ +const struct unit_table_t memory_units[] = { + { "", 1 }, + { "b", 1<< 0 }, + { "byte", 1<< 0 }, + { "bytes", 1<< 0 }, + { "kb", 1<<10 }, + { "kbyte", 1<<10 }, + { "kbytes", 1<<10 }, + { "kilobyte", 1<<10 }, + { "kilobytes", 1<<10 }, + { "kilobits", 1<<7 }, + { "kilobit", 1<<7 }, + { "kbits", 1<<7 }, + { "kbit", 1<<7 }, + { "m", 1<<20 }, + { "mb", 1<<20 }, + { "mbyte", 1<<20 }, + { "mbytes", 1<<20 }, + { "megabyte", 1<<20 }, + { "megabytes", 1<<20 }, + { "megabits", 1<<17 }, + { "megabit", 1<<17 }, + { "mbits", 1<<17 }, + { "mbit", 1<<17 }, + { "gb", 1<<30 }, + { "gbyte", 1<<30 }, + { "gbytes", 1<<30 }, + { "gigabyte", 1<<30 }, + { "gigabytes", 1<<30 }, + { "gigabits", 1<<27 }, + { "gigabit", 1<<27 }, + { "gbits", 1<<27 }, + { "gbit", 1<<27 }, + { "tb", UINT64_C(1)<<40 }, + { "tbyte", UINT64_C(1)<<40 }, + { "tbytes", UINT64_C(1)<<40 }, + { "terabyte", UINT64_C(1)<<40 }, + { "terabytes", UINT64_C(1)<<40 }, + { "terabits", UINT64_C(1)<<37 }, + { "terabit", UINT64_C(1)<<37 }, + { "tbits", UINT64_C(1)<<37 }, + { "tbit", UINT64_C(1)<<37 }, + { NULL, 0 }, +}; + +/** Table to map the names of time units to the number of seconds they + * contain. */ +const struct unit_table_t time_units[] = { + { "", 1 }, + { "second", 1 }, + { "seconds", 1 }, + { "minute", 60 }, + { "minutes", 60 }, + { "hour", 60*60 }, + { "hours", 60*60 }, + { "day", 24*60*60 }, + { "days", 24*60*60 }, + { "week", 7*24*60*60 }, + { "weeks", 7*24*60*60 }, + { "month", 2629728, }, /* about 30.437 days */ + { "months", 2629728, }, + { NULL, 0 }, +}; + +/** Table to map the names of time units to the number of milliseconds + * they contain. */ +const struct unit_table_t time_msec_units[] = { + { "", 1 }, + { "msec", 1 }, + { "millisecond", 1 }, + { "milliseconds", 1 }, + { "second", 1000 }, + { "seconds", 1000 }, + { "minute", 60*1000 }, + { "minutes", 60*1000 }, + { "hour", 60*60*1000 }, + { "hours", 60*60*1000 }, + { "day", 24*60*60*1000 }, + { "days", 24*60*60*1000 }, + { "week", 7*24*60*60*1000 }, + { "weeks", 7*24*60*60*1000 }, + { NULL, 0 }, +}; + +/** Parse a string <b>val</b> containing a number, zero or more + * spaces, and an optional unit string. If the unit appears in the + * table <b>u</b>, then multiply the number by the unit multiplier. + * On success, set *<b>ok</b> to 1 and return this product. + * Otherwise, set *<b>ok</b> to 0. + */ +uint64_t +config_parse_units(const char *val, const unit_table_t *u, int *ok) +{ + uint64_t v = 0; + double d = 0; + int use_float = 0; + char *cp; + + tor_assert(ok); + + v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp); + if (!*ok || (cp && *cp == '.')) { + d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp); + if (!*ok) + goto done; + use_float = 1; + } + + if (!cp) { + *ok = 1; + v = use_float ? ((uint64_t)d) : v; + goto done; + } + + cp = (char*) eat_whitespace(cp); + + for ( ;u->unit;++u) { + if (!strcasecmp(u->unit, cp)) { + if (use_float) + v = (uint64_t)(u->multiplier * d); + else + v *= u->multiplier; + *ok = 1; + goto done; + } + } + log_warn(LD_CONFIG, "Unknown unit '%s'.", cp); + *ok = 0; + done: + + if (*ok) + return v; + else + return 0; +} + +/** Parse a string in the format "number unit", where unit is a unit of + * information (byte, KB, M, etc). On success, set *<b>ok</b> to true + * and return the number of bytes specified. Otherwise, set + * *<b>ok</b> to false and return 0. */ +uint64_t +config_parse_memunit(const char *s, int *ok) +{ + uint64_t u = config_parse_units(s, memory_units, ok); + return u; +} + +/** Parse a string in the format "number unit", where unit is a unit of + * time in milliseconds. On success, set *<b>ok</b> to true and return + * the number of milliseconds in the provided interval. Otherwise, set + * *<b>ok</b> to 0 and return -1. */ +int +config_parse_msec_interval(const char *s, int *ok) +{ + uint64_t r; + r = config_parse_units(s, time_msec_units, ok); + if (r > INT_MAX) { + log_warn(LD_CONFIG, "Msec interval '%s' is too long", s); + *ok = 0; + return -1; + } + return (int)r; +} + +/** Parse a string in the format "number unit", where unit is a unit of time. + * On success, set *<b>ok</b> to true and return the number of seconds in + * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1. + */ +int +config_parse_interval(const char *s, int *ok) +{ + uint64_t r; + r = config_parse_units(s, time_units, ok); + if (r > INT_MAX) { + log_warn(LD_CONFIG, "Interval '%s' is too long", s); + *ok = 0; + return -1; + } + return (int)r; +} diff --git a/src/lib/confmgt/unitparse.h b/src/lib/confmgt/unitparse.h new file mode 100644 index 0000000000..216361a7d4 --- /dev/null +++ b/src/lib/confmgt/unitparse.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file unitparse.h + * @brief Header for lib/confmgt/unitparse.c + **/ + +#ifndef TOR_LIB_CONFMGT_UNITPARSE_H +#define TOR_LIB_CONFMGT_UNITPARSE_H + +#include <lib/cc/torint.h> + +/** Mapping from a unit name to a multiplier for converting that unit into a + * base unit. Used by config_parse_unit. */ +typedef struct unit_table_t { + const char *unit; /**< The name of the unit */ + uint64_t multiplier; /**< How many of the base unit appear in this unit */ +} unit_table_t; + +extern const unit_table_t memory_units[]; +extern const unit_table_t time_units[]; +extern const struct unit_table_t time_msec_units[]; + +uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok); + +uint64_t config_parse_memunit(const char *s, int *ok); +int config_parse_msec_interval(const char *s, int *ok); +int config_parse_interval(const char *s, int *ok); + +#endif /* !defined(TOR_LIB_CONFMGT_UNITPARSE_H) */ |