[dovecot-cvs] dovecot/src/lib-storage/index/mbox
mbox-sync-private.h, 1.35, 1.36 mbox-sync-rewrite.c, 1.34,
1.35 mbox-sync.c, 1.105, 1.106
cras at dovecot.org
cras at dovecot.org
Thu Oct 14 20:56:41 EEST 2004
Update of /var/lib/cvs/dovecot/src/lib-storage/index/mbox
In directory talvi:/tmp/cvs-serv11667/lib-storage/index/mbox
Modified Files:
mbox-sync-private.h mbox-sync-rewrite.c mbox-sync.c
Log Message:
If rewriting began with expunged data areas, we didn't overwrite them which
left garbage into mbox and broke things.
Index: mbox-sync-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-private.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- mbox-sync-private.h 5 Oct 2004 00:26:40 -0000 1.35
+++ mbox-sync-private.h 14 Oct 2004 17:56:39 -0000 1.36
@@ -130,7 +130,7 @@
const struct mbox_sync_mail *mail);
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,
- uoff_t end_offset, uoff_t move_diff, uoff_t extra_space,
+ uoff_t end_offset, off_t move_diff, uoff_t extra_space,
uint32_t first_seq, uint32_t last_seq);
int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset);
Index: mbox-sync-rewrite.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-rewrite.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- mbox-sync-rewrite.c 7 Oct 2004 20:14:28 -0000 1.34
+++ mbox-sync-rewrite.c 14 Oct 2004 17:56:39 -0000 1.35
@@ -276,7 +276,8 @@
static int mbox_sync_read_and_move(struct mbox_sync_context *sync_ctx,
struct mbox_sync_mail *mails,
uint32_t seq, uint32_t idx, uint32_t padding,
- uoff_t move_diff, uoff_t end_offset)
+ off_t move_diff, uoff_t expunged_space,
+ uoff_t end_offset)
{
struct mbox_sync_mail_context mail_ctx;
uint32_t old_prev_msg_uid;
@@ -301,7 +302,14 @@
so we have to fool it. */
old_prev_msg_uid = sync_ctx->prev_msg_uid;
sync_ctx->prev_msg_uid = mails[idx].uid == 0 ? 0 : mails[idx].uid-1;
- sync_ctx->dest_first_mail = mails[idx].from_offset == 0;
+ if (mails[idx].from_offset+1 - expunged_space != 0) {
+ sync_ctx->dest_first_mail = mails[idx].from_offset == 0;
+ } else {
+ /* we need to skip over the initial \n (it's already counted in
+ expunged_space) */
+ sync_ctx->dest_first_mail = TRUE;
+ mails[idx].from_offset++;
+ }
mbox_sync_parse_next_mail(sync_ctx->input, &mail_ctx);
if (mails[idx].space != 0)
@@ -313,6 +321,14 @@
str_append_c(mail_ctx.header, '\n');
}
+ if (sync_ctx->dest_first_mail && expunged_space > 0) {
+ /* move From-line (after parsing headers so we don't
+ overwrite them) */
+ if (mbox_move(sync_ctx, 0, mails[idx].from_offset,
+ mails[idx].offset - mails[idx].from_offset) < 0)
+ return -1;
+ }
+
sync_ctx->prev_msg_uid = old_prev_msg_uid;
sync_ctx->dest_first_mail = FALSE;
@@ -340,6 +356,7 @@
/* the header may actually be moved backwards if there was expunged
space which we wanted to remove */
+ i_assert(dest_offset >= str_len(mail_ctx.header));
dest_offset -= str_len(mail_ctx.header);
if (pwrite_full(sync_ctx->fd, str_data(mail_ctx.header),
str_len(mail_ctx.header), dest_offset) < 0) {
@@ -361,11 +378,12 @@
}
int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
- uoff_t end_offset, uoff_t move_diff, uoff_t extra_space,
+ uoff_t end_offset, off_t move_diff, uoff_t extra_space,
uint32_t first_seq, uint32_t last_seq)
{
struct mbox_sync_mail *mails;
uoff_t offset, dest_offset, next_end_offset, next_move_diff;
+ uoff_t expunged_space;
uint32_t idx, first_nonexpunged_idx, padding_per_mail;
size_t size;
int ret = 0;
@@ -385,21 +403,23 @@
/* after expunge the next mail must have been missing space, or we
would have moved it backwards already */
+ expunged_space = 0;
for (first_nonexpunged_idx = 0;; first_nonexpunged_idx++) {
i_assert(first_nonexpunged_idx != idx);
if ((mails[first_nonexpunged_idx].flags & MBOX_EXPUNGED) == 0)
break;
+ expunged_space += mails[first_nonexpunged_idx].space;
}
i_assert(mails[first_nonexpunged_idx].space < 0);
/* start moving backwards. */
while (idx-- > first_nonexpunged_idx) {
if (idx == first_nonexpunged_idx) {
- /* give the rest of the extra space to first mail */
- i_assert((uoff_t)-mails[idx].space <= move_diff);
- i_assert(move_diff + mails[idx].space >=
- padding_per_mail);
- padding_per_mail = move_diff + mails[idx].space;
+ /* give the rest of the extra space to first mail.
+ we might also have to move the mail backwards to
+ fill the expunged space */
+ padding_per_mail = move_diff + expunged_space +
+ mails[idx].space;
}
next_end_offset = mails[idx].offset;
@@ -409,12 +429,15 @@
next_move_diff = -mails[idx].space;
if (mbox_sync_read_and_move(sync_ctx, mails,
first_seq + idx, idx,
- padding_per_mail, move_diff,
+ padding_per_mail,
+ move_diff, expunged_space,
end_offset) < 0) {
ret = -1;
break;
}
move_diff -= next_move_diff + mails[idx].space;
+ if (idx == first_nonexpunged_idx)
+ move_diff += expunged_space;
} else {
/* this mail provides more space. just move it forward
from the extra space offset and set end_offset to
@@ -447,6 +470,8 @@
mails[idx].offset += move_diff;
}
+ i_assert(idx > 0 || move_diff == 0);
+
end_offset = next_end_offset;
mails[idx].from_offset += move_diff;
i_assert(move_diff < OFF_T_MAX);
Index: mbox-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync.c,v
retrieving revision 1.105
retrieving revision 1.106
diff -u -d -r1.105 -r1.106
--- mbox-sync.c 13 Oct 2004 20:40:25 -0000 1.105
+++ mbox-sync.c 14 Oct 2004 17:56:39 -0000 1.106
@@ -105,11 +105,6 @@
if (mail_ctx->seq == 1)
sync_ctx->seen_first_mail = TRUE;
- if (mail_ctx->seq > 1 && sync_ctx->dest_first_mail) {
- /* First message was expunged and this is the next one.
- Skip \n header */
- mail_ctx->mail.from_offset++;
- }
mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx);
i_assert(sync_ctx->input->v_offset != mail_ctx->mail.from_offset ||
@@ -530,6 +525,13 @@
/* move the header backwards to fill expunged space */
move_diff = -sync_ctx->expunged_space;
+ if (sync_ctx->dest_first_mail) {
+ /* we're moving this mail to beginning of file.
+ skip the initial \n (it's already counted in
+ expunged_space) */
+ mail_ctx->mail.from_offset++;
+ }
+
/* read the From-line before rewriting overwrites it */
if (mbox_read_from_line(mail_ctx) < 0)
return -1;
@@ -546,6 +548,12 @@
mail_ctx->mail.offset += move_diff;
if (mbox_write_from_line(mail_ctx) < 0)
return -1;
+ } else {
+ if (sync_ctx->dest_first_mail) {
+ /* didn't have enough space, move the offset
+ back so seeking into it doesn't fail */
+ mail_ctx->mail.from_offset--;
+ }
}
} else if (mail_ctx->need_rewrite ||
buffer_get_used_size(sync_ctx->syncs) != 0 ||
More information about the dovecot-cvs
mailing list