sdbox-save.c revision cc0a651962a3e54d5a62231ac5847ae7f9f7de7f
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2007-2015 Dovecot authors, see the included COPYING file */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainensdbox_save_file_get_file(struct mailbox_transaction_context *t, uint32_t seq)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen unsigned int count;
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen i_assert(((struct sdbox_file *)file)->written_to_disk);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainensdbox_save_alloc(struct mailbox_transaction_context *t)
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)t->box;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen i_assert((t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* use the existing allocated structure */
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainenvoid sdbox_save_add_file(struct mail_save_context *_ctx, struct dbox_file *file)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen unsigned int count;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen /* a plugin may leave a previously saved file open.
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen we'll close it here to avoid eating too many fds. */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenint sdbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ctx->append_ctx = dbox_file_append_init(file);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ret = dbox_file_get_append_stream(ctx->append_ctx,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenstatic int dbox_save_mail_write_metadata(struct dbox_save_context *ctx,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct sdbox_file *sfile = (struct sdbox_file *)file;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen const ARRAY_TYPE(mail_attachment_extref) *extrefs_arr;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen unsigned int i, count;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen i_assert(file->msg_header_size == sizeof(dbox_msg_hdr));
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen file->msg_header_size - file->file_header_size;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen dbox_save_write_metadata(&ctx->ctx, ctx->dbox_output,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen dbox_msg_header_fill(&dbox_msg_hdr, message_size);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (o_stream_pwrite(ctx->dbox_output, &dbox_msg_hdr,
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen dbox_file_set_syscall_error(file, "pwrite()");
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen /* remember the attachment paths until commit time */
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen extrefs_arr = index_attachment_save_get_extrefs(&ctx->ctx);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen pool_alloconly_create("sdbox attachment paths", 512);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen for (i = 0; i < count; i++) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *path = p_strdup(sfile->attachment_pool,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen array_append(&sfile->attachment_paths, &path, 1);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic int dbox_save_finish_write(struct mail_save_context *_ctx)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* we can't change ctime, but we can add the date to cache */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen struct index_mail *mail = (struct index_mail *)_ctx->dest_mail;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen files = array_idx_modifiable(&ctx->files, array_count(&ctx->files) - 1);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (dbox_save_mail_write_metadata(&ctx->ctx, *files) < 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen mail_index_expunge(ctx->ctx.trans, ctx->ctx.seq);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen array_delete(&ctx->files, array_count(&ctx->files) - 1, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (dbox_file_append_commit(&ctx->append_ctx) < 0)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenint sdbox_save_finish(struct mail_save_context *ctx)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainenvoid sdbox_save_cancel(struct mail_save_context *_ctx)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainenstatic int dbox_save_assign_uids(struct sdbox_save_context *ctx,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen unsigned int i, count, n = 0;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen for (i = 0; i < count; i++) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen struct sdbox_file *sfile = (struct sdbox_file *)files[i];
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen ret = seq_range_array_iter_nth(&iter, n++, &uid);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void dbox_save_unref_files(struct sdbox_save_context *ctx)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen unsigned int i, count;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen files = array_get_modifiable(&ctx->files, &count);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen for (i = 0; i < count; i++) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenint sdbox_transaction_save_commit_pre(struct mail_save_context *_ctx)
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen struct mailbox_transaction_context *_t = _ctx->transaction;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* the mail must be freed in the commit_pre() */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (sdbox_sync_begin(ctx->mbox, SDBOX_SYNC_FLAG_FORCE |
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen /* update dbox header flags */
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen dbox_save_update_header_flags(&ctx->ctx, ctx->sync_ctx->sync_view,
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen ctx->mbox->hdr_ext_id, offsetof(struct sdbox_index_header, flags));
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen /* assign UIDs for new messages */
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen hdr = mail_index_get_header(ctx->sync_ctx->sync_view);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid,
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (dbox_save_assign_uids(ctx, &_t->changes->saved_uids) < 0) {
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen _t->changes->uid_validity = hdr->uid_validity;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid sdbox_transaction_save_commit_post(struct mail_save_context *_ctx,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct mail_index_transaction_commit_result *result)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen struct mail_storage *storage = _ctx->transaction->box->storage;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen _ctx->transaction = NULL; /* transaction is already freed */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen mail_index_sync_set_commit_result(ctx->sync_ctx->index_sync_ctx,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (sdbox_sync_finish(&ctx->sync_ctx, TRUE) < 0)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (storage->set->parsed_fsync_mode != FSYNC_MODE_NEVER) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen const char *box_path = mailbox_get_path(&ctx->mbox->box);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenvoid sdbox_transaction_save_rollback(struct mail_save_context *_ctx)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen struct sdbox_save_context *ctx = (struct sdbox_save_context *)_ctx;