bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* updated for each appended mail: */
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek#define CYDIR_SAVECTX(s) container_of(s, struct cydir_save_context, ctx)
d97860e16db095a14038d50efda1e4bb64375128Timo Sirainen return i_strdup_printf("temp.%s.P%sQ%uM%s.%s",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen dec2str(ioloop_timeval.tv_usec), my_hostname);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic const char *
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainencydir_get_save_path(struct cydir_save_context *ctx, unsigned int num)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainencydir_save_alloc(struct mailbox_transaction_context *t)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_mailbox *mbox = CYDIR_MAILBOX(t->box);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen ctx->tmp_basename = cydir_generate_tmp_filename();
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainenint cydir_save_begin(struct mail_save_context *_ctx, struct istream *input)
9287cdd3d77d361ef75a987da24a97a5f43b4954Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen struct mailbox_transaction_context *trans = _ctx->transaction;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen path = cydir_get_save_path(ctx, ctx->mail_count);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ctx->fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0660);
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(trans->box, "open(%s) failed: %m",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* add to index */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mail_index_update_keywords(ctx->trans, ctx->seq,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen mail_index_update_modseq(ctx->trans, ctx->seq,
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen mail_set_seq_saving(_ctx->dest_mail, ctx->seq);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenint cydir_save_continue(struct mail_save_context *_ctx)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);
c68f28e2cf5f9621511bece0414335e551dc82c6Timo Sirainen if (index_storage_save_continue(_ctx, ctx->input,
1e73a28edcf5ec105d238a7d7c95c390e8c84c8fTimo Sirainenstatic int cydir_save_flush(struct cydir_save_context *ctx, const char *path)
b66484774d4059fa10671cbc50b6489fa40b117fTimo Sirainen struct mail_storage *storage = &ctx->mbox->storage->storage;
ad9afb64630511d5e25bc5bc11c5304986156928Timo Sirainen if (o_stream_finish(ctx->ctx.data.output) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "write(%s) failed: %s", path,
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "fsync(%s) failed: %m", path);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (ctx->ctx.data.received_date == (time_t)-1) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "fstat(%s) failed: %m", path);
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "utime(%s) failed: %m", path);
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "close(%s) failed: %m", path);
1e73a28edcf5ec105d238a7d7c95c390e8c84c8fTimo Sirainenint cydir_save_finish(struct mail_save_context *_ctx)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);
1e73a28edcf5ec105d238a7d7c95c390e8c84c8fTimo Sirainen const char *path = cydir_get_save_path(ctx, ctx->mail_count);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen index_mail_cache_parse_deinit(_ctx->dest_mail,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenvoid cydir_save_cancel(struct mail_save_context *_ctx)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenint cydir_transaction_save_commit_pre(struct mail_save_context *_ctx)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen struct mailbox_transaction_context *_t = _ctx->transaction;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen unsigned int n;
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen if (cydir_sync_begin(ctx->mbox, &ctx->sync_ctx, TRUE) < 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
8cf32443413f811d514123c5c74c95c87594b0e3Timo Sirainen mail_index_append_finish_uids(ctx->trans, hdr->next_uid,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen _t->changes->uid_validity = ctx->sync_ctx->uid_validity;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_printfa(src_path, "%s/%s.", dir, ctx->tmp_basename);
8cf32443413f811d514123c5c74c95c87594b0e3Timo Sirainen seq_range_array_iter_init(&iter, &_t->changes->saved_uids); n = 0;
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen while (seq_range_array_iter_nth(&iter, n++, &uid)) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (rename(str_c(src_path), str_c(dest_path)) < 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen "rename(%s, %s) failed: %m",
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenvoid cydir_transaction_save_commit_post(struct mail_save_context *_ctx,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index_transaction_commit_result *result)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen _ctx->transaction = NULL; /* transaction is already freed */
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (void)cydir_sync_finish(&ctx->sync_ctx, TRUE);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainenvoid cydir_transaction_save_rollback(struct mail_save_context *_ctx)
a97fdf205b182250b0fe56c0f6f418bc22fb09a3Josef 'Jeff' Sipek struct cydir_save_context *ctx = CYDIR_SAVECTX(_ctx);