# HG changeset patch # User Timo Sirainen # Date 1112092219 -10800 # Node ID 9a08cf5e5f610e3d2236beb49243073ea49ee9aa # Parent b79853b4b005ac9d38c97ea7e2d1f04c15f13982 i_stream_sync() replaced istream_raw_mbox_flush(). Use i_stream_stat() instead of fstat() directly. Now we have the possibility to use istreams as read-only mboxes. diff -r b79853b4b005 -r 9a08cf5e5f61 src/lib-storage/index/mbox/istream-raw-mbox.c --- a/src/lib-storage/index/mbox/istream-raw-mbox.c Tue Mar 29 13:28:06 2005 +0300 +++ b/src/lib-storage/index/mbox/istream-raw-mbox.c Tue Mar 29 13:30:19 2005 +0300 @@ -271,6 +271,23 @@ rstream->eof = FALSE; } +static void _sync(struct _istream *stream) +{ + struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream; + + i_stream_sync(rstream->input); + + rstream->istream.skip = 0; + rstream->istream.pos = 0; +} + +static const struct stat *_stat(struct _istream *stream) +{ + struct raw_mbox_istream *rstream = (struct raw_mbox_istream *)stream; + + return i_stream_stat(rstream->input); +} + struct istream *i_stream_create_raw_mbox(pool_t pool, struct istream *input) { struct raw_mbox_istream *rstream; @@ -291,6 +308,8 @@ rstream->istream.read = _read; rstream->istream.seek = _seek; + rstream->istream.sync = _sync; + rstream->istream.stat = _stat; return _i_stream_create(&rstream->istream, pool, -1, input->real_stream->abs_start_offset); @@ -496,19 +515,6 @@ return rstream->corrupted ? -1 : 0; } -void istream_raw_mbox_flush(struct istream *stream) -{ - struct raw_mbox_istream *rstream = - (struct raw_mbox_istream *)stream->real_stream; - - /* kludgy */ - rstream->input->real_stream->skip = 0; - rstream->input->real_stream->pos = 0; - - rstream->istream.skip = 0; - rstream->istream.pos = 0; -} - int istream_raw_mbox_is_eof(struct istream *stream) { struct raw_mbox_istream *rstream = diff -r b79853b4b005 -r 9a08cf5e5f61 src/lib-storage/index/mbox/istream-raw-mbox.h --- a/src/lib-storage/index/mbox/istream-raw-mbox.h Tue Mar 29 13:28:06 2005 +0300 +++ b/src/lib-storage/index/mbox/istream-raw-mbox.h Tue Mar 29 13:30:19 2005 +0300 @@ -33,9 +33,6 @@ contain a valid From-line. */ int istream_raw_mbox_seek(struct istream *stream, uoff_t offset); -/* Flush all buffering. Call if you modify the mbox. */ -void istream_raw_mbox_flush(struct istream *stream); - /* Returns TRUE if we've read the whole mbox. */ int istream_raw_mbox_is_eof(struct istream *stream); diff -r b79853b4b005 -r 9a08cf5e5f61 src/lib-storage/index/mbox/mbox-sync-private.h --- a/src/lib-storage/index/mbox/mbox-sync-private.h Tue Mar 29 13:28:06 2005 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync-private.h Tue Mar 29 13:30:19 2005 +0300 @@ -88,7 +88,7 @@ struct index_mailbox *ibox; enum mbox_sync_flags flags; struct istream *input, *file_input; - int fd; + int write_fd; struct mail_index_sync_ctx *index_sync_ctx; struct mail_index_view *sync_view; diff -r b79853b4b005 -r 9a08cf5e5f61 src/lib-storage/index/mbox/mbox-sync-rewrite.c --- a/src/lib-storage/index/mbox/mbox-sync-rewrite.c Tue Mar 29 13:28:06 2005 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync-rewrite.c Tue Mar 29 13:30:19 2005 +0300 @@ -21,9 +21,10 @@ if (size == 0 || source == dest) return 0; - istream_raw_mbox_flush(sync_ctx->input); + i_stream_sync(sync_ctx->input); - output = o_stream_create_file(sync_ctx->fd, default_pool, 4096, FALSE); + output = o_stream_create_file(sync_ctx->write_fd, default_pool, + 4096, FALSE); i_stream_seek(sync_ctx->file_input, source); o_stream_seek(output, dest); @@ -57,7 +58,7 @@ memset(space, ' ', sizeof(space)); while (size > sizeof(space)) { - if (pwrite_full(sync_ctx->fd, space, + if (pwrite_full(sync_ctx->write_fd, space, sizeof(space), offset) < 0) { mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()"); return -1; @@ -65,7 +66,7 @@ size -= sizeof(space); } - if (pwrite_full(sync_ctx->fd, space, size, offset) < 0) { + if (pwrite_full(sync_ctx->write_fd, space, size, offset) < 0) { mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()"); return -1; } @@ -265,7 +266,7 @@ ctx->header_last_change != 0) str_truncate(ctx->header, ctx->header_last_change); - if (pwrite_full(ctx->sync_ctx->fd, + if (pwrite_full(ctx->sync_ctx->write_fd, str_data(ctx->header) + ctx->header_first_change, str_len(ctx->header) - ctx->header_first_change, ctx->hdr_offset + ctx->header_first_change + @@ -280,7 +281,7 @@ ctx->sync_ctx->update_base_uid_last = 0; } - istream_raw_mbox_flush(ctx->sync_ctx->input); + i_stream_sync(ctx->sync_ctx->input); return 1; } @@ -368,7 +369,7 @@ space which we wanted to remove */ i_assert(dest_offset >= str_len(mail_ctx.header)); dest_offset -= str_len(mail_ctx.header); - if (pwrite_full(sync_ctx->fd, str_data(mail_ctx.header), + if (pwrite_full(sync_ctx->write_fd, str_data(mail_ctx.header), str_len(mail_ctx.header), dest_offset) < 0) { mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()"); return -1; @@ -498,6 +499,6 @@ i_assert(mails[idx].from_offset == start_offset); i_assert(move_diff + (off_t)expunged_space >= 0); - istream_raw_mbox_flush(sync_ctx->input); + i_stream_sync(sync_ctx->input); return ret; } diff -r b79853b4b005 -r 9a08cf5e5f61 src/lib-storage/index/mbox/mbox-sync.c --- a/src/lib-storage/index/mbox/mbox-sync.c Tue Mar 29 13:28:06 2005 +0300 +++ b/src/lib-storage/index/mbox/mbox-sync.c Tue Mar 29 13:30:19 2005 +0300 @@ -454,13 +454,13 @@ { string_t *str = ctx->sync_ctx->from_line; - if (pwrite_full(ctx->sync_ctx->fd, str_data(str), str_len(str), + if (pwrite_full(ctx->sync_ctx->write_fd, str_data(str), str_len(str), ctx->mail.from_offset) < 0) { mbox_set_syscall_error(ctx->sync_ctx->ibox, "pwrite_full()"); return -1; } - istream_raw_mbox_flush(ctx->sync_ctx->input); + i_stream_sync(ctx->sync_ctx->input); return 0; } @@ -724,7 +724,7 @@ { struct mail_index_view *sync_view = sync_ctx->sync_view; uint32_t seq1, seq2; - uoff_t file_size; + const struct stat *st; if (mail_index_lookup_uid_range(sync_view, uid, (uint32_t)-1, &seq1, &seq2) < 0) { @@ -734,9 +734,15 @@ if (seq1 == 0) { /* doesn't exist anymore, seek to end of file */ - file_size = i_stream_get_size(sync_ctx->ibox->mbox_file_stream); + st = i_stream_stat(sync_ctx->ibox->mbox_file_stream); + if (st == NULL) { + mbox_set_syscall_error(sync_ctx->ibox, + "i_stream_stat()"); + return -1; + } + if (istream_raw_mbox_seek(sync_ctx->ibox->mbox_stream, - file_size) < 0) { + st->st_size) < 0) { mail_storage_set_critical(sync_ctx->ibox->box.storage, "Error seeking to end of mbox file %s", sync_ctx->ibox->path); @@ -951,6 +957,8 @@ string_t *str; unsigned int uid_validity; + i_assert(sync_ctx->write_fd != -1); + uid_validity = sync_ctx->base_uid_validity != 0 ? sync_ctx->base_uid_validity : sync_ctx->hdr->uid_validity; i_assert(uid_validity != 0); @@ -970,7 +978,8 @@ my_hostname, dec2str(ioloop_time), my_hostname, uid_validity, sync_ctx->next_uid-1); - if (pwrite_full(sync_ctx->fd, str_data(str), str_len(str), 0) < 0) { + if (pwrite_full(sync_ctx->write_fd, + str_data(str), str_len(str), 0) < 0) { if (!ENOSPACE(errno)) { mbox_set_syscall_error(sync_ctx->ibox, "pwrite_full()"); @@ -978,7 +987,7 @@ } /* out of disk space, truncate to empty */ - (void)ftruncate(sync_ctx->fd, 0); + (void)ftruncate(sync_ctx->write_fd, 0); } return 0; } @@ -986,6 +995,7 @@ static int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx, struct mbox_sync_mail_context *mail_ctx) { + const struct stat *st; uoff_t file_size, offset, padding, trailer_size; if (!istream_raw_mbox_is_eof(sync_ctx->input)) { @@ -994,12 +1004,20 @@ return 0; } - file_size = i_stream_get_size(sync_ctx->file_input); + st = i_stream_stat(sync_ctx->file_input); + if (st == NULL) { + mbox_set_syscall_error(sync_ctx->ibox, "i_stream_stat()"); + return -1; + } + + file_size = st->st_size; i_assert(file_size >= sync_ctx->file_input->v_offset); trailer_size = file_size - sync_ctx->file_input->v_offset; i_assert(trailer_size <= 1); if (sync_ctx->need_space_seq != 0) { + i_assert(sync_ctx->write_fd != -1); + i_assert(sync_ctx->space_diff < 0); padding = MBOX_HEADER_PADDING * (sync_ctx->seq - sync_ctx->need_space_seq + 1); @@ -1014,13 +1032,13 @@ i_assert(sync_ctx->space_diff < 0); - if (file_set_size(sync_ctx->fd, + if (file_set_size(sync_ctx->write_fd, file_size + -sync_ctx->space_diff) < 0) { mbox_set_syscall_error(sync_ctx->ibox, "file_set_size()"); return -1; } - istream_raw_mbox_flush(sync_ctx->input); + i_stream_sync(sync_ctx->input); if (mbox_sync_rewrite(sync_ctx, file_size, -sync_ctx->space_diff, padding, @@ -1035,8 +1053,17 @@ } if (sync_ctx->expunged_space > 0) { + i_assert(sync_ctx->write_fd != -1); + /* copy trailer, then truncate the file */ - file_size = i_stream_get_size(sync_ctx->file_input); + st = i_stream_stat(sync_ctx->file_input); + if (st == NULL) { + mbox_set_syscall_error(sync_ctx->ibox, + "i_stream_stat()"); + return -1; + } + + file_size = st->st_size; if (file_size == (uoff_t)sync_ctx->expunged_space) { /* everything deleted, the trailer_size still contains the \n trailer though */ @@ -1051,7 +1078,8 @@ offset + sync_ctx->expunged_space, trailer_size) < 0) return -1; - if (ftruncate(sync_ctx->fd, offset + trailer_size) < 0) { + if (ftruncate(sync_ctx->write_fd, + offset + trailer_size) < 0) { mbox_set_syscall_error(sync_ctx->ibox, "ftruncate()"); return -1; } @@ -1062,17 +1090,18 @@ } sync_ctx->expunged_space = 0; - istream_raw_mbox_flush(sync_ctx->input); + i_stream_sync(sync_ctx->input); } return 0; } static int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx) { - struct stat st; + const struct stat *st; - if (fstat(sync_ctx->fd, &st) < 0) { - mbox_set_syscall_error(sync_ctx->ibox, "fstat()"); + st = i_stream_stat(sync_ctx->file_input); + if (st == NULL) { + mbox_set_syscall_error(sync_ctx->ibox, "i_stream_stat()"); return -1; } @@ -1101,25 +1130,26 @@ &sync_ctx->next_uid, sizeof(sync_ctx->next_uid)); } - if ((uint32_t)st.st_mtime != sync_ctx->hdr->sync_stamp && + if ((uint32_t)st->st_mtime != sync_ctx->hdr->sync_stamp && !sync_ctx->ibox->mbox_sync_dirty) { - uint32_t sync_stamp = st.st_mtime; + uint32_t sync_stamp = st->st_mtime; mail_index_update_header(sync_ctx->t, offsetof(struct mail_index_header, sync_stamp), &sync_stamp, sizeof(sync_stamp)); } - if ((uint64_t)st.st_size != sync_ctx->hdr->sync_size && + + if ((uint64_t)st->st_size != sync_ctx->hdr->sync_size && !sync_ctx->ibox->mbox_sync_dirty) { - uint64_t sync_size = st.st_size; + uint64_t sync_size = st->st_size; mail_index_update_header(sync_ctx->t, offsetof(struct mail_index_header, sync_size), &sync_size, sizeof(sync_size)); } - sync_ctx->ibox->mbox_dirty_stamp = st.st_mtime; - sync_ctx->ibox->mbox_dirty_size = st.st_size; + sync_ctx->ibox->mbox_dirty_stamp = st->st_mtime; + sync_ctx->ibox->mbox_dirty_size = st->st_size; return 0; } @@ -1150,7 +1180,7 @@ enum mbox_sync_flags flags) { struct mbox_sync_mail_context mail_ctx; - struct stat st; + const struct stat *st; uint32_t min_msg_count; int ret, partial; @@ -1159,18 +1189,20 @@ if ((flags & MBOX_SYNC_HEADER) != 0) min_msg_count = 1; else { - if (fstat(sync_ctx->fd, &st) < 0) { - mbox_set_syscall_error(sync_ctx->ibox, "stat()"); + st = i_stream_stat(sync_ctx->file_input); + if (st == NULL) { + mbox_set_syscall_error(sync_ctx->ibox, + "i_stream_stat()"); return -1; } - if ((uint32_t)st.st_mtime == sync_ctx->hdr->sync_stamp && - (uint64_t)st.st_size == sync_ctx->hdr->sync_size) { + if ((uint32_t)st->st_mtime == sync_ctx->hdr->sync_stamp && + (uint64_t)st->st_size == sync_ctx->hdr->sync_size) { /* file is fully synced */ sync_ctx->ibox->mbox_sync_dirty = FALSE; min_msg_count = 0; } else if ((flags & MBOX_SYNC_UNDIRTY) != 0 || - (uint64_t)st.st_size == sync_ctx->hdr->sync_size) { + (uint64_t)st->st_size == sync_ctx->hdr->sync_size) { /* we want to do full syncing. always do this if file size hasn't changed but timestamp has. it most likely means that someone had modified some header @@ -1390,7 +1422,8 @@ sync_ctx.file_input = sync_ctx.ibox->mbox_file_stream; sync_ctx.input = sync_ctx.ibox->mbox_stream; - sync_ctx.fd = sync_ctx.ibox->mbox_fd; + sync_ctx.write_fd = sync_ctx.ibox->mbox_readonly ? -1 : + sync_ctx.ibox->mbox_fd; sync_ctx.flags = flags; sync_ctx.delay_writes = sync_ctx.ibox->mbox_readonly || sync_ctx.ibox->readonly ||