<32bit big-endian: settings count>
<NUL-terminated string: key>[settings count]
- <64bit big-endian: base settings size>
- <NUL-terminated string: error string - if client attempts to access this
- settings block, it must fail with this error.
- NUL = no error, followed by settings>
- Repeat until "base settings size" is reached:
- <32bit big-endian: key index number>
- [<strlist/boollist key>]
- <NUL-terminated string: value>
-
<32bit big-endian: filter count>
Repeat for "filter count":
<64bit big-endian: filter settings size>
- <NUL-terminated string: error string>
+ <NUL-terminated string: error string - if client attempts to access this
+ settings block, it must fail with this error.
+ NUL = no error, followed by settings>
Repeat until "filter settings size" is reached:
<32bit big-endian: key index number>
[<strlist/boollist key>]
}
ctx.filter_output_count = 0;
+ uoff_t filter_count_offset = output->offset;
+ uint32_t filter_count = 0;
+ if (dest != CONFIG_DUMP_FULL_DEST_STDOUT) {
+ o_stream_nsend(output, &filter_count,
+ sizeof(filter_count));
+ }
+
uoff_t blob_size_offset = output->offset;
+ /* Write base settings - add it as an empty filter */
+ ctx.filter_indexes_be32[ctx.filter_output_count] = 0;
+ ctx.filter_offsets_be64[ctx.filter_output_count] =
+ cpu64_to_be(blob_size_offset);
+ ctx.filter_output_count++;
+
if (dest != CONFIG_DUMP_FULL_DEST_STDOUT) {
o_stream_nsend(output, &blob_size, sizeof(blob_size));
o_stream_nsend(output, "", 1); /* no error */
if (output_blob_size(output, blob_size_offset) < 0)
break;
}
- uoff_t filter_count_offset = output->offset;
- uint32_t filter_count = 0;
- if (dest != CONFIG_DUMP_FULL_DEST_STDOUT) {
- o_stream_nsend(output, &filter_count,
- sizeof(filter_count));
- }
+
int ret;
T_BEGIN {
ret = config_dump_full_sections(&ctx, i, info,
"\x00\x00\x01\x00"), // settings count
"'setting key' points outside area" },
- /* base settings size is truncated */
- { DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x1D" // full size
- "\x00\x00\x00\x01" // event filter count
- "\x00" // event filter[0]
- "\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x0F" // block size
- "N\x00" // block name
- "\x00\x00\x00\x01" // settings count
- "K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00"),
- "Area too small when reading size of 'base settings size'" },
- /* base settings size is zero */
- { DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x1E" // full size
- "\x00\x00\x00\x01" // event filter count
- "\x00" // event filter[0]
- "\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x10" // block size
- "N\x00" // block name
- "\x00\x00\x00\x01" // settings count
- "K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x00"), // base settings size
- "'base settings error' points outside area" },
- /* base settings error is not NUL-terminated */
- { DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x20" // full size
- "\x00\x00\x00\x01" // event filter count
- "\x00" // event filter[0]
- "\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x12" // block size
- "N\x00" // block name
- "\x00\x00\x00\x01" // settings count
- "K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "E" // base settings error
- "\x00"), // trailing garbage so we can have NUL
- "'base settings error' points outside area" },
-
/* filter count is truncated */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x22" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x19" // full size
"\x00\x00\x00\x01" // event filter count
"\x00" // event filter[0]
"\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x14" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x0B" // block size
"N\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00"), // filter count
"Area too small when reading uint of 'filter count'" },
/* filter settings size is truncated */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x2A" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x21" // full size
"\x00\x00\x00\x01" // event filter count
"\x00" // event filter[0]
"\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x1B" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x12" // block size
"N\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00\x01" // filter count
"\x00\x00\x00\x00\x00\x00\x00"), // filter settings size
"Area too small when reading size of 'filter settings size'" },
/* filter settings is truncated */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x2B" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x22" // full size
"\x00\x00\x00\x01" // event filter count
"\x00" // event filter[0]
"\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x1D" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x14" // block size
"N\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00\x01" // filter count
"\x00\x00\x00\x00\x00\x00\x10\x00"), // filter settings size
"'filter settings size' points outside area" },
/* filter error is missing */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x38" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x2F" // full size
"\x00\x00\x00\x01" // event filter count
"\x00" // event filter[0]
"\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x2A" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x21" // block size
"N\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00\x01" // filter count
"\x00\x00\x00\x00\x00\x00\x00\x00" // filter settings size
"\x00\x00\x00\x00" // event filter index
"'filter error string' points outside area" },
/* filter error is not NUL-terminated */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x46" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x3D" // full size
"\x00\x00\x00\x01" // event filter count
"\x00" // event filter[0]
"\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x38" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x2F" // block size
"master_service\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00\x01" // filter count
"\x00\x00\x00\x00\x00\x00\x00\x01" // filter settings size
"E" // filter error string
"'filter error string' points outside area" },
/* invalid filter string */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x3B" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x32" // full size
"\x00\x00\x00\x01" // event filter count
"F\x00" // event filter[0]
"F\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x2B" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x22" // block size
"N\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00\x01" // filter count
"\x00\x00\x00\x00\x00\x00\x00\x01" // filter settings size
"\x00" // filter error string
/* Duplicate block name */
{ DATA("DOVECOT-CONFIG\t1.0\n"
- "\x00\x00\x00\x00\x00\x00\x00\x43" // full size
+ "\x00\x00\x00\x00\x00\x00\x00\x3A" // full size
"\x00\x00\x00\x01" // event filter count
"\x00" // event filter[0]
"\x00" // override event filter[0]
- "\x00\x00\x00\x00\x00\x00\x00\x2B" // block size
+ "\x00\x00\x00\x00\x00\x00\x00\x22" // block size
"N\x00" // block name
"\x00\x00\x00\x01" // settings count
"K\x00" // setting[0] key
- "\x00\x00\x00\x00\x00\x00\x00\x01" // base settings size
- "\x00" // base settings error
"\x00\x00\x00\x01" // filter count
"\x00\x00\x00\x00\x00\x00\x00\x01" // filter settings size
"\x00" // filter error string
const char *name;
size_t block_end_offset;
- const char *error; /* if non-NULL, accessing the block must fail */
- size_t base_start_offset, base_end_offset;
-
uint32_t filter_count;
size_t filter_indexes_start_offset;
size_t filter_offsets_start_offset;
return -1;
}
- /* <base settings size> */
- uint64_t base_settings_size;
- if (settings_block_read_size(mmap, &offset, block_end_offset,
- "base settings size", &base_settings_size,
- error_r) < 0)
- return -1;
- block->base_end_offset = offset + base_settings_size;
-
- /* <base settings error string> */
- if (settings_block_read_str(mmap, &offset,
- block->base_end_offset,
- "base settings error", &error,
- error_r) < 0)
- return -1;
- if (error[0] != '\0')
- block->error = error;
- block->base_start_offset = offset;
-
- /* skip over the key-value pairs */
- offset = block->base_end_offset;
-
/* <filter count> */
if (settings_block_read_uint32(mmap, &offset, block_end_offset,
"filter count", &block->filter_count,
ctx->info->name);
return -1;
}
- if (block->error != NULL) {
- *error_r = block->error;
- return -1;
- }
if (!block->settings_validated &&
(ctx->flags & SETTINGS_GET_NO_KEY_VALIDATION) == 0) {
.type = LOG_TYPE_DEBUG,
};
- /* go through the filters in reverse sorted order, so we always set the
- setting just once, never overriding anything. */
+ /* So through the filters in reverse sorted order, so we always set the
+ setting just once, never overriding anything. A filter for the base
+ settings is expected to always exist. */
bool seen_filter = FALSE;
for (uint32_t i = block->filter_count; i > 0; ) {
i--;
}
filter_offset += strlen(filter_error) + 1;
- if (ctx->filter_name != NULL && !seen_filter) {
+ if (ctx->filter_name != NULL && !seen_filter &&
+ event_filter != EVENT_FILTER_MATCH_ALWAYS) {
bool op_not;
const char *value =
event_filter_find_field_exact(
seen_filter = TRUE;
}
- if (event_filter != EVENT_FILTER_MATCH_ALWAYS) {
- int ret = settings_instance_override(ctx,
- mmap->override_event_filters[event_filter_idx],
- error_r);
- if (ret < 0)
- return -1;
- if (ret > 0)
- seen_filter = TRUE;
- }
+ /* Apply overrides specific to this filter before the
+ filter settings themselves. For base settings the
+ filter is EVENT_FILTER_MATCH_ALWAYS, which applies
+ the rest of the overrides that weren't already
+ handled. This way global setting overrides don't
+ override named filters' settings, unless the
+ override is specifically using the filter name
+ as prefix. */
+ int ret = settings_instance_override(ctx,
+ mmap->override_event_filters[event_filter_idx],
+ error_r);
+ if (ret < 0)
+ return -1;
+ if (ret > 0)
+ seen_filter = TRUE;
if (settings_mmap_apply_blob(ctx, block,
filter_offset, filter_end_offset,
return -1;
}
}
-
- /* Apply any leftover overrides after filters and
- filter overrides were already handled. This way global
- setting overrides don't override named filters' settings,
- unless the override is specifically using the filter name
- as prefix. */
- int ret = settings_instance_override(ctx, NULL, error_r);
- if (ret < 0)
- return -1;
- if (ret > 0)
- seen_filter = TRUE;
-
- /* apply the base settings last after all filters */
- if (settings_mmap_apply_blob(ctx, block, block->base_start_offset,
- block->base_end_offset, error_r) < 0)
- return -1;
return seen_filter ? 1 : 0;
}
/* If we're being called while applying filters, only apply
the overrides that have a matching filter. This preserves
the expected order in which settings are applied. */
- if (event_filter != NULL && !set->always_match &&
+ if (!set->always_match &&
event_filter != EVENT_FILTER_MATCH_ALWAYS &&
(set->filter_event == NULL ||
!event_filter_match(event_filter, set->filter_event,
}
} else {
/* No configuration file - apply all overrides */
- ret = settings_instance_override(ctx, NULL, error_r);
+ ret = settings_instance_override(ctx, EVENT_FILTER_MATCH_ALWAYS,
+ error_r);
}
if (ret > 0)
seen_filter = TRUE;