[dovecot-cvs] dovecot/src/lib ostream-crlf.c, 1.3,
1.4 ostream-crlf.h, 1.1, 1.2
cras at dovecot.org
cras at dovecot.org
Mon Aug 23 06:58:10 EEST 2004
Update of /home/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv679/lib
Modified Files:
ostream-crlf.c ostream-crlf.h
Log Message:
Changed LF stream to replace only CRLF pairs. Changed send functions to
return the number of input bytes consumed rather than number of bytes
actually sent. This fixes send_istream().
Index: ostream-crlf.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ostream-crlf.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ostream-crlf.c 22 Aug 2004 11:19:52 -0000 1.3
+++ ostream-crlf.c 23 Aug 2004 03:58:08 -0000 1.4
@@ -1,5 +1,8 @@
/* Copyright (c) 2004 Timo Sirainen */
+/* The code is quite ugly because we want the send functions to return correcly
+ the number of input bytes consumed, not number of bytes actually sent. */
+
#include "lib.h"
#include "buffer.h"
#include "istream.h"
@@ -15,6 +18,8 @@
int last_cr;
};
+static const struct const_iovec cr_iov = { "\r", 1 };
+
static void _close(struct _iostream *stream)
{
struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
@@ -71,8 +76,9 @@
return ret;
}
-static ssize_t sendv_crlf(struct crlf_ostream *cstream,
- const struct const_iovec *iov, size_t iov_count)
+static ssize_t
+sendv_crlf(struct crlf_ostream *cstream, const struct const_iovec *iov,
+ size_t iov_count, const char *diff, ssize_t *total_r)
{
ssize_t ret;
size_t pos;
@@ -81,11 +87,18 @@
if (ret > 0) {
pos = (size_t)ret - 1;
while (pos >= iov->iov_len) {
+ *total_r += iov->iov_len + *diff;
pos -= iov->iov_len;
iov++;
+ diff++;
}
cstream->last_cr = *((const char *)iov->iov_base + pos) == '\r';
+
+ if (pos + 1 == iov->iov_len)
+ *total_r += iov->iov_len + *diff;
+ else
+ *total_r += pos;
}
cstream->ostream.ostream.offset = cstream->output->offset;
return ret;
@@ -95,21 +108,23 @@
_sendv_crlf(struct _ostream *stream, const struct const_iovec *iov,
size_t iov_count)
{
- static const struct const_iovec cr_iov = { "\r", 1 };
struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
- buffer_t *buf;
+ buffer_t *iov_buf, *diff_buf;
const unsigned char *data;
struct const_iovec new_iov;
size_t vec, i, len, start, new_iov_count = 0, new_iov_size = 0;
- ssize_t ret;
+ ssize_t ret, total;
int last_cr;
last_cr = cstream->last_cr;
t_push();
- buf = buffer_create_dynamic(unsafe_data_stack_pool,
- sizeof(struct const_iovec *) * IOVBUF_COUNT,
- (size_t)-1);
+ iov_buf = buffer_create_dynamic(unsafe_data_stack_pool,
+ sizeof(struct const_iovec *) *
+ IOVBUF_COUNT, (size_t)-1);
+ diff_buf = buffer_create_dynamic(unsafe_data_stack_pool,
+ IOVBUF_COUNT, (size_t)-1);
+ total = 0;
for (vec = 0; vec < iov_count; vec++) {
data = iov[vec].iov_base;
len = iov[vec].iov_len;
@@ -134,27 +149,32 @@
new_iov.iov_base = data + start;
new_iov.iov_len = i - start;
- buffer_append(buf, &new_iov, sizeof(new_iov));
+ buffer_append(iov_buf, &new_iov,
+ sizeof(new_iov));
+ buffer_append_c(diff_buf, 0);
new_iov_count++;
new_iov_size += new_iov.iov_len;
}
start = i;
if (i != len) {
- buffer_append(buf, &cr_iov, sizeof(cr_iov));
+ buffer_append(iov_buf, &cr_iov, sizeof(cr_iov));
+ buffer_append_c(diff_buf, -1);
new_iov_count++;
new_iov_size++;
}
if (new_iov_count >= IOVBUF_COUNT-1) {
- ret = sendv_crlf(cstream, buf->data,
- new_iov_count);
+ ret = sendv_crlf(cstream, iov_buf->data,
+ new_iov_count, diff_buf->data,
+ &total);
if (ret != (ssize_t)new_iov_size) {
t_pop();
- return ret;
+ return ret < 0 ? ret : total;
}
- buffer_set_used_size(buf, 0);
+ buffer_set_used_size(iov_buf, 0);
+ buffer_set_used_size(diff_buf, 0);
new_iov_count = 0;
new_iov_size = 0;
}
@@ -167,8 +187,31 @@
last_cr = data[len-1] == '\r';
}
- ret = sendv_crlf(cstream, buf->data, new_iov_count);
+ ret = sendv_crlf(cstream, iov_buf->data, new_iov_count,
+ diff_buf->data, &total);
t_pop();
+ return ret < 0 ? ret : total;
+}
+
+static ssize_t
+sendv_lf(struct crlf_ostream *cstream, const struct const_iovec *iov,
+ size_t iov_count, const char *diff, ssize_t *total_r)
+{
+ ssize_t ret;
+ size_t left;
+
+ ret = o_stream_sendv(cstream->output, iov, iov_count);
+ if (ret >= 0) {
+ left = (size_t)ret;
+ while (left >= iov->iov_len) {
+ *total_r += iov->iov_len + *diff;
+ left -= iov->iov_len;
+ iov++;
+ diff++;
+ }
+ *total_r += left;
+ }
+ cstream->ostream.ostream.offset = cstream->output->offset;
return ret;
}
@@ -177,45 +220,80 @@
size_t iov_count)
{
struct crlf_ostream *cstream = (struct crlf_ostream *)stream;
- buffer_t *buf;
+ buffer_t *iov_buf, *diff_buf;
const unsigned char *data;
struct const_iovec new_iov;
- size_t vec, i, len, start, new_iov_count = 0, new_iov_size = 0;
- ssize_t ret;
+ size_t vec, i, len, start, next, new_iov_count = 0, new_iov_size = 0;
+ ssize_t ret, total;
+ int diff;
t_push();
- buf = buffer_create_dynamic(unsafe_data_stack_pool,
- sizeof(struct const_iovec *) * IOVBUF_COUNT,
- (size_t)-1);
+ iov_buf = buffer_create_dynamic(unsafe_data_stack_pool,
+ sizeof(struct const_iovec *) *
+ IOVBUF_COUNT, (size_t)-1);
+ diff_buf = buffer_create_dynamic(unsafe_data_stack_pool,
+ IOVBUF_COUNT, (size_t)-1);
+ total = 0;
for (vec = 0; vec < iov_count; vec++) {
data = iov[vec].iov_base;
len = iov[vec].iov_len;
for (i = start = 0;; i++) {
- if (i != len && data[i] != '\r')
- continue;
-
- if (i != start) {
- new_iov.iov_base = data + start;
- new_iov.iov_len = i - start;
+ if (i != len) {
+ if (data[i] != '\n' || i == 0 ||
+ data[i-1] != '\r')
+ continue;
+ }
- buffer_append(buf, &new_iov, sizeof(new_iov));
+ if (start == 0 && i > 0 && data[0] != '\n' &&
+ cstream->last_cr) {
+ /* bare CR, keep it */
+ buffer_append(iov_buf, &cr_iov, sizeof(cr_iov));
+ buffer_append_c(diff_buf, -1);
new_iov_count++;
- new_iov_size += new_iov.iov_len;
+ new_iov_size++;
}
- start = i+1;
+
+ next = i;
+ if (i != len) {
+ /* skipping an CR */
+ i--;
+ cstream->last_cr = FALSE;
+ diff = 1;
+ } else if (i != start && data[i-1] == '\r') {
+ /* data ends with CR, don't add it yet */
+ i--;
+ cstream->last_cr = TRUE;
+ diff = 1;
+ } else {
+ /* data doesn't end with CR */
+ cstream->last_cr = FALSE;
+ diff = 0;
+ }
+
+ new_iov.iov_base = data + start;
+ new_iov.iov_len = i - start;
+
+ buffer_append(iov_buf, &new_iov, sizeof(new_iov));
+ buffer_append_c(diff_buf, diff);
+ new_iov_count++;
+ new_iov_size += new_iov.iov_len;
+
+ start = i = next;
if (new_iov_count == IOVBUF_COUNT) {
- ret = o_stream_sendv(cstream->output,
- buf->data, new_iov_count);
+ ret = sendv_lf(cstream, iov_buf->data,
+ new_iov_count, diff_buf->data,
+ &total);
stream->ostream.offset =
cstream->output->offset;
if (ret != (ssize_t)new_iov_size) {
t_pop();
- return ret;
+ return ret < 0 ? ret : total;
}
- buffer_set_used_size(buf, 0);
+ buffer_set_used_size(iov_buf, 0);
+ buffer_set_used_size(diff_buf, 0);
new_iov_count = 0;
new_iov_size = 0;
}
@@ -225,11 +303,18 @@
}
}
- ret = o_stream_sendv(cstream->output, buf->data, new_iov_count);
+ if (new_iov_count == 0) {
+ /* Tried to send only CR. */
+ ret = 0;
+ total++;
+ } else {
+ ret = sendv_lf(cstream, iov_buf->data, new_iov_count,
+ diff_buf->data, &total);
+ }
stream->ostream.offset = cstream->output->offset;
t_pop();
- return ret;
+ return ret < 0 ? ret : total;
}
static off_t
Index: ostream-crlf.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/ostream-crlf.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ostream-crlf.h 22 Aug 2004 05:04:16 -0000 1.1
+++ ostream-crlf.h 23 Aug 2004 03:58:08 -0000 1.2
@@ -3,7 +3,7 @@
/* Replace all plain LFs with CRLF. */
struct ostream *o_stream_create_crlf(pool_t pool, struct ostream *output);
-/* Remove all CRs. */
+/* Replace all CRLF pairs with plain LFs. */
struct ostream *o_stream_create_lf(pool_t pool, struct ostream *output);
#endif
More information about the dovecot-cvs
mailing list