Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-index/mbox/mbox-append.c @ 1882:01a83df6c232 HEAD
Fixed "LF not found where expected" error happening in some conditions.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 11 Nov 2003 18:36:59 +0200 |
parents | 9bbe17257bba |
children |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "ioloop.h" #include "istream.h" #include "hex-binary.h" #include "md5.h" #include "mbox-index.h" #include "mail-index-util.h" #include "mail-cache.h" static int mbox_index_append_next(struct mail_index *index, struct mail_cache_transaction_ctx *trans_ctx, struct istream *input) { struct mail_index_record *rec; struct mbox_header_context ctx; struct istream *hdr_stream; enum mail_index_record_flag index_flags; time_t received_date; uoff_t hdr_offset, body_offset, end_offset; const unsigned char *data; unsigned char md5_digest[16]; size_t size, pos; int dirty, save_md5 = FALSE; /* get the From-line */ pos = 0; while (i_stream_read_data(input, &data, &size, pos) > 0) { for (; pos < size; pos++) { if (data[pos] == '\n') break; } if (pos < size) break; } if (size == 0) return -2; if (pos == size || size <= 5 || memcmp(data, "From ", 5) != 0) { /* a) no \n found, or line too long b) not a From-line */ index_set_error(index, "Error indexing mbox file %s: " "From-line not found where expected", index->mailbox_path); index->set_flags |= MAIL_INDEX_HDR_FLAG_FSCK; return -1; } /* parse the From-line */ received_date = mbox_from_parse_date(data + 5, size - 5); if (received_date == (time_t)-1) received_date = ioloop_time; i_stream_skip(input, pos+1); hdr_offset = input->v_offset; /* now, find the end of header. also stops at "\nFrom " if it's found (broken messages) */ mbox_skip_header(input); body_offset = input->v_offset; index_flags = 0; /* parse the header and cache wanted fields. get the message flags from Status and X-Status fields. temporarily limit the stream length so the message body is parsed properly. the stream length limit is raised again by mbox_header_cb after reading the headers. it uses Content-Length if available or finds the next From-line. */ mbox_header_init_context(&ctx, index, input); hdr_stream = i_stream_create_limit(default_pool, input, hdr_offset, body_offset - hdr_offset); i_stream_seek(hdr_stream, 0); message_parse_header(NULL, hdr_stream, NULL, mbox_header_cb, &ctx); i_stream_unref(hdr_stream); dirty = FALSE; /* try Content-Length */ end_offset = body_offset + ctx.content_length; if (ctx.content_length == (uoff_t)-1 || !mbox_verify_end_of_body(input, end_offset)) { /* failed, search for From-line */ if (ctx.content_length != (uoff_t)-1) { /* broken, rewrite it */ dirty = TRUE; } i_stream_seek(input, body_offset); mbox_skip_message(input); ctx.content_length = input->v_offset - body_offset; } if (index->header->messages_count == 0 && ctx.uid_validity != index->header->uid_validity) { /* UID validity is different */ if (ctx.uid_validity != 0) { /* change it in index */ index->header->uid_validity = ctx.uid_validity; index->header->next_uid = 1; index->header->last_nonrecent_uid = 0; index->inconsistent = TRUE; } else if (!index->mailbox_readonly) { /* we have to write it to mbox */ if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) { /* try again */ return 0; } dirty = TRUE; } } if (ctx.uid >= index->header->next_uid) { /* X-UID header looks ok */ index->header->next_uid = ctx.uid; } else if (!index->mailbox_readonly) { /* Write X-UID for it */ dirty = TRUE; } else { /* save MD5 */ save_md5 = TRUE; } if (dirty && !index->mailbox_readonly) { if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) { /* try again */ return 0; } index->header->flags |= MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES; index_flags |= MAIL_INDEX_FLAG_DIRTY; } /* add message to index */ rec = index->append(index); if (rec == NULL) return -1; /* save message flags */ rec->msg_flags = ctx.flags; mail_index_mark_flag_changes(index, rec, 0, rec->msg_flags); if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_INDEX_FLAGS, &index_flags, sizeof(index_flags))) return -1; /* location offset = beginning of headers in message */ if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_LOCATION_OFFSET, &hdr_offset, sizeof(hdr_offset))) return -1; if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_RECEIVED_DATE, &received_date, sizeof(received_date))) return -1; if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_PHYSICAL_BODY_SIZE, &ctx.content_length, sizeof(ctx.content_length))) return -1; if (save_md5) { md5_final(&ctx.md5, md5_digest); if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_MD5, md5_digest, sizeof(md5_digest))) return -1; } return 1; } int mbox_index_append_stream(struct mail_index *index, struct istream *input) { struct mail_cache_transaction_ctx *trans_ctx; uoff_t offset; int ret; if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE)) return -1; if (mail_cache_transaction_begin(index->cache, TRUE, &trans_ctx) <= 0) return -1; do { offset = input->v_offset; if (input->v_offset != 0) { /* we're at the [\r]\n before the From-line, skip it */ if (!mbox_skip_crlf(input)) { index_set_error(index, "Error indexing mbox file %s: " "LF not found where expected", index->mailbox_path); index->set_flags |= MAIL_INDEX_HDR_FLAG_FSCK; ret = -1; break; } } t_push(); ret = mbox_index_append_next(index, trans_ctx, input); t_pop(); if (ret == -2) { /* EOF */ ret = 1; break; } if (ret == 0) { /* we want to rescan this message with exclusive locking */ i_stream_seek(input, offset); } } while (ret > 0); if (ret >= 0 && index->mbox_lock_type == MAIL_LOCK_EXCLUSIVE) { /* Write missing X-IMAPbase and new/changed X-UID headers */ if (!mbox_index_rewrite(index)) ret = -1; } if (ret >= 0) { if (!mail_cache_transaction_commit(trans_ctx)) ret = -1; } if (!mail_cache_transaction_end(trans_ctx)) ret = -1; return ret; }