cydir-save.c revision ad48319996942463675b53877092ab7e13a7a75a
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "lib.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "array.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "hostpid.h"
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen#include "istream.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "istream-crlf.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "ostream.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "str.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "index-mail.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "cydir-storage.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include "cydir-sync.h"
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include <stdio.h>
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen#include <utime.h>
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenstruct cydir_save_context {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen struct mail_save_context ctx;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen struct cydir_mailbox *mbox;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct mail_index_transaction *trans;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen char *tmp_basename;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen unsigned int mail_count;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct cydir_sync_context *sync_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen /* updated for each appended mail: */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen uint32_t seq;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen struct istream *input;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct mail *mail;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen int fd;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen unsigned int failed:1;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen unsigned int finished:1;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen};
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstatic char *cydir_generate_tmp_filename(void)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen static unsigned int create_count = 0;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch return i_strdup_printf("temp.%s.P%sQ%uM%s.%s",
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch dec2str(ioloop_timeval.tv_sec), my_pid,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen create_count++,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dec2str(ioloop_timeval.tv_usec), my_hostname);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstatic const char *
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainencydir_get_save_path(struct cydir_save_context *ctx, unsigned int num)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen const char *dir;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dir = mailbox_list_get_path(ctx->mbox->ibox.box.list,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->mbox->ibox.box.name,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen}
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstruct mail_save_context *
1b75b342eca820e52ca27e6bc33e0062d63eece3Timo Sirainencydir_save_alloc(struct mailbox_transaction_context *_t)
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen struct cydir_transaction_context *t =
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen (struct cydir_transaction_context *)_t;
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek struct cydir_mailbox *mbox = (struct cydir_mailbox *)t->ictx.ibox;
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek struct cydir_save_context *ctx = t->save_ctx;
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch if (t->save_ctx != NULL)
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch return &t->save_ctx->ctx;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx = t->save_ctx = i_new(struct cydir_save_context, 1);
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx->ctx.transaction = &t->ictx.mailbox_ctx;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx->mbox = mbox;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx->trans = t->ictx.trans;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx->tmp_basename = cydir_generate_tmp_filename();
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch return &ctx->ctx;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch}
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Boschint cydir_save_begin(struct mail_save_context *_ctx, struct istream *input)
1b75b342eca820e52ca27e6bc33e0062d63eece3Timo Sirainen{
1b75b342eca820e52ca27e6bc33e0062d63eece3Timo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct mailbox_transaction_context *trans = _ctx->transaction;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen enum mail_flags save_flags;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct istream *crlf_input;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen T_BEGIN {
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen const char *path;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen path = cydir_get_save_path(ctx, ctx->mail_count);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen ctx->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0660);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen if (ctx->fd != -1) {
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen _ctx->output =
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen o_stream_create_fd_file(ctx->fd, 0, FALSE);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen o_stream_cork(_ctx->output);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen } else {
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen mail_storage_set_critical(trans->box->storage,
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen "open(%s) failed: %m", path);
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen ctx->failed = TRUE;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen }
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen } T_END;
eb2091a2dedf5513dded8a980b79e206c716962dTimo Sirainen if (ctx->failed)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen return -1;
eb2091a2dedf5513dded8a980b79e206c716962dTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen /* add to index */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen save_flags = _ctx->flags & ~MAIL_RECENT;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_append(ctx->trans, 0, &ctx->seq);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen save_flags);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (_ctx->keywords != NULL) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_update_keywords(ctx->trans, ctx->seq,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen MODIFY_REPLACE, _ctx->keywords);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (_ctx->min_modseq != 0) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_update_modseq(ctx->trans, ctx->seq,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen _ctx->min_modseq);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (_ctx->dest_mail == NULL) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (ctx->mail == NULL)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->mail = mail_alloc(trans, 0, NULL);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen _ctx->dest_mail = ctx->mail;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_set_seq(_ctx->dest_mail, ctx->seq);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen crlf_input = i_stream_create_crlf(input);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen i_stream_unref(&crlf_input);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen return ctx->failed ? -1 : 0;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen}
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenint cydir_save_continue(struct mail_save_context *_ctx)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen{
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct mail_storage *storage = &ctx->mbox->storage->storage;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (ctx->failed)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen return -1;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen do {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (o_stream_send_istream(_ctx->output, ctx->input) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_storage_set_critical(storage,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen "o_stream_send_istream(%s) failed: %m",
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen cydir_get_save_path(ctx, ctx->mail_count));
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->failed = TRUE;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return -1;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen index_mail_cache_parse_continue(_ctx->dest_mail);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen /* both tee input readers may consume data from our primary
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen input stream. we'll have to make sure we don't return with
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen one of the streams still having data in them. */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen } while (i_stream_read(ctx->input) > 0);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return 0;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenint cydir_save_finish(struct mail_save_context *_ctx)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen{
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
28715adb0aa53197a25aac72f1bdd44f44df3cd1Timo Sirainen struct mail_storage *storage = &ctx->mbox->storage->storage;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen const char *path = cydir_get_save_path(ctx, ctx->mail_count);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen struct stat st;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->finished = TRUE;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (o_stream_flush(_ctx->output) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_storage_set_critical(storage,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen "o_stream_flush(%s) failed: %m", path);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->failed = TRUE;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (!storage->set->fsync_disable) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (fsync(ctx->fd) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_storage_set_critical(storage,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen "fsync(%s) failed: %m", path);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->failed = TRUE;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (_ctx->received_date == (time_t)-1) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (fstat(ctx->fd, &st) == 0)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen _ctx->received_date = st.st_mtime;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen else {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_storage_set_critical(storage,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen "fstat(%s) failed: %m", path);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->failed = TRUE;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen }
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen } else {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct utimbuf ut;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ut.actime = ioloop_time;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ut.modtime = _ctx->received_date;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (utime(path, &ut) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_storage_set_critical(storage,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen "utime(%s) failed: %m", path);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->failed = TRUE;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen o_stream_destroy(&_ctx->output);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (close(ctx->fd) < 0) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_storage_set_critical(storage,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen "close(%s) failed: %m", path);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->failed = TRUE;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen }
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen ctx->fd = -1;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen if (!ctx->failed)
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen ctx->mail_count++;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen else {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (unlink(path) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_storage_set_critical(storage,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen "unlink(%s) failed: %m", path);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen index_mail_cache_parse_deinit(_ctx->dest_mail,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen _ctx->received_date, !ctx->failed);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen i_stream_unref(&ctx->input);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen index_save_context_free(_ctx);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return ctx->failed ? -1 : 0;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenvoid cydir_save_cancel(struct mail_save_context *_ctx)
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen{
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->failed = TRUE;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen (void)cydir_save_finish(_ctx);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenint cydir_transaction_save_commit_pre(struct cydir_save_context *ctx)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen struct mailbox_transaction_context *_t = ctx->ctx.transaction;
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek const struct mail_index_header *hdr;
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen struct seq_range_iter iter;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen uint32_t uid;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen const char *dir;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen string_t *src_path, *dest_path;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch unsigned int n, src_prefixlen, dest_prefixlen;
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch i_assert(ctx->finished);
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (cydir_sync_begin(ctx->mbox, &ctx->sync_ctx, TRUE) < 0) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->failed = TRUE;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen cydir_transaction_save_rollback(ctx);
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen return -1;
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen }
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen mail_index_append_finish_uids(ctx->trans, hdr->next_uid,
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch &_t->changes->saved_uids);
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch _t->changes->uid_validity = ctx->sync_ctx->uid_validity;
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch dir = mailbox_list_get_path(ctx->mbox->ibox.box.list,
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch ctx->mbox->ibox.box.name,
994a2b017b5b7da97914baa1ef711b124c8d15a7Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen src_path = t_str_new(256);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_printfa(src_path, "%s/%s.", dir, ctx->tmp_basename);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen src_prefixlen = str_len(src_path);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dest_path = t_str_new(256);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_append(dest_path, dir);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_append_c(dest_path, '/');
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dest_prefixlen = str_len(dest_path);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen seq_range_array_iter_init(&iter, &_t->changes->saved_uids); n = 0;
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch while (seq_range_array_iter_nth(&iter, n++, &uid) > 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_truncate(src_path, src_prefixlen);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_truncate(dest_path, dest_prefixlen);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_printfa(src_path, "%u", n-1);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_printfa(dest_path, "%u.", uid);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (rename(str_c(src_path), str_c(dest_path)) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_storage_set_critical(&ctx->mbox->storage->storage,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen "rename(%s, %s) failed: %m",
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_c(src_path), str_c(dest_path));
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->failed = TRUE;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen cydir_transaction_save_rollback(ctx);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return -1;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen }
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (ctx->mail != NULL)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen mail_free(&ctx->mail);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return 0;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenvoid cydir_transaction_save_commit_post(struct cydir_save_context *ctx)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->ctx.transaction = NULL; /* transaction is already freed */
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen (void)cydir_sync_finish(&ctx->sync_ctx, TRUE);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen cydir_transaction_save_rollback(ctx);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen}
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvivoid cydir_transaction_save_rollback(struct cydir_save_context *ctx)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen{
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (!ctx->finished)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen cydir_save_cancel(&ctx->ctx);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen if (ctx->sync_ctx != NULL)
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen (void)cydir_sync_finish(&ctx->sync_ctx, FALSE);
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen if (ctx->mail != NULL)
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen mail_free(&ctx->mail);
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen i_free(ctx->tmp_basename);
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen i_free(ctx);
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen}
30f128cc663b8aeb68bb3bfb9ed49ab2e48029e1Timo Sirainen