[dovecot-cvs] dovecot/src/lib-storage mail-save.c,NONE,1.1 mail-save.h,NONE,1.1 Makefile.am,1.6,1.7

cras at procontrol.fi cras at procontrol.fi
Wed May 7 16:06:49 EEST 2003


Update of /home/cvs/dovecot/src/lib-storage
In directory danu:/tmp/cvs-serv16292

Modified Files:
	Makefile.am 
Added Files:
	mail-save.c mail-save.h 
Log Message:
cleanup: message saving code isn't index-specific



--- NEW FILE: mail-save.c ---
/* Copyright (C) 2002 Timo Sirainen */

#include "lib.h"
#include "istream.h"
#include "ostream.h"
#include "message-parser.h"
#include "mail-storage.h"
#include "mail-save.h"

static int write_with_crlf(struct ostream *output, const void *v_data,
			   size_t size)
{
	const unsigned char *data = v_data;
	size_t i, start;

	i_assert(size <= SSIZE_T_MAX);

	if (size == 0)
		return 0;

	start = 0;
	for (i = 0; i < size; i++) {
		if (data[i] == '\n' && (i == 0 || data[i-1] != '\r')) {
			/* missing CR */
			if (o_stream_send(output, data + start, i - start) < 0)
				return -1;
			if (o_stream_send(output, "\r", 1) < 0)
				return -1;

			/* \n is written next time */
			start = i;
		}
	}

	/* if last char is \r, leave it to buffer */
	if (data[size-1] == '\r')
		size--;

	if (o_stream_send(output, data + start, size - start) < 0)
		return -1;

	return size;
}

static int write_with_lf(struct ostream *output, const void *v_data,
			 size_t size)
{
	const unsigned char *data = v_data;
	size_t i, start;

	i_assert(size <= SSIZE_T_MAX);

	if (size == 0)
		return 0;

	start = 0;
	for (i = 0; i < size; i++) {
		if (data[i] == '\n' && i > 0 && data[i-1] == '\r') {
			/* \r\n - skip \r */
			if (o_stream_send(output, data + start,
					   i - start - 1) < 0)
				return -1;

			/* \n is written next time */
			start = i;
		}
	}

	/* if last char is \r, leave it to buffer */
	if (data[size-1] == '\r')
		size--;

	if (o_stream_send(output, data + start, size - start) < 0)
		return -1;

	return size;
}

static void set_write_error(struct mail_storage *storage,
			    struct ostream *output, const char *path)
{
	errno = output->stream_errno;
	if (ENOSPACE(errno))
		mail_storage_set_error(storage, "Not enough disk space");
	else {
		mail_storage_set_critical(storage,
					  "Can't write to file %s: %m", path);
	}
}

static int save_headers(struct istream *input, struct ostream *output,
			header_callback_t *header_callback, void *context,
			write_func_t *write_func)
{
	struct message_header_parser_ctx *hdr_ctx;
	struct message_header_line *hdr;
	int ret, failed = FALSE;

	hdr_ctx = message_parse_header_init(input, NULL);
	while ((hdr = message_parse_header_next(hdr_ctx)) != NULL) {
		ret = header_callback(hdr->name, write_func, context);
		if (ret <= 0) {
			if (ret < 0) {
				failed = TRUE;
				break;
			}
			continue;
		}

		if (!hdr->eoh) {
			if (!hdr->continued) {
				(void)o_stream_send(output, hdr->name,
						    hdr->name_len);
				(void)o_stream_send(output, ": ", 2);
			}
			(void)o_stream_send(output, hdr->value, hdr->value_len);
			if (!hdr->no_newline)
				write_func(output, "\n", 1);
		}
	}
	if (!failed) {
		if (header_callback(NULL, write_func, context) < 0)
			failed = TRUE;

		/* end of headers */
		write_func(output, "\n", 1);
	}
	message_parse_header_deinit(hdr_ctx);

	return !failed;
}

int mail_storage_save(struct mail_storage *storage, const char *path,
		      struct istream *input, struct ostream *output, int crlf,
		      header_callback_t *header_callback, void *context)
{
        write_func_t *write_func;
	const unsigned char *data;
	size_t size;
	ssize_t ret;
	int failed;

	write_func = crlf ? write_with_crlf : write_with_lf;

	if (header_callback != NULL) {
		if (!save_headers(input, output, header_callback,
				  context, write_func))
			return FALSE;
	}

	failed = FALSE;
	for (;;) {
		data = i_stream_get_data(input, &size);
		if (!failed) {
			ret = write_func(output, data, size);
			if (ret < 0) {
				set_write_error(storage, output, path);
				failed = TRUE;
			} else {
				size = ret;
			}
		}
		i_stream_skip(input, size);

		ret = i_stream_read(input);
		if (ret < 0) {
			errno = input->stream_errno;
			if (errno == 0) {
				/* EOF */
				if (input->v_offset != input->v_limit) {
					/* too early */
					mail_storage_set_error(storage,
						"Unexpected EOF");
					failed = TRUE;
				}
				break;
			} else if (errno == EAGAIN) {
				mail_storage_set_error(storage,
					"Timeout while waiting for input");
			} else {
				mail_storage_set_critical(storage,
					"Error reading mail from client: %m");
			}
			failed = TRUE;
			break;
		}
	}

	return !failed;
}

--- NEW FILE: mail-save.h ---
#ifndef __MAIL_SAVE_H
#define __MAIL_SAVE_H

typedef int write_func_t(struct ostream *, const void *, size_t);

/* Return -1 = failure, 0 = don't write the header, 1 = write it */
typedef int header_callback_t(const char *name,
			      write_func_t *write_func, void *context);

int mail_storage_save(struct mail_storage *storage, const char *path,
		      struct istream *input, struct ostream *output, int crlf,
		      header_callback_t *header_callback, void *context);

#endif

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/Makefile.am,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Makefile.am	20 Jan 2003 14:52:51 -0000	1.6
+++ Makefile.am	7 May 2003 12:06:47 -0000	1.7
@@ -8,9 +8,11 @@
 	-I$(top_srcdir)/src/lib-imap
 
 libstorage_a_SOURCES = \
+	mail-save.c \
 	mail-search.c \
 	mail-storage.c
 
 noinst_HEADERS = \
+	mail-save.h \
 	mail-search.h \
 	mail-storage.h




More information about the dovecot-cvs mailing list