cydir-save.c revision ad48319996942463675b53877092ab7e13a7a75a
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen /* updated for each appended mail: */
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen static unsigned int create_count = 0;
8836c374dc344a48d4f6cefdf224089f3a0c40c6Stephan Bosch return i_strdup_printf("temp.%s.P%sQ%uM%s.%s",
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dec2str(ioloop_timeval.tv_usec), my_hostname);
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenstatic const char *
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainencydir_get_save_path(struct cydir_save_context *ctx, unsigned int num)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen const char *dir;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen dir = mailbox_list_get_path(ctx->mbox->ibox.box.list,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num);
1b75b342eca820e52ca27e6bc33e0062d63eece3Timo Sirainencydir_save_alloc(struct mailbox_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;
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx = t->save_ctx = i_new(struct cydir_save_context, 1);
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch ctx->tmp_basename = cydir_generate_tmp_filename();
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Boschint cydir_save_begin(struct mail_save_context *_ctx, struct istream *input)
1b75b342eca820e52ca27e6bc33e0062d63eece3Timo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct mailbox_transaction_context *trans = _ctx->transaction;
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 mail_storage_set_critical(trans->box->storage,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen /* add to index */
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_update_keywords(ctx->trans, ctx->seq,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen mail_index_update_modseq(ctx->trans, ctx->seq,
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenint cydir_save_continue(struct mail_save_context *_ctx)
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen struct mail_storage *storage = &ctx->mbox->storage->storage;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen if (o_stream_send_istream(_ctx->output, ctx->input) < 0) {
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainen "o_stream_send_istream(%s) failed: %m",
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen index_mail_cache_parse_continue(_ctx->dest_mail);
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 Sirainenint cydir_save_finish(struct mail_save_context *_ctx)
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 index_mail_cache_parse_deinit(_ctx->dest_mail,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainenvoid cydir_save_cancel(struct mail_save_context *_ctx)
d29c3ac4da9857ffcce57eec726d042c292e2becTimo Sirainen struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx;
17fc2a887a5683b2e1bbd6bd9fdf0cdb97b509fbTimo Sirainenint cydir_transaction_save_commit_pre(struct cydir_save_context *ctx)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen struct mailbox_transaction_context *_t = ctx->ctx.transaction;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen const char *dir;
f1b04cf99c9e45c318f31e6c5ade595ee7e595a5Stephan Bosch unsigned int n, src_prefixlen, dest_prefixlen;
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen if (cydir_sync_begin(ctx->mbox, &ctx->sync_ctx, TRUE) < 0) {
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->uid_validity = ctx->sync_ctx->uid_validity;
96e3a90451b495d8bedbe5dd731539269cb8c08dStephan Bosch dir = mailbox_list_get_path(ctx->mbox->ibox.box.list,
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen str_printfa(src_path, "%s/%s.", dir, ctx->tmp_basename);
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 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 Sirainenvoid cydir_transaction_save_commit_post(struct cydir_save_context *ctx)
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen ctx->ctx.transaction = NULL; /* transaction is already freed */
ba54c712141b9764a2e06ed8dfb35bc3154b53c7Timo Sirainen (void)cydir_sync_finish(&ctx->sync_ctx, TRUE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvivoid cydir_transaction_save_rollback(struct cydir_save_context *ctx)