# HG changeset patch # User Timo Sirainen # Date 1031875283 -10800 # Node ID ed0d5b17c7a4e834573d187c0f09e6d7f5644965 # Parent 94382d79ae47c34b36a1dc8eac61cb5c2a2cf26b Added extra functions for easier printing of error messages. Moved file_set_size() to generic function in lib. If there's no space to build hash file, it builds itself in anon-mmaped memory and stays there. diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-custom-flags.c --- a/src/lib-index/mail-custom-flags.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-custom-flags.c Fri Sep 13 03:01:23 2002 +0300 @@ -21,7 +21,7 @@ struct _MailCustomFlags { MailIndex *index; - char *path; + char *filepath; int fd; int lock_type; @@ -37,13 +37,21 @@ static int lock_file(MailCustomFlags *mcf, int type); +static void index_cf_set_syscall_error(MailCustomFlags *mcf, + const char *function) +{ + i_assert(function != NULL); + + index_set_error(mcf->index, "%s failed with custom flags file %s: %m", + function, mcf->filepath); +} + static int update_mmap(MailCustomFlags *mcf) { mcf->mmap_base = mmap_rw_file(mcf->fd, &mcf->mmap_length); if (mcf->mmap_base == MAP_FAILED) { mcf->mmap_base = NULL; - index_set_error(mcf->index, "mmap() failed for " - "custom flags file %s: %m", mcf->path); + index_cf_set_syscall_error(mcf, "mmap()"); return FALSE; } @@ -65,15 +73,13 @@ pos = lseek(mcf->fd, 0, SEEK_SET); if (pos == -1) { - index_set_error(mcf->index, "lseek() failed for " - "custom flags file %s: %m", mcf->path); + index_cf_set_syscall_error(mcf, "lseek()"); return FALSE; } /* write the header - it's a 4 byte counter as hex */ if (write_full(mcf->fd, buf, HEADER_SIZE) < 0) { - index_set_error(mcf->index, "write() failed for " - "custom flags file %s: %m", mcf->path); + index_cf_set_syscall_error(mcf, "write_full()"); return FALSE; } @@ -133,7 +139,8 @@ if (mcf->custom_flags[num] != NULL) { i_warning("Error in custom flags file %s: " - "Duplicated ID %u", mcf->path, num); + "Duplicated ID %u", mcf->filepath, + num); i_free(mcf->custom_flags[num]); } @@ -188,8 +195,7 @@ while (fcntl(mcf->fd, F_SETLKW, &fl) == -1) { if (errno != EINTR) { - index_set_error(mcf->index, "fcntl() failed for " - "custom flags file %s: %m", mcf->path); + index_cf_set_syscall_error(mcf, "fcntl(F_SETLKW)"); return FALSE; } } @@ -230,7 +236,7 @@ mcf = i_new(MailCustomFlags, 1); mcf->index = index; - mcf->path = i_strdup(path); + mcf->filepath = i_strdup(path); mcf->fd = fd; if (!update_mmap(mcf)) { @@ -264,7 +270,7 @@ (void)munmap(mcf->mmap_base, mcf->mmap_length); (void)close(mcf->fd); - i_free(mcf->path); + i_free(mcf->filepath); i_free(mcf); } @@ -272,9 +278,8 @@ { int i; - if (lseek(mcf->fd, 0, SEEK_SET) == -1) { - index_set_error(mcf->index, "lseek() failed for " - "custom flags file %s: %m", mcf->path); + if (lseek(mcf->fd, 0, SEEK_SET) < 0) { + index_cf_set_syscall_error(mcf, "lseek()"); return FALSE; } @@ -294,8 +299,7 @@ } if (write_full(mcf->fd, mcf->sync_counter, COUNTER_SIZE) < 0) { - index_set_error(mcf->index, "write() failed for " - "custom flags file %s: %m", mcf->path); + index_cf_set_syscall_error(mcf, "write_full()"); return FALSE; } @@ -316,16 +320,15 @@ /* add the flag */ pos = lseek(mcf->fd, 0, SEEK_END); - if (pos == -1) { - index_set_error(mcf->index, "lseek() failed for " - "custom flags file %s: %m", mcf->path); + if (pos < 0) { + index_cf_set_syscall_error(mcf, "lseek()"); return FALSE; } if (pos != (off_t)mcf->mmap_length) { - index_set_error(mcf->index, "custom flags file %s was " + index_set_error(mcf->index, "Custom flags file %s was " "changed by someone while we were" - "trying to modify it", mcf->path); + "trying to modify it", mcf->filepath); return FALSE; } @@ -339,8 +342,7 @@ } if (write_full(mcf->fd, buf, len) < 0) { - index_set_error(mcf->index, "write() failed for " - "custom flags file %s: %m", mcf->path); + index_cf_set_syscall_error(mcf, "write_full()"); return FALSE; } @@ -387,10 +389,7 @@ mcf->mmap_length -= linelen; if (ftruncate(mcf->fd, (off_t) mcf->mmap_length) == -1) { - index_set_error(mcf->index, - "ftruncate() failed for " - "custom flags file %s: %m", - mcf->path); + index_cf_set_syscall_error(mcf, "ftruncate()"); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-hash.c --- a/src/lib-index/mail-hash.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-hash.c Fri Sep 13 03:01:23 2002 +0300 @@ -2,6 +2,7 @@ #include "lib.h" #include "ioloop.h" +#include "file-set-size.h" #include "primes.h" #include "mmap-util.h" #include "write-full.h" @@ -35,6 +36,9 @@ through lots of records just to find an empty spot */ #define HASH_FUNC(uid) (uid * 2) +#define HASH_FILE_SIZE(records) \ + (sizeof(MailHashHeader) + (records) * sizeof(MailHashRecord)) + struct _MailHash { MailIndex *index; @@ -48,12 +52,15 @@ size_t mmap_length; MailHashHeader *header; + unsigned int anon_mmap:1; unsigned int dirty_mmap:1; unsigned int modified:1; }; static int mmap_update_real(MailHash *hash) { + i_assert(!hash->anon_mmap); + if (hash->mmap_base != NULL) (void)munmap(hash->mmap_base, hash->mmap_length); @@ -187,83 +194,36 @@ hash->mmap_base = NULL; } - (void)close(hash->fd); + if (hash->fd != -1) + (void)close(hash->fd); i_free(hash->filepath); i_free(hash); } -static int file_set_size(int fd, off_t size) +int mail_hash_sync_file(MailHash *hash) { - char block[1024]; - int ret, old_errno; - off_t pos; - - i_assert(size >= 0); + if (!hash->modified) + return TRUE; + hash->modified = FALSE; - /* try truncating it to the size we want. if this succeeds, the written - area is full of zeros - exactly what we want. however, this may not - work at all, in which case we fallback to write()ing the zeros. */ - ret = ftruncate(fd, size); - old_errno = errno; - - pos = lseek(fd, 0, SEEK_END); - if (ret != -1 && pos == size) - return lseek(fd, 0, SEEK_SET) == 0; - - if (pos == -1) - return FALSE; - if (pos > size) { - /* ftruncate() failed for some reason, even while we were - trying to make the file smaller */ - errno = old_errno; + if (hash->anon_mmap || + msync(hash->mmap_base, hash->mmap_length, MS_SYNC) == 0) + return TRUE; + else { + index_set_error(hash->index, "msync() failed for %s: %m", + hash->filepath); return FALSE; } - - /* start growing the file */ - size -= pos; - memset(block, 0, sizeof(block)); - - while ((uoff_t)size > sizeof(block)) { - /* write in 1kb blocks */ - if (write_full(fd, block, sizeof(block)) < 0) - return FALSE; - size -= sizeof(block); - } - - /* write the remainder */ - return write_full(fd, block, (size_t)size) == 0; } -static int hash_rebuild_to_file(MailIndex *index, int fd, - unsigned int hash_size, - unsigned int messages_count) +static void hash_build(MailIndex *index, void *mmap_base, + unsigned int hash_size) { MailHashHeader *hdr; MailHashRecord *rec; + MailIndexHeader *idx_hdr; MailIndexRecord *idx_rec; - void *mmap_base; unsigned int i, count; - size_t mmap_length; - size_t new_size; - - i_assert(hash_size < MAX_HASH_SIZE); - - /* fill the file with zeros */ - new_size = sizeof(MailHashHeader) + hash_size * sizeof(MailHashRecord); - if (!file_set_size(fd, (off_t)new_size)) { - index_set_error(index, "Failed to fill temp hash to size " - "%"PRIuSIZE_T": %m", new_size); - return FALSE; - } - - /* now, mmap() it */ - mmap_base = mmap_rw_file(fd, &mmap_length); - if (mmap_base == MAP_FAILED) { - index_set_error(index, "mmap()ing temp hash failed: %m"); - return FALSE; - } - - i_assert(mmap_length == new_size); /* we have empty hash file mmap()ed now. fill it by reading the messages from index. */ @@ -276,12 +236,12 @@ idx_rec = index->next(index, idx_rec); } - if (count != messages_count) { + idx_hdr = index->get_header(index); + if (count != idx_hdr->messages_count) { /* mark this as an error but don't fail because of it. */ - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Missing messages while rebuilding " - "hash file %s - %u found, header says %u", - index->filepath, count, messages_count); + index_set_corrupted(index, "Missing messages while rebuilding " + "hash file - %u found, header says %u", + count, idx_hdr->messages_count); } /* setup header */ @@ -289,23 +249,53 @@ hdr->indexid = index->indexid; hdr->sync_id = ioloop_time; hdr->used_records = count; - - return munmap(mmap_base, mmap_length) == 0; } -int mail_hash_sync_file(MailHash *hash) +static int hash_rebuild_to_file(MailIndex *index, int fd, const char *path, + unsigned int hash_size) { - if (!hash->modified) - return TRUE; - hash->modified = FALSE; + void *mmap_base; + size_t mmap_length, new_size; - if (msync(hash->mmap_base, hash->mmap_length, MS_SYNC) == 0) - return TRUE; - else { - index_set_error(hash->index, "msync() failed for %s: %m", - hash->filepath); + i_assert(hash_size < MAX_HASH_SIZE); + + new_size = HASH_FILE_SIZE(hash_size); + + /* fill the file with zeros */ + if (file_set_size(fd, (off_t)new_size) < 0) { + index_set_error(index, "Failed to fill temp hash to " + "size %"PRIuSIZE_T": %m", new_size); return FALSE; } + + /* now, mmap() it */ + mmap_base = mmap_rw_file(fd, &mmap_length); + if (mmap_base == MAP_FAILED) { + index_set_error(index, + "mmap()ing temp hash failed: %m"); + return FALSE; + } + i_assert(mmap_length == new_size); + + hash_build(index, mmap_base, hash_size); + + if (msync(mmap_base, mmap_length, MS_SYNC) < 0) { + index_set_error(index, "msync() failed for temp hash %s: %m", + path); + (void)munmap(mmap_base, mmap_length); + return FALSE; + } + + (void)munmap(mmap_base, mmap_length); + + /* we don't want to leave partially written hash around */ + if (fsync(fd) < 0) { + index_set_error(index, "fsync() failed with temp hash %s: %m", + path); + return FALSE; + } + + return TRUE; } int mail_hash_rebuild(MailHash *hash) @@ -313,15 +303,13 @@ MailIndexHeader *index_header; const char *path; unsigned int hash_size; - int fd; + int fd, failed; if (!hash->index->set_lock(hash->index, MAIL_LOCK_EXCLUSIVE)) return FALSE; - /* first get the number of messages in index */ + /* figure out size for our hash */ index_header = hash->index->get_header(hash->index); - - /* then figure out size for our hash */ hash_size = primes_closest(index_header->messages_count * 100 / MIN_PERCENTAGE); if (hash_size < MIN_HASH_SIZE) @@ -332,47 +320,59 @@ /* either our calculation overflowed, or we reached the max. value primes_closest() gave us. and there's more mails - very unlikely. */ - index_set_error(hash->index, "Too many mails in mailbox (%u), " - "max. hash file size reached for %s", - index_header->messages_count, hash->filepath); + index_set_corrupted(hash->index, "Too many mails in mailbox " + "(%u)", index_header->messages_count); return FALSE; } - /* create the hash in a new temp file */ + /* build the hash in a temp file, renaming it to the real hash + once finished */ fd = mail_index_create_temp_file(hash->index, &path); - if (fd == -1) - return FALSE; + if (fd != -1) { + failed = !hash_rebuild_to_file(hash->index, fd, + path, hash_size); - if (!hash_rebuild_to_file(hash->index, fd, hash_size, - index_header->messages_count)) { - (void)close(fd); - (void)unlink(path); - return FALSE; + if (!failed && rename(path, hash->filepath) < 0) { + index_set_error(hash->index, "rename(%s, %s) failed: %m", + path, hash->filepath); + failed = TRUE; + } + + if (failed) { + int old_errno = errno; + + (void)close(fd); + (void)unlink(path); + fd = -1; + + errno = old_errno; + } } - if (fsync(fd) == -1) { - index_set_error(hash->index, - "fsync() failed with temp hash %s: %m", path); - (void)close(fd); - (void)unlink(path); - return FALSE; - } + if (fd == -1) { + /* building hash to file failed. if it was because there + was no space in disk, we could just as well keep it in + memory */ + if (errno != ENOSPC) + return FALSE; - /* replace old hash file with this new one */ - if (rename(path, hash->filepath) == -1) { - index_set_error(hash->index, "rename(%s, %s) failed: %m", - path, hash->filepath); + if (hash->mmap_base != NULL) + (void)munmap(hash->mmap_base, hash->mmap_length); - (void)close(fd); - (void)unlink(path); - return FALSE; + hash->mmap_length = HASH_FILE_SIZE(hash_size); + hash->mmap_base = mmap_anonymous(hash->mmap_length); + hash_build(hash->index, hash->mmap_base, hash_size); + + /* make sure it doesn't exist anymore */ + (void)unlink(hash->filepath); } /* switch fds */ if (hash->fd != -1) (void)close(hash->fd); hash->fd = fd; - hash->dirty_mmap = TRUE; + hash->anon_mmap = fd == -1; + hash->dirty_mmap = !hash->anon_mmap; return TRUE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index-compress.c --- a/src/lib-index/mail-index-compress.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index-compress.c Fri Sep 13 03:01:23 2002 +0300 @@ -52,8 +52,7 @@ /* truncate the file to get rid of the extra records */ fsize = (size_t) ((char *) hole_rec - (char *) index->mmap_base); if (ftruncate(index->fd, (off_t)fsize) == -1) { - index_set_error(index, "ftruncate() failed for %s: %m", - index->filepath); + index_set_syscall_error(index, "ftruncate()"); return FALSE; } @@ -104,9 +103,8 @@ rec = index->lookup(index, 1); while (rec != NULL) { if (rec->data_position + rec->data_size > mmap_data_size) { - index_set_error(index, "Error in index file %s: " - "data_position+data_size points " - "outside file", index->filepath); + index_set_corrupted(index, "data_position+data_size " + "points outside file"); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index-data.c --- a/src/lib-index/mail-index-data.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index-data.c Fri Sep 13 03:01:23 2002 +0300 @@ -31,6 +31,29 @@ unsigned int dirty_mmap:1; }; +void index_data_set_corrupted(MailIndexData *data, const char *fmt, ...) +{ + va_list va; + + INDEX_MARK_CORRUPTED(data->index); + + va_start(va, fmt); + t_push(); + index_set_error(data->index, "Corrupted index data file %s: %s", + data->filepath, t_strdup_vprintf(fmt, va)); + t_pop(); + va_end(va); +} + +static void index_data_set_syscall_error(MailIndexData *data, + const char *function) +{ + i_assert(function != NULL); + + index_set_error(data->index, "%s failed with index data file %s: %m", + function, data->filepath); +} + static int mmap_update(MailIndexData *data, uoff_t pos, size_t size) { if (!data->dirty_mmap && (size != 0 && pos+size <= data->mmap_length)) @@ -42,13 +65,10 @@ data->mmap_base = mmap_rw_file(data->fd, &data->mmap_length); if (data->mmap_base == MAP_FAILED) { data->mmap_base = NULL; - index_set_error(data->index, "index data: mmap() failed with " - "file %s: %m", data->filepath); + index_data_set_syscall_error(data, "mmap()"); return FALSE; } else if (data->mmap_length < sizeof(MailIndexDataHeader)) { - INDEX_MARK_CORRUPTED(data->index); - index_set_error(data->index, "index data: truncated data " - "file %s", data->filepath); + index_data_set_corrupted(data, "File too small"); return FALSE; } else { data->dirty_mmap = FALSE; @@ -119,7 +139,7 @@ /* move temp file into .data file, deleting old one if it already exists */ realpath = t_strconcat(index->filepath, DATA_FILE_PREFIX, NULL); - if (rename(temppath, realpath) == -1) { + if (rename(temppath, realpath) < 0) { index_set_error(index, "rename(%s, %s) failed: %m", temppath, realpath); (void)unlink(temppath); @@ -174,9 +194,8 @@ { MailIndexDataHeader hdr; - if (ftruncate(data->fd, sizeof(MailIndexDataHeader)) == -1) { - index_set_error(data->index, "ftruncate() failed for data file " - "%s: %m", data->filepath); + if (ftruncate(data->fd, sizeof(MailIndexDataHeader)) < 0) { + index_data_set_syscall_error(data, "ftruncate()"); return FALSE; } @@ -184,15 +203,13 @@ hdr.indexid = data->index->indexid; hdr.deleted_space = 0; - if (lseek(data->fd, 0, SEEK_SET) == -1) { - index_set_error(data->index, "lseek() failed for data file " - "%s: %m", data->filepath); + if (lseek(data->fd, 0, SEEK_SET) < 0) { + index_data_set_syscall_error(data, "lseek()"); return FALSE; } if (write_full(data->fd, &hdr, sizeof(hdr)) < 0) { - index_set_error(data->index, "write() failed for data file " - "%s: %m", data->filepath); + index_data_set_syscall_error(data, "write_full()"); return FALSE; } @@ -212,21 +229,18 @@ i_assert((size & (MEM_ALIGN_SIZE-1)) == 0); pos = lseek(data->fd, 0, SEEK_END); - if (pos == -1) { - index_set_error(data->index, "lseek() failed with file %s: %m", - data->filepath); + if (pos < 0) { + index_data_set_syscall_error(data, "lseek()"); return 0; } if (pos < (int)sizeof(MailIndexDataHeader)) { - index_set_error(data->index, "Header missing from data file %s", - data->filepath); + index_data_set_corrupted(data, "Header is missing"); return 0; } if (write_full(data->fd, buffer, size) < 0) { - index_set_error(data->index, "Error appending to file %s: %m", - data->filepath); + index_data_set_syscall_error(data, "write_full()"); return 0; } @@ -260,16 +274,14 @@ int mail_index_data_sync_file(MailIndexData *data) { if (data->mmap_base != NULL) { - if (msync(data->mmap_base, data->mmap_length, MS_SYNC) == -1) { - index_set_error(data->index, "msync() failed for " - "%s: %m", data->filepath); + if (msync(data->mmap_base, data->mmap_length, MS_SYNC) < 0) { + index_data_set_syscall_error(data, "msync()"); return FALSE; } } - if (fsync(data->fd) == -1) { - index_set_error(data->index, "fsync() failed for %s: %m", - data->filepath); + if (fsync(data->fd) < 0) { + index_data_set_syscall_error(data, "fsync()"); return FALSE; } @@ -295,14 +307,13 @@ if (index_rec->data_position > data->mmap_length || (data->mmap_length - index_rec->data_position < index_rec->data_size)) { - INDEX_MARK_CORRUPTED(data->index); - index_set_error(data->index, "Error in data file %s: " - "Given data size larger than file size " - "(%"PRIuUOFF_T" + %u > %"PRIuSIZE_T") " - "for record %u", - data->filepath, index_rec->data_position, - index_rec->data_size, data->mmap_length, - index_rec->uid); + index_data_set_corrupted(data, "Given data size larger than " + "file size (%"PRIuUOFF_T + " + %u > %"PRIuSIZE_T") for record %u", + index_rec->data_position, + index_rec->data_size, + data->mmap_length, + index_rec->uid); return NULL; } @@ -317,11 +328,10 @@ this as it won't crash and is quite likely noticed later. */ if (pos + sizeof(MailIndexDataRecord) > max_pos || pos + DATA_RECORD_SIZE(rec) > max_pos) { - INDEX_MARK_CORRUPTED(data->index); - index_set_error(data->index, "Error in data file %s: " - "Field size points outside file " - "(%"PRIuUOFF_T" / %"PRIuUOFF_T")", - data->filepath, pos, max_pos); + index_data_set_corrupted(data, "Field size points " + "outside file (%"PRIuUOFF_T + " / %"PRIuUOFF_T")", + pos, max_pos); break; } @@ -361,12 +371,9 @@ rec = (MailIndexDataRecord *) ((char *) data->mmap_base + pos); end_pos = pos + DATA_RECORD_SIZE(rec); if (end_pos < pos || end_pos > max_pos) { - INDEX_MARK_CORRUPTED(data->index); - index_set_error(data->index, "Error in data file %s: " - "Field size points outside file " - "(%"PRIuUOFF_T" + %u > %"PRIuUOFF_T")", - data->filepath, pos, rec->full_field_size, - max_pos); + index_data_set_corrupted(data, "Field size points outside file " + "(%"PRIuUOFF_T" + %u > %"PRIuUOFF_T")", + pos, rec->full_field_size, max_pos); return NULL; } @@ -380,9 +387,8 @@ if (rec->full_field_size > INT_MAX) { /* we already check that the full_field_size is within file, so this can happen only if the file really is huge.. */ - INDEX_MARK_CORRUPTED(data->index); - index_set_error(data->index, "Error in data file %s: " - "full_field_size > INT_MAX", data->filepath); + index_data_set_corrupted(data, "full_field_size (%u) > INT_MAX", + rec->full_field_size); return FALSE; } @@ -394,11 +400,9 @@ } } - INDEX_MARK_CORRUPTED(data->index); - index_set_error(data->index, "Error in data file %s: " - "Missing \\0 with field %u (%"PRIuUOFF_T")", - data->filepath, rec->field, - DATA_FILE_POSITION(data, rec)); + index_data_set_corrupted(data, "Missing \\0 with field %u " + "(%"PRIuUOFF_T")", rec->field, + DATA_FILE_POSITION(data, rec)); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index-data.h --- a/src/lib-index/mail-index-data.h Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index-data.h Fri Sep 13 03:01:23 2002 +0300 @@ -43,4 +43,8 @@ /* Return the whole data file mmap()ed. */ void *mail_index_data_get_mmaped(MailIndexData *data, size_t *size); +/* "Error in index data file %s: ...". Also marks the index file as + corrupted. */ +void index_data_set_corrupted(MailIndexData *data, const char *fmt, ...); + #endif diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index-update.c --- a/src/lib-index/mail-index-update.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index-update.c Fri Sep 13 03:01:23 2002 +0300 @@ -134,10 +134,8 @@ if (max_size > INT_MAX) { /* rec->data_size most likely corrupted */ - index_set_error(update->index, "Error in index file %s: " - "data_size points outside file", - update->index->filepath); - update->index->header->flags |= MAIL_INDEX_FLAG_REBUILD; + index_set_corrupted(update->index, + "data_size points outside file"); return FALSE; } @@ -171,13 +169,11 @@ if (src_size > max_size || max_size - src_size < pos) { /* corrupted data file - old value had a field larger than expected */ - index_set_error(update->index, - "Error in index file %s: " - "full_field_size points outside " - "data_size (field %d?)", - update->index->filepath, - rec == NULL ? -1 : (int)rec->field); - update->index->header->flags |= MAIL_INDEX_FLAG_REBUILD; + index_set_corrupted(update->index, + "full_field_size points outside " + "data_size (field %d?)", + update->index->filepath, + rec == NULL ? -1 : (int)rec->field); return FALSE; } memcpy(destrec->data, src, src_size); @@ -418,10 +414,9 @@ part = message_part_deserialize(pool, value, size); if (part == NULL) { /* corrupted, rebuild it */ - index_set_error(update->index, "Error in index " - "file %s: Corrupted cached " - "MessagePart data", - update->index->filepath); + index_set_corrupted(update->index, + "Corrupted cached " + "MessagePart data"); } } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index-util.c --- a/src/lib-index/mail-index-util.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index-util.c Fri Sep 13 03:01:23 2002 +0300 @@ -28,6 +28,29 @@ } } +void index_set_corrupted(MailIndex *index, const char *fmt, ...) +{ + va_list va; + + INDEX_MARK_CORRUPTED(index); + index->inconsistent = TRUE; + + va_start(va, fmt); + t_push(); + index_set_error(index, "Corrupted index file %s: %s", + index->filepath, t_strdup_vprintf(fmt, va)); + t_pop(); + va_end(va); +} + +void index_set_syscall_error(MailIndex *index, const char *function) +{ + i_assert(function != NULL); + + index_set_error(index, "%s failed with index file %s: %m", + function, index->filepath); +} + void index_reset_error(MailIndex *index) { if (index->error != NULL) { diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index-util.h --- a/src/lib-index/mail-index-util.h Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index-util.h Fri Sep 13 03:01:23 2002 +0300 @@ -5,6 +5,12 @@ void index_set_error(MailIndex *index, const char *fmt, ...) __attr_format__(2, 3); +/* "Error in index file %s: ...". Also marks the index file as corrupted. */ +void index_set_corrupted(MailIndex *index, const char *fmt, ...); + +/* "%s failed with index file %s: %m" */ +void index_set_syscall_error(MailIndex *index, const char *function); + /* Reset the current error */ void index_reset_error(MailIndex *index); diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-index.c --- a/src/lib-index/mail-index.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-index.c Fri Sep 13 03:01:23 2002 +0300 @@ -40,15 +40,12 @@ index->mmap_base = mmap_rw_file(index->fd, &index->mmap_length); if (index->mmap_base == MAP_FAILED) { index->mmap_base = NULL; - index_set_error(index, "index: mmap() failed with file %s: %m", - index->filepath); + index_set_syscall_error(index, "mmap()"); return FALSE; } if (index->mmap_length < sizeof(MailIndexHeader)) { - index_set_error(index, "truncated index file %s", - index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "File too small"); return FALSE; } @@ -134,9 +131,8 @@ return FALSE; if (index->mmap_base != NULL) { - if (msync(index->mmap_base, index->mmap_length, MS_SYNC) == -1) { - index_set_error(index, "msync() failed for %s: %m", - index->filepath); + if (msync(index->mmap_base, index->mmap_length, MS_SYNC) < 0) { + index_set_syscall_error(index, "msync()"); return FALSE; } } @@ -151,15 +147,13 @@ /* keep index's modify stamp same as the sync file's stamp */ ut.actime = ioloop_time; ut.modtime = index->file_sync_stamp; - if (utime(index->filepath, &ut) == -1) { - index_set_error(index, "utime() failed for %s: %m", - index->filepath); + if (utime(index->filepath, &ut) < 0) { + index_set_syscall_error(index, "utime()"); return FALSE; } - if (fsync(index->fd) == -1) { - index_set_error(index, "fsync() failed for %s: %m", - index->filepath); + if (fsync(index->fd) < 0) { + index_set_syscall_error(index, "fsync()"); return FALSE; } @@ -170,14 +164,12 @@ { i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE); - if (msync(index->mmap_base, size, MS_SYNC) == -1) { - index_set_error(index, "msync() failed for %s: %m", - index->filepath); + if (msync(index->mmap_base, size, MS_SYNC) < 0) { + index_set_syscall_error(index, "msync()"); return FALSE; } - if (fsync(index->fd) == -1) { - index_set_error(index, "fsync() failed for %s: %m", - index->filepath); + if (fsync(index->fd) < 0) { + index_set_syscall_error(index, "fsync()"); return FALSE; } @@ -227,12 +219,9 @@ fl.l_start = 0; fl.l_len = 0; - if (fcntl(index->fd, F_SETLK, &fl) == -1) { - if (errno != EINTR && errno != EACCES) { - index_set_error(index, "fcntl(F_SETLKW, %d) " - "failed for file %s: %m", fl.l_type, - index->filepath); - } + if (fcntl(index->fd, F_SETLK, &fl) < 0) { + if (errno != EINTR && errno != EACCES) + index_set_syscall_error(index, "fcntl(F_SETLK)"); return FALSE; } @@ -249,7 +238,7 @@ if (index->inconsistent) { /* index is in inconsistent state and nothing else than - free() is allowed for it. */ + free() is allowed for it. FIXME: what about msync()ing.. */ return FALSE; } @@ -287,11 +276,9 @@ fl.l_start = 0; fl.l_len = 0; - while (fcntl(index->fd, F_SETLKW, &fl) == -1) { + while (fcntl(index->fd, F_SETLKW, &fl) < 0) { if (errno != EINTR) { - index_set_error(index, "fcntl(F_SETLKW, %d) " - "failed for file %s: %m", fl.l_type, - index->filepath); + index_set_syscall_error(index, "fcntl(F_SETLKW)"); return FALSE; } } @@ -692,7 +679,7 @@ "-%s", my_hostname); } - if (rename(path, index_path) == -1) { + if (rename(path, index_path) < 0) { index_set_error(index, "rename(%s, %s) failed: %m", path, index_path); (void)close(fd); @@ -817,19 +804,15 @@ if (hdr->first_hole_position < sizeof(MailIndexHeader) || (hdr->first_hole_position - sizeof(MailIndexHeader)) % sizeof(MailIndexRecord) != 0) { - index_set_error(index, "Error in index file %s: " - "first_hole_position contains invalid value", - index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "first_hole_position contains " + "invalid value"); return FALSE; } /* make sure position is in range.. */ if (hdr->first_hole_position >= index->mmap_length) { - index_set_error(index, "Error in index file %s: " - "first_hole_position points outside file", - index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "first_hole_position points " + "outside file"); return FALSE; } @@ -839,10 +822,8 @@ sizeof(MailIndexHeader)) / sizeof(MailIndexRecord); if (index->header->first_hole_records > max_records || first_records + index->header->first_hole_records > max_records) { - index_set_error(index, "Error in index file %s: " - "first_hole_records points outside file", - index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "first_hole_records points " + "outside file"); return FALSE; } @@ -885,10 +866,8 @@ "isn't mmap()ed (dirty_mmap not properly set)"); } - index_set_error(index, "Error in index file %s: " - "Header contains invalid message count", - index->filepath); - index->set_flags |= MAIL_INDEX_FLAG_FSCK; + index_set_corrupted(index, + "Header contains invalid message count"); return NULL; } @@ -905,10 +884,8 @@ i_assert(rec <= last_rec); if (rec->uid == 0) { - index_set_error(index, "Error in index file %s: " - "first_hole_position wasn't updated " - "properly", index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "first_hole_position " + "wasn't updated properly"); return NULL; } return rec; @@ -1093,10 +1070,8 @@ datarec = mail_index_data_lookup(index->data, rec, field); if (datarec == NULL) { /* corrupted, the field should have been there */ - index_set_error(index, "Error in index file %s: " - "Field not found from data file", - index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "Field %u not found from data file " + "for record %u", field, rec->uid); return NULL; } @@ -1192,10 +1167,12 @@ } else if (rec->uid < index->header->first_unseen_uid_lowwater) index->header->first_unseen_uid_lowwater = rec->uid; - if (index->header->seen_messages_count == 0) - INDEX_MARK_CORRUPTED(index); - else + if (index->header->seen_messages_count == 0) { + index_set_corrupted(index, "seen_messages_count in " + "header is invalid"); + } else { index->header->seen_messages_count--; + } } if ((old_flags & MAIL_DELETED) == 0 && @@ -1211,10 +1188,12 @@ } else if ((old_flags & MAIL_DELETED) && (new_flags & MAIL_DELETED) == 0) { /* deleted -> undeleted */ - if (index->header->deleted_messages_count == 0) - INDEX_MARK_CORRUPTED(index); - else + if (index->header->deleted_messages_count == 0) { + index_set_corrupted(index, "deleted_messages_count in " + "header is invalid"); + } else { index->header->deleted_messages_count--; + } } } @@ -1241,8 +1220,7 @@ /* truncate index file */ file_size = (off_t)index->header->first_hole_position; if (ftruncate(index->fd, file_size) < 0) { - index_set_error(index, "ftruncate() failed for index file " - "%s: %m", index->filepath); + index_set_syscall_error(index, "ftruncate()"); return FALSE; } @@ -1335,10 +1313,8 @@ /* update message counts */ if (hdr->messages_count == 0) { /* corrupted */ - index_set_error(index, "Error in index file %s: " - "Header says there's no mail while expunging", - index->filepath); - INDEX_MARK_CORRUPTED(index); + index_set_corrupted(index, "Header says there's no mail " + "while expunging"); return FALSE; } @@ -1385,14 +1361,12 @@ pos = lseek(index->fd, 0, SEEK_END); if (pos < 0) { - index_set_error(index, "lseek() failed with file %s: %m", - index->filepath); + index_set_syscall_error(index, "lseek()"); return FALSE; } if (write_full(index->fd, *rec, sizeof(MailIndexRecord)) < 0) { - index_set_error(index, "Error appending to file %s: %m", - index->filepath); + index_set_syscall_error(index, "write_full()"); return FALSE; } @@ -1404,9 +1378,8 @@ index->header->sync_id++; index->dirty_mmap = TRUE; - if (msync(index->mmap_base, sizeof(MailIndexHeader), MS_SYNC) == -1) { - index_set_error(index, "msync() failed for %s: %m", - index->filepath); + if (msync(index->mmap_base, sizeof(MailIndexHeader), MS_SYNC) < 0) { + index_set_syscall_error(index, "msync()"); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mail-modifylog.c --- a/src/lib-index/mail-modifylog.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mail-modifylog.c Fri Sep 13 03:01:23 2002 +0300 @@ -34,6 +34,25 @@ unsigned int second_log:1; }; +static void modifylog_set_syscall_error(MailModifyLog *log, + const char *function) +{ + i_assert(function != NULL); + + index_set_error(log->index, "%s failed with modify log file %s: %m", + function, log->filepath); +} + +static void modifylog_set_corrupted(MailModifyLog *log) +{ + index_set_error(log->index, "Modify log %s is corrupted", + log->filepath); + + /* make sure we don't get back here */ + log->index->inconsistent = TRUE; + (void)unlink(log->filepath); +} + static int file_lock(int fd, int wait_lock, int lock_type) { struct flock fl; @@ -58,21 +77,16 @@ int ret; ret = file_lock(log->fd, FALSE, lock_type); - if (ret == -1) { - index_set_error(log->index, "fcntl() failed with file %s: %m", - log->filepath); - } + if (ret == -1) + modifylog_set_syscall_error(log, "fcntl(F_SETLK)"); return ret; } static int mail_modifylog_wait_lock(MailModifyLog *log) { - if (file_lock(log->fd, TRUE, F_RDLCK) < 1) { - index_set_error(log->index, "fcntl() failed with file %s: %m", - log->filepath); - return FALSE; - } + if (file_lock(log->fd, TRUE, F_RDLCK) < 1) + modifylog_set_syscall_error(log, "fcntl(F_SETLKW)"); return TRUE; } @@ -115,9 +129,7 @@ if (log->mmap_base == MAP_FAILED) { log->mmap_base = NULL; log->header = NULL; - index_set_error(log->index, - "modify log: mmap() failed with file %s: %m", - log->filepath); + modifylog_set_syscall_error(log, "mmap()"); return FALSE; } @@ -188,7 +200,7 @@ return FALSE; } - if (ftruncate(fd, sizeof(hdr)) == -1) { + if (ftruncate(fd, sizeof(hdr)) < 0) { index_set_error(log->index, "ftruncate() failed for modify " "log %s: %m", path); return FALSE; @@ -364,16 +376,14 @@ return TRUE; if (log->mmap_base != NULL) { - if (msync(log->mmap_base, log->mmap_length, MS_SYNC) == -1) { - index_set_error(log->index, "msync() failed for %s: %m", - log->filepath); + if (msync(log->mmap_base, log->mmap_length, MS_SYNC) < 0) { + modifylog_set_syscall_error(log, "msync()"); return FALSE; } } - if (fsync(log->fd) == -1) { - index_set_error(log->index, "fsync() failed for %s: %m", - log->filepath); + if (fsync(log->fd) < 0) { + modifylog_set_syscall_error(log, "fsync()"); return FALSE; } @@ -399,15 +409,13 @@ } } - if (lseek(log->fd, 0, SEEK_END) == -1) { - index_set_error(log->index, "lseek() failed with file %s: %m", - log->filepath); + if (lseek(log->fd, 0, SEEK_END) < 0) { + modifylog_set_syscall_error(log, "lseek()"); return FALSE; } if (write_full(log->fd, rec, sizeof(ModifyLogRecord)) < 0) { - index_set_error(log->index, "Error appending to file %s: %m", - log->filepath); + modifylog_set_syscall_error(log, "write_full()"); return FALSE; } @@ -597,9 +605,7 @@ if (max_records-- == 0) { /* log contains more data than it should have - must be corrupted. */ - index_set_error(log->index, - "Modify log %s is corrupted", - log->filepath); + modifylog_set_corrupted(log); return NULL; } @@ -669,9 +675,7 @@ if (max_records-- == 0) { /* log contains more data than it should have - must be corrupted. */ - index_set_error(log->index, - "Modify log %s is corrupted", - log->filepath); + modifylog_set_corrupted(log); return NULL; } *arr++ = rec->uid; diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/maildir/maildir-build.c --- a/src/lib-index/maildir/maildir-build.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/maildir/maildir-build.c Fri Sep 13 03:01:23 2002 +0300 @@ -39,7 +39,7 @@ /* check that file size is somewhat reasonable */ if (fstat(fd, &st) == -1) { - index_set_error(index, "fstat() failed with file %s: %m", path); + index_set_error(index, "fstat() failed for file %s: %m", path); return FALSE; } @@ -123,7 +123,7 @@ dirp = opendir(source_dir); if (dirp == NULL) { - index_set_error(index, "Couldn't build index from %s: %m", + index_set_error(index, "opendir() failed for dir %s: %m", source_dir); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/maildir/maildir-index.c --- a/src/lib-index/maildir/maildir-index.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/maildir/maildir-index.c Fri Sep 13 03:01:23 2002 +0300 @@ -166,10 +166,8 @@ /* we need to update the flags in the file name */ old_fname = index->lookup_field(index, rec, FIELD_TYPE_LOCATION); if (old_fname == NULL) { - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Corrupted index file %s: " - "Missing location field for record %u", - index->filepath, rec->uid); + index_data_set_corrupted(index, "Missing location field for " + "record %u", rec->uid); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/maildir/maildir-open.c --- a/src/lib-index/maildir/maildir-open.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/maildir/maildir-open.c Fri Sep 13 03:01:23 2002 +0300 @@ -15,10 +15,8 @@ fname = index->lookup_field(index, rec, FIELD_TYPE_LOCATION); if (fname == NULL) { - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Corrupted index file %s: " - "Missing location field for record %u", - index->filepath, rec->uid); + index_data_set_corrupted(index, "Missing location field for " + "record %u", rec->uid); return NULL; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/maildir/maildir-rebuild.c --- a/src/lib-index/maildir/maildir-rebuild.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/maildir/maildir-rebuild.c Fri Sep 13 03:01:23 2002 +0300 @@ -32,8 +32,7 @@ /* truncate the file first, so it won't contain any invalid data even if we crash */ if (ftruncate(index->fd, sizeof(MailIndexHeader)) == -1) { - index_set_error(index, "Can't truncate index file %s: %m", - index->filepath); + index_set_syscall_error(index, "ftruncate()"); return FALSE; } @@ -53,7 +52,7 @@ /* update sync stamp */ if (stat(cur_dir, &st) == -1) { - index_set_error(index, "fstat() failed for maildir %s: %m", + index_set_error(index, "stat() failed for maildir %s: %m", cur_dir); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/maildir/maildir-sync.c --- a/src/lib-index/maildir/maildir-sync.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/maildir/maildir-sync.c Fri Sep 13 03:01:23 2002 +0300 @@ -4,6 +4,7 @@ #include "ioloop.h" #include "hash.h" #include "maildir-index.h" +#include "mail-index-data.h" #include "mail-index-util.h" #include @@ -37,7 +38,7 @@ /* file itself changed - reload the header */ fd = open(path, O_RDONLY); if (fd == -1) { - index_set_error(index, "Error opening file %s: %m", + index_set_error(index, "open() failed for file %s: %m", path); failed = TRUE; } else { @@ -77,10 +78,9 @@ for (seq = 1; rec != NULL; rec = index->next(index, rec), seq++) { fname = index->lookup_field(index, rec, FIELD_TYPE_LOCATION); if (fname == NULL) { - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Corrupted index file %s: " - "Missing location field for record %u", - index->filepath, rec->uid); + index_data_set_corrupted(index->data, + "Missing location field for " + "record %u", rec->uid); return FALSE; } @@ -109,7 +109,7 @@ file_changed = FALSE; else { if (stat(str, &st) == -1) { - index_set_error(index, "stat() failed with " + index_set_error(index, "stat() failed for " "file %s: %m", str); return FALSE; } @@ -181,10 +181,8 @@ return FALSE; if (index->header->messages_count >= INT_MAX/32) { - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Corrupted index file %s: Header " - "says %u messages", index->filepath, - index->header->messages_count); + index_set_corrupted(index, "Header says %u messages", + index->header->messages_count); return FALSE; } @@ -195,7 +193,7 @@ files which will be added then. */ dirp = opendir(dir); if (dirp == NULL) { - index_set_error(index, "Couldn't sync index in dir %s: %m", + index_set_error(index, "opendir() failed for dir %s: %m", dir); return FALSE; } @@ -247,8 +245,7 @@ i_assert(index->lock_type != MAIL_LOCK_SHARED); if (fstat(index->fd, &sti) == -1) { - index_set_error(index, "fstat() failed with index file %s: %m", - index->filepath); + index_set_syscall_error(index, "fstat()"); return FALSE; } @@ -257,7 +254,7 @@ mail. */ cur_dir = t_strconcat(index->dir, "/cur", NULL); if (stat(cur_dir, &std) == -1) { - index_set_error(index, "fstat() failed for maildir %s: %m", + index_set_error(index, "stat() failed for maildir %s: %m", cur_dir); return FALSE; } @@ -270,7 +267,7 @@ /* move mail from new/ to cur/ */ new_dir = t_strconcat(index->dir, "/new", NULL); if (stat(new_dir, &std) == -1) { - index_set_error(index, "fstat() failed for maildir " + index_set_error(index, "stat() failed for maildir " "%s: %m", new_dir); return FALSE; } @@ -305,7 +302,7 @@ /* update sync stamp */ if (stat(cur_dir, &std) == -1) { - index_set_error(index, "fstat() failed for maildir %s: %m", + index_set_error(index, "stat() failed for maildir %s: %m", cur_dir); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-fsck.c --- a/src/lib-index/mbox/mbox-fsck.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-fsck.c Fri Sep 13 03:01:23 2002 +0300 @@ -271,8 +271,7 @@ but fcntl() locking requires it. */ fd = open(index->mbox_path, O_RDWR); if (fd == -1) { - index_set_error(index, "Can't open mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "open()"); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-index.c --- a/src/lib-index/mbox/mbox-index.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.c Fri Sep 13 03:01:23 2002 +0300 @@ -5,10 +5,19 @@ #include "rfc822-tokenize.h" #include "mbox-index.h" #include "mail-index-util.h" +#include "mail-index-data.h" #include "mail-custom-flags.h" static MailIndex mbox_index; +void mbox_set_syscall_error(MailIndex *index, const char *function) +{ + i_assert(function != NULL); + + index_set_error(index, "%s failed with mbox file %s: %m", + function, index->mbox_path); +} + void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index) { memset(ctx, 0, sizeof(MboxHeaderContext)); @@ -300,17 +309,13 @@ location = index->lookup_field_raw(index, rec, FIELD_TYPE_LOCATION, &size); if (location == NULL) { - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Corrupted index file %s: " - "Missing location field for record %u", - index->filepath, rec->uid); + index_data_set_corrupted(index->data, "Missing location field " + "for record %u", rec->uid); *offset = 0; return FALSE; } else if (size != sizeof(uoff_t) || *location > OFF_T_MAX) { - INDEX_MARK_CORRUPTED(index); - index_set_error(index, "Corrupted index file %s: " - "Invalid location field for record %u", - index->filepath, rec->uid); + index_data_set_corrupted(index->data, "Invalid location field " + "for record %u", rec->uid); *offset = 0; return FALSE; } else { diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-index.h --- a/src/lib-index/mbox/mbox-index.h Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.h Fri Sep 13 03:01:23 2002 +0300 @@ -12,7 +12,7 @@ int received; } MboxHeaderContext; -MailIndex *mbox_index_alloc(const char *dir, const char *mbox_path); +void mbox_set_syscall_error(MailIndex *index, const char *function);; void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index); void mbox_header_free_context(MboxHeaderContext *ctx); @@ -28,6 +28,7 @@ int mbox_mail_get_start_offset(MailIndex *index, MailIndexRecord *rec, uoff_t *offset); +MailIndex *mbox_index_alloc(const char *dir, const char *mbox_path); int mbox_index_rebuild(MailIndex *index); int mbox_index_sync(MailIndex *index); int mbox_index_fsck(MailIndex *index); diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-open.c --- a/src/lib-index/mbox/mbox-open.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-open.c Fri Sep 13 03:01:23 2002 +0300 @@ -25,15 +25,13 @@ fd = open(index->mbox_path, O_RDONLY); if (fd == -1) { - index_set_error(index, "Can't open mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "open()"); return NULL; } pos = lseek(fd, (off_t)offset, SEEK_SET); if (pos == -1) { - index_set_error(index, "lseek() failed with mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "lseek()"); (void)close(fd); return NULL; } @@ -73,8 +71,7 @@ if (!failed) { if (lseek(fd, (off_t)offset, SEEK_SET) < 0) { - index_set_error(index, "lseek() failed with mbox file " - "%s: %m", index->mbox_path); + mbox_set_syscall_error(index, "lseek()"); failed = TRUE; } } else { diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-rebuild.c --- a/src/lib-index/mbox/mbox-rebuild.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-rebuild.c Fri Sep 13 03:01:23 2002 +0300 @@ -33,17 +33,15 @@ /* update indexid */ index->indexid = index->header->indexid; - if (msync(index->mmap_base, sizeof(MailIndexHeader), MS_SYNC) == -1) { - index_set_error(index, "msync() failed for index file %s: %m", - index->filepath); + if (msync(index->mmap_base, sizeof(MailIndexHeader), MS_SYNC) < 0) { + index_set_syscall_error(index, "msync()"); return FALSE; } /* truncate the file first, so it won't contain any invalid data even if we crash */ - if (ftruncate(index->fd, sizeof(MailIndexHeader)) == -1) { - index_set_error(index, "Can't truncate index file %s: %m", - index->filepath); + if (ftruncate(index->fd, sizeof(MailIndexHeader)) < 0) { + index_set_syscall_error(index, "ftruncate()"); return FALSE; } @@ -55,8 +53,7 @@ but fcntl() locking requires it. */ fd = open(index->mbox_path, O_RDWR); if (fd == -1) { - index_set_error(index, "Error opening mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "open()"); return FALSE; } @@ -80,8 +77,7 @@ /* update sync stamp */ if (stat(index->mbox_path, &st) == -1) { - index_set_error(index, "fstat() failed for mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "fstat()"); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-rewrite.c --- a/src/lib-index/mbox/mbox-rewrite.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-rewrite.c Fri Sep 13 03:01:23 2002 +0300 @@ -168,8 +168,7 @@ if (inbuf->offset >= end_offset) { /* fsck should have noticed it.. */ index_set_error(index, "Error rewriting mbox file %s: " - "Unexpected end of file", - index->mbox_path); + "Unexpected end of file", index->mbox_path); return FALSE; } @@ -269,10 +268,8 @@ MailIndexRecord *rec; IOBuffer *inbuf, *outbuf; uoff_t offset; - const uoff_t *location; const char *path; unsigned int seq; - size_t size; int in_fd, out_fd, failed; i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE); @@ -287,8 +284,7 @@ in_fd = open(index->mbox_path, O_RDWR); if (in_fd == -1) { - index_set_error(index, "Can't open mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "open()"); return FALSE; } inbuf = io_buffer_create_mmap(in_fd, default_pool, @@ -305,22 +301,14 @@ rec = index->lookup(index, 1); while (rec != NULL) { /* get offset to beginning of mail headers */ - location = index->lookup_field_raw(index, rec, - FIELD_TYPE_LOCATION, &size); - if (size != sizeof(uoff_t) || *location <= inbuf->offset) { + if (!mbox_mail_get_start_offset(index, rec, &offset)) { /* fsck should have fixed it */ - index_set_error(index, "Error rewriting mbox file %s: " - "Invalid location field in index", - index->mbox_path); failed = TRUE; break; } - offset = *location; if (offset + rec->header_size + rec->body_size > inbuf->size) { - index_set_error(index, "Error rewriting mbox file %s: " - "Invalid message size in index", - index->mbox_path); + index_set_corrupted(index, "Invalid message size"); failed = TRUE; break; } @@ -354,8 +342,7 @@ (void)io_buffer_send(outbuf, "\n", 1); if (outbuf->closed) { errno = outbuf->buf_errno; - index_set_error(index, "Error rewriting mbox file %s: " - "write() failed: %m", index->mbox_path); + mbox_set_syscall_error(index, "write()"); failed = TRUE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-index/mbox/mbox-sync.c --- a/src/lib-index/mbox/mbox-sync.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-index/mbox/mbox-sync.c Fri Sep 13 03:01:23 2002 +0300 @@ -60,8 +60,7 @@ i_assert(index->lock_type != MAIL_LOCK_SHARED); if (stat(index->mbox_path, &st) == -1) { - index_set_error(index, "stat() failed with mbox file %s: %m", - index->mbox_path); + mbox_set_syscall_error(index, "stat()"); return FALSE; } diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib-storage/index/index-status.c --- a/src/lib-storage/index/index-status.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib-storage/index/index-status.c Fri Sep 13 03:01:23 2002 +0300 @@ -52,8 +52,8 @@ rec = index->lookup_uid_range(index, lowwater_uid, hdr->next_uid - 1); if (rec == NULL) { - i_warning("index header's seen_messages_count or " - "first_unseen_uid_lowwater is invalid."); + i_error("index header's seen_messages_count or " + "first_unseen_uid_lowwater is invalid."); INDEX_MARK_CORRUPTED(index); return 0; } else { diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib/Makefile.am --- a/src/lib/Makefile.am Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib/Makefile.am Fri Sep 13 03:01:23 2002 +0300 @@ -15,6 +15,7 @@ compat.c \ failures.c \ fdpass.c \ + file-set-size.c \ gmtoff.c \ hash.c \ hex-binary.c \ @@ -47,6 +48,7 @@ compat.h \ failures.h \ fdpass.h \ + file-set-size.h \ gmtoff.h \ hash.h \ hex-binary.h \ diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib/file-set-size.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/file-set-size.c Fri Sep 13 03:01:23 2002 +0300 @@ -0,0 +1,71 @@ +/* + file-set-size.c - portable way to grow/shrink file size + + Copyright (c) 2002 Timo Sirainen + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "lib.h" +#include "write-full.h" + +#include + +int file_set_size(int fd, off_t size) +{ + char block[1024]; + int ret, old_errno; + off_t pos; + + i_assert(size >= 0); + + /* try truncating it to the size we want. if this succeeds, the written + area is full of zeros - exactly what we want. however, this may not + work at all, in which case we fallback to write()ing the zeros. */ + ret = ftruncate(fd, size); + old_errno = errno; + + pos = lseek(fd, 0, SEEK_END); + if (ret != -1 && pos == size) + return lseek(fd, 0, SEEK_SET) < 0 ? -1 : 0; + + if (pos < 0) + return -1; + if (pos > size) { + /* ftruncate() failed for some reason, even while we were + trying to make the file smaller */ + errno = old_errno; + return -1; + } + + /* start growing the file */ + size -= pos; + memset(block, 0, sizeof(block)); + + while ((uoff_t)size > sizeof(block)) { + /* write in 1kb blocks */ + if (write_full(fd, block, sizeof(block)) < 0) + return -1; + size -= sizeof(block); + } + + /* write the remainder */ + return write_full(fd, block, (size_t)size) < 0 ? -1 : 0; +} diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib/file-set-size.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/file-set-size.h Fri Sep 13 03:01:23 2002 +0300 @@ -0,0 +1,8 @@ +#ifndef __FILE_SET_SIZE_H +#define __FILE_SET_SIZE_H + +/* Shrink/grow file. If file is grown, the new data is guaranteed to + be zeros. Returns -1 if failed, 0 if successful. */ +int file_set_size(int fd, off_t size); + +#endif diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib/mmap-util.c --- a/src/lib/mmap-util.c Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib/mmap-util.c Fri Sep 13 03:01:23 2002 +0300 @@ -26,6 +26,10 @@ #include "lib.h" #include "mmap-util.h" +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +#endif + static void *mmap_file(int fd, size_t *length, int access) { off_t size; @@ -81,6 +85,12 @@ return mmap_base; } +void *mmap_anonymous(size_t length) +{ + return mmap(NULL, length, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +} + #ifndef HAVE_MADVISE int madvise(void *start, size_t length, int advice) { diff -r 94382d79ae47 -r ed0d5b17c7a4 src/lib/mmap-util.h --- a/src/lib/mmap-util.h Fri Sep 13 02:09:45 2002 +0300 +++ b/src/lib/mmap-util.h Fri Sep 13 03:01:23 2002 +0300 @@ -21,4 +21,6 @@ void *mmap_aligned(int fd, int access, off_t offset, size_t length, void **data_start, size_t *mmap_length); +void *mmap_anonymous(size_t length); + #endif