dbox-save.c revision 9865d9e7c5713e41db939222ed9c0225a11fb99e
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2007-2013 Dovecot authors, see the included COPYING file */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenvoid dbox_save_add_to_index(struct dbox_save_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct mail_save_data *mdata = &ctx->ctx.data;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_index_append(ctx->trans, mdata->uid, &ctx->seq);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mail_index_update_keywords(ctx->trans, ctx->seq,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen mail_index_update_modseq(ctx->trans, ctx->seq,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenvoid dbox_save_begin(struct dbox_save_context *ctx, struct istream *input)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct mail_storage *_storage = _ctx->transaction->box->storage;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen struct dbox_storage *storage = (struct dbox_storage *)_storage;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen ctx->mail = mail_alloc(_ctx->transaction, 0, NULL);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen mail_set_seq_saving(_ctx->dest_mail, ctx->seq);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* write a dummy header. it'll get rewritten when we're finished */
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen memset(&dbox_msg_hdr, 0, sizeof(dbox_msg_hdr));
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (o_stream_send(ctx->dbox_output, &dbox_msg_hdr,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen sizeof(dbox_msg_hdr)) < 0) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail_storage_set_critical(_storage, "write(%s) failed: %m",
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen index_attachment_save_begin(_ctx, storage->attachment_fs, ctx->input);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenint dbox_save_continue(struct mail_save_context *_ctx)
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen struct mail_storage *storage = _ctx->transaction->box->storage;
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen if (o_stream_send_istream(_ctx->data.output, ctx->input) < 0) {
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen "write(%s) failed: %m",
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen index_mail_cache_parse_continue(_ctx->dest_mail);
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen /* both tee input readers may consume data from our primary
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen input stream. we'll have to make sure we don't return with
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen one of the streams still having data in them. */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenvoid dbox_save_end(struct dbox_save_context *ctx)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct mail_save_data *mdata = &ctx->ctx.data;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct ostream *dbox_output = ctx->dbox_output;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (index_attachment_save_finish(&ctx->ctx) < 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen mail_storage_set_critical(ctx->ctx.transaction->box->storage,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen "write(%s) failed: %m",
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen /* e.g. zlib plugin had changed this */
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen index_mail_cache_parse_deinit(ctx->ctx.dest_mail,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenvoid dbox_save_write_metadata(struct mail_save_context *_ctx,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct ostream *output, uoff_t output_msg_size,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen struct mail_save_data *mdata = &ctx->ctx.data;
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen memset(&metadata_hdr, 0, sizeof(metadata_hdr));
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen memcpy(metadata_hdr.magic_post, DBOX_MAGIC_POST,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen o_stream_nsend(output, &metadata_hdr, sizeof(metadata_hdr));
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen if (output_msg_size != ctx->input->v_offset) {
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen /* a plugin changed the data written to disk, so the
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen "message size" dbox header doesn't contain the actual
38a4c09de37bc2ebdc38427a2b958c46dfdcffb1Timo Sirainen "physical" message size. we need to save it as a
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen separate metadata header. */
0f55802e8fdd95ae4290da6da077819209b71f70Timo Sirainen str_printfa(str, "%c%llx\n", DBOX_METADATA_PHYSICAL_SIZE,
20b136f04257b0ba338e49f31a999c0d4b243647Timo Sirainen str_printfa(str, "%c%lx\n", DBOX_METADATA_RECEIVED_TIME,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (mail_get_virtual_size(_ctx->dest_mail, &vsize) < 0)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen (unsigned long long)vsize);
992118a50af940482b6cf884a89be56d7015580aTimo Sirainen i_assert(strchr(mdata->pop3_uidl, '\n') == NULL);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen str_printfa(str, "%c%s\n", DBOX_METADATA_POP3_UIDL,
c37e5edd83ff696d396131f7147ef971cf678911Timo Sirainen str_printfa(str, "%c%u\n", DBOX_METADATA_POP3_ORDER,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen str_printfa(str, "%c%s\n", DBOX_METADATA_GUID, guid);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen /* save the original mailbox name so if mailbox indexes get
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen corrupted we can place at least some (hopefully most) of
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen the messages to correct mailboxes. */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen str_printfa(str, "%c%s\n", DBOX_METADATA_ORIG_MAILBOX,
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen dbox_attachment_save_write_metadata(_ctx, str);
c06cd6539a3dbd68eb546464076187be6bc4290fTimo Sirainen o_stream_nsend(output, str_data(str), str_len(str));
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainenvoid dbox_save_update_header_flags(struct dbox_save_context *ctx,
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen mail_index_get_header_ext(sync_view, ext_id, &data, &data_size);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen old_flags = *((const uint8_t *)data + flags_offset);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* grow old dbox header */
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen mail_index_ext_resize_hdr(ctx->trans, ext_id, flags_offset+1);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* flags changed, update them */