sdbox-save.c revision e8762c2b4914db7997fa9eb644a91586952d1876
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "lib.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "array.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "fdatasync-path.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "hex-binary.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "hex-dec.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "str.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "istream.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "istream-crlf.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "ostream.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "write-full.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "index-mail.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mail-copy.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "dbox-save.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "sdbox-storage.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "sdbox-file.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "sdbox-sync.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <stdlib.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstruct sdbox_save_context {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct dbox_save_context ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct sdbox_mailbox *mbox;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct sdbox_sync_context *sync_ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct dbox_file_append_context *append_ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen uint32_t first_saved_seq;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ARRAY_DEFINE(files, struct dbox_file *);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen};
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstruct dbox_file *
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainensdbox_save_file_get_file(struct mailbox_transaction_context *t, uint32_t seq)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct sdbox_save_context *ctx =
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (struct sdbox_save_context *)t->save_ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct dbox_file *const *files;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int count;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_assert(seq >= ctx->first_saved_seq);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen files = array_get(&ctx->files, &count);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_assert(count > 0);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen return files[seq - ctx->first_saved_seq];
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstruct mail_save_context *
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainensdbox_save_alloc(struct mailbox_transaction_context *t)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)t->box;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen struct sdbox_save_context *ctx =
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen (struct sdbox_save_context *)t->save_ctx;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen if (ctx != NULL) {
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen /* use the existing allocated structure */
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen ctx->ctx.finished = FALSE;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen return &ctx->ctx.ctx;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx = i_new(struct sdbox_save_context, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->ctx.ctx.transaction = t;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->ctx.trans = t->itrans;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->mbox = mbox;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen i_array_init(&ctx->files, 32);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen t->save_ctx = &ctx->ctx.ctx;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen return t->save_ctx;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen}
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainenvoid sdbox_save_add_file(struct mail_save_context *_ctx, struct dbox_file *file)
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen{
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_append(&ctx->files, &file, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenint sdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen struct dbox_file *file;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen int ret;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen file = sdbox_file_create(ctx->mbox);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ctx->append_ctx = dbox_file_append_init(file);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ret = dbox_file_get_append_stream(ctx->append_ctx,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen &ctx->ctx.dbox_output);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (ret <= 0) {
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen i_assert(ret != 0);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen dbox_file_append_rollback(&ctx->append_ctx);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen dbox_file_unref(&file);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ctx->ctx.failed = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return -1;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ctx->ctx.cur_file = file;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen dbox_save_begin(&ctx->ctx, input);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (ctx->first_saved_seq == 0)
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen ctx->first_saved_seq = ctx->ctx.seq;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen sdbox_save_add_file(_ctx, file);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return ctx->ctx.failed ? -1 : 0;
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen}
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainenstatic int dbox_save_mail_write_metadata(struct dbox_save_context *ctx,
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen struct dbox_file *file)
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen{
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen struct dbox_message_header dbox_msg_hdr;
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen uoff_t message_size;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen uint8_t guid_128[MAIL_GUID_128_SIZE];
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen i_assert(file->msg_header_size == sizeof(dbox_msg_hdr));
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen message_size = ctx->dbox_output->offset -
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen file->msg_header_size - file->file_header_size;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen dbox_save_write_metadata(&ctx->ctx, ctx->dbox_output, NULL, guid_128);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen dbox_msg_header_fill(&dbox_msg_hdr, message_size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (o_stream_pwrite(ctx->dbox_output, &dbox_msg_hdr,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen sizeof(dbox_msg_hdr),
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen file->file_header_size) < 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen dbox_file_set_syscall_error(file, "pwrite()");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen return 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic int dbox_save_finish_write(struct mail_save_context *_ctx)
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen{
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen struct dbox_file *const *files;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen ctx->ctx.finished = TRUE;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (ctx->ctx.dbox_output == NULL)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (_ctx->save_date != (time_t)-1) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* we can't change ctime, but we can add the date to cache */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct index_mail *mail = (struct index_mail *)_ctx->dest_mail;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen uint32_t t = _ctx->save_date;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen index_mail_cache_parse_deinit(_ctx->dest_mail,
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen _ctx->received_date, !ctx->ctx.failed);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen files = array_idx_modifiable(&ctx->files, array_count(&ctx->files) - 1);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen dbox_save_end(&ctx->ctx);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (!ctx->ctx.failed) T_BEGIN {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (dbox_save_mail_write_metadata(&ctx->ctx, *files) < 0)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen ctx->ctx.failed = TRUE;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen } T_END;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (ctx->ctx.failed)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen dbox_file_append_rollback(&ctx->append_ctx);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen else if (dbox_file_append_commit(&ctx->append_ctx) < 0)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen ctx->ctx.failed = TRUE;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen i_stream_unref(&ctx->ctx.input);
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen dbox_file_close(*files);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ctx->ctx.dbox_output = NULL;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return ctx->ctx.failed ? -1 : 0;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen}
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenint sdbox_save_finish(struct mail_save_context *ctx)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen{
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen int ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ret = dbox_save_finish_write(ctx);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen index_save_context_free(ctx);
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen return ret;
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenvoid sdbox_save_cancel(struct mail_save_context *_ctx)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->failed = TRUE;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen (void)sdbox_save_finish(_ctx);
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen}
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic int dbox_save_assign_uids(struct sdbox_save_context *ctx,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen const ARRAY_TYPE(seq_range) *uids)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct dbox_file *const *files;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct seq_range_iter iter;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int i, count, n = 0;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen uint32_t uid;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen bool ret;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen seq_range_array_iter_init(&iter, uids);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen files = array_get(&ctx->files, &count);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen for (i = 0; i < count; i++) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct sdbox_file *sfile = (struct sdbox_file *)files[i];
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen ret = seq_range_array_iter_nth(&iter, n++, &uid);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen i_assert(ret);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen if (sdbox_file_assign_uid(sfile, uid) < 0)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return -1;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen return 0;
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen}
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainenstatic void dbox_save_unref_files(struct sdbox_save_context *ctx)
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen{
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen struct mail_storage *storage = &ctx->mbox->storage->storage.storage;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct dbox_file **files;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen unsigned int i, count;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen files = array_get_modifiable(&ctx->files, &count);
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen for (i = 0; i < count; i++) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (ctx->ctx.failed) {
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen if (unlink(files[i]->cur_path) < 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_storage_set_critical(storage,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "unlink(%s) failed: %m",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen files[i]->cur_path);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen dbox_file_unref(&files[i]);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen array_free(&ctx->files);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainenint sdbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen{
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen struct mailbox_transaction_context *_t = _ctx->transaction;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen const struct mail_index_header *hdr;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_assert(ctx->ctx.finished);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (array_count(&ctx->files) == 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 0;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (sdbox_sync_begin(ctx->mbox, SDBOX_SYNC_FLAG_FORCE |
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen SDBOX_SYNC_FLAG_FSYNC, &ctx->sync_ctx) < 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen sdbox_transaction_save_rollback(_ctx);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen /* assign UIDs for new messages */
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid,
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen &_t->changes->saved_uids);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (dbox_save_assign_uids(ctx, &_t->changes->saved_uids) < 0) {
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen sdbox_transaction_save_rollback(_ctx);
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen return -1;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen if (ctx->ctx.mail != NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_free(&ctx->ctx.mail);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen _t->changes->uid_validity = hdr->uid_validity;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return 0;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen}
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainenvoid sdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen struct mail_index_transaction_commit_result *result)
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen{
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen _ctx->transaction = NULL; /* transaction is already freed */
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen if (array_count(&ctx->files) == 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen sdbox_transaction_save_rollback(_ctx);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen result);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (sdbox_sync_finish(&ctx->sync_ctx, TRUE) < 0)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ctx->ctx.failed = TRUE;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen if (!ctx->mbox->storage->storage.storage.set->fsync_disable) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (fdatasync_path(ctx->mbox->box.path) < 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_error("fdatasync_path(%s) failed: %m",
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen ctx->mbox->box.path);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sdbox_transaction_save_rollback(_ctx);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenvoid sdbox_transaction_save_rollback(struct mail_save_context *_ctx)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (!ctx->ctx.finished)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen sdbox_save_cancel(_ctx);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen dbox_save_unref_files(ctx);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ctx->sync_ctx != NULL)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen (void)sdbox_sync_finish(&ctx->sync_ctx, FALSE);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (ctx->ctx.mail != NULL)
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail_free(&ctx->ctx.mail);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen i_free(ctx);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen