static void
test_filter(CamelMimeFilter *f, const char *inname, const char *outname)
{
	CamelStreamMem *in, *out;
	CamelStream *indisk, *outdisk, *filter;
	int id;

	camel_test_push("Data file `%s'", inname);

	camel_test_push("setup");

	indisk = camel_stream_fs_new_with_name(inname, O_RDONLY, 0);
	check(indisk);
	outdisk = camel_stream_fs_new_with_name(outname, O_RDONLY, 0);
	check(outdisk);

	out = (CamelStreamMem *)camel_stream_mem_new();
	check(camel_stream_write_to_stream(outdisk, (CamelStream *)out) > 0);

	camel_test_pull();

	camel_test_push("reading through filter stream");

	in = (CamelStreamMem *)camel_stream_mem_new();

	filter = (CamelStream *)camel_stream_filter_new_with_stream(indisk);
	check_count(indisk, 2);
	id = camel_stream_filter_add((CamelStreamFilter *)filter, f);
	check_count(f, 2);

	check(camel_stream_write_to_stream(filter, (CamelStream *)in) > 0);
	check_msg(in->buffer->len == out->buffer->len
		  && memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0,
		  "Buffer content mismatch, %d != %d, in = '%.*s' != out = '%.*s'", in->buffer->len, out->buffer->len,
		  in->buffer->len, in->buffer->data, out->buffer->len, out->buffer->data);

	camel_test_pull();

	camel_stream_filter_remove((CamelStreamFilter *)filter, id);
	check_count(f, 1);
	camel_mime_filter_reset(f);

	check_unref(filter, 1);
	check_count(indisk, 1);
	check_count(f, 1);
	check_unref(in, 1);

	check(camel_stream_reset(indisk) == 0);

	camel_test_push("writing through filter stream");

	in = (CamelStreamMem *)camel_stream_mem_new();
	filter = (CamelStream *)camel_stream_filter_new_with_stream((CamelStream *)in);
	check_count(in, 2);
	id = camel_stream_filter_add((CamelStreamFilter *)filter, f);
	check_count(f, 2);

	check(camel_stream_write_to_stream(indisk, filter) > 0);
	check(camel_stream_flush(filter) == 0);
	check_msg(in->buffer->len == out->buffer->len
		  && memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0,
		  "Buffer content mismatch, %d != %d, in = '%.*s' != out = '%.*s'", in->buffer->len, out->buffer->len,
		  in->buffer->len, in->buffer->data, out->buffer->len, out->buffer->data);

	camel_stream_filter_remove((CamelStreamFilter *)filter, id);
	check_unref(filter, 1);
	check_unref(in, 1);
	check_unref(indisk, 1);
	check_unref(outdisk, 1);
	check_unref(out, 1);

	camel_test_pull();

	camel_test_pull();
}
static gint
camel_movemail_copy_filter (gint fromfd,
                            gint tofd,
                            goffset start,
                            gsize bytes,
                            CamelMimeFilter *filter)
{
    gchar buffer[4096 + PRE_SIZE];
    gint written = 0;
    gchar *filterbuffer;
    gint filterlen, filterpre;

    d (printf ("writing %d bytes ... ", bytes));

    camel_mime_filter_reset (filter);

    if (lseek (fromfd, start, SEEK_SET) != start)
        return -1;

    while (bytes > 0) {
        gint toread, towrite;

        toread = bytes;
        if (bytes > 4096)
            toread = 4096;
        else
            toread = bytes;
        do {
            towrite = read (fromfd, buffer + PRE_SIZE, toread);
        } while (towrite == -1 && errno == EINTR);

        if (towrite == -1)
            return -1;

        d (printf ("read %d unfiltered bytes\n", towrite));

        /* check for 'end of file' */
        if (towrite == 0) {
            d (printf ("end of file?\n"));
            camel_mime_filter_complete (
                filter, buffer + PRE_SIZE, towrite, PRE_SIZE,
                &filterbuffer, &filterlen, &filterpre);
            towrite = filterlen;
            if (towrite == 0)
                break;
        } else {
            camel_mime_filter_filter (
                filter, buffer + PRE_SIZE, towrite, PRE_SIZE,
                &filterbuffer, &filterlen, &filterpre);
            towrite = filterlen;
        }

        d (printf ("writing %d filtered bytes\n", towrite));

        do {
            toread = write (tofd, filterbuffer, towrite);
        } while (toread == -1 && errno == EINTR);

        if (toread == -1)
            return -1;

        written += toread;
        bytes -= toread;
    }

    d (printf ("written %d bytes\n", written));

    return written;
}