Tor 0.4.9.0-alpha-dev
type_defs.c
Go to the documentation of this file.
1/* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5/* See LICENSE for licensing information */
6
7/**
8 * @file type_defs.c
9 * @brief Definitions for various low-level configuration types.
10 *
11 * This module creates a number of var_type_def_t objects, to be used by
12 * typedvar.c in manipulating variables.
13 *
14 * The types here are common types that can be implemented with Tor's
15 * low-level functionality. To define new types, see var_type_def_st.h.
16 **/
17
18#include "orconfig.h"
19#include "lib/conf/conftypes.h"
20#include "lib/conf/confdecl.h"
24
29#include "lib/log/escape.h"
30#include "lib/log/log.h"
31#include "lib/log/util_bug.h"
32#include "lib/malloc/malloc.h"
34#include "lib/string/printf.h"
35
37
38#include <stddef.h>
39#include <string.h>
40#include <errno.h>
41
42//////
43// CONFIG_TYPE_STRING
44// CONFIG_TYPE_FILENAME
45//
46// These two types are the same for now, but they have different names.
47//
48// Warning: For this type, the default value (NULL) and "" are considered
49// different values. That is generally risky, and best avoided for other
50// types in the future.
51//////
52
53static int
54string_parse(void *target, const char *value, char **errmsg,
55 const void *params)
56{
57 (void)params;
58 (void)errmsg;
59 char **p = (char**)target;
60 *p = tor_strdup(value);
61 return 0;
62}
63
64static char *
65string_encode(const void *value, const void *params)
66{
67 (void)params;
68 const char **p = (const char**)value;
69 return *p ? tor_strdup(*p) : NULL;
70}
71
72static void
73string_clear(void *value, const void *params)
74{
75 (void)params;
76 char **p = (char**)value;
77 tor_free(*p); // sets *p to NULL.
78}
79
80static const var_type_fns_t string_fns = {
81 .parse = string_parse,
82 .encode = string_encode,
83 .clear = string_clear,
84};
85
86/////
87// CONFIG_TYPE_INT
88// CONFIG_TYPE_POSINT
89//
90// These types are implemented as int, possibly with a restricted range.
91/////
92
93/**
94 * Parameters for parsing an integer type.
95 **/
96typedef struct int_type_params_t {
97 int minval; /**< Lowest allowed value */
98 int maxval; /**< Highest allowed value */
100
101static const int_parse_params_t INT_PARSE_UNRESTRICTED = {
102 .minval = INT_MIN,
103 .maxval = INT_MAX,
104};
105
106static const int_parse_params_t INT_PARSE_POSINT = {
107 .minval = 0,
108 .maxval = INT_MAX,
109};
110
111static int
112int_parse(void *target, const char *value, char **errmsg, const void *params)
113{
114 const int_parse_params_t *pp;
115 if (params) {
116 pp = params;
117 } else {
118 pp = &INT_PARSE_UNRESTRICTED;
119 }
120 int *p = target;
121 int ok=0;
122 *p = (int)tor_parse_long(value, 10, pp->minval, pp->maxval, &ok, NULL);
123 if (!ok) {
124 tor_asprintf(errmsg, "Integer %s is malformed or out of bounds. "
125 "Allowed values are between %d and %d.",
126 value, pp->minval, pp->maxval);
127 return -1;
128 }
129 return 0;
130}
131
132static char *
133int_encode(const void *value, const void *params)
134{
135 (void)params;
136 int v = *(int*)value;
137 char *result;
138 tor_asprintf(&result, "%d", v);
139 return result;
140}
141
142static void
143int_clear(void *value, const void *params)
144{
145 (void)params;
146 *(int*)value = 0;
147}
148
149static bool
150int_ok(const void *value, const void *params)
151{
152 const int_parse_params_t *pp = params;
153 if (pp) {
154 int v = *(int*)value;
155 return pp->minval <= v && v <= pp->maxval;
156 } else {
157 return true;
158 }
159}
160
161static const var_type_fns_t int_fns = {
162 .parse = int_parse,
163 .encode = int_encode,
164 .clear = int_clear,
165 .ok = int_ok,
166};
167
168/////
169// CONFIG_TYPE_UINT64
170//
171// This type is an unrestricted u64.
172/////
173
174static int
175uint64_parse(void *target, const char *value, char **errmsg,
176 const void *params)
177{
178 (void)params;
179 (void)errmsg;
180 uint64_t *p = target;
181 int ok=0;
182 *p = tor_parse_uint64(value, 10, 0, UINT64_MAX, &ok, NULL);
183 if (!ok) {
184 tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
185 value);
186 return -1;
187 }
188 return 0;
189}
190
191static char *
192uint64_encode(const void *value, const void *params)
193{
194 (void)params;
195 uint64_t v = *(uint64_t*)value;
196 char *result;
197 tor_asprintf(&result, "%"PRIu64, v);
198 return result;
199}
200
201static void
202uint64_clear(void *value, const void *params)
203{
204 (void)params;
205 *(uint64_t*)value = 0;
206}
207
208static const var_type_fns_t uint64_fns = {
209 .parse = uint64_parse,
210 .encode = uint64_encode,
211 .clear = uint64_clear,
212};
213
214/////
215// CONFIG_TYPE_INTERVAL
216// CONFIG_TYPE_MSEC_INTERVAL
217// CONFIG_TYPE_MEMUNIT
218//
219// These types are implemented using the config_parse_units() function.
220// The intervals are stored as ints, whereas memory units are stored as
221// uint64_ts.
222/////
223
224static int
225units_parse_u64(void *target, const char *value, char **errmsg,
226 const void *params)
227{
228 const unit_table_t *table = params;
229 tor_assert(table);
230 uint64_t *v = (uint64_t*)target;
231 int ok=1;
232 char *msg = NULL;
233 *v = config_parse_units(value, table, &ok, &msg);
234 if (!ok) {
235 tor_asprintf(errmsg, "Provided value is malformed or out of bounds: %s",
236 msg);
237 tor_free(msg);
238 return -1;
239 }
240 if (BUG(msg)) {
241 tor_free(msg);
242 }
243 return 0;
244}
245
246static int
247units_parse_int(void *target, const char *value, char **errmsg,
248 const void *params)
249{
250 const unit_table_t *table = params;
251 tor_assert(table);
252 int *v = (int*)target;
253 int ok=1;
254 char *msg = NULL;
255 uint64_t u64 = config_parse_units(value, table, &ok, &msg);
256 if (!ok) {
257 tor_asprintf(errmsg, "Provided value is malformed or out of bounds: %s",
258 msg);
259 tor_free(msg);
260 return -1;
261 }
262 if (BUG(msg)) {
263 tor_free(msg);
264 }
265 if (u64 > INT_MAX) {
266 tor_asprintf(errmsg, "Provided value %s is too large", value);
267 return -1;
268 }
269 *v = (int) u64;
270 return 0;
271}
272
273static bool
274units_ok_int(const void *value, const void *params)
275{
276 (void)params;
277 int v = *(int*)value;
278 return v >= 0;
279}
280
281static const var_type_fns_t memunit_fns = {
282 .parse = units_parse_u64,
283 .encode = uint64_encode, // doesn't use params
284 .clear = uint64_clear, // doesn't use params
285};
286
287static const var_type_fns_t interval_fns = {
288 .parse = units_parse_int,
289 .encode = int_encode, // doesn't use params
290 .clear = int_clear, // doesn't use params,
291 .ok = units_ok_int // can't use int_ok, since that expects int params.
292};
293
294/////
295// CONFIG_TYPE_DOUBLE
296//
297// This is a nice simple double.
298/////
299
300static int
301double_parse(void *target, const char *value, char **errmsg,
302 const void *params)
303{
304 (void)params;
305 (void)errmsg;
306 double *v = (double*)target;
307 char *endptr=NULL;
308 errno = 0;
309 *v = strtod(value, &endptr);
310 if (endptr == value || *endptr != '\0') {
311 // Either there are no converted characters, or there were some characters
312 // that didn't get converted.
313 tor_asprintf(errmsg, "Could not convert %s to a number.", escaped(value));
314 return -1;
315 }
316 if (errno == ERANGE) {
317 // strtod will set errno to ERANGE on underflow or overflow.
318 bool underflow = -.00001 < *v && *v < .00001;
319 tor_asprintf(errmsg,
320 "%s is too %s to express as a floating-point number.",
321 escaped(value), underflow ? "small" : "large");
322 return -1;
323 }
324 return 0;
325}
326
327static char *
328double_encode(const void *value, const void *params)
329{
330 (void)params;
331 double v = *(double*)value;
332 char *result;
333 tor_asprintf(&result, "%f", v);
334 return result;
335}
336
337static void
338double_clear(void *value, const void *params)
339{
340 (void)params;
341 double *v = (double *)value;
342 *v = 0.0;
343}
344
345static const var_type_fns_t double_fns = {
346 .parse = double_parse,
347 .encode = double_encode,
348 .clear = double_clear,
349};
350
351/////
352// CONFIG_TYPE_BOOL
353// CONFIG_TYPE_AUTOBOOL
354//
355// These types are implemented as a case-insensitive string-to-integer
356// mapping.
357/////
358
359typedef struct enumeration_table_t {
360 const char *name;
361 int value;
363
364typedef struct enumeration_params_t {
365 const char *allowed_val_string;
366 const enumeration_table_t *table;
368
369static int
370enum_parse(void *target, const char *value, char **errmsg,
371 const void *params_)
372{
373 const enumeration_params_t *params = params_;
374 const enumeration_table_t *table = params->table;
375 int *p = (int *)target;
376 for (; table->name; ++table) {
377 if (!strcasecmp(value, table->name)) {
378 *p = table->value;
379 return 0;
380 }
381 }
382 tor_asprintf(errmsg, "Unrecognized value %s. %s",
383 value, params->allowed_val_string);
384 return -1;
385}
386
387static char *
388enum_encode(const void *value, const void *params_)
389{
390 int v = *(const int*)value;
391 const enumeration_params_t *params = params_;
392 const enumeration_table_t *table = params->table;
393 for (; table->name; ++table) {
394 if (v == table->value)
395 return tor_strdup(table->name);
396 }
397 return NULL; // error.
398}
399
400static void
401enum_clear(void *value, const void *params_)
402{
403 int *p = (int*)value;
404 const enumeration_params_t *params = params_;
405 const enumeration_table_t *table = params->table;
406 tor_assert(table->name);
407 *p = table->value;
408}
409
410static bool
411enum_ok(const void *value, const void *params_)
412{
413 int v = *(const int*)value;
414 const enumeration_params_t *params = params_;
415 const enumeration_table_t *table = params->table;
416 for (; table->name; ++table) {
417 if (v == table->value)
418 return true;
419 }
420 return false;
421}
422
423static const enumeration_table_t enum_table_bool[] = {
424 { "0", 0 },
425 { "1", 1 },
426 { NULL, 0 },
427};
428
429static const enumeration_params_t enum_params_bool = {
430 "Allowed values are 0 and 1.",
431 enum_table_bool
432};
433
434static const enumeration_table_t enum_table_autobool[] = {
435 { "0", 0 },
436 { "1", 1 },
437 { "auto", -1 },
438 { NULL, 0 },
439};
440
441static const enumeration_params_t enum_params_autobool = {
442 "Allowed values are 0, 1, and auto.",
443 enum_table_autobool
444};
445
446static const var_type_fns_t enum_fns = {
447 .parse = enum_parse,
448 .encode = enum_encode,
449 .clear = enum_clear,
450 .ok = enum_ok,
451};
452
453/////
454// CONFIG_TYPE_ISOTIME
455//
456// This is a time_t, encoded in ISO8601 format.
457/////
458
459static int
460time_parse(void *target, const char *value, char **errmsg,
461 const void *params)
462{
463 (void) params;
464 time_t *p = target;
465 if (parse_iso_time(value, p) < 0) {
466 tor_asprintf(errmsg, "Invalid time %s", escaped(value));
467 return -1;
468 }
469 return 0;
470}
471
472static char *
473time_encode(const void *value, const void *params)
474{
475 (void)params;
476 time_t v = *(const time_t *)value;
477 char *result = tor_malloc(ISO_TIME_LEN+1);
478 format_iso_time(result, v);
479 return result;
480}
481
482static void
483time_clear(void *value, const void *params)
484{
485 (void)params;
486 time_t *t = value;
487 *t = 0;
488}
489
490static const var_type_fns_t time_fns = {
491 .parse = time_parse,
492 .encode = time_encode,
493 .clear = time_clear,
494};
495
496/////
497// CONFIG_TYPE_CSV
498//
499// This type is a comma-separated list of strings, stored in a smartlist_t.
500// An empty list may be encoded either as an empty smartlist, or as NULL.
501/////
502
503static int
504csv_parse(void *target, const char *value, char **errmsg,
505 const void *params)
506{
507 (void)params;
508 (void)errmsg;
509 smartlist_t **sl = (smartlist_t**)target;
510 *sl = smartlist_new();
511 smartlist_split_string(*sl, value, ",",
512 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
513 return 0;
514}
515
516static char *
517csv_encode(const void *value, const void *params)
518{
519 (void)params;
520 const smartlist_t *sl = *(const smartlist_t **)value;
521 if (! sl)
522 return tor_strdup("");
523
524 return smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
525}
526
527static void
528csv_clear(void *value, const void *params)
529{
530 (void)params;
531 smartlist_t **sl = (smartlist_t**)value;
532 if (!*sl)
533 return;
534 SMARTLIST_FOREACH(*sl, char *, cp, tor_free(cp));
535 smartlist_free(*sl); // clears pointer.
536}
537
538static const var_type_fns_t csv_fns = {
539 .parse = csv_parse,
540 .encode = csv_encode,
541 .clear = csv_clear,
542};
543
544/////
545// CONFIG_TYPE_CSV_INTERVAL
546//
547// This type used to be a list of time intervals, used to determine a download
548// schedule. Now, only the first interval counts: everything after the first
549// comma is discarded.
550/////
551
552static int
553legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
554 const void *params)
555{
556 (void)params;
557 /* We used to have entire smartlists here. But now that all of our
558 * download schedules use exponential backoff, only the first part
559 * matters. */
560 const char *comma = strchr(value, ',');
561 const char *val = value;
562 char *tmp = NULL;
563 if (comma) {
564 tmp = tor_strndup(val, comma - val);
565 val = tmp;
566 }
567
568 int rv = units_parse_int(target, val, errmsg, &time_units);
569 tor_free(tmp);
570 return rv;
571}
572
573static const var_type_fns_t legacy_csv_interval_fns = {
574 .parse = legacy_csv_interval_parse,
575 .encode = int_encode,
576 .clear = int_clear,
577};
578
579/////
580// CONFIG_TYPE_LINELIST
581// CONFIG_TYPE_LINELIST_S
582// CONFIG_TYPE_LINELIST_V
583//
584// A linelist is a raw config_line_t list. Order is preserved.
585//
586// The LINELIST type is used for homogeneous lists, where all the lines
587// have the same key.
588//
589// The LINELIST_S and LINELIST_V types are used for the case where multiple
590// lines of different keys are kept in a single list, to preserve their
591// relative order. The unified list is stored as a "virtual" variable whose
592// type is LINELIST_V; the individual sublists are treated as variables of
593// type LINELIST_S.
594//
595// A linelist may be fragile or non-fragile. Assigning a line to a fragile
596// linelist replaces the list with the line. If the line has the "APPEND"
597// command set on it, or if the list is non-fragile, the line is appended.
598// Either way, the new list is non-fragile.
599/////
600
601static int
602linelist_kv_parse(void *target, const struct config_line_t *line,
603 char **errmsg, const void *params)
604{
605 (void)params;
606 (void)errmsg;
607 config_line_t **lines = target;
608
609 if (*lines && (*lines)->fragile) {
610 if (line->command == CONFIG_LINE_APPEND) {
611 (*lines)->fragile = 0;
612 } else {
613 config_free_lines(*lines); // sets it to NULL
614 }
615 }
616
617 config_line_append(lines, line->key, line->value);
618 return 0;
619}
620
621static int
622linelist_kv_virt_noparse(void *target, const struct config_line_t *line,
623 char **errmsg, const void *params)
624{
625 (void)target;
626 (void)line;
627 (void)params;
628 *errmsg = tor_strdup("Cannot assign directly to virtual option.");
629 return -1;
630}
631
632static struct config_line_t *
633linelist_kv_encode(const char *key, const void *value,
634 const void *params)
635{
636 (void)key;
637 (void)params;
638 config_line_t *lines = *(config_line_t **)value;
639 return config_lines_dup(lines);
640}
641
642static struct config_line_t *
643linelist_s_kv_encode(const char *key, const void *value,
644 const void *params)
645{
646 (void)params;
647 config_line_t *lines = *(config_line_t **)value;
648 return config_lines_dup_and_filter(lines, key);
649}
650
651static void
652linelist_clear(void *target, const void *params)
653{
654 (void)params;
655 config_line_t **lines = target;
656 config_free_lines(*lines); // sets it to NULL
657}
658
659static bool
660linelist_eq(const void *a, const void *b, const void *params)
661{
662 (void)params;
663 const config_line_t *lines_a = *(const config_line_t **)a;
664 const config_line_t *lines_b = *(const config_line_t **)b;
665 return config_lines_eq(lines_a, lines_b);
666}
667
668static int
669linelist_copy(void *target, const void *value, const void *params)
670{
671 (void)params;
672 config_line_t **ptr = (config_line_t **)target;
673 const config_line_t *val = *(const config_line_t **)value;
674 config_free_lines(*ptr);
675 *ptr = config_lines_dup(val);
676 return 0;
677}
678
679static void
680linelist_mark_fragile(void *target, const void *params)
681{
682 (void)params;
683 config_line_t **ptr = (config_line_t **)target;
684 if (*ptr)
685 (*ptr)->fragile = 1;
686}
687
688static const var_type_fns_t linelist_fns = {
689 .kv_parse = linelist_kv_parse,
690 .kv_encode = linelist_kv_encode,
691 .clear = linelist_clear,
692 .eq = linelist_eq,
693 .copy = linelist_copy,
694 .mark_fragile = linelist_mark_fragile,
695};
696
697static const var_type_fns_t linelist_v_fns = {
698 .kv_parse = linelist_kv_virt_noparse,
699 .kv_encode = linelist_kv_encode,
700 .clear = linelist_clear,
701 .eq = linelist_eq,
702 .copy = linelist_copy,
703 .mark_fragile = linelist_mark_fragile,
704};
705
706static const var_type_fns_t linelist_s_fns = {
707 .kv_parse = linelist_kv_parse,
708 .kv_encode = linelist_s_kv_encode,
709 .clear = linelist_clear,
710 .eq = linelist_eq,
711 .copy = linelist_copy,
712};
713
714/////
715// CONFIG_TYPE_ROUTERSET
716//
717// XXXX to this module.
718/////
719
720/////
721// CONFIG_TYPE_IGNORE
722//
723// Used to indicate an option that cannot be stored or encoded.
724/////
725
726static int
727ignore_parse(void *target, const char *value, char **errmsg,
728 const void *params)
729{
730 (void)target;
731 (void)value;
732 (void)errmsg;
733 (void)params;
734 return 0;
735}
736
737static char *
738ignore_encode(const void *value, const void *params)
739{
740 (void)value;
741 (void)params;
742 return NULL;
743}
744
745static const var_type_fns_t ignore_fns = {
746 .parse = ignore_parse,
747 .encode = ignore_encode,
748};
749
750const var_type_def_t STRING_type_defn = {
751 .name="String", .fns=&string_fns };
752const var_type_def_t FILENAME_type_defn = {
753 .name="Filename", .fns=&string_fns };
754const var_type_def_t INT_type_defn = {
755 .name="SignedInteger", .fns=&int_fns,
756 .params=&INT_PARSE_UNRESTRICTED };
757const var_type_def_t POSINT_type_defn = {
758 .name="Integer", .fns=&int_fns,
759 .params=&INT_PARSE_POSINT };
760const var_type_def_t UINT64_type_defn = {
761 .name="Integer", .fns=&uint64_fns, };
762const var_type_def_t MEMUNIT_type_defn = {
763 .name="DataSize", .fns=&memunit_fns,
764 .params=&memory_units };
765const var_type_def_t INTERVAL_type_defn = {
766 .name="TimeInterval", .fns=&interval_fns,
767 .params=&time_units };
768const var_type_def_t MSEC_INTERVAL_type_defn = {
769 .name="TimeMsecInterval",
770 .fns=&interval_fns,
771 .params=&time_msec_units };
772const var_type_def_t DOUBLE_type_defn = {
773 .name="Float", .fns=&double_fns, };
774const var_type_def_t BOOL_type_defn = {
775 .name="Boolean", .fns=&enum_fns,
776 .params=&enum_params_bool };
777const var_type_def_t AUTOBOOL_type_defn = {
778 .name="Boolean+Auto", .fns=&enum_fns,
779 .params=&enum_params_autobool };
780const var_type_def_t ISOTIME_type_defn = {
781 .name="Time", .fns=&time_fns, };
782const var_type_def_t CSV_type_defn = {
783 .name="CommaList", .fns=&csv_fns, };
784const var_type_def_t CSV_INTERVAL_type_defn = {
785 .name="TimeInterval",
786 .fns=&legacy_csv_interval_fns, };
787const var_type_def_t LINELIST_type_defn = {
788 .name="LineList", .fns=&linelist_fns,
789 .flags=CFLG_NOREPLACE };
790/*
791 * A "linelist_s" is a derived view of a linelist_v: inspecting
792 * it gets part of a linelist_v, and setting it adds to the linelist_v.
793 */
794const var_type_def_t LINELIST_S_type_defn = {
795 .name="Dependent", .fns=&linelist_s_fns,
796 .flags=CFLG_NOREPLACE|
797 /* The operations we disable here are
798 * handled by the linelist_v. */
800const var_type_def_t LINELIST_V_type_defn = {
801 .name="Virtual", .fns=&linelist_v_fns,
802 .flags=CFLG_NOREPLACE|CFLG_NOSET };
803const var_type_def_t IGNORE_type_defn = {
804 .name="Ignored", .fns=&ignore_fns,
806};
807const var_type_def_t OBSOLETE_type_defn = {
808 .name="Obsolete", .fns=&ignore_fns,
809 .flags=CFLG_GROUP_OBSOLETE,
810};
811
812/**
813 * Table mapping conf_type_t values to var_type_def_t objects.
814 **/
816 [CONFIG_TYPE_STRING] = &STRING_type_defn,
817 [CONFIG_TYPE_FILENAME] = &FILENAME_type_defn,
818 [CONFIG_TYPE_INT] = &INT_type_defn,
819 [CONFIG_TYPE_POSINT] = &POSINT_type_defn,
820 [CONFIG_TYPE_UINT64] = &UINT64_type_defn,
821 [CONFIG_TYPE_MEMUNIT] = &MEMUNIT_type_defn,
822 [CONFIG_TYPE_INTERVAL] = &INTERVAL_type_defn,
823 [CONFIG_TYPE_MSEC_INTERVAL] = &MSEC_INTERVAL_type_defn,
824 [CONFIG_TYPE_DOUBLE] = &DOUBLE_type_defn,
825 [CONFIG_TYPE_BOOL] = &BOOL_type_defn,
826 [CONFIG_TYPE_AUTOBOOL] = &AUTOBOOL_type_defn,
827 [CONFIG_TYPE_ISOTIME] = &ISOTIME_type_defn,
828 [CONFIG_TYPE_CSV] = &CSV_type_defn,
829 [CONFIG_TYPE_CSV_INTERVAL] = &CSV_INTERVAL_type_defn,
830 [CONFIG_TYPE_LINELIST] = &LINELIST_type_defn,
831 [CONFIG_TYPE_LINELIST_S] = &LINELIST_S_type_defn,
832 [CONFIG_TYPE_LINELIST_V] = &LINELIST_V_type_defn,
833 [CONFIG_TYPE_IGNORE] = &IGNORE_type_defn,
834 [CONFIG_TYPE_OBSOLETE] = &OBSOLETE_type_defn,
835};
836
837/**
838 * Return a pointer to the var_type_def_t object for the given
839 * config_type_t value, or NULL if no such type definition exists.
840 **/
841const var_type_def_t *
843{
844 int t = type;
845 tor_assert(t >= 0);
847 return NULL;
848 return type_definitions_table[t];
849}
Utility macros to handle different features and behavior in different compilers.
#define ARRAY_LENGTH(x)
Macros for generating a configuration struct from a list of its individual fields.
config_line_t * config_lines_dup_and_filter(const config_line_t *inp, const char *key)
Definition: confline.c:235
void config_line_append(config_line_t **lst, const char *key, const char *val)
Definition: confline.c:32
config_line_t * config_lines_dup(const config_line_t *inp)
Definition: confline.c:226
int config_lines_eq(const config_line_t *a, const config_line_t *b)
Definition: confline.c:287
Header for confline.c.
#define CONFIG_LINE_APPEND
Definition: confline.h:22
Types used to specify configurable options.
config_type_t
Definition: conftypes.h:39
@ CONFIG_TYPE_AUTOBOOL
Definition: conftypes.h:51
@ CONFIG_TYPE_ISOTIME
Definition: conftypes.h:53
@ CONFIG_TYPE_CSV_INTERVAL
Definition: conftypes.h:56
@ CONFIG_TYPE_LINELIST_V
Definition: conftypes.h:64
@ CONFIG_TYPE_CSV
Definition: conftypes.h:54
@ CONFIG_TYPE_LINELIST_S
Definition: conftypes.h:62
@ CONFIG_TYPE_DOUBLE
Definition: conftypes.h:49
@ CONFIG_TYPE_IGNORE
Definition: conftypes.h:77
@ CONFIG_TYPE_INTERVAL
Definition: conftypes.h:45
@ CONFIG_TYPE_MSEC_INTERVAL
Definition: conftypes.h:46
@ CONFIG_TYPE_INT
Definition: conftypes.h:43
@ CONFIG_TYPE_FILENAME
Definition: conftypes.h:41
@ CONFIG_TYPE_MEMUNIT
Definition: conftypes.h:48
@ CONFIG_TYPE_STRING
Definition: conftypes.h:40
@ CONFIG_TYPE_OBSOLETE
Definition: conftypes.h:71
@ CONFIG_TYPE_UINT64
Definition: conftypes.h:44
@ CONFIG_TYPE_BOOL
Definition: conftypes.h:50
@ CONFIG_TYPE_POSINT
Definition: conftypes.h:42
@ CONFIG_TYPE_LINELIST
Definition: conftypes.h:61
#define CFLG_GROUP_OBSOLETE
Definition: conftypes.h:214
#define CFLG_NODUMP
Definition: conftypes.h:154
#define CFLG_NOCMP
Definition: conftypes.h:186
#define CFLG_NOCOPY
Definition: conftypes.h:176
#define CFLG_NOREPLACE
Definition: conftypes.h:194
#define CFLG_NOSET
Definition: conftypes.h:167
const char * escaped(const char *s)
Definition: escape.c:126
Header for escape.c.
Headers for log.c.
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, uint64_t max, int *ok, char **next)
Definition: parse_int.c:110
long tor_parse_long(const char *s, int base, long min, long max, int *ok, char **next)
Definition: parse_int.c:59
Header for parse_int.c.
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
Header for printf.c.
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition: smartlist.c:279
Header for smartlist.c.
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
unsigned int command
Definition: confline.h:35
unsigned int fragile
Definition: confline.h:39
const char * name
int(* parse)(void *target, const char *value, char **errmsg, const void *params)
int(* kv_parse)(void *target, const struct config_line_t *line, char **errmsg, const void *params)
int parse_iso_time(const char *cp, time_t *t)
Definition: time_fmt.c:423
void format_iso_time(char *buf, time_t t)
Definition: time_fmt.c:326
Header for time_fmt.c.
const var_type_def_t * lookup_type_def(config_type_t type)
Definition: type_defs.c:842
static const var_type_def_t * type_definitions_table[]
Definition: type_defs.c:815
Header for lib/confmgt/type_defs.c.
Header for lib/confmgt/typedvar.c.
const struct unit_table_t time_units[]
Definition: unitparse.c:76
const struct unit_table_t time_msec_units[]
Definition: unitparse.c:97
const struct unit_table_t memory_units[]
Definition: unitparse.c:27
uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok, char **errmsg_out)
Definition: unitparse.c:127
Header for lib/confmgt/unitparse.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103
Structure declarations for typedvar type definitions.