]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mdbox: Allow reflink-copying a mail when wanted GUID matches the current GUID.
authorTimo Sirainen <tss@iki.fi>
Wed, 9 Jan 2013 03:35:20 +0000 (05:35 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 9 Jan 2013 03:35:20 +0000 (05:35 +0200)
src/lib-storage/index/dbox-multi/mdbox-save.c

index cf43df2bf24a90f2c7295595403094b90e81ae81..a673c90f037ea8c696ce68c3f15ef86159631371 100644 (file)
@@ -412,14 +412,14 @@ int mdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
        struct dbox_save_mail *save_mail;
        struct mdbox_mailbox *src_mbox;
        struct mdbox_mail_index_record rec;
-       const void *data;
+       const void *guid_data;
+       guid_128_t wanted_guid;
        bool expunged;
 
        ctx->ctx.finished = TRUE;
 
        if (mail->box->storage != _ctx->transaction->box->storage ||
-           _ctx->transaction->box->disable_reflink_copy_to ||
-           _ctx->guid != NULL)
+           _ctx->transaction->box->disable_reflink_copy_to)
                return mail_storage_copy(_ctx, mail);
        src_mbox = (struct mdbox_mailbox *)mail->box;
 
@@ -429,6 +429,20 @@ int mdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
                              &rec.map_uid) < 0)
                return -1;
 
+       mail_index_lookup_ext(mail->transaction->view, mail->seq,
+                             src_mbox->guid_ext_id, &guid_data, &expunged);
+       if (guid_data == NULL || guid_128_is_empty(guid_data)) {
+               /* missing GUID, something's broken. don't copy using
+                  refcounting. */
+               return mail_storage_copy(_ctx, mail);
+       } else if (_ctx->guid != NULL &&
+                  (guid_128_from_string(_ctx->guid, wanted_guid) < 0 ||
+                   memcmp(guid_data, wanted_guid, sizeof(wanted_guid)) != 0)) {
+               /* GUID change requested. we can't do it with refcount
+                  copying */
+               return mail_storage_copy(_ctx, mail);
+       }
+
        /* remember the map_uid so we can later increase its refcount */
        if (!array_is_created(&ctx->copy_map_uids))
                i_array_init(&ctx->copy_map_uids, 32);
@@ -439,12 +453,8 @@ int mdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
        mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
                              ctx->mbox->ext_id, &rec, NULL);
 
-       mail_index_lookup_ext(mail->transaction->view, mail->seq,
-                             src_mbox->guid_ext_id, &data, &expunged);
-       if (data != NULL) {
-               mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
-                                     ctx->mbox->guid_ext_id, data, NULL);
-       }
+       mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
+                             ctx->mbox->guid_ext_id, guid_data, NULL);
        index_copy_cache_fields(_ctx, mail, ctx->ctx.seq);
 
        save_mail = array_append_space(&ctx->mails);