mbox-sync-rewrite.c revision 313fe89df4d91cd0cd7f3558dc6d7fd21ad39eee
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenint mbox_move(struct mbox_sync_context *sync_ctx,
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen output = o_stream_create_file(sync_ctx->fd, default_pool, 4096, FALSE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return o_stream_send_istream(output, input) < 0 ? -1 : 0;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenstatic void mbox_sync_headers_add_space(struct mbox_sync_mail_context *ctx,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const unsigned char *data;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* Append at the end of X-Keywords header,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen or X-UID if it doesn't exist */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen pos = ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] != (size_t)-1 ?
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen data = buffer_get_data(ctx->header, &data_size);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen p = buffer_get_space_unsafe(ctx->header, pos, size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void mbox_sync_header_remove_space(struct mbox_sync_mail_context *ctx,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const unsigned char *data;
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek /* find the end of the lwsp */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (end+1 == data_size || !IS_LWSP(data[end+1]))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* and remove what we can */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen str_delete(ctx->header, nonspace, end-nonspace);
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainenstatic void mbox_sync_headers_remove_space(struct mbox_sync_mail_context *ctx,
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen static enum header_position space_positions[] = {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (ctx->header_first_change > ctx->hdr_pos[pos])
d1ba8ecbb936ace90179d2292952546708d68f71Timo Sirainen mbox_sync_header_remove_space(ctx, ctx->hdr_pos[pos],
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainenint mbox_sync_try_rewrite(struct mbox_sync_mail_context *ctx)
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen const unsigned char *data;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen old_hdr_size = ctx->body_offset - ctx->hdr_offset;
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen /* do we have enough space? */
e0a84bcd487b05872da59781452168609b5c1f2cTimo Sirainen mbox_sync_headers_add_space(ctx, old_hdr_size - new_hdr_size);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen i_assert(ctx->header_first_change != (size_t)-1);
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen str_truncate(ctx->header, ctx->header_last_change);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (pwrite_full(ctx->sync_ctx->fd, data + ctx->header_first_change,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ctx->hdr_offset + ctx->header_first_change) < 0) {
31633d676642b83305b8d46da495d9bb4e2d1ff8Timo Sirainen // FIXME: error handling
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomistatic void mbox_sync_fix_from_offset(struct mbox_sync_context *sync_ctx,
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen offset_p = buffer_get_space_unsafe(sync_ctx->ibox->mbox_data_buf,
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen *offset_p = (*offset_p & 1) | (((*offset_p >> 1) + diff) << 1);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainenstatic int mbox_sync_read_and_move(struct mbox_sync_context *sync_ctx,
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen i_stream_seek(sync_ctx->file_input, mails[idx].offset);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_ctx.mail.body_size = mails[idx].body_size;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen mbox_sync_parse_next_mail(sync_ctx->file_input, &mail_ctx);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mbox_sync_update_header_from(&mail_ctx, &mails[idx]);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen i_assert(mail_ctx.mail.space == mails[idx].space);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen /* we're moving next message - update it's from_offset */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen mbox_sync_fix_from_offset(sync_ctx, idx+1, mails[idx+1].space);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mbox_sync_headers_add_space(&mail_ctx, extra_per_mail);
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi } else if (mail_ctx.mail.space <= extra_per_mail) {
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi mbox_sync_headers_add_space(&mail_ctx, extra_per_mail -
50168536f8d04626d71860c73b2efc18d407d083Aki Tuomi mbox_sync_headers_remove_space(&mail_ctx, mail_ctx.mail.space -
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen /* now we have to move it. first move the body of the message,
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen then write the header and leave the extra space to beginning of
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (mbox_move(sync_ctx, offset + mails[idx+1].space, offset,
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen // FIXME: error handling
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen *end_offset = offset + mails[idx+1].space - str_len(mail_ctx.header);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen if (pwrite_full(sync_ctx->fd, str_data(mail_ctx.header),
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen // FIXME: error handling
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen mails[idx].space += mails[idx+1].space - extra_per_mail;
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenint mbox_sync_rewrite(struct mbox_sync_context *sync_ctx, buffer_t *mails_buf,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen uint32_t first_seq, uint32_t last_seq, off_t extra_space)
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen mails = buffer_get_modifyable_data(mails_buf, &size);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen /* FIXME: see if we can be faster by going back a few mails
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen (update first_seq and last_seq). */
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen extra_per_mail = (extra_space / (last_seq - first_seq + 1));
6e5a4cdf7ef123589e2409e0012b1024c97957d5Aki Tuomi end_offset = mails[last_seq-1].offset + mails[last_seq-1].space;
865a82c1e9bba11609835a36674964649025bf77Timo Sirainen /* start moving backwards */
3db05c8c00faca6ab9ac8391e1d6977365f4d1b3Timo Sirainen /* offset points to beginning of headers. read the
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen header again, update it and give enough space to
f0ecd925c7feb815c4b9acf84772fcd56c02319bTimo Sirainen if (mbox_sync_read_and_move(sync_ctx, mails, idx,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* X-Keywords: xx [offset] \n
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen X-Keywords: xx [end_offset] \n
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen move data forward so mails before us gets the extra
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen space (ie. we temporarily get more space to us) */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen offset = mails[idx].offset + mails[idx].space;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (mbox_move(sync_ctx, offset + mails[idx+1].space,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen // FIXME: error handling
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen mails[idx].space += mails[idx+1].space - extra_per_mail;