# HG changeset patch # User Timo Sirainen # Date 1220164287 -10800 # Node ID 612eb505775fd75094faa9f00db13bf92de03cd5 # Parent fcf0c5ac597595f761a66147dbed826049f5a6ef Write CPU endianess to transaction log header and check it's correct when reading. diff -r fcf0c5ac5975 -r 612eb505775f src/lib-index/mail-transaction-log-file.c --- a/src/lib-index/mail-transaction-log-file.c Sat Aug 30 15:24:55 2008 +0300 +++ b/src/lib-index/mail-transaction-log-file.c Sun Aug 31 09:31:27 2008 +0300 @@ -180,6 +180,9 @@ hdr->hdr_size = sizeof(struct mail_transaction_log_header); hdr->indexid = log->index->indexid; hdr->create_stamp = ioloop_time; +#ifndef WORDS_BIGENDIAN + hdr->compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN; +#endif if (index->fd != -1) { /* not creating index - make sure we have latest header */ @@ -345,6 +348,27 @@ file_unlock(&file->file_lock); } +static ssize_t +mail_transaction_log_file_read_header(struct mail_transaction_log_file *file) +{ + ssize_t pos; + int ret; + + memset(&file->hdr, 0, sizeof(file->hdr)); + + /* try to read the whole header, but it's not necessarily an error to + read less since the older versions of the log format could be + smaller. */ + pos = 0; + do { + ret = pread(file->fd, PTR_OFFSET(&file->hdr, pos), + sizeof(file->hdr) - pos, pos); + if (ret > 0) + pos += ret; + } while (ret > 0 && pos < (ssize_t)sizeof(file->hdr)); + return ret < 0 ? -1 : pos; +} + static int mail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file, bool ignore_estale) @@ -357,24 +381,40 @@ if (file->corrupted) return 0; - ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0); + ret = mail_transaction_log_file_read_header(file); if (ret < 0) { if (errno != ESTALE || !ignore_estale) { mail_index_file_set_syscall_error(file->log->index, file->filepath, - "pread_full()"); + "pread()"); } return -1; } - if (ret == 0) { + if (file->hdr.major_version != MAIL_TRANSACTION_LOG_MAJOR_VERSION) { + /* incompatible version - fix silently */ + return 0; + } + if (ret < MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE) { mail_transaction_log_file_set_corrupted(file, "unexpected end of file while reading header"); return 0; } - if (file->hdr.major_version != MAIL_TRANSACTION_LOG_MAJOR_VERSION) { - /* incompatible version - fix silently */ - return 0; + if (file->hdr.minor_version >= 2 || file->hdr.major_version > 1) { + /* we have compatibility flags */ + enum mail_index_header_compat_flags compat_flags = 0; + +#ifndef WORDS_BIGENDIAN + compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN; +#endif + if (file->hdr.compat_flags != compat_flags) { + /* architecture change */ + mail_index_set_error(file->log->index, + "Rebuilding index file %s: " + "CPU architecture changed", + file->log->index->filepath); + return 0; + } } if (file->hdr.hdr_size < MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE) { mail_transaction_log_file_set_corrupted(file, diff -r fcf0c5ac5975 -r 612eb505775f src/lib-index/mail-transaction-log.h --- a/src/lib-index/mail-transaction-log.h Sat Aug 30 15:24:55 2008 +0300 +++ b/src/lib-index/mail-transaction-log.h Sun Aug 31 09:31:27 2008 +0300 @@ -5,7 +5,7 @@ struct mail_index_transaction; #define MAIL_TRANSACTION_LOG_MAJOR_VERSION 1 -#define MAIL_TRANSACTION_LOG_MINOR_VERSION 1 +#define MAIL_TRANSACTION_LOG_MINOR_VERSION 2 #define MAIL_TRANSACTION_LOG_HEADER_MIN_SIZE 24 struct mail_transaction_log_header { @@ -18,7 +18,10 @@ uint32_t prev_file_seq; uint32_t prev_file_offset; uint32_t create_stamp; - uint64_t initial_modseq; + uint64_t initial_modseq; /* v1.1+ */ + + uint8_t compat_flags; /* enum mail_index_header_compat_flags, v1.2+ */ + uint8_t unused[3]; }; enum mail_transaction_type { diff -r fcf0c5ac5975 -r 612eb505775f src/util/logview.c --- a/src/util/logview.c Sat Aug 30 15:24:55 2008 +0300 +++ b/src/util/logview.c Sun Aug 31 09:31:27 2008 +0300 @@ -45,6 +45,7 @@ printf("create stamp = %u\n", hdr.create_stamp); printf("initial modseq = %llu\n", (unsigned long long)hdr.initial_modseq); + printf("compat flags = %x\n", hdr.compat_flags); *modseq_r = hdr.initial_modseq; }