break;
}
+ if (size == 0)
+ return -1;
+
if (pos == size || size <= 5 ||
strncmp((const char *) data, "From ", 5) != 0) {
/* a) no \n found, or line too long
uoff_t offset;
int ret;
- if (input->v_offset == input->v_size) {
+ if (input->eof) {
/* no new data */
return TRUE;
}
}
}
- if (input->v_offset == input->v_size) {
- ret = 1;
- break;
- }
-
t_push();
ret = mbox_index_append_next(index, trans_ctx, input);
t_pop();
+ if (input->eof) {
+ ret = 1;
+ break;
+ }
+
if (ret == 0) {
/* we want to rescan this message with exclusive
locking */
const unsigned char *data;
size_t size;
- if (end_offset > input->v_size) {
- /* missing data */
- return FALSE;
- }
-
i_stream_seek(input, end_offset);
- if (input->v_offset == input->v_size) {
+ /* read forward a bit */
+ if (i_stream_read_data(input, &data, &size, 6) < 0)
+ return FALSE;
+
+ if (input->eof) {
/* end of file. a bit unexpected though,
since \n is missing. */
return TRUE;
}
- /* read forward a bit */
- if (i_stream_read_data(input, &data, &size, 6) < 0)
- return FALSE;
-
/* either there should be the next From-line,
or [\r]\n at end of file */
if (size > 0 && data[0] == '\r') {
break;
}
- if (offset + body_size > input->v_size) {
- mail_cache_set_corrupted(index->cache,
- "Invalid message size");
- failed = TRUE;
- break;
- }
-
if (!dirty_found) {
/* first dirty message */
dirty_found = TRUE;
{
const unsigned char *msg;
size_t i, size;
+ int ret;
- while (i_stream_read_data(input, &msg, &size, 0) > 0) {
+ while ((ret = i_stream_read_data(input, &msg, &size, 0)) > 0) {
for (i = 0; i < size; i++) {
if (msg[i] == '\n') {
i_stream_skip(input, i+1);
/* skip the From-line */
skip_line(input);
+ if (input->eof)
+ return -1;
header_offset = input->v_offset;
first_rec = last_rec = NULL;
}
}
- if (input->v_offset == input->v_size)
- break;
-
ret = match_next_record(index, rec, &seq, input, &rec, &dirty);
- if (ret < 0)
+ if (ret < 0) {
+ if (input->eof)
+ break;
return FALSE;
+ }
if (ret == 0) {
/* Get back to line before From */
index->header->flags &= ~MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES;
}
- if (input->v_offset == input->v_size ||
- (index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD))
+ if (input->eof || (index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD))
return TRUE;
else
return mbox_index_append_stream(index, input);
failed = TRUE;
} else {
failed = !mbox_sync_from_stream(index, input);
- continue_offset = failed || input->v_offset == input->v_size ||
+ continue_offset = failed || input->eof ||
(index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) ?
(uoff_t)-1 : input->v_offset;
i_stream_unref(input);
old_limit = input->v_limit;
limit = input->v_offset + max_virtual_size;
i_stream_set_read_limit(input, I_MIN(limit, old_limit));
- ret = o_stream_send_istream(output, input) > 0;
+ ret = o_stream_send_istream(output, input);
i_stream_set_read_limit(input, old_limit);
return ret;
failed = o_stream_send_istream(ctx->output, ctx->input) < 0;
i_stream_set_read_limit(ctx->input, old_limit);
- if (failed || ctx->input->v_offset != ctx->from_offset)
+ if (failed || (ctx->input->v_offset != ctx->from_offset &&
+ ctx->from_offset != 0))
return FALSE;
return TRUE;
}
stream->istream.v_offset + fstream->skip_left;
if (read_limit <= stream->pos - stream->skip) {
/* virtual limit reached == EOF */
+ stream->istream.eof = TRUE;
return -1;
}
if (ret == 0) {
/* EOF */
stream->istream.stream_errno = 0;
+ stream->istream.eof = TRUE;
return -1;
}
if (errno == ECONNRESET || errno == ETIMEDOUT) {
/* treat as disconnection */
stream->istream.stream_errno = 0;
+ stream->istream.eof = TRUE;
return -1;
}
fstream->istream.seek = _seek;
/* get size of fd if it's a file */
- if (fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
- st.st_size = 0;
- else
+ if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
fstream->file = TRUE;
- return _i_stream_create(&fstream->istream, pool, fd, 0,
- (uoff_t)st.st_size);
+ return _i_stream_create(&fstream->istream, pool, fd, 0, 0);
}
(uoff_t)mstream->mmap_offset + stream->pos) {
/* end of file */
stream->istream.stream_errno = 0;
+ stream->istream.eof = TRUE;
return -1;
}
i_assert(stream->v_size == 0 || v_offset <= stream->v_size);
+ stream->eof = FALSE;
if (_stream->high_pos != 0) {
_stream->pos = _stream->high_pos;
_stream->high_pos = 0;
return -1;
}
+ stream->eof = FALSE;
return _stream->read(_stream);
}
{
struct _istream *_stream = stream->real_stream;
- i_assert(v_offset <= stream->v_size);
+ i_assert(stream->v_size == 0 || v_offset <= stream->v_size);
if (stream->closed)
return;
+ stream->eof = FALSE;
_stream->high_pos = 0;
_stream->seek(_stream, v_offset);
}
int stream_errno;
unsigned int mmaped:1; /* be careful when copying data */
unsigned int closed:1;
+ unsigned int eof:1;
struct _istream *real_stream;
};
out_offset = outstream->ostream.offset +
(instream->v_limit - instream->v_offset);
- i_assert(out_offset <= instream->start_offset + instream->v_size);
+ i_assert(instream->v_size == 0 ||
+ out_offset <= instream->start_offset + instream->v_size);
while (in_offset > in_start_offset) {
if (in_offset - in_start_offset <= buffer_size)
return (off_t) (instream->v_limit - in_start_offset);
}
-static off_t _send_istream(struct _ostream *outstream, struct istream *instream)
+static off_t send_istream_fd(struct _ostream *outstream,
+ struct istream *instream, int in_fd)
{
struct file_ostream *foutstream = (struct file_ostream *) outstream;
uoff_t old_limit;
off_t ret;
- int in_fd, overlapping;
+ int overlapping;
i_assert(instream->v_limit <= OFF_T_MAX);
i_assert(instream->v_offset <= instream->v_limit);
if (instream->v_offset == instream->v_limit)
return 0;
- in_fd = i_stream_get_fd(instream);
if (in_fd != foutstream->fd)
overlapping = 0;
else {
}
}
+static off_t _send_istream(struct _ostream *outstream, struct istream *instream)
+{
+ struct stat st;
+ int in_fd, ret;
+
+ in_fd = i_stream_get_fd(instream);
+ if (fstat(in_fd, &st) < 0) {
+ outstream->ostream.stream_errno = errno;
+ return -1;
+ }
+
+ if (instream->v_limit != 0)
+ return send_istream_fd(outstream, instream, in_fd);
+ else {
+ /* easier this way so we know exactly how much data we're
+ moving */
+ i_stream_set_read_limit(instream, st.st_size);
+ ret = send_istream_fd(outstream, instream, in_fd);
+ i_stream_set_read_limit(instream, 0);
+ return ret;
+ }
+}
+
struct ostream *
o_stream_create_file(int fd, pool_t pool, size_t max_buffer_size,
int autoclose_fd)