"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/plugins/virtual/virtual-sync.c" between
dovecot-2.3.16.tar.gz and dovecot-2.3.17.tar.gz

About: Dovecot is an IMAP and POP3 server, written with security primarily in mind.

virtual-sync.c  (dovecot-2.3.16):virtual-sync.c  (dovecot-2.3.17)
skipping to change at line 148 skipping to change at line 148
/* another process just added a new mailbox. /* another process just added a new mailbox.
we can't handle this currently. */ we can't handle this currently. */
mbox->inconsistent = TRUE; mbox->inconsistent = TRUE;
mail_storage_set_error(mbox->box.storage, MAIL_ERROR_TEMP, t_strdup_print f( mail_storage_set_error(mbox->box.storage, MAIL_ERROR_TEMP, t_strdup_print f(
"Backend mailbox '%s' added by another session. " "Backend mailbox '%s' added by another session. "
"Reopen the virtual mailbox.", name)); "Reopen the virtual mailbox.", name));
return -1; return -1;
} }
static bool
virtual_mailbox_ext2_header_read(struct virtual_mailbox *mbox,
struct mail_index_view *view,
const struct virtual_mail_index_header *ext_hdr)
{
const char *box_path = mailbox_get_path(&mbox->box);
const struct virtual_mail_index_ext2_header *ext2_hdr;
const struct virtual_mail_index_mailbox_ext2_record *ext2_rec;
const void *ext2_data;
size_t ext2_size;
struct virtual_backend_box *bbox;
mail_index_get_header_ext(view, mbox->virtual_ext2_id,
&ext2_data, &ext2_size);
ext2_hdr = ext2_data;
if (ext2_size == 0) {
/* ext2 is missing - silently add it */
return FALSE;
}
if (ext2_size < sizeof(*ext2_hdr)) {
i_error("virtual index %s: Invalid ext2 header size: %zu",
box_path, ext2_size);
return FALSE;
}
if (ext2_hdr->hdr_size > ext2_size) {
i_error("virtual index %s: ext2 header size too large: %u > %zu",
box_path, ext2_hdr->hdr_size, ext2_size);
return FALSE;
}
if (ext2_hdr->ext_record_size < sizeof(*ext2_rec)) {
i_error("virtual index %s: Invalid ext2 record size: %u",
box_path, ext2_hdr->ext_record_size);
return FALSE;
}
if (ext_hdr->change_counter != ext2_hdr->change_counter) {
i_warning("virtual index %s: "
"Extension header change_counter mismatch (%u != %u) -
"
"Index was modified by an older version?",
box_path, ext_hdr->change_counter,
ext2_hdr->change_counter);
return FALSE;
}
size_t mailboxes_size = ext2_size - ext2_hdr->hdr_size;
if (mailboxes_size % ext2_hdr->ext_record_size != 0 ||
mailboxes_size / ext2_hdr->ext_record_size != ext_hdr->mailbox_count)
{
i_error("virtual index %s: Invalid ext2 size: "
"hdr_size=%u record_size=%u total_size=%zu mailbox_count=
%u",
box_path, ext2_hdr->hdr_size, ext2_hdr->ext_record_size,
ext2_size, ext_hdr->mailbox_count);
return FALSE;
}
ext2_rec = CONST_PTR_OFFSET(ext2_data, ext2_hdr->hdr_size);
array_foreach_elem(&mbox->backend_boxes, bbox) {
if (bbox->sync_mailbox_idx1 == 0)
continue;
guid_128_copy(bbox->sync_guid,
ext2_rec[bbox->sync_mailbox_idx1-1].guid);
}
return TRUE;
}
int virtual_mailbox_ext_header_read(struct virtual_mailbox *mbox, int virtual_mailbox_ext_header_read(struct virtual_mailbox *mbox,
struct mail_index_view *view, struct mail_index_view *view,
bool *broken_r) bool *broken_r)
{ {
const char *box_path = mailbox_get_path(&mbox->box); const char *box_path = mailbox_get_path(&mbox->box);
const struct virtual_mail_index_header *ext_hdr; const struct virtual_mail_index_header *ext_hdr;
const struct mail_index_header *hdr; const struct mail_index_header *hdr;
const struct virtual_mail_index_mailbox_record *mailboxes; const struct virtual_mail_index_mailbox_record *mailboxes;
struct virtual_backend_box *bbox, **bboxes; struct virtual_backend_box *bbox, **bboxes;
const void *ext_data; const void *ext_data;
skipping to change at line 260 skipping to change at line 324
bbox->sync_mailbox_idx1 = i+1; bbox->sync_mailbox_idx1 = i+1;
} }
ext_name_offset += mailboxes[i].name_len; ext_name_offset += mailboxes[i].name_len;
prev_mailbox_id = mailboxes[i].id; prev_mailbox_id = mailboxes[i].id;
} }
if (i < ext_mailbox_count) { if (i < ext_mailbox_count) {
*broken_r = TRUE; *broken_r = TRUE;
mbox->ext_header_rewrite = TRUE; mbox->ext_header_rewrite = TRUE;
ret = 0; ret = 0;
} }
if (!*broken_r && ext_mailbox_count > 0) {
if (!virtual_mailbox_ext2_header_read(mbox, view, ext_hdr))
mbox->ext_header_rewrite = TRUE;
}
mbox->highest_mailbox_id = ext_hdr == NULL ? 0 : mbox->highest_mailbox_id = ext_hdr == NULL ? 0 :
ext_hdr->highest_mailbox_id; ext_hdr->highest_mailbox_id;
/* do not mark it initialized if it's broken */ /* do not mark it initialized if it's broken */
mbox->sync_initialized = !*broken_r; mbox->sync_initialized = !*broken_r;
/* assign new mailbox IDs if any are missing */ /* assign new mailbox IDs if any are missing */
bboxes = array_get_modifiable(&mbox->backend_boxes, &count); bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (bboxes[i]->mailbox_id == 0) { if (bboxes[i]->mailbox_id == 0) {
bboxes[i]->mailbox_id = ++mbox->highest_mailbox_id; bboxes[i]->mailbox_id = ++mbox->highest_mailbox_id;
skipping to change at line 284 skipping to change at line 353
array_sort(&mbox->backend_boxes, bbox_mailbox_id_cmp); array_sort(&mbox->backend_boxes, bbox_mailbox_id_cmp);
if (ret == 0) if (ret == 0)
mbox->ext_header_rewrite = TRUE; mbox->ext_header_rewrite = TRUE;
return ret; return ret;
} }
static void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx) static void virtual_sync_ext_header_rewrite(struct virtual_sync_context *ctx)
{ {
struct virtual_mail_index_header ext_hdr; struct virtual_mail_index_header ext_hdr;
struct virtual_mail_index_mailbox_record mailbox; struct virtual_mail_index_mailbox_record mailbox;
struct virtual_mail_index_mailbox_ext2_record ext2_rec;
struct virtual_backend_box **bboxes; struct virtual_backend_box **bboxes;
buffer_t *buf; buffer_t *buf, *buf2;
const void *ext_data; const void *ext_data;
size_t ext_size; size_t ext_size;
unsigned int i, mailbox_pos, name_pos, count; unsigned int i, mailbox_pos, name_pos, count;
bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count); bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
mailbox_pos = sizeof(ext_hdr); mailbox_pos = sizeof(ext_hdr);
name_pos = mailbox_pos + sizeof(mailbox) * count; name_pos = mailbox_pos + sizeof(mailbox) * count;
i_zero(&ext_hdr); i_zero(&ext_hdr);
i_zero(&mailbox); i_zero(&mailbox);
i_zero(&ext2_rec);
ext_hdr.change_counter = ++ctx->mbox->prev_change_counter; ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
ext_hdr.mailbox_count = count; ext_hdr.mailbox_count = count;
ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id; ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
ext_hdr.search_args_crc32 = ctx->mbox->search_args_crc32; ext_hdr.search_args_crc32 = ctx->mbox->search_args_crc32;
buf = t_buffer_create(name_pos + 256); buf = buffer_create_dynamic(default_pool, name_pos + 256);
buffer_append(buf, &ext_hdr, sizeof(ext_hdr)); buffer_append(buf, &ext_hdr, sizeof(ext_hdr));
struct virtual_mail_index_ext2_header ext2_hdr = {
.version = VIRTUAL_MAIL_INDEX_EXT2_HEADER_VERSION,
.ext_record_size = sizeof(struct virtual_mail_index_mailbox_ext2_
record),
.hdr_size = sizeof(struct virtual_mail_index_ext2_header),
.change_counter = ext_hdr.change_counter,
};
buf2 = buffer_create_dynamic(default_pool, sizeof(ext2_hdr) +
sizeof(ext2_rec) * count);
buffer_append(buf2, &ext2_hdr, sizeof(ext2_hdr));
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
i_assert(i == 0 || i_assert(i == 0 ||
bboxes[i]->mailbox_id > bboxes[i-1]->mailbox_id); bboxes[i]->mailbox_id > bboxes[i-1]->mailbox_id);
bboxes[i]->sync_mailbox_idx1 = i+1; bboxes[i]->sync_mailbox_idx1 = i+1;
mailbox.id = bboxes[i]->mailbox_id; mailbox.id = bboxes[i]->mailbox_id;
mailbox.name_len = strlen(bboxes[i]->name); mailbox.name_len = strlen(bboxes[i]->name);
mailbox.uid_validity = bboxes[i]->sync_uid_validity; mailbox.uid_validity = bboxes[i]->sync_uid_validity;
mailbox.highest_modseq = bboxes[i]->ondisk_highest_modseq; mailbox.highest_modseq = bboxes[i]->ondisk_highest_modseq;
mailbox.next_uid = bboxes[i]->sync_next_uid; mailbox.next_uid = bboxes[i]->sync_next_uid;
buffer_write(buf, mailbox_pos, &mailbox, sizeof(mailbox)); buffer_write(buf, mailbox_pos, &mailbox, sizeof(mailbox));
buffer_write(buf, name_pos, bboxes[i]->name, mailbox.name_len); buffer_write(buf, name_pos, bboxes[i]->name, mailbox.name_len);
guid_128_copy(ext2_rec.guid, bboxes[i]->sync_guid);
buffer_append(buf2, &ext2_rec, sizeof(ext2_rec));
mailbox_pos += sizeof(mailbox); mailbox_pos += sizeof(mailbox);
name_pos += mailbox.name_len; name_pos += mailbox.name_len;
/* repair the value */ /* repair the value */
if (ctx->mbox->highest_mailbox_id < mailbox.id) if (ctx->mbox->highest_mailbox_id < mailbox.id)
ctx->mbox->highest_mailbox_id = mailbox.id; ctx->mbox->highest_mailbox_id = mailbox.id;
} }
if (ctx->mbox->highest_mailbox_id != ext_hdr.highest_mailbox_id) { if (ctx->mbox->highest_mailbox_id != ext_hdr.highest_mailbox_id) {
ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id; ext_hdr.highest_mailbox_id = ctx->mbox->highest_mailbox_id;
buffer_write(buf, 0, &ext_hdr, sizeof(ext_hdr)); buffer_write(buf, 0, &ext_hdr, sizeof(ext_hdr));
} }
i_assert(buf->used == name_pos); i_assert(buf->used == name_pos);
/* update base extension */
mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id, mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
&ext_data, &ext_size); &ext_data, &ext_size);
if (ext_size < name_pos) { if (ext_size < name_pos) {
mail_index_ext_resize(ctx->trans, ctx->mbox->virtual_ext_id, mail_index_ext_resize(ctx->trans, ctx->mbox->virtual_ext_id,
name_pos, name_pos,
sizeof(struct virtual_mail_index_record), sizeof(struct virtual_mail_index_record),
sizeof(uint32_t)); sizeof(uint32_t));
} }
mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id, mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
0, buf->data, name_pos); 0, buf->data, name_pos);
/* update ext2 */
mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext2_id,
&ext_data, &ext_size);
if (ext_size != buf2->used) {
mail_index_ext_resize(ctx->trans, ctx->mbox->virtual_ext2_id,
buf2->used, 0, 0);
}
mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext2_id,
0, buf2->data, buf2->used);
buffer_free(&buf);
buffer_free(&buf2);
} }
static void virtual_sync_ext_header_update(struct virtual_sync_context *ctx) static void virtual_sync_ext_header_update(struct virtual_sync_context *ctx)
{ {
struct virtual_mail_index_header ext_hdr; struct virtual_mail_index_header ext_hdr;
if (!ctx->ext_header_changed) if (!ctx->ext_header_changed)
return; return;
/* we changed something - update the change counter in header */ /* we changed something - update the change counter in header */
ext_hdr.change_counter = ++ctx->mbox->prev_change_counter; ext_hdr.change_counter = ++ctx->mbox->prev_change_counter;
mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id, mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
offsetof(struct virtual_mail_index_header, change_counter), offsetof(struct virtual_mail_index_header, change_counter),
&ext_hdr.change_counter, sizeof(ext_hdr.change_counter)); &ext_hdr.change_counter, sizeof(ext_hdr.change_counter));
mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext2_id,
offsetof(struct virtual_mail_index_ext2_header, change_counter),
&ext_hdr.change_counter, sizeof(ext_hdr.change_counter));
} }
static int virtual_sync_index_rec(struct virtual_sync_context *ctx, static int virtual_sync_index_rec(struct virtual_sync_context *ctx,
const struct mail_index_sync_rec *sync_rec) const struct mail_index_sync_rec *sync_rec)
{ {
uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id; uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
struct virtual_backend_box *bbox; struct virtual_backend_box *bbox;
const struct virtual_mail_index_record *vrec; const struct virtual_mail_index_record *vrec;
const void *data; const void *data;
enum mail_flags flags; enum mail_flags flags;
skipping to change at line 1112 skipping to change at line 1212
if (mailbox_sync_deinit(&sync_ctx, &sync_status) < 0) { if (mailbox_sync_deinit(&sync_ctx, &sync_status) < 0) {
if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND ) if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_NOTFOUND )
return -1; return -1;
/* mailbox was deleted */ /* mailbox was deleted */
virtual_sync_backend_box_deleted(ctx, bbox); virtual_sync_backend_box_deleted(ctx, bbox);
return 0; return 0;
} }
return 0; return 0;
} }
static bool
virtual_bbox_mailbox_equals(struct virtual_backend_box *bbox,
const struct mailbox_status *status,
struct mailbox_metadata *metadata,
const char **reason_r)
{
if (!guid_128_equals(bbox->sync_guid, metadata->guid)) {
*reason_r = t_strdup_printf("GUID changed: %s -> %s",
guid_128_to_string(bbox->sync_guid),
guid_128_to_string(metadata->guid));
return FALSE;
}
if (bbox->sync_uid_validity != status->uidvalidity) {
*reason_r = t_strdup_printf("UIDVALIDITY changed: %u -> %u",
bbox->sync_uid_validity, status->uidvalidity);
return FALSE;
}
if (bbox->sync_next_uid != status->uidnext) {
*reason_r = t_strdup_printf("UIDNEXT changed: %u -> %u",
bbox->sync_next_uid, status->uidnext);
return FALSE;
}
if (bbox->sync_highest_modseq != status->highest_modseq) {
*reason_r = t_strdup_printf("HIGHESTMODSEQ changed: "
"%"PRIu64" -> %"PRIu64,
bbox->sync_highest_modseq, status->highest_modseq);
return FALSE;
}
return TRUE;
}
static void virtual_sync_backend_ext_header(struct virtual_sync_context *ctx, static void virtual_sync_backend_ext_header(struct virtual_sync_context *ctx,
struct virtual_backend_box *bbox) struct virtual_backend_box *bbox)
{ {
const unsigned int uidval_pos = const unsigned int uidval_pos =
offsetof(struct virtual_mail_index_mailbox_record, offsetof(struct virtual_mail_index_mailbox_record,
uid_validity); uid_validity);
struct mailbox_status status; struct mailbox_status status;
struct virtual_mail_index_mailbox_record mailbox; struct virtual_mail_index_mailbox_record mailbox;
unsigned int mailbox_offset; struct virtual_mail_index_mailbox_ext2_record ext2;
unsigned int mailbox_offset, ext2_offset;
uint64_t wanted_ondisk_highest_modseq; uint64_t wanted_ondisk_highest_modseq;
struct mailbox_metadata metadata;
const char *reason;
mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY | mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY |
STATUS_HIGHESTMODSEQ, &status); STATUS_HIGHESTMODSEQ, &status);
wanted_ondisk_highest_modseq = wanted_ondisk_highest_modseq =
array_count(&bbox->sync_pending_removes) > 0 ? 0 : array_count(&bbox->sync_pending_removes) > 0 ? 0 :
status.highest_modseq; status.highest_modseq;
if (bbox->sync_uid_validity == status.uidvalidity && if (mailbox_get_metadata(bbox->box, MAILBOX_METADATA_GUID,
bbox->sync_next_uid == status.uidnext && &metadata) < 0) {
bbox->sync_highest_modseq == status.highest_modseq && /* Either a temporary failure or the mailbox was already
deleted. Either way, it doesn't really matter at this point.
We'll just leave the error handling until the next sync. */
return;
}
if (virtual_bbox_mailbox_equals(bbox, &status, &metadata, &reason) &&
bbox->ondisk_highest_modseq == wanted_ondisk_highest_modseq) bbox->ondisk_highest_modseq == wanted_ondisk_highest_modseq)
return; return;
/* mailbox changed - update extension header */ /* mailbox changed - update extension header */
bbox->sync_uid_validity = status.uidvalidity; bbox->sync_uid_validity = status.uidvalidity;
bbox->sync_highest_modseq = status.highest_modseq; bbox->sync_highest_modseq = status.highest_modseq;
bbox->ondisk_highest_modseq = wanted_ondisk_highest_modseq; bbox->ondisk_highest_modseq = wanted_ondisk_highest_modseq;
bbox->sync_next_uid = status.uidnext; bbox->sync_next_uid = status.uidnext;
guid_128_copy(bbox->sync_guid, metadata.guid);
if (ctx->mbox->ext_header_rewrite) { if (ctx->mbox->ext_header_rewrite) {
/* we'll rewrite the entire header later */ /* we'll rewrite the entire header later */
return; return;
} }
i_zero(&mailbox); i_zero(&mailbox);
mailbox.uid_validity = bbox->sync_uid_validity; mailbox.uid_validity = bbox->sync_uid_validity;
mailbox.highest_modseq = bbox->ondisk_highest_modseq; mailbox.highest_modseq = bbox->ondisk_highest_modseq;
mailbox.next_uid = bbox->sync_next_uid; mailbox.next_uid = bbox->sync_next_uid;
i_zero(&ext2);
guid_128_copy(ext2.guid, bbox->sync_guid);
i_assert(bbox->sync_mailbox_idx1 > 0); i_assert(bbox->sync_mailbox_idx1 > 0);
mailbox_offset = sizeof(struct virtual_mail_index_header) + mailbox_offset = sizeof(struct virtual_mail_index_header) +
(bbox->sync_mailbox_idx1-1) * sizeof(mailbox); (bbox->sync_mailbox_idx1-1) * sizeof(mailbox);
ext2_offset = sizeof(struct virtual_mail_index_ext2_header) +
(bbox->sync_mailbox_idx1-1) * sizeof(ext2);
mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id, mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext_id,
mailbox_offset + uidval_pos, mailbox_offset + uidval_pos,
CONST_PTR_OFFSET(&mailbox, uidval_pos), CONST_PTR_OFFSET(&mailbox, uidval_pos),
sizeof(mailbox) - uidval_pos); sizeof(mailbox) - uidval_pos);
mail_index_update_header_ext(ctx->trans, ctx->mbox->virtual_ext2_id,
ext2_offset, &ext2, sizeof(ext2));
ctx->ext_header_changed = TRUE; ctx->ext_header_changed = TRUE;
} }
static void virtual_sync_backend_box_deleted(struct virtual_sync_context *ctx, static void virtual_sync_backend_box_deleted(struct virtual_sync_context *ctx,
struct virtual_backend_box *bbox) struct virtual_backend_box *bbox)
{ {
ARRAY_TYPE(seq_range) removed_uids; ARRAY_TYPE(seq_range) removed_uids;
const struct virtual_backend_uidmap *uidmap; const struct virtual_backend_uidmap *uidmap;
/* delay its full removal until the next time we open the virtual /* delay its full removal until the next time we open the virtual
skipping to change at line 1204 skipping to change at line 1352
return 0; return 0;
} }
return 1; return 1;
} }
static int virtual_sync_backend_box(struct virtual_sync_context *ctx, static int virtual_sync_backend_box(struct virtual_sync_context *ctx,
struct virtual_backend_box *bbox) struct virtual_backend_box *bbox)
{ {
enum mailbox_sync_flags sync_flags; enum mailbox_sync_flags sync_flags;
struct mailbox_status status; struct mailbox_status status;
const char *reason;
int ret; int ret;
if (bbox->deleted) if (bbox->deleted)
return 0; return 0;
/* if we already did some changes to index, commit them before /* if we already did some changes to index, commit them before
syncing starts. */ syncing starts. */
virtual_backend_box_sync_mail_unset(bbox); virtual_backend_box_sync_mail_unset(bbox);
sync_flags = ctx->flags & (MAILBOX_SYNC_FLAG_FULL_READ | sync_flags = ctx->flags & (MAILBOX_SYNC_FLAG_FULL_READ |
MAILBOX_SYNC_FLAG_FULL_WRITE | MAILBOX_SYNC_FLAG_FULL_WRITE |
MAILBOX_SYNC_FLAG_FAST); MAILBOX_SYNC_FLAG_FAST);
if (bbox->search_result == NULL) { if (bbox->search_result == NULL) {
struct mailbox_metadata metadata;
/* a) first sync in this process. /* a) first sync in this process.
b) we had auto-closed this backend mailbox. b) we had auto-closed this backend mailbox.
first try to quickly check if the mailbox has changed. first try to quickly check if the mailbox has changed.
if we can do that check from mailbox list index, we don't if we can do that check from mailbox list index, we don't
even need to open the mailbox. */ even need to open the mailbox. */
i_assert(array_count(&bbox->sync_pending_removes) == 0); i_assert(array_count(&bbox->sync_pending_removes) == 0);
if (bbox->box->opened || bbox->open_failed) { if (bbox->box->opened || bbox->open_failed) {
/* a) index already opened, refresh it /* a) index already opened, refresh it
b) delayed error handling for mailbox_open() b) delayed error handling for mailbox_open()
that failed in virtual_notify_changes() */ that failed in virtual_notify_changes() */
if ((ret = virtual_try_open_and_sync_backend_box(ctx, bbo x, sync_flags)) <= 0) if ((ret = virtual_try_open_and_sync_backend_box(ctx, bbo x, sync_flags)) <= 0)
return ret; return ret;
bbox->open_failed = FALSE; bbox->open_failed = FALSE;
} }
if (mailbox_get_status(bbox->box, STATUS_UIDVALIDITY | if ((mailbox_get_status(bbox->box, STATUS_UIDVALIDITY |
STATUS_UIDNEXT | STATUS_HIGHESTMODSEQ, STATUS_UIDNEXT | STATUS_HIGHESTMODSEQ,
&status) < 0) { &status) < 0) ||
(mailbox_get_metadata(bbox->box, MAILBOX_METADATA_GUID,
&metadata) < 0)) {
if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_ NOTFOUND) if (mailbox_get_last_mail_error(bbox->box) != MAIL_ERROR_ NOTFOUND)
return -1; return -1;
/* mailbox was deleted */ /* mailbox was deleted */
virtual_sync_backend_box_deleted(ctx, bbox); virtual_sync_backend_box_deleted(ctx, bbox);
return 0; return 0;
} }
if (status.uidvalidity == bbox->sync_uid_validity && if (guid_128_is_empty(bbox->sync_guid)) {
status.uidnext == bbox->sync_next_uid && /* upgrading from old virtual index */
status.highest_modseq == bbox->sync_highest_modseq) { guid_128_copy(bbox->sync_guid, metadata.guid);
ctx->mbox->ext_header_rewrite = TRUE;
}
if (virtual_bbox_mailbox_equals(bbox, &status, &metadata, &reason
)) {
/* mailbox hasn't changed since we last opened it, /* mailbox hasn't changed since we last opened it,
skip it for now. skip it for now.
we'll still need to create the bbox->uids mapping we'll still need to create the bbox->uids mapping
using the current index. */ using the current index. */
if (array_count(&bbox->uids) == 0) if (array_count(&bbox->uids) == 0)
virtual_sync_backend_handle_old_vmsgs(ctx, bbox, NULL); virtual_sync_backend_handle_old_vmsgs(ctx, bbox, NULL);
return 0; return 0;
} }
e_debug(ctx->mbox->box.event, "Backend mailbox %s changed: %s",
bbox->box->vname, reason);
if (!bbox->box->opened) { if (!bbox->box->opened) {
/* first time we're opening the index */ /* first time we're opening the index */
if ((ret = virtual_try_open_and_sync_backend_box(ctx, bbo x, sync_flags)) <= 0) if ((ret = virtual_try_open_and_sync_backend_box(ctx, bbo x, sync_flags)) <= 0)
return ret; return ret;
} }
virtual_backend_box_sync_mail_set(bbox); virtual_backend_box_sync_mail_set(bbox);
if (status.uidvalidity != bbox->sync_uid_validity) { if ((status.uidvalidity != bbox->sync_uid_validity) ||
/* UID validity changed since last sync (or this is !guid_128_equals(metadata.guid, bbox->sync_guid)) {
the first sync), do a full search */ /* UID validity or GUID changed since last sync (or
this is the first sync), do a full search */
bbox->first_sync = TRUE;
ret = virtual_sync_backend_box_init(bbox); ret = virtual_sync_backend_box_init(bbox);
} else { } else {
/* build the initial search using the saved modseq. */ /* build the initial search using the saved modseq. */
ret = virtual_sync_backend_box_continue(ctx, bbox); ret = virtual_sync_backend_box_continue(ctx, bbox);
} }
i_assert(bbox->search_result != NULL || ret < 0); i_assert(bbox->search_result != NULL || ret < 0);
} else { } else {
/* sync using the existing search result */ /* sync using the existing search result */
i_assert(bbox->box->opened); i_assert(bbox->box->opened);
i_array_init(&ctx->sync_expunges, 32); i_array_init(&ctx->sync_expunges, 32);
skipping to change at line 1330 skipping to change at line 1490
vrec = &vmails[i].vrec; vrec = &vmails[i].vrec;
if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) { if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
/* add the rest of the newly seen messages */ /* add the rest of the newly seen messages */
for (; j < uidmap_count; j++) { for (; j < uidmap_count; j++) {
add_rec.rec.real_uid = uidmap[j].real_uid; add_rec.rec.real_uid = uidmap[j].real_uid;
array_push_back(&ctx->all_adds, &add_rec); array_push_back(&ctx->all_adds, &add_rec);
} }
bbox = virtual_backend_box_lookup(ctx->mbox, bbox = virtual_backend_box_lookup(ctx->mbox,
vrec->mailbox_id); vrec->mailbox_id);
if (bbox == NULL) { if (bbox == NULL || bbox->first_sync) {
/* the entire mailbox is lost */ /* the entire mailbox is lost */
mail_index_expunge(ctx->trans, vseq); mail_index_expunge(ctx->trans, vseq);
continue; continue;
} }
uidmap = array_get_modifiable(&bbox->uids, uidmap = array_get_modifiable(&bbox->uids,
&uidmap_count); &uidmap_count);
j = 0; j = 0;
add_rec.rec.mailbox_id = bbox->mailbox_id; add_rec.rec.mailbox_id = bbox->mailbox_id;
bbox->sync_seen = TRUE; bbox->sync_seen = TRUE;
} }
skipping to change at line 1387 skipping to change at line 1547
struct virtual_backend_box *const *bboxes; struct virtual_backend_box *const *bboxes;
struct virtual_add_record add_rec; struct virtual_add_record add_rec;
struct virtual_backend_uidmap *uidmap; struct virtual_backend_uidmap *uidmap;
unsigned int i, j, count, uidmap_count; unsigned int i, j, count, uidmap_count;
/* if there are any mailboxes we didn't yet sync, add new messages in /* if there are any mailboxes we didn't yet sync, add new messages in
them */ them */
i_zero(&add_rec); i_zero(&add_rec);
bboxes = array_get(&ctx->mbox->backend_boxes, &count); bboxes = array_get(&ctx->mbox->backend_boxes, &count);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
bboxes[i]->first_sync = FALSE; /* this is the end of the sync */
if (bboxes[i]->sync_seen) if (bboxes[i]->sync_seen)
continue; continue;
add_rec.rec.mailbox_id = bboxes[i]->mailbox_id; add_rec.rec.mailbox_id = bboxes[i]->mailbox_id;
uidmap = array_get_modifiable(&bboxes[i]->uids, &uidmap_count); uidmap = array_get_modifiable(&bboxes[i]->uids, &uidmap_count);
for (j = 0; j < uidmap_count; j++) { for (j = 0; j < uidmap_count; j++) {
add_rec.rec.real_uid = uidmap[j].real_uid; add_rec.rec.real_uid = uidmap[j].real_uid;
array_push_back(&ctx->all_adds, &add_rec); array_push_back(&ctx->all_adds, &add_rec);
} }
} }
 End of changes. 28 change blocks. 
15 lines changed or deleted 182 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)