/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "mail-index-private.h"
{
/* extension headers always start from 64bit offsets, so if base header
doesn't happen to be 64bit aligned we'll skip some bytes */
/* nothing to do, skip allocations and all */
return 0;
}
for (i = 0; i < old_count; i++)
ext_offset = offset;
"Header extension #%d (%s) goes outside header",
return -1;
}
"Broken extension #%d (%s): %s",
return -1;
}
"Duplicate header extension %s",
return -1;
}
}
return 0;
}
{
const char *name;
return 0;
}
/* Extension header contains:
- struct mail_index_keyword_header
- struct mail_index_keyword_header_rec * keywords_count
- const char names[] * keywords_count
*/
/* Keywords can only be added into same mapping. Removing requires a
new mapping (recreating the index file) */
/* nothing changed */
return 0;
}
/* make sure the header is valid */
"Keywords removed unexpectedly",
return -1;
}
"keywords_count larger than header size",
return -1;
}
for (i = 0; i < kw_hdr->keywords_count; i++) {
"name_offset points outside allocated header",
return -1;
}
}
"Keyword header doesn't end with NUL",
return -1;
}
/* create file -> index mapping */
#ifdef DEBUG
/* Check that existing headers are still the same. It's behind DEBUG
since it's pretty useless waste of CPU normally. */
const unsigned int *old_idx;
unsigned int kw_idx;
"Keywords changed unexpectedly",
return -1;
}
}
#endif
/* Register the newly seen keywords */
for (; i < kw_hdr->keywords_count; i++) {
unsigned int kw_idx;
if (*keyword == '\0') {
"Empty keyword name in header",
return -1;
}
}
return 0;
}
const struct mail_index_header *hdr,
{
#ifndef WORDS_BIGENDIAN
#endif
/* major version change */
return FALSE;
}
/* we've already complained about it */
*error_r = "Header's corrupted flag is set";
return FALSE;
}
/* architecture change */
*error_r = "CPU architecture changed";
return FALSE;
}
"Corrupted header sizes (base %u, full %u)",
return FALSE;
}
return FALSE;
}
"indexid changed: %u -> %u",
}
}
return TRUE;
}
{
}
}
const char **error_r)
{
return 0;
/* following some extra checks that only take a bit of CPU */
return -1;
}
return 0;
}
*error_r = "next_uid=0";
return 0;
}
"messages_count is higher in header than record map (%u > %u)",
return 0;
}
"seen_messages_count %u > messages_count %u",
return 0;
}
"deleted_messages_count %u > messages_count %u",
return 0;
}
switch (hdr->minor_version) {
case 0:
/* upgrade silently from v1.0 */
if (hdr->first_recent_uid == 0)
/* fall through */
case 1:
/* pre-v1.1.rc6: make sure the \Recent flags are gone */
/* fall through */
case 2:
/* pre-v2.2 (although should have been done in v2.1 already):
make sure the old unused fields are cleared */
}
if (hdr->first_recent_uid == 0) {
*error_r = "first_recent_uid=0";
return 0;
}
"first_recent_uid %u > next_uid %u",
return 0;
}
"first_unseen_uid_lowwater %u > next_uid %u",
return 0;
}
"first_deleted_uid_lowwater %u > next_uid %u",
return 0;
}
if (hdr->messages_count > 0) {
/* last message's UID must be smaller than next_uid.
also make sure it's not zero. */
*error_r = "last message has uid=0";
return -1;
}
"last message uid %u >= next_uid %u",
return 0;
}
}
return 1;
}