config-request.c revision 2ed05ea827dc49e715a4859a2ca485dc1934f1a3
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "lib.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "array.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "str.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "hash.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "ostream.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "settings-parser.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "master-service-settings.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "all-settings.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "config-parser.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "config-request.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct config_export_context {
fa9e4066f08beec538e775443c5be79dd423fcabahrens pool_t pool;
fa9e4066f08beec538e775443c5be79dd423fcabahrens string_t *value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens string_t *prefix;
fa9e4066f08beec538e775443c5be79dd423fcabahrens HASH_TABLE(char *, char *) keys;
fa9e4066f08beec538e775443c5be79dd423fcabahrens enum config_dump_scope scope;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_request_callback_t *callback;
fa9e4066f08beec538e775443c5be79dd423fcabahrens void *context;
6b90ca488b504d3422b169269c3a86ccad80322clling
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *modules;
fa9e4066f08beec538e775443c5be79dd423fcabahrens enum config_dump_flags flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct config_module_parser *parsers;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct config_module_parser *dup_parsers;
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct master_service_settings_output output;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool failed;
fa9e4066f08beec538e775443c5be79dd423fcabahrens};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void config_export_size(string_t *str, uoff_t size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens static const char suffixes[] = { 'B', 'k', 'M', 'G', 'T' };
fa9e4066f08beec538e775443c5be79dd423fcabahrens char suffix = suffixes[0];
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (size == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append_c(str, '0');
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 1; i < N_ELEMENTS(suffixes) && (size % 1024) == 0; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens suffix = suffixes[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens size /= 1024;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%llu %c", (unsigned long long)size, suffix);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void config_export_time(string_t *str, unsigned int stamp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *suffix = "secs";
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (stamp == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append_c(str, '0');
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (stamp % 60 == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens stamp /= 60;
fa9e4066f08beec538e775443c5be79dd423fcabahrens suffix = "mins";
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (stamp % 60 == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens stamp /= 60;
fa9e4066f08beec538e775443c5be79dd423fcabahrens suffix = "hours";
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (stamp % 24 == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens stamp /= 24;
fa9e4066f08beec538e775443c5be79dd423fcabahrens suffix = "days";
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (stamp % 7 == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens stamp /= 7;
fa9e4066f08beec538e775443c5be79dd423fcabahrens suffix = "weeks";
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%u %s", stamp, suffix);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void config_export_time_msecs(string_t *str, unsigned int stamp_msecs)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((stamp_msecs % 1000) == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_export_time(str, stamp_msecs/1000);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%u ms", stamp_msecs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensbool config_export_type(string_t *str, const void *value,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const void *default_value,
fa9e4066f08beec538e775443c5be79dd423fcabahrens enum setting_type type, bool dump_default,
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool *dump_r)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (type) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_BOOL: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const bool *val = value, *dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dump_default || dval == NULL || *val != *dval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(str, *val ? "yes" : "no");
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_SIZE: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const uoff_t *val = value, *dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dump_default || dval == NULL || *val != *dval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_export_size(str, *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_UINT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_UINT_OCT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_TIME:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_TIME_MSECS: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const unsigned int *val = value, *dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dump_default || dval == NULL || *val != *dval) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (type) {
b81d61a68b235e0529ebadc18e14d9d1dd52a258lling case SET_UINT_OCT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "0%o", *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_TIME:
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_export_time(str, *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_TIME_MSECS:
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_export_time_msecs(str, *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%u", *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_IN_PORT: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const in_port_t *val = value, *dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dump_default || dval == NULL || *val != *dval)
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%u", *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_STR_VARS: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *val = value, *sval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *_dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *dval = _dval == NULL ? NULL : *_dval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_assert(*val == NULL ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens **val == SETTING_STRVAR_UNEXPANDED[0]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens sval = *val == NULL ? NULL : (*val + 1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((dump_default || null_strcmp(sval, dval) != 0) &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens sval != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(str, sval);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *dump_r = TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_STR: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *val = value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *_dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *dval = _dval == NULL ? NULL : *_dval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((dump_default || null_strcmp(*val, dval) != 0) &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens *val != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(str, *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *dump_r = TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_ENUM: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *val = value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned int len = strlen(*val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dump_default)
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(str, *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *_dval = default_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *dval = _dval == NULL ? NULL : *_dval;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_assert(dval != NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (strncmp(*val, dval, len) != 0 ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens ((*val)[len] != ':' && (*val)[len] != '\0'))
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(str, *val);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens default:
fa9e4066f08beec538e775443c5be79dd423fcabahrens return FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenssetting_export_section_name(string_t *str, const struct setting_define *def,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const void *set, unsigned int idx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *name;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size_t name_offset;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (def->type != SET_DEFLIST_UNIQUE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* not unique, use the index */
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%u", idx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens name_offset = def->list_info->type_offset;
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_assert(name_offset != (size_t)-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens name = CONST_PTR_OFFSET(set, name_offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*name == NULL || **name == '\0') {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* no name, this one isn't unique. use the index. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_printfa(str, "%u", idx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(str, settings_section_escape(*name));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenssettings_export(struct config_export_context *ctx,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct setting_parser_info *info,
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool parent_unique_deflist,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const void *set, const void *change_set)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct setting_define *def;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const void *value, *default_value, *change_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens void *const *children, *const *change_children = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned int i, count, count2, prefix_len;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *str;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *key;
fa9e4066f08beec538e775443c5be79dd423fcabahrens bool dump, dump_default = FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (def = info->defines; def->key != NULL; def++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens value = CONST_PTR_OFFSET(set, def->offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens default_value = info->defaults == NULL ? NULL :
fa9e4066f08beec538e775443c5be79dd423fcabahrens CONST_PTR_OFFSET(info->defaults, def->offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens change_value = CONST_PTR_OFFSET(change_set, def->offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (ctx->scope) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case CONFIG_DUMP_SCOPE_ALL:
fa9e4066f08beec538e775443c5be79dd423fcabahrens dump_default = TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case CONFIG_DUMP_SCOPE_SET:
fa9e4066f08beec538e775443c5be79dd423fcabahrens dump_default = *((const char *)change_value) != 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case CONFIG_DUMP_SCOPE_CHANGED:
fa9e4066f08beec538e775443c5be79dd423fcabahrens dump_default = FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!parent_unique_deflist ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens (ctx->flags & CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* .. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else if (*((const char *)change_value) == 0 &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens def->offset != info->type_offset) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* this is mainly for service {} blocks. if value
fa9e4066f08beec538e775443c5be79dd423fcabahrens hasn't changed, it's the default. even if
fa9e4066f08beec538e775443c5be79dd423fcabahrens info->defaults has a different value. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens default_value = value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* value is set explicitly, but we don't know the
fa9e4066f08beec538e775443c5be79dd423fcabahrens default here. assume it's not the default. */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dump_default = TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dump = FALSE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens count = 0; children = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_truncate(ctx->value, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (def->type) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_BOOL:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_SIZE:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_UINT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_UINT_OCT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_TIME:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_TIME_MSECS:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_IN_PORT:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_STR_VARS:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_STR:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_ENUM:
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!config_export_type(ctx->value, value,
fa9e4066f08beec538e775443c5be79dd423fcabahrens default_value, def->type,
fa9e4066f08beec538e775443c5be79dd423fcabahrens dump_default, &dump))
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_unreached();
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_DEFLIST:
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_DEFLIST_UNIQUE: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const ARRAY_TYPE(void_array) *val = value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const ARRAY_TYPE(void_array) *change_val = change_value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!array_is_created(val))
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens children = array_get(val, &count);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < count; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (i > 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append_c(ctx->value, ' ');
fa9e4066f08beec538e775443c5be79dd423fcabahrens setting_export_section_name(ctx->value, def, children[i], i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens change_children = array_get(change_val, &count2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_assert(count == count2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_STRLIST: {
fa9e4066f08beec538e775443c5be79dd423fcabahrens const ARRAY_TYPE(const_string) *val = value;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *const *strings;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!array_is_created(val))
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens key = p_strconcat(ctx->pool, str_c(ctx->prefix),
fa9e4066f08beec538e775443c5be79dd423fcabahrens def->key, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (hash_table_lookup(ctx->keys, key) != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* already added all of these */
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens hash_table_insert(ctx->keys, key, key);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* for doveconf -n to see this KEY_LIST */
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->callback(key, "", CONFIG_KEY_LIST, ctx->context);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens strings = array_get(val, &count);
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_assert(count % 2 == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < count; i += 2) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str = p_strdup_printf(ctx->pool, "%s%s%c%s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_c(ctx->prefix),
fa9e4066f08beec538e775443c5be79dd423fcabahrens def->key,
fa9e4066f08beec538e775443c5be79dd423fcabahrens SETTINGS_SEPARATOR,
fa9e4066f08beec538e775443c5be79dd423fcabahrens strings[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->callback(str, strings[i+1],
fa9e4066f08beec538e775443c5be79dd423fcabahrens CONFIG_KEY_NORMAL, ctx->context);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens count = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens case SET_ALIAS:
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (str_len(ctx->value) > 0 || dump) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens key = p_strconcat(ctx->pool, str_c(ctx->prefix),
fa9e4066f08beec538e775443c5be79dd423fcabahrens def->key, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (hash_table_lookup(ctx->keys, key) == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens enum config_key_type type;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (def->offset == info->type_offset &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens parent_unique_deflist)
fa9e4066f08beec538e775443c5be79dd423fcabahrens type = CONFIG_KEY_UNIQUE_KEY;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else if (SETTING_TYPE_IS_DEFLIST(def->type))
fa9e4066f08beec538e775443c5be79dd423fcabahrens type = CONFIG_KEY_LIST;
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens type = CONFIG_KEY_NORMAL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->callback(key, str_c(ctx->value), type,
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->context);
fa9e4066f08beec538e775443c5be79dd423fcabahrens hash_table_insert(ctx->keys, key, key);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_assert(count == 0 || children != NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens prefix_len = str_len(ctx->prefix);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < count; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append(ctx->prefix, def->key);
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append_c(ctx->prefix, SETTINGS_SEPARATOR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens setting_export_section_name(ctx->prefix, def, children[i], i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_append_c(ctx->prefix, SETTINGS_SEPARATOR);
fa9e4066f08beec538e775443c5be79dd423fcabahrens settings_export(ctx, def->list_info,
fa9e4066f08beec538e775443c5be79dd423fcabahrens def->type == SET_DEFLIST_UNIQUE,
fa9e4066f08beec538e775443c5be79dd423fcabahrens children[i], change_children[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens str_truncate(ctx->prefix, prefix_len);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstruct config_export_context *
fa9e4066f08beec538e775443c5be79dd423fcabahrensconfig_export_init(const char *const *modules, enum config_dump_scope scope,
fa9e4066f08beec538e775443c5be79dd423fcabahrens enum config_dump_flags flags,
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_request_callback_t *callback, void *context)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct config_export_context *ctx;
fa9e4066f08beec538e775443c5be79dd423fcabahrens pool_t pool;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens pool = pool_alloconly_create(MEMPOOL_GROWING"config export", 1024*64);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx = p_new(pool, struct config_export_context, 1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->pool = pool;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->modules = modules == NULL ? NULL : p_strarray_dup(pool, modules);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->flags = flags;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->callback = callback;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->context = context;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->scope = scope;
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->value = str_new(pool, 256);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->prefix = str_new(pool, 64);
fa9e4066f08beec538e775443c5be79dd423fcabahrens hash_table_create(&ctx->keys, ctx->pool, 0, str_hash, strcmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return ctx;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid config_export_by_filter(struct config_export_context *ctx,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct config_filter *filter)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *error;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (config_filter_parsers_get(config_filter, ctx->pool,
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->modules, filter,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &ctx->dup_parsers, &ctx->output,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &error) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_error("%s", error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->failed = TRUE;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->parsers = ctx->dup_parsers;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid config_export_parsers(struct config_export_context *ctx,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct config_module_parser *parsers)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->parsers = parsers;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid config_export_get_output(struct config_export_context *ctx,
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct master_service_settings_output *output_r)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens *output_r = ctx->output;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void config_export_free(struct config_export_context *ctx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ctx->dup_parsers != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_filter_parsers_free(ctx->dup_parsers);
fa9e4066f08beec538e775443c5be79dd423fcabahrens hash_table_destroy(&ctx->keys);
fa9e4066f08beec538e775443c5be79dd423fcabahrens pool_unref(&ctx->pool);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensint config_export_finish(struct config_export_context **_ctx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct config_export_context *ctx = *_ctx;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const struct config_module_parser *parser;
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *error;
fa9e4066f08beec538e775443c5be79dd423fcabahrens unsigned int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int ret = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *_ctx = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (ctx->failed) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_export_free(ctx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; ctx->parsers[i].root != NULL; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens parser = &ctx->parsers[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!config_module_want_parser(config_module_parsers,
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->modules, parser->root))
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens T_BEGIN {
fa9e4066f08beec538e775443c5be79dd423fcabahrens settings_export(ctx, parser->root, FALSE,
fa9e4066f08beec538e775443c5be79dd423fcabahrens settings_parser_get(parser->parser),
fa9e4066f08beec538e775443c5be79dd423fcabahrens settings_parser_get_changes(parser->parser));
fa9e4066f08beec538e775443c5be79dd423fcabahrens } T_END;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ctx->flags & CONFIG_DUMP_FLAG_CHECK_SETTINGS) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens settings_parse_var_skip(parser->parser);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!settings_parser_check(parser->parser, ctx->pool,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &error)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((ctx->flags & CONFIG_DUMP_FLAG_CALLBACK_ERRORS) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->callback(NULL, error, CONFIG_KEY_ERROR,
fa9e4066f08beec538e775443c5be79dd423fcabahrens ctx->context);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens i_error("%s", error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens config_export_free(ctx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return ret;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens