sdbox-save.c revision 1f19649986397419d014febd1337c6eb7b530f26
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "lib.h"
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "array.h"
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "fdatasync-path.h"
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "hex-binary.h"
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "hex-dec.h"
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody#include "str.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "istream.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "istream-crlf.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "ostream.h"
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch#include "write-full.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "index-mail.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "mail-copy.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "dbox-save.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "sdbox-storage.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "sdbox-file.h"
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody#include "sdbox-sync.h"
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch#include <stdlib.h>
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodystruct sdbox_save_context {
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct dbox_save_context ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct sdbox_mailbox *mbox;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct sdbox_sync_context *sync_ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct dbox_file_append_context *append_ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek uint32_t first_saved_seq;
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi ARRAY_DEFINE(files, struct dbox_file *);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody};
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodystruct dbox_file *
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodysdbox_save_file_get_file(struct mailbox_transaction_context *t, uint32_t seq)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody{
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct sdbox_save_context *ctx =
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody (struct sdbox_save_context *)t->save_ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct dbox_file *const *files;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody unsigned int count;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek i_assert(seq >= ctx->first_saved_seq);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody files = array_get(&ctx->files, &count);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody i_assert(count > 0);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody return files[seq - ctx->first_saved_seq];
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody}
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodystruct mail_save_context *
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodysdbox_save_alloc(struct mailbox_transaction_context *t)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody{
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)t->box;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody struct sdbox_save_context *ctx =
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody (struct sdbox_save_context *)t->save_ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody if (ctx != NULL) {
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody /* use the existing allocated structure */
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ctx->ctx.finished = FALSE;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody return &ctx->ctx.ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody }
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ctx = i_new(struct sdbox_save_context, 1);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ctx->ctx.ctx.transaction = t;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ctx->ctx.trans = t->itrans;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody ctx->mbox = mbox;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody i_array_init(&ctx->files, 32);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody t->save_ctx = &ctx->ctx.ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody return t->save_ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody}
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodyvoid sdbox_save_add_file(struct mail_save_context *_ctx, struct dbox_file *file)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody{
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody array_append(&ctx->files, &file, 1);
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody}
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmodyint sdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
629e96c5e2d4724b713ca7d62e59ed033107edcdPhil Carmody{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_file *file;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int ret;
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch file = sdbox_file_create(ctx->mbox);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->append_ctx = dbox_file_append_init(file);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = dbox_file_get_append_stream(ctx->append_ctx,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch &ctx->ctx.dbox_output);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (ret <= 0) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch i_assert(ret != 0);
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch dbox_file_append_rollback(&ctx->append_ctx);
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch dbox_file_unref(&file);
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch ctx->ctx.failed = TRUE;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return -1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->ctx.cur_file = file;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch dbox_save_begin(&ctx->ctx, input);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (ctx->first_saved_seq == 0)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->first_saved_seq = ctx->ctx.seq;
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi sdbox_save_add_file(_ctx, file);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return ctx->ctx.failed ? -1 : 0;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic int dbox_save_mail_write_metadata(struct dbox_save_context *ctx,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_file *file)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_message_header dbox_msg_hdr;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch uoff_t message_size;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch uint8_t guid_128[MAIL_GUID_128_SIZE];
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek i_assert(file->msg_header_size == sizeof(dbox_msg_hdr));
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch message_size = ctx->dbox_output->offset -
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch file->msg_header_size - file->file_header_size;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch dbox_save_write_metadata(&ctx->ctx, ctx->dbox_output,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch message_size, NULL, guid_128);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch dbox_msg_header_fill(&dbox_msg_hdr, message_size);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (o_stream_pwrite(ctx->dbox_output, &dbox_msg_hdr,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch sizeof(dbox_msg_hdr),
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch file->file_header_size) < 0) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch dbox_file_set_syscall_error(file, "pwrite()");
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return -1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return 0;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic int dbox_save_finish_write(struct mail_save_context *_ctx)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_file *const *files;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->ctx.finished = TRUE;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (ctx->ctx.dbox_output == NULL)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return -1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (_ctx->save_date != (time_t)-1) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch /* we can't change ctime, but we can add the date to cache */
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct index_mail *mail = (struct index_mail *)_ctx->dest_mail;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch uint32_t t = _ctx->save_date;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch index_mail_cache_parse_deinit(_ctx->dest_mail,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch _ctx->received_date, !ctx->ctx.failed);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody files = array_idx_modifiable(&ctx->files, array_count(&ctx->files) - 1);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody dbox_save_end(&ctx->ctx);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (!ctx->ctx.failed) T_BEGIN {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (dbox_save_mail_write_metadata(&ctx->ctx, *files) < 0)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->ctx.failed = TRUE;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch } T_END;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (ctx->ctx.failed)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch dbox_file_append_rollback(&ctx->append_ctx);
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch else if (dbox_file_append_commit(&ctx->append_ctx) < 0)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->ctx.failed = TRUE;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch i_stream_unref(&ctx->ctx.input);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch dbox_file_close(*files);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->ctx.dbox_output = NULL;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch return ctx->ctx.failed ? -1 : 0;
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch}
87b4215acbf020aa5b8dea686b23fc664140cda0Stephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschint sdbox_save_finish(struct mail_save_context *ctx)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch int ret;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = dbox_save_finish_write(ctx);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch index_save_context_free(ctx);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return ret;
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek}
62461eb609e1d852e027cf4e07d30d51288678a2Aki Tuomi
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschvoid sdbox_save_cancel(struct mail_save_context *_ctx)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ctx->failed = TRUE;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch (void)sdbox_save_finish(_ctx);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic int dbox_save_assign_uids(struct sdbox_save_context *ctx,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch const ARRAY_TYPE(seq_range) *uids)
191153d1a5b0eb0c129139570e3aa5212f28d2acJosef 'Jeff' Sipek{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_file *const *files;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct seq_range_iter iter;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch unsigned int i, count, n = 0;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch uint32_t uid;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch bool ret;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch seq_range_array_iter_init(&iter, uids);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch files = array_get(&ctx->files, &count);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch for (i = 0; i < count; i++) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct sdbox_file *sfile = (struct sdbox_file *)files[i];
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch ret = seq_range_array_iter_nth(&iter, n++, &uid);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch i_assert(ret);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (sdbox_file_assign_uid(sfile, uid) < 0)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return -1;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch return 0;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Boschstatic void dbox_save_unref_files(struct sdbox_save_context *ctx)
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch{
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct mail_storage *storage = &ctx->mbox->storage->storage.storage;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch struct dbox_file **files;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch unsigned int i, count;
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch files = array_get_modifiable(&ctx->files, &count);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch for (i = 0; i < count; i++) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (ctx->ctx.failed) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch if (unlink(files[i]->cur_path) < 0) {
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch mail_storage_set_critical(storage,
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch "unlink(%s) failed: %m",
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch files[i]->cur_path);
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
d6bbf85809664a810726b5c711c7213874d8df57Phil Carmody dbox_file_unref(&files[i]);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch }
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch array_free(&ctx->files);
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch}
4a272f5b8bacf2852c2e53f3aa8e899e0d5c604fStephan Bosch
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodyint sdbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody struct mailbox_transaction_context *_t = _ctx->transaction;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody const struct mail_index_header *hdr;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
bee4935fb14a078052e4524070910fd0b8135ef7Phil Carmody i_assert(ctx->ctx.finished);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (array_count(&ctx->files) == 0)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody return 0;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (sdbox_sync_begin(ctx->mbox, SDBOX_SYNC_FLAG_FORCE |
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody SDBOX_SYNC_FLAG_FSYNC, &ctx->sync_ctx) < 0) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody sdbox_transaction_save_rollback(_ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody return -1;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody /* assign UIDs for new messages */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid,
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody &_t->changes->saved_uids);
bee4935fb14a078052e4524070910fd0b8135ef7Phil Carmody if (dbox_save_assign_uids(ctx, &_t->changes->saved_uids) < 0) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody sdbox_transaction_save_rollback(_ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody return -1;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ctx->ctx.mail != NULL)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody mail_free(&ctx->ctx.mail);
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody _t->changes->uid_validity = hdr->uid_validity;
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody return 0;
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody}
bee4935fb14a078052e4524070910fd0b8135ef7Phil Carmody
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmodyvoid sdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
47ca7a853a116b1be3d73b46301d97e572f2f806Phil Carmody struct mail_index_transaction_commit_result *result)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody _ctx->transaction = NULL; /* transaction is already freed */
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (array_count(&ctx->files) == 0) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody sdbox_transaction_save_rollback(_ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody return;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody result);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (sdbox_sync_finish(&ctx->sync_ctx, TRUE) < 0)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody ctx->ctx.failed = TRUE;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (!ctx->mbox->storage->storage.storage.set->fsync_disable) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (fdatasync_path(ctx->mbox->box.path) < 0) {
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody i_error("fdatasync_path(%s) failed: %m",
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody ctx->mbox->box.path);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody }
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody sdbox_transaction_save_rollback(_ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmodyvoid sdbox_transaction_save_rollback(struct mail_save_context *_ctx)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody{
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (!ctx->ctx.finished)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody sdbox_save_cancel(_ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody dbox_save_unref_files(ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ctx->sync_ctx != NULL)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody (void)sdbox_sync_finish(&ctx->sync_ctx, FALSE);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody if (ctx->ctx.mail != NULL)
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody mail_free(&ctx->ctx.mail);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody i_free(ctx);
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody}
42826d96c8d0bba9eddc85b01bf70d7db571ae7fPhil Carmody