]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
fixes
authorTimo Sirainen <tss@iki.fi>
Thu, 17 Jun 2004 23:08:48 +0000 (02:08 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 17 Jun 2004 23:08:48 +0000 (02:08 +0300)
--HG--
branch : HEAD

src/lib-storage/index/mbox/istream-raw-mbox.c
src/lib-storage/index/mbox/mbox-sync-private.h
src/lib-storage/index/mbox/mbox-sync-rewrite.c
src/lib-storage/index/mbox/mbox-sync.c

index d072997383960905f1c6b0575d8bd053942a30ff..5cb9a57198ef41a49d37e951505845623d3c4614 100644 (file)
@@ -103,6 +103,22 @@ static int mbox_read_from_line(struct raw_mbox_istream *rstream)
        return 0;
 }
 
+static void handle_end_of_mail(struct raw_mbox_istream *rstream, size_t pos)
+{
+       rstream->mail_size = rstream->istream.istream.v_offset + pos -
+               rstream->hdr_offset;
+
+       if (rstream->body_offset != (uoff_t)-1 &&
+           rstream->hdr_offset + rstream->mail_size < rstream->body_offset) {
+               /* "headers\n\nFrom ..", the second \n belongs to next
+                  message which we didn't know at the time yet. */
+               i_assert(rstream->body_offset ==
+                        rstream->hdr_offset + rstream->mail_size + 1);
+               rstream->body_offset =
+                       rstream->hdr_offset + rstream->mail_size;
+       }
+}
+
 static ssize_t _read(struct _istream *stream)
 {
        static const char *mbox_from = "\nFrom ";
@@ -114,6 +130,8 @@ static ssize_t _read(struct _istream *stream)
        size_t i, pos, new_pos, from_start_pos;
        ssize_t ret = 0;
 
+       i_assert(stream->istream.v_offset >= rstream->from_offset);
+
        if (rstream->eom) {
                if (rstream->body_offset == (uoff_t)-1) {
                        /* missing \n from headers */
@@ -134,8 +152,9 @@ static ssize_t _read(struct _istream *stream)
        do {
                ret = i_stream_read(rstream->input);
                buf = i_stream_get_data(rstream->input, &pos);
-       } while (ret > 0 &&
-                stream->istream.v_offset + pos <= rstream->input_peak_offset);
+       } while (ret > 0 && (pos == 1 ||
+                            stream->istream.v_offset + pos <=
+                            rstream->input_peak_offset));
 
        if (ret < 0) {
                if (ret == -2)
@@ -155,8 +174,7 @@ static ssize_t _read(struct _istream *stream)
 
                rstream->eom = TRUE;
                rstream->next_eof = TRUE;
-               rstream->mail_size = stream->istream.v_offset + pos -
-                       rstream->hdr_offset;
+               handle_end_of_mail(rstream, pos);
                return ret < 0 ? _read(stream) : ret;
        }
 
@@ -211,10 +229,8 @@ static ssize_t _read(struct _istream *stream)
                                         /* rewind "\nFrom " */
                                        from_start_pos -= 6;
 
-                                       rstream->mail_size =
-                                               stream->istream.v_offset +
-                                               from_start_pos -
-                                               rstream->hdr_offset;
+                                       handle_end_of_mail(rstream,
+                                                          from_start_pos);
                                        break;
                                }
                                from_start_pos = 0;
index 0dbdd63b1900c16b0fd0168749814c081065792d..c852e690e41d4c01b1f37e84a301cc59565ce1b2 100644 (file)
@@ -108,6 +108,7 @@ int mbox_sync_try_rewrite(struct mbox_sync_mail_context *ctx, off_t move_diff);
 int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
                      uint32_t first_seq, uint32_t last_seq, off_t extra_space);
 
+int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset);
 int mbox_move(struct mbox_sync_context *sync_ctx,
              uoff_t dest, uoff_t source, uoff_t size);
 
index 6fe1846c62942ab0b8204faf2eca5eb849a476f6..3fe32189309b139db57c8c92d25e92a37d140e45 100644 (file)
@@ -263,7 +263,8 @@ static int mbox_sync_read_and_move(struct mbox_sync_context *sync_ctx,
        uint32_t old_prev_msg_uid;
        uoff_t offset;
 
-       i_stream_seek(sync_ctx->input, mails[idx].offset);
+       if (mbox_sync_seek(sync_ctx, mails[idx].from_offset) < 0)
+               return -1;
 
        memset(&mail_ctx, 0, sizeof(mail_ctx));
        mail_ctx.sync_ctx = sync_ctx;
@@ -338,6 +339,7 @@ static int mbox_sync_fill_leftover(struct mbox_sync_context *sync_ctx,
        uint32_t old_prev_msg_uid;
 
        i_assert(start_offset < end_offset);
+
        i_stream_seek(sync_ctx->input, mails[idx].offset);
 
        memset(&mail_ctx, 0, sizeof(mail_ctx));
@@ -368,7 +370,9 @@ static int mbox_sync_fill_leftover(struct mbox_sync_context *sync_ctx,
                return -1;
        }
 
+       /* just a cleanup - shouldn't be needed anymore */
        mails[idx].offset = start_offset;
+       mails[idx].space = 0;
        return 0;
 }
 
@@ -463,7 +467,6 @@ int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
                }
 
                /* now parse it again and give it more space */
-               mails[idx].space = extra_per_mail;
                mails[idx+1].space = 0; /* from_offset doesn't move.. */
                if (mbox_sync_fill_leftover(sync_ctx, mails,
                                            first_seq + idx, idx,
index 7c2e29553d6be1dbbfcfa541ad4903f2c41cefb1..15f475c932a3957863b588b691222d261a0728fa 100644 (file)
@@ -125,6 +125,18 @@ static int mbox_sync_lock(struct mbox_sync_context *sync_ctx, int lock_type)
        return 1;
 }
 
+int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
+{
+       if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
+               mail_storage_set_critical(sync_ctx->ibox->box.storage,
+                       "Unexpectedly lost From-line at offset %"PRIuUOFF_T
+                       " from mbox file %s", from_offset,
+                       sync_ctx->ibox->path);
+               return -1;
+       }
+       return 0;
+}
+
 static int mbox_sync_grow_file(struct mbox_sync_context *sync_ctx,
                               struct mbox_sync_mail_context *mail_ctx,
                               uoff_t grow_size)
@@ -200,6 +212,7 @@ mbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx,
        mail_ctx->mail.body_size =
                istream_raw_mbox_get_body_size(sync_ctx->input,
                                               mail_ctx->content_length);
+       i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
 
        /* save the offset permanently with recent flag state */
        mail_ctx->mail.from_offset = mail_ctx->from_offset;
@@ -714,7 +727,8 @@ static int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
                if (sync_ctx->need_space_seq != 0) {
                        if (mbox_sync_handle_missing_space(mail_ctx) < 0)
                                return -1;
-                       i_stream_seek(sync_ctx->input, offset);
+                       if (mbox_sync_seek(sync_ctx, offset) < 0)
+                               return -1;
                } else if (sync_ctx->expunged_space > 0) {
                        if (!expunged) {
                                /* move the body */
@@ -724,7 +738,8 @@ static int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
                                              mail_ctx->body_offset,
                                              mail_ctx->mail.body_size) < 0)
                                        return -1;
-                               i_stream_seek(sync_ctx->input, offset);
+                               if (mbox_sync_seek(sync_ctx, offset) < 0)
+                                       return -1;
                        }
                } else if (sync_ctx->seq >= min_message_count) {
                        mbox_sync_buffer_delete_old(sync_ctx->syncs, uid+1);
@@ -775,7 +790,10 @@ static int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx,
                sync_ctx->space_diff -= extra_space;
 
                sync_ctx->space_diff += sync_ctx->expunged_space;
-               sync_ctx->expunged_space -= -sync_ctx->space_diff;
+               if (sync_ctx->expunged_space <= -sync_ctx->space_diff)
+                       sync_ctx->expunged_space = 0;
+               else
+                       sync_ctx->expunged_space -= -sync_ctx->space_diff;
 
                if (mail_ctx->have_eoh && !mail_ctx->updated)
                        str_append_c(mail_ctx->header, '\n');
@@ -958,14 +976,8 @@ static int mbox_sync_update_imap_base(struct mbox_sync_context *sync_ctx)
 {
        struct mbox_sync_mail_context mail_ctx;
 
-       if (istream_raw_mbox_seek(sync_ctx->input, 0) < 0) {
-               /* doesn't begin with a From-line, which is weird because it
-                  just did. */
-               mail_storage_set_critical(sync_ctx->ibox->box.storage,
-                       "Unexpectedly lost From-header line from mbox file %s",
-                       sync_ctx->ibox->path);
+       if (mbox_sync_seek(sync_ctx, 0) < 0)
                return -1;
-       }
 
        sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view, FALSE);
        sync_ctx->update_base_uid_last = sync_ctx->next_uid-1;