From: Timo Sirainen Date: Thu, 7 Aug 2008 18:05:47 +0000 (-0400) Subject: mailbox_save_init() API was split to multiple functions. X-Git-Tag: 1.2.alpha1~86 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e3aeeb634245e80d4f643f8d2eea11d6b72336d8;p=thirdparty%2Fdovecot%2Fcore.git mailbox_save_init() API was split to multiple functions. This allows adding more parameters easily in future. --HG-- branch : HEAD --- diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c index cd1bd0826c..84ffbf2ada 100644 --- a/src/imap/cmd-append.c +++ b/src/imap/cmd-append.c @@ -327,9 +327,11 @@ static bool cmd_append_continue_parsing(struct client_command_context *cmd) /* save the mail */ ctx->input = i_stream_create_limit(client->input, ctx->msg_size); - ret = mailbox_save_init(ctx->t, flags, keywords, - internal_date, timezone_offset, NULL, - ctx->input, FALSE, &ctx->save_ctx); + ctx->save_ctx = mailbox_save_alloc(ctx->t); + mailbox_save_set_flags(ctx->save_ctx, flags, keywords); + mailbox_save_set_received_date(ctx->save_ctx, + internal_date, timezone_offset); + ret = mailbox_save_begin(&ctx->save_ctx, ctx->input); if (keywords != NULL) mailbox_keywords_free(ctx->box, &keywords); diff --git a/src/lib-storage/index/cydir/cydir-save.c b/src/lib-storage/index/cydir/cydir-save.c index 67873d921f..7deec9f25d 100644 --- a/src/lib-storage/index/cydir/cydir-save.c +++ b/src/lib-storage/index/cydir/cydir-save.c @@ -28,8 +28,7 @@ struct cydir_save_context { uint32_t seq; struct istream *input; struct ostream *output; - struct mail *mail, *cur_dest_mail; - time_t cur_received_date; + struct mail *mail; int fd; unsigned int failed:1; @@ -57,29 +56,33 @@ cydir_get_save_path(struct cydir_save_context *ctx, unsigned int num) return t_strdup_printf("%s/%s.%u", dir, ctx->tmp_basename, num); } -int cydir_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset ATTR_UNUSED, - const char *from_envelope ATTR_UNUSED, - struct istream *input, struct mail **dest_mail, - struct mail_save_context **ctx_r) +struct mail_save_context * +cydir_save_alloc(struct mailbox_transaction_context *_t) { struct cydir_transaction_context *t = (struct cydir_transaction_context *)_t; struct cydir_mailbox *mbox = (struct cydir_mailbox *)t->ictx.ibox; struct cydir_save_context *ctx = t->save_ctx; - enum mail_flags save_flags; - struct istream *crlf_input; i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); - if (ctx == NULL) { - ctx = t->save_ctx = i_new(struct cydir_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; - ctx->mbox = mbox; - ctx->trans = t->ictx.trans; - ctx->tmp_basename = cydir_generate_tmp_filename(); - } + if (t->save_ctx != NULL) + return &t->save_ctx->ctx; + + ctx = t->save_ctx = i_new(struct cydir_save_context, 1); + ctx->ctx.transaction = &t->ictx.mailbox_ctx; + ctx->mbox = mbox; + ctx->trans = t->ictx.trans; + ctx->tmp_basename = cydir_generate_tmp_filename(); + return &ctx->ctx; +} + +int cydir_save_begin(struct mail_save_context *_ctx, struct istream *input) +{ + struct cydir_save_context *ctx = (struct cydir_save_context *)_ctx; + struct mailbox_transaction_context *trans = _ctx->transaction; + enum mail_flags save_flags; + struct istream *crlf_input; T_BEGIN { const char *path; @@ -91,7 +94,7 @@ int cydir_save_init(struct mailbox_transaction_context *_t, o_stream_create_fd_file(ctx->fd, 0, FALSE); o_stream_cork(ctx->output); } else { - mail_storage_set_critical(_t->box->storage, + mail_storage_set_critical(trans->box->storage, "open(%s) failed: %m", path); ctx->failed = TRUE; } @@ -100,30 +103,25 @@ int cydir_save_init(struct mailbox_transaction_context *_t, return -1; /* add to index */ - save_flags = flags & ~MAIL_RECENT; + save_flags = _ctx->flags & ~MAIL_RECENT; mail_index_append(ctx->trans, 0, &ctx->seq); mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE, save_flags); - if (keywords != NULL) { + if (_ctx->keywords != NULL) { mail_index_update_keywords(ctx->trans, ctx->seq, - MODIFY_REPLACE, keywords); + MODIFY_REPLACE, _ctx->keywords); } - if (*dest_mail == NULL) { + if (_ctx->dest_mail == NULL) { if (ctx->mail == NULL) - ctx->mail = mail_alloc(_t, 0, NULL); - *dest_mail = ctx->mail; + ctx->mail = mail_alloc(trans, 0, NULL); + _ctx->dest_mail = ctx->mail; } - mail_set_seq(*dest_mail, ctx->seq); + mail_set_seq(_ctx->dest_mail, ctx->seq); crlf_input = i_stream_create_crlf(input); - ctx->input = index_mail_cache_parse_init(*dest_mail, crlf_input); + ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input); i_stream_unref(&crlf_input); - - ctx->cur_dest_mail = *dest_mail; - ctx->cur_received_date = received_date; - - *ctx_r = &ctx->ctx; return ctx->failed ? -1 : 0; } @@ -145,7 +143,7 @@ int cydir_save_continue(struct mail_save_context *_ctx) ctx->failed = TRUE; return -1; } - index_mail_cache_parse_continue(ctx->cur_dest_mail); + index_mail_cache_parse_continue(_ctx->dest_mail); /* both tee input readers may consume data from our primary input stream. we'll have to make sure we don't return with @@ -177,9 +175,9 @@ int cydir_save_finish(struct mail_save_context *_ctx) } } - if (ctx->cur_received_date == (time_t)-1) { + if (_ctx->received_date == (time_t)-1) { if (fstat(ctx->fd, &st) == 0) - ctx->cur_received_date = st.st_mtime; + _ctx->received_date = st.st_mtime; else { mail_storage_set_critical(storage, "fstat(%s) failed: %m", path); @@ -189,7 +187,7 @@ int cydir_save_finish(struct mail_save_context *_ctx) struct utimbuf ut; ut.actime = ioloop_time; - ut.modtime = ctx->cur_received_date; + ut.modtime = _ctx->received_date; if (utime(path, &ut) < 0) { mail_storage_set_critical(storage, "utime(%s) failed: %m", path); @@ -214,8 +212,8 @@ int cydir_save_finish(struct mail_save_context *_ctx) } } - index_mail_cache_parse_deinit(ctx->cur_dest_mail, - ctx->cur_received_date, !ctx->failed); + index_mail_cache_parse_deinit(_ctx->dest_mail, + _ctx->received_date, !ctx->failed); i_stream_unref(&ctx->input); return ctx->failed ? -1 : 0; diff --git a/src/lib-storage/index/cydir/cydir-storage.c b/src/lib-storage/index/cydir/cydir-storage.c index c4ce9a4cfb..15c36cec08 100644 --- a/src/lib-storage/index/cydir/cydir-storage.c +++ b/src/lib-storage/index/cydir/cydir-storage.c @@ -453,7 +453,8 @@ struct mailbox cydir_mailbox = { index_storage_search_deinit, index_storage_search_next_nonblock, index_storage_search_next_update_seq, - cydir_save_init, + cydir_save_alloc, + cydir_save_begin, cydir_save_continue, cydir_save_finish, cydir_save_cancel, diff --git a/src/lib-storage/index/cydir/cydir-storage.h b/src/lib-storage/index/cydir/cydir-storage.h index dad1039ae3..296f5cca0d 100644 --- a/src/lib-storage/index/cydir/cydir-storage.h +++ b/src/lib-storage/index/cydir/cydir-storage.h @@ -33,11 +33,9 @@ extern struct mail_vfuncs cydir_mail_vfuncs; void cydir_transaction_class_init(void); void cydir_transaction_class_deinit(void); -int cydir_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, struct mail_save_context **ctx_r); +struct mail_save_context * +cydir_save_alloc(struct mailbox_transaction_context *_t); +int cydir_save_begin(struct mail_save_context *ctx, struct istream *input); int cydir_save_continue(struct mail_save_context *ctx); int cydir_save_finish(struct mail_save_context *ctx); void cydir_save_cancel(struct mail_save_context *ctx); diff --git a/src/lib-storage/index/dbox/dbox-save.c b/src/lib-storage/index/dbox/dbox-save.c index 69dd41e890..b3e8c13b3d 100644 --- a/src/lib-storage/index/dbox/dbox-save.c +++ b/src/lib-storage/index/dbox/dbox-save.c @@ -36,9 +36,7 @@ struct dbox_save_context { /* updated for each appended mail: */ uint32_t seq; struct istream *input; - struct mail *mail, *cur_dest_mail; - time_t cur_received_date; - enum mail_flags cur_flags; + struct mail *mail; string_t *cur_keywords; struct dbox_file *cur_file; @@ -61,17 +59,31 @@ static void dbox_save_keywords(struct dbox_save_context *ctx, keywords); } -int dbox_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset ATTR_UNUSED, - const char *from_envelope ATTR_UNUSED, - struct istream *input, struct mail **dest_mail, - struct mail_save_context **ctx_r) +struct mail_save_context * +dbox_save_alloc(struct mailbox_transaction_context *_t) { struct dbox_transaction_context *t = (struct dbox_transaction_context *)_t; struct dbox_mailbox *mbox = (struct dbox_mailbox *)t->ictx.ibox; - struct dbox_save_context *ctx = t->save_ctx; + struct dbox_save_context *ctx; + + i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); + + if (t->save_ctx != NULL) + return &t->save_ctx->ctx; + + ctx = t->save_ctx = i_new(struct dbox_save_context, 1); + ctx->ctx.transaction = &t->ictx.mailbox_ctx; + ctx->mbox = mbox; + ctx->trans = t->ictx.trans; + ctx->append_ctx = dbox_index_append_begin(mbox->dbox_index); + i_array_init(&ctx->mails, 32); + return &ctx->ctx; +} + +int dbox_save_begin(struct mail_save_context *_ctx, struct istream *input) +{ + struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx; struct dbox_message_header dbox_msg_hdr; struct dbox_save_mail *save_mail; struct istream *crlf_input; @@ -79,17 +91,6 @@ int dbox_save_init(struct mailbox_transaction_context *_t, const struct stat *st; uoff_t mail_size; - i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); - - if (ctx == NULL) { - ctx = t->save_ctx = i_new(struct dbox_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; - ctx->mbox = mbox; - ctx->trans = t->ictx.trans; - ctx->append_ctx = dbox_index_append_begin(mbox->dbox_index); - i_array_init(&ctx->mails, 32); - } - /* get the size of the mail to be saved, if possible */ st = i_stream_stat(input, TRUE); mail_size = st == NULL || st->st_size == -1 ? 0 : st->st_size; @@ -101,26 +102,24 @@ int dbox_save_init(struct mailbox_transaction_context *_t, } /* add to index */ - save_flags = flags & ~MAIL_RECENT; + save_flags = _ctx->flags & ~MAIL_RECENT; mail_index_append(ctx->trans, 0, &ctx->seq); mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE, save_flags); - if (keywords != NULL) { + if (_ctx->keywords != NULL) { mail_index_update_keywords(ctx->trans, ctx->seq, - MODIFY_REPLACE, keywords); + MODIFY_REPLACE, _ctx->keywords); } - if (*dest_mail == NULL) { + if (_ctx->dest_mail == NULL) { if (ctx->mail == NULL) - ctx->mail = mail_alloc(_t, 0, NULL); - *dest_mail = ctx->mail; + ctx->mail = mail_alloc(_ctx->transaction, 0, NULL); + _ctx->dest_mail = ctx->mail; } - mail_set_seq(*dest_mail, ctx->seq); - - ctx->cur_dest_mail = *dest_mail; + mail_set_seq(_ctx->dest_mail, ctx->seq); crlf_input = i_stream_create_lf(input); - ctx->input = index_mail_cache_parse_init(*dest_mail, crlf_input); + ctx->input = index_mail_cache_parse_init(_ctx->dest_mail, crlf_input); i_stream_unref(&crlf_input); save_mail = array_append_space(&ctx->mails); @@ -134,18 +133,15 @@ int dbox_save_init(struct mailbox_transaction_context *_t, o_stream_cork(ctx->cur_output); if (o_stream_send(ctx->cur_output, &dbox_msg_hdr, sizeof(dbox_msg_hdr)) < 0) { - mail_storage_set_critical(_t->box->storage, + mail_storage_set_critical(_ctx->transaction->box->storage, "o_stream_send(%s) failed: %m", dbox_file_get_path(ctx->cur_file)); ctx->failed = TRUE; } - ctx->cur_received_date = received_date != (time_t)-1 ? - received_date : ioloop_time; - ctx->cur_flags = flags; - dbox_save_keywords(ctx, keywords); - - *ctx_r = &ctx->ctx; + if (_ctx->received_date == (time_t)-1) + _ctx->received_date = ioloop_time; + dbox_save_keywords(ctx, _ctx->keywords); return ctx->failed ? -1 : 0; } @@ -169,7 +165,7 @@ int dbox_save_continue(struct mail_save_context *_ctx) ctx->failed = TRUE; return -1; } - index_mail_cache_parse_continue(ctx->cur_dest_mail); + index_mail_cache_parse_continue(_ctx->dest_mail); /* both tee input readers may consume data from our primary input stream. we'll have to make sure we don't return with @@ -193,17 +189,17 @@ static void dbox_save_write_metadata(struct dbox_save_context *ctx) str = t_str_new(256); /* write first fields that don't change */ str_printfa(str, "%c%lx\n", DBOX_METADATA_RECEIVED_TIME, - (unsigned long)ctx->cur_received_date); + (unsigned long)ctx->ctx.received_date); str_printfa(str, "%c%lx\n", DBOX_METADATA_SAVE_TIME, (unsigned long)ioloop_time); - if (mail_get_virtual_size(ctx->cur_dest_mail, &vsize) < 0) + if (mail_get_virtual_size(ctx->ctx.dest_mail, &vsize) < 0) i_unreached(); str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE, (unsigned long long)vsize); /* flags */ str_append_c(str, DBOX_METADATA_FLAGS); - dbox_mail_metadata_flags_append(str, ctx->cur_flags); + dbox_mail_metadata_flags_append(str, ctx->ctx.flags); str_append_c(str, '\n'); /* keywords */ @@ -254,8 +250,8 @@ int dbox_save_finish(struct mail_save_context *_ctx) if (ctx->cur_output == NULL) return -1; - index_mail_cache_parse_deinit(ctx->cur_dest_mail, - ctx->cur_received_date, !ctx->failed); + index_mail_cache_parse_deinit(_ctx->dest_mail, + _ctx->received_date, !ctx->failed); if (!ctx->failed) T_BEGIN { const char *cur_path; diff --git a/src/lib-storage/index/dbox/dbox-storage.c b/src/lib-storage/index/dbox/dbox-storage.c index caff4772ea..25dd5a4099 100644 --- a/src/lib-storage/index/dbox/dbox-storage.c +++ b/src/lib-storage/index/dbox/dbox-storage.c @@ -713,7 +713,8 @@ struct mailbox dbox_mailbox = { index_storage_search_deinit, index_storage_search_next_nonblock, index_storage_search_next_update_seq, - dbox_save_init, + dbox_save_alloc, + dbox_save_begin, dbox_save_continue, dbox_save_finish, dbox_save_cancel, diff --git a/src/lib-storage/index/dbox/dbox-storage.h b/src/lib-storage/index/dbox/dbox-storage.h index 96889b1d91..838ff54e0d 100644 --- a/src/lib-storage/index/dbox/dbox-storage.h +++ b/src/lib-storage/index/dbox/dbox-storage.h @@ -82,11 +82,9 @@ dbox_mail_alloc(struct mailbox_transaction_context *t, enum mail_fetch_field wanted_fields, struct mailbox_header_lookup_ctx *wanted_headers); -int dbox_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, struct mail_save_context **ctx_r); +struct mail_save_context * +dbox_save_alloc(struct mailbox_transaction_context *_t); +int dbox_save_begin(struct mail_save_context *ctx, struct istream *input); int dbox_save_continue(struct mail_save_context *ctx); int dbox_save_finish(struct mail_save_context *ctx); void dbox_save_cancel(struct mail_save_context *ctx); diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c index 95a3c1bb61..8f18a0971c 100644 --- a/src/lib-storage/index/maildir/maildir-save.c +++ b/src/lib-storage/index/maildir/maildir-save.c @@ -54,7 +54,6 @@ struct maildir_save_context { struct istream *input; struct ostream *output; int fd; - time_t received_date; uint32_t first_seq, seq; unsigned int want_mails:1; @@ -346,52 +345,51 @@ static int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir, return fd; } -int maildir_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset ATTR_UNUSED, - const char *from_envelope ATTR_UNUSED, - struct istream *input, struct mail **dest_mail, - struct mail_save_context **ctx_r) +struct mail_save_context * +maildir_save_alloc(struct mailbox_transaction_context *_t) { struct maildir_transaction_context *t = (struct maildir_transaction_context *)_t; - struct maildir_save_context *ctx; - struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox; i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); if (t->save_ctx == NULL) t->save_ctx = maildir_save_transaction_init(t); - ctx = t->save_ctx; + return &t->save_ctx->ctx; +} + +int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input) +{ + struct maildir_transaction_context *t = + (struct maildir_transaction_context *)_ctx->transaction; + struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; - flags &= ~MAIL_RECENT; - if (mbox->ibox.keep_recent) - flags |= MAIL_RECENT; + _ctx->flags &= ~MAIL_RECENT; + if (ctx->mbox->ibox.keep_recent) + _ctx->flags |= MAIL_RECENT; T_BEGIN { /* create a new file in tmp/ directory */ const char *fname; - ctx->fd = maildir_create_tmp(mbox, ctx->tmpdir, &fname); + ctx->fd = maildir_create_tmp(ctx->mbox, ctx->tmpdir, &fname); if (ctx->fd == -1) ctx->failed = TRUE; else { - ctx->received_date = received_date; ctx->input = (ctx->mbox->storage->storage.flags & MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ? i_stream_create_crlf(input) : i_stream_create_lf(input); - maildir_save_add(t, fname, flags, keywords, *dest_mail); + maildir_save_add(t, fname, _ctx->flags, _ctx->keywords, + _ctx->dest_mail); } } T_END; - if (ctx->failed) - return -1; - ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE); - o_stream_cork(ctx->output); - - *ctx_r = &ctx->ctx; + if (!ctx->failed) { + ctx->output = o_stream_create_fd_file(ctx->fd, 0, FALSE); + o_stream_cork(ctx->output); + } return ctx->failed ? -1 : 0; } @@ -446,10 +444,10 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx) ctx->failed = TRUE; } - if (ctx->received_date != (time_t)-1) { + if (ctx->ctx.received_date != (time_t)-1) { /* set the received_date by modifying mtime */ buf.actime = ioloop_time; - buf.modtime = ctx->received_date; + buf.modtime = ctx->ctx.received_date; if (utime(path, &buf) < 0) { ctx->failed = TRUE; @@ -458,7 +456,7 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx) } } else if (ctx->fd != -1) { if (fstat(ctx->fd, &st) == 0) - ctx->received_date = st.st_mtime; + ctx->ctx.received_date = st.st_mtime; else { ctx->failed = TRUE; mail_storage_set_critical(storage, @@ -467,7 +465,7 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx) } else { /* hardlinked */ if (stat(path, &st) == 0) - ctx->received_date = st.st_mtime; + ctx->ctx.received_date = st.st_mtime; else { ctx->failed = TRUE; mail_storage_set_critical(storage, @@ -477,7 +475,8 @@ static int maildir_save_finish_real(struct mail_save_context *_ctx) if (ctx->cur_dest_mail != NULL) { index_mail_cache_parse_deinit(ctx->cur_dest_mail, - ctx->received_date, !ctx->failed); + ctx->ctx.received_date, + !ctx->failed); } i_stream_unref(&ctx->input); diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index 74abe78798..8ce23f7148 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -1058,7 +1058,8 @@ struct mailbox maildir_mailbox = { index_storage_search_deinit, index_storage_search_next_nonblock, index_storage_search_next_update_seq, - maildir_save_init, + maildir_save_alloc, + maildir_save_begin, maildir_save_continue, maildir_save_finish, maildir_save_cancel, diff --git a/src/lib-storage/index/maildir/maildir-storage.h b/src/lib-storage/index/maildir/maildir-storage.h index c66dd38926..8be7ec5811 100644 --- a/src/lib-storage/index/maildir/maildir-storage.h +++ b/src/lib-storage/index/maildir/maildir-storage.h @@ -126,12 +126,9 @@ bool maildir_set_deleted(struct maildir_mailbox *mbox); void maildir_transaction_class_init(void); void maildir_transaction_class_deinit(void); -int maildir_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, - struct mail_save_context **ctx_r); +struct mail_save_context * +maildir_save_alloc(struct mailbox_transaction_context *_t); +int maildir_save_begin(struct mail_save_context *ctx, struct istream *input); int maildir_save_continue(struct mail_save_context *ctx); int maildir_save_finish(struct mail_save_context *ctx); void maildir_save_cancel(struct mail_save_context *ctx); diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c index a119e52daf..758883defa 100644 --- a/src/lib-storage/index/mbox/mbox-save.c +++ b/src/lib-storage/index/mbox/mbox-save.c @@ -40,7 +40,6 @@ struct mbox_save_context { struct mail *mail; uoff_t append_offset, mail_offset; time_t orig_atime; - time_t received_date; string_t *headers; size_t space_end_idx; @@ -424,44 +423,50 @@ mbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input) return ret; } -int mbox_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset ATTR_UNUSED, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, struct mail_save_context **ctx_r) +struct mail_save_context * +mbox_save_alloc(struct mailbox_transaction_context *_t) { struct mbox_transaction_context *t = (struct mbox_transaction_context *)_t; struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox; - struct mbox_save_context *ctx = t->save_ctx; - enum mail_flags save_flags; - uint64_t offset; + struct mbox_save_context *ctx; i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0); + if (t->save_ctx != NULL) + return &t->save_ctx->ctx; + + ctx = t->save_ctx = i_new(struct mbox_save_context, 1); + ctx->ctx.transaction = &t->ictx.mailbox_ctx; + ctx->mbox = mbox; + ctx->trans = t->ictx.trans; + ctx->append_offset = (uoff_t)-1; + ctx->headers = str_new(default_pool, 512); + ctx->mail_offset = (uoff_t)-1; + return &ctx->ctx; +} + +int mbox_save_begin(struct mail_save_context *_ctx, struct istream *input) +{ + struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx; + struct mbox_transaction_context *t = + (struct mbox_transaction_context *)_ctx->transaction; + enum mail_flags save_flags; + uint64_t offset; + /* FIXME: we could write timezone_offset to From-line.. */ - if (received_date == (time_t)-1) - received_date = ioloop_time; - - if (ctx == NULL) { - ctx = t->save_ctx = i_new(struct mbox_save_context, 1); - ctx->ctx.transaction = &t->ictx.mailbox_ctx; - ctx->mbox = mbox; - ctx->trans = t->ictx.trans; - ctx->append_offset = (uoff_t)-1; - ctx->headers = str_new(default_pool, 512); - ctx->mail_offset = (uoff_t)-1; - } + if (_ctx->received_date == (time_t)-1) + _ctx->received_date = ioloop_time; ctx->failed = FALSE; ctx->seq = 0; - if (mbox_save_init_file(ctx, t, *dest_mail != NULL) < 0) { + if (mbox_save_init_file(ctx, t, _ctx->dest_mail != NULL) < 0) { ctx->failed = TRUE; return -1; } - save_flags = (flags & ~MAIL_RECENT) | MAIL_RECENT; + save_flags = (_ctx->flags & ~MAIL_RECENT) | MAIL_RECENT; str_truncate(ctx->headers, 0); if (ctx->synced) { if (ctx->mbox->mbox_save_md5) @@ -476,42 +481,42 @@ int mbox_save_init(struct mailbox_transaction_context *_t, mail_index_append(ctx->trans, ctx->next_uid, &ctx->seq); mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE, save_flags & ~MAIL_RECENT); - if (keywords != NULL) { + if (_ctx->keywords != NULL) { mail_index_update_keywords(ctx->trans, ctx->seq, - MODIFY_REPLACE, keywords); + MODIFY_REPLACE, + _ctx->keywords); } offset = ctx->output->offset == 0 ? 0 : ctx->output->offset - 1; mail_index_update_ext(ctx->trans, ctx->seq, - mbox->mbox_ext_idx, &offset, NULL); + ctx->mbox->mbox_ext_idx, &offset, NULL); ctx->next_uid++; /* parse and cache the mail headers as we read it */ - if (*dest_mail == NULL) { - if (ctx->mail == NULL) - ctx->mail = mail_alloc(_t, 0, NULL); - *dest_mail = ctx->mail; + if (_ctx->dest_mail == NULL) { + if (ctx->mail == NULL) { + ctx->mail = mail_alloc(_ctx->transaction, + 0, NULL); + } + _ctx->dest_mail = ctx->mail; } - mail_set_seq(*dest_mail, ctx->seq); + mail_set_seq(_ctx->dest_mail, ctx->seq); } mbox_save_append_flag_headers(ctx->headers, save_flags); - mbox_save_append_keyword_headers(ctx, keywords); + mbox_save_append_keyword_headers(ctx, _ctx->keywords); str_append_c(ctx->headers, '\n'); - i_assert(mbox->mbox_lock_type == F_WRLCK); + i_assert(ctx->mbox->mbox_lock_type == F_WRLCK); ctx->mail_offset = ctx->output->offset; ctx->eoh_offset = (uoff_t)-1; ctx->last_char = '\n'; - ctx->received_date = received_date; - if (write_from_line(ctx, received_date, from_envelope) < 0) + if (write_from_line(ctx, _ctx->received_date, _ctx->from_envelope) < 0) ctx->failed = TRUE; else ctx->input = mbox_save_get_input_stream(ctx, input); - - *ctx_r = &ctx->ctx; return ctx->failed ? -1 : 0; } @@ -670,7 +675,7 @@ int mbox_save_finish(struct mail_save_context *_ctx) } if (ctx->mail != NULL) { - index_mail_cache_parse_deinit(ctx->mail, ctx->received_date, + index_mail_cache_parse_deinit(ctx->mail, ctx->ctx.received_date, !ctx->failed); } if (ctx->input != NULL) diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index 9f7553557d..15deb252df 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -1012,7 +1012,8 @@ struct mailbox mbox_mailbox = { index_storage_search_deinit, index_storage_search_next_nonblock, index_storage_search_next_update_seq, - mbox_save_init, + mbox_save_alloc, + mbox_save_begin, mbox_save_continue, mbox_save_finish, mbox_save_cancel, diff --git a/src/lib-storage/index/mbox/mbox-storage.h b/src/lib-storage/index/mbox/mbox-storage.h index 7749a5b2a2..c154de0a63 100644 --- a/src/lib-storage/index/mbox/mbox-storage.h +++ b/src/lib-storage/index/mbox/mbox-storage.h @@ -73,11 +73,9 @@ void mbox_transaction_class_deinit(void); struct mailbox_sync_context * mbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags); -int mbox_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, struct mail_save_context **ctx_r); +struct mail_save_context * +mbox_save_alloc(struct mailbox_transaction_context *_t); +int mbox_save_begin(struct mail_save_context *ctx, struct istream *input); int mbox_save_continue(struct mail_save_context *ctx); int mbox_save_finish(struct mail_save_context *ctx); void mbox_save_cancel(struct mail_save_context *ctx); diff --git a/src/lib-storage/index/raw/raw-storage.c b/src/lib-storage/index/raw/raw-storage.c index f9e617f870..df6e660d88 100644 --- a/src/lib-storage/index/raw/raw-storage.c +++ b/src/lib-storage/index/raw/raw-storage.c @@ -308,6 +308,7 @@ struct mailbox raw_mailbox = { NULL, NULL, NULL, + NULL, mail_storage_copy, index_storage_is_inconsistent } diff --git a/src/lib-storage/mail-copy.c b/src/lib-storage/mail-copy.c index 5bbe4d7baa..ceb524ca7c 100644 --- a/src/lib-storage/mail-copy.c +++ b/src/lib-storage/mail-copy.c @@ -25,8 +25,13 @@ int mail_storage_copy(struct mailbox_transaction_context *t, struct mail *mail, if (*from_envelope == '\0') from_envelope = NULL; - if (mailbox_save_init(t, flags, keywords, received_date, - 0, from_envelope, input, dest_mail, &ctx) < 0) + ctx = mailbox_save_alloc(t); + mailbox_save_set_flags(ctx, flags, keywords); + mailbox_save_set_received_date(ctx, received_date, 0); + mailbox_save_set_from_envelope(ctx, from_envelope); + mailbox_save_set_dest_mail(ctx, dest_mail); + + if (mailbox_save_begin(&ctx, input) < 0) return -1; do { diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h index 5a38a1d82f..22f8b858d9 100644 --- a/src/lib-storage/mail-storage-private.h +++ b/src/lib-storage/mail-storage-private.h @@ -160,13 +160,9 @@ struct mailbox_vfuncs { /* Internal search function which updates ctx->seq */ int (*search_next_update_seq)(struct mail_search_context *ctx); - int (*save_init)(struct mailbox_transaction_context *t, - enum mail_flags flags, - struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, - struct mail_save_context **ctx_r); + struct mail_save_context * + (*save_alloc)(struct mailbox_transaction_context *t); + int (*save_begin)(struct mail_save_context *ctx, struct istream *input); int (*save_continue)(struct mail_save_context *ctx); int (*save_finish)(struct mail_save_context *ctx); void (*save_cancel)(struct mail_save_context *ctx); @@ -320,6 +316,14 @@ struct mail_search_context { struct mail_save_context { struct mailbox_transaction_context *transaction; struct mail *dest_mail; + + enum mail_flags flags; + struct mail_keywords *keywords; + + time_t received_date; + int received_tz_offset; + + char *from_envelope; }; struct mailbox_sync_context { diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 30f14593ff..747d773756 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -784,23 +784,61 @@ mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t) return t->box; } -int mailbox_save_init(struct mailbox_transaction_context *t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail *dest_mail, struct mail_save_context **ctx_r) -{ - if (t->box->v.save_init == NULL) { - mail_storage_set_error(t->box->storage, MAIL_ERROR_NOTPOSSIBLE, +struct mail_save_context * +mailbox_save_alloc(struct mailbox_transaction_context *t) +{ + struct mail_save_context *ctx; + + ctx = t->box->v.save_alloc(t); + ctx->received_date = (time_t)-1; + return ctx; +} + +void mailbox_save_set_flags(struct mail_save_context *ctx, + enum mail_flags flags, + struct mail_keywords *keywords) +{ + ctx->flags = flags; + ctx->keywords = keywords; +} + +void mailbox_save_set_received_date(struct mail_save_context *ctx, + time_t received_date, int timezone_offset) +{ + ctx->received_date = received_date; + ctx->received_tz_offset = timezone_offset; +} + +void mailbox_save_set_from_envelope(struct mail_save_context *ctx, + const char *envelope) +{ + i_free(ctx->from_envelope); + ctx->from_envelope = i_strdup(envelope); +} + +void mailbox_save_set_dest_mail(struct mail_save_context *ctx, + struct mail *mail) +{ + ctx->dest_mail = mail; +} + +int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input) +{ + struct mailbox *box = (*ctx)->transaction->box; + int ret; + + if (box->v.save_begin == NULL) { + mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, "Saving messages not supported"); - return -1; + ret = -1; + } else { + ret = box->v.save_begin(*ctx, input); } - if (t->box->v.save_init(t, flags, keywords, - received_date, timezone_offset, - from_envelope, input, &dest_mail, ctx_r) < 0) - return -1; - (*ctx_r)->dest_mail = dest_mail; + if (ret < 0) { + mailbox_save_cancel(ctx); + return -1; + } return 0; } @@ -814,6 +852,7 @@ int mailbox_save_finish(struct mail_save_context **_ctx) struct mail_save_context *ctx = *_ctx; *_ctx = NULL; + i_free(ctx->from_envelope); return ctx->transaction->box->v.save_finish(ctx); } @@ -822,6 +861,7 @@ void mailbox_save_cancel(struct mail_save_context **_ctx) struct mail_save_context *ctx = *_ctx; *_ctx = NULL; + i_free(ctx->from_envelope); ctx->transaction->box->v.save_cancel(ctx); } diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h index d603678067..9e9933a419 100644 --- a/src/lib-storage/mail-storage.h +++ b/src/lib-storage/mail-storage.h @@ -449,24 +449,35 @@ void mailbox_search_result_sync(struct mail_search_result *result, ARRAY_TYPE(seq_range) *removed_uids, ARRAY_TYPE(seq_range) *added_uids); -/* Save a mail into mailbox. timezone_offset specifies the timezone in - minutes in which received_date was originally given with. To use - current time, set received_date to (time_t)-1. - - If dest_mail is set, the saved message can be accessed using it. Note that +/* Initialize saving a new mail. You must not try to save more than one mail + at a time. */ +struct mail_save_context * +mailbox_save_alloc(struct mailbox_transaction_context *t); +/* Set the flags and keywords. Nothing is set by default. */ +void mailbox_save_set_flags(struct mail_save_context *ctx, + enum mail_flags flags, + struct mail_keywords *keywords); +/* If received date isn't specified the current time is used. timezone_offset + specifies the preferred timezone in minutes, but it may be ignored if + backend doesn't support storing it. */ +void mailbox_save_set_received_date(struct mail_save_context *ctx, + time_t received_date, int timezone_offset); +/* Set the envelope sender. This is currently used only with mbox files to + specify the address in From_-line. */ +void mailbox_save_set_from_envelope(struct mail_save_context *ctx, + const char *envelope); +/* If dest_mail is set, the saved message can be accessed using it. Note that setting it may require mailbox syncing, so don't set it unless you need it. Also you shouldn't try to access it before mailbox_save_finish() is - called. - - The given input stream is never read in these functions, only the data - inside it is used. So you should call i_stream_read() yourself and then - call mailbox_save_continue() whenever more data is read. -*/ -int mailbox_save_init(struct mailbox_transaction_context *t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail *dest_mail, struct mail_save_context **ctx_r); + called. */ +void mailbox_save_set_dest_mail(struct mail_save_context *ctx, + struct mail *mail); +/* Begin saving the message. All mail_save_set_*() calls must have been called + before this function. If the save initialization fails, the context is freed + and -1 is returned. After beginning the save you should keep calling + i_stream_read() and calling mailbox_save_continue() as long as there's + more input. */ +int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input); int mailbox_save_continue(struct mail_save_context *ctx); int mailbox_save_finish(struct mail_save_context **ctx); void mailbox_save_cancel(struct mail_save_context **ctx); diff --git a/src/plugins/acl/acl-mailbox.c b/src/plugins/acl/acl-mailbox.c index bde7f42da5..a072925792 100644 --- a/src/plugins/acl/acl-mailbox.c +++ b/src/plugins/acl/acl-mailbox.c @@ -246,23 +246,17 @@ static int acl_save_get_flags(struct mailbox *box, enum mail_flags *flags, } static int -acl_save_init(struct mailbox_transaction_context *t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, struct mail_save_context **ctx_r) +acl_save_begin(struct mail_save_context *ctx, struct istream *input) { - struct acl_mailbox *abox = ACL_CONTEXT(t->box); + struct mailbox *box = ctx->transaction->box; + struct acl_mailbox *abox = ACL_CONTEXT(box); - if (mailbox_acl_right_lookup(t->box, ACL_STORAGE_RIGHT_INSERT) <= 0) + if (mailbox_acl_right_lookup(box, ACL_STORAGE_RIGHT_INSERT) <= 0) return -1; - if (acl_save_get_flags(t->box, &flags, &keywords) < 0) + if (acl_save_get_flags(box, &ctx->flags, &ctx->keywords) < 0) return -1; - return abox->module_ctx.super. - save_init(t, flags, keywords, received_date, - timezone_offset, from_envelope, - input, dest_mail, ctx_r); + return abox->module_ctx.super.save_begin(ctx, input); } static int @@ -342,7 +336,7 @@ struct mailbox *acl_mailbox_open_box(struct mailbox *box) box->v.allow_new_keywords = acl_allow_new_keywords; box->v.close = acl_mailbox_close; box->v.mail_alloc = acl_mail_alloc; - box->v.save_init = acl_save_init; + box->v.save_begin = acl_save_begin; box->v.keywords_create = acl_keywords_create; box->v.copy = acl_copy; box->v.transaction_commit = acl_transaction_commit; diff --git a/src/plugins/quota/quota-storage.c b/src/plugins/quota/quota-storage.c index 2b561d8811..7ef5781bc6 100644 --- a/src/plugins/quota/quota-storage.c +++ b/src/plugins/quota/quota-storage.c @@ -187,12 +187,9 @@ quota_copy(struct mailbox_transaction_context *t, struct mail *mail, } static int -quota_save_init(struct mailbox_transaction_context *t, - enum mail_flags flags, struct mail_keywords *keywords, - time_t received_date, int timezone_offset, - const char *from_envelope, struct istream *input, - struct mail **dest_mail, struct mail_save_context **ctx_r) +quota_save_begin(struct mail_save_context *ctx, struct istream *input) { + struct mailbox_transaction_context *t = ctx->transaction; struct quota_transaction_context *qt = QUOTA_CONTEXT(t); struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box); const struct stat *st; @@ -224,19 +221,16 @@ quota_save_init(struct mailbox_transaction_context *t, } } - if (*dest_mail == NULL) { + if (ctx->dest_mail == NULL) { /* we always want to know the mail size */ if (qt->tmp_mail == NULL) { qt->tmp_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE, NULL); } - *dest_mail = qt->tmp_mail; + ctx->dest_mail = qt->tmp_mail; } - return qbox->module_ctx.super. - save_init(t, flags, keywords, received_date, - timezone_offset, from_envelope, - input, dest_mail, ctx_r); + return qbox->module_ctx.super.save_begin(ctx, input); } static int quota_save_finish(struct mail_save_context *ctx) @@ -371,7 +365,7 @@ quota_mailbox_open(struct mail_storage *storage, const char *name, box->v.transaction_commit = quota_mailbox_transaction_commit; box->v.transaction_rollback = quota_mailbox_transaction_rollback; box->v.mail_alloc = quota_mail_alloc; - box->v.save_init = quota_save_init; + box->v.save_begin = quota_save_begin; box->v.save_finish = quota_save_finish; box->v.copy = quota_copy; box->v.sync_notify = quota_mailbox_sync_notify; diff --git a/src/plugins/virtual/virtual-storage.c b/src/plugins/virtual/virtual-storage.c index d6cb1dad87..9cfca23f0b 100644 --- a/src/plugins/virtual/virtual-storage.c +++ b/src/plugins/virtual/virtual-storage.c @@ -459,23 +459,6 @@ virtual_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx return ret; } -static int -virtual_save_init(struct mailbox_transaction_context *_t, - enum mail_flags flags ATTR_UNUSED, - struct mail_keywords *keywords ATTR_UNUSED, - time_t received_date ATTR_UNUSED, - int timezone_offset ATTR_UNUSED, - const char *from_envelope ATTR_UNUSED, - struct istream *input ATTR_UNUSED, - struct mail **dest_mail ATTR_UNUSED, - struct mail_save_context **ctx_r) -{ - mail_storage_set_error(_t->box->storage, MAIL_ERROR_NOTPOSSIBLE, - "Can't save to virtual mailboxes"); - *ctx_r = NULL; - return -1; -} - static void virtual_class_init(void) { virtual_transaction_class_init(); @@ -537,7 +520,8 @@ struct mailbox virtual_mailbox = { index_storage_search_deinit, index_storage_search_next_nonblock, index_storage_search_next_update_seq, - virtual_save_init, + NULL, + NULL, NULL, NULL, NULL,