コード例 #1
0
static int
cmd_save_to_mailbox(struct save_cmd_context *ctx, struct mailbox *box,
		    struct istream *input)
{
	struct mail_storage *storage = mailbox_get_storage(box);
	struct mailbox_transaction_context *trans;
	struct mail_save_context *save_ctx;
	ssize_t ret;
	bool save_failed = FALSE;

	if (mailbox_open(box) < 0) {
		i_error("Failed to open mailbox %s: %s",
			mailbox_get_vname(box), mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_storage(&ctx->ctx, storage);
		return -1;
	}

	trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_EXTERNAL);
	save_ctx = mailbox_save_alloc(trans);
	if (mailbox_save_begin(&save_ctx, input) < 0) {
		i_error("Saving failed: %s", mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_storage(&ctx->ctx, storage);
		mailbox_transaction_rollback(&trans);
		return -1;
	}
	while ((ret = i_stream_read(input)) > 0 || ret == -2) {
		if (mailbox_save_continue(save_ctx) < 0) {
			save_failed = TRUE;
			ret = -1;
			break;
		}
	}
	i_assert(ret == -1);

	if (input->stream_errno != 0) {
		i_error("read(msg input) failed: %s", i_stream_get_error(input));
		doveadm_mail_failed_error(&ctx->ctx, MAIL_ERROR_TEMP);
	} else if (save_failed) {
		i_error("Saving failed: %s", mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_storage(&ctx->ctx, storage);
	} else if (mailbox_save_finish(&save_ctx) < 0) {
		i_error("Saving failed: %s",
			mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_storage(&ctx->ctx, storage);
	} else if (mailbox_transaction_commit(&trans) < 0) {
		i_error("Save transaction commit failed: %s",
			mailbox_get_last_error(box, NULL));
		doveadm_mail_failed_storage(&ctx->ctx, storage);
	} else {
		ret = 0;
	}
	if (save_ctx != NULL)
		mailbox_save_cancel(&save_ctx);
	if (trans != NULL)
		mailbox_transaction_rollback(&trans);
	i_assert(input->eof);
	return ret < 0 ? -1 : 0;
}
コード例 #2
0
ファイル: mail-copy.c プロジェクト: Raffprta/core
int mail_storage_copy(struct mail_save_context *ctx, struct mail *mail)
{
	if (ctx->data.keywords != NULL) {
		/* keywords gets unreferenced twice: first in
		   mailbox_save_cancel()/_finish() and second time in
		   mailbox_copy(). */
		mailbox_keywords_ref(ctx->data.keywords);
	}

	if (mail_storage_try_copy(&ctx, mail) < 0) {
		if (ctx != NULL)
			mailbox_save_cancel(&ctx);
		return -1;
	}
	return mailbox_save_finish(&ctx);
}
コード例 #3
0
ファイル: cmd-append.c プロジェクト: bsmr-dovecot/core
static void cmd_append_finish_catenate(struct client_command_context *cmd)
{
	struct cmd_append_context *ctx = cmd->context;

	i_stream_chain_append_eof(ctx->catchain);
	i_stream_unref(&ctx->input);
	ctx->catenate = FALSE;
	ctx->catchain = NULL;

	if (ctx->failed) {
		/* APPEND has already failed */
		if (ctx->save_ctx != NULL)
			mailbox_save_cancel(&ctx->save_ctx);
	} else {
		if (mailbox_save_finish(&ctx->save_ctx) < 0) {
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
		}
	}
}
コード例 #4
0
ファイル: cmd-append.c プロジェクト: bsmr-dovecot/core
static bool cmd_append_continue_message(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_append_context *ctx = cmd->context;
	int ret = 0;

	if (cmd->cancel) {
		/* cancel the command immediately (disconnection) */
		cmd_append_finish(ctx);
		return TRUE;
	}

	if (ctx->save_ctx != NULL) {
		while (ctx->litinput->v_offset != ctx->literal_size) {
			ret = i_stream_read(ctx->litinput);
			if (mailbox_save_continue(ctx->save_ctx) < 0) {
				/* we still have to finish reading the message
				   from client */
				mailbox_save_cancel(&ctx->save_ctx);
				break;
			}
			if (ret == -1 || ret == 0)
				break;
		}
	}

	if (ctx->save_ctx == NULL) {
		/* saving has already failed, we're just eating away the
		   literal */
		(void)i_stream_read(ctx->litinput);
		i_stream_skip(ctx->litinput,
			      i_stream_get_data_size(ctx->litinput));
	}

	if (ctx->litinput->eof || client->input->closed) {
		uoff_t lit_offset = ctx->litinput->v_offset;

		/* finished - do one more read, to make sure istream-chain
		   unreferences its stream, which is needed for litinput's
		   unreferencing to seek the client->input to correct
		   position. the seek is needed to avoid trying to seek
		   backwards in the ctx->input's parent stream. */
		i_stream_seek(ctx->input, ctx->input->v_offset);
		(void)i_stream_read(ctx->input);
		i_stream_unref(&ctx->litinput);

		if (ctx->failed) {
			if (ctx->save_ctx != NULL)
				mailbox_save_cancel(&ctx->save_ctx);
		} else if (ctx->save_ctx == NULL) {
			/* failed above */
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
		} else if (lit_offset != ctx->literal_size) {
			/* client disconnected before it finished sending the
			   whole message. */
			ctx->failed = TRUE;
			mailbox_save_cancel(&ctx->save_ctx);
			client_disconnect(client,
				get_disconnect_reason(ctx, lit_offset));
		} else if (ctx->catenate) {
			/* CATENATE isn't finished yet */
		} else if (mailbox_save_finish(&ctx->save_ctx) < 0) {
			client_send_box_error(cmd, ctx->box);
			ctx->failed = TRUE;
		}

		if (client->input->closed) {
			cmd_append_finish(ctx);
			return TRUE;
		}

		/* prepare for the next message (or its part with catenate) */
		ctx->message_input = FALSE;
		imap_parser_reset(ctx->save_parser);

		if (ctx->catenate) {
			cmd->func = cmd_append_continue_catenate;
			return cmd_append_continue_catenate(cmd);
		}

		i_stream_unref(&ctx->input);
		cmd->func = cmd_append_parse_new_msg;
		return cmd_append_parse_new_msg(cmd);
	}
	return FALSE;
}