Currently the default settings can be given only via the defaults struct.
With this change it's possible to separately track whether settings changes
are intended to be defaults or explicit configuration changes.
Only the explicit config changes are visible in e.g. "doveconf -n" output,
while all the changes will be written to the binary config file.
dump_ctx.filter_written = FALSE;
if (dest == CONFIG_DUMP_FULL_DEST_STDOUT) {
export_ctx = config_export_init(
- CONFIG_DUMP_SCOPE_SET,
+ CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES,
CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS,
config_dump_full_stdout_callback, &dump_ctx);
} else {
export_ctx = config_export_init(
- CONFIG_DUMP_SCOPE_SET,
+ CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES,
CONFIG_DUMP_FLAG_HIDE_LIST_DEFAULTS,
config_dump_full_callback, &dump_ctx);
}
if (dest == CONFIG_DUMP_FULL_DEST_STDOUT) {
export_ctx = config_export_init(
- CONFIG_DUMP_SCOPE_CHANGED, flags,
- config_dump_full_stdout_callback, &dump_ctx);
+ CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES,
+ flags, config_dump_full_stdout_callback,
+ &dump_ctx);
} else {
export_ctx = config_export_init(
- CONFIG_DUMP_SCOPE_CHANGED, flags,
- config_dump_full_callback, &dump_ctx);
+ CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES,
+ flags, config_dump_full_callback, &dump_ctx);
}
struct config_filter_parser *filter_parser =
config_parsed_get_global_filter_parser(config);
dest[i].root = all_roots[i];
dest[i].parser = settings_parser_init(pool, all_roots[i],
settings_parser_flags);
+ settings_parse_set_change_counter(dest[i].parser,
+ CONFIG_PARSER_CHANGE_EXPLICIT);
}
return dest;
}
ctx.root_module_parsers[i].parser =
settings_parser_init(ctx.pool, all_roots[i],
settings_parser_flags);
+ settings_parse_set_change_counter(ctx.root_module_parsers[i].parser,
+ CONFIG_PARSER_CHANGE_EXPLICIT);
for (unsigned int j = 0; j < i; j++) {
if (strcmp(all_roots[j]->name, all_roots[i]->name) == 0) {
/* Just fatal - it's difficult to continue
#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
+/* change_counter used for default settings created internally */
+#define CONFIG_PARSER_CHANGE_INTERNAL 1
+/* change_counter used for settings changed by configuration file */
+#define CONFIG_PARSER_CHANGE_EXPLICIT 2
+
struct config_parsed;
enum config_parse_flags {
/* hidden - dump default only if it's explicitly set */
/* fall through */
case CONFIG_DUMP_SCOPE_SET:
+ if (def->type == SET_DEFLIST ||
+ def->type == SET_DEFLIST_UNIQUE)
+ break;
+ if (*((const uint8_t *)change_value) < CONFIG_PARSER_CHANGE_EXPLICIT) {
+ /* setting is unchanged in config file */
+ continue;
+ }
+ dump_default = TRUE;
+ break;
+ case CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES:
+ if (def->type == SET_DEFLIST ||
+ def->type == SET_DEFLIST_UNIQUE)
+ break;
dump_default = *((const char *)change_value) != 0;
break;
case CONFIG_DUMP_SCOPE_CHANGED:
+ if (*((const uint8_t *)change_value) < CONFIG_PARSER_CHANGE_EXPLICIT) {
+ /* setting is unchanged in config file */
+ continue;
+ }
dump_default = FALSE;
break;
}
CONFIG_DUMP_SCOPE_ALL_WITHOUT_HIDDEN,
/* Dump all that have explicitly been set */
CONFIG_DUMP_SCOPE_SET,
+ /* Same as CONFIG_DUMP_SCOPE_SET, but also dump any defaults overridden
+ via strings (instead of the defaults struct). */
+ CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES,
/* Dump only settings that differ from defaults */
CONFIG_DUMP_SCOPE_CHANGED
};
const char *const *set_filter_path =
setting_name_filter == NULL ? empty_str_array :
t_strsplit(setting_name_filter, "/");
+ if (scope == CONFIG_DUMP_SCOPE_CHANGED)
+ scope = CONFIG_DUMP_SCOPE_SET;
+ else
+ scope = CONFIG_DUMP_SCOPE_SET_AND_DEFAULT_OVERRIDES;
config_dump_human_filter_path(scope, set_filter_path,
filter_parser->children_head, output, 0,
list_prefix, &list_prefix_sent,