[dovecot-cvs] dovecot/src/lib-index/mbox mbox-sync-full.c,NONE,1.1 Makefile.am,1.3,1.4 mbox-index.c,1.40,1.41 mbox-index.h,1.17,1.18 mbox-lock.c,1.8,1.9 mbox-lock.h,1.3,1.4 mbox-open.c,1.16,1.17 mbox-rebuild.c,1.16,1.17 mbox-rewrite.c,1.30,1.31 mbox-sync.c,1.14,1.15 Message-Id: <20021026193839.E009A23861@danu.procontrol.fi>

cras at procontrol.fi cras at procontrol.fi
Sat Oct 26 23:38:39 EEST 2002


Update of /home/cvs/dovecot/src/lib-index/mbox
In directory danu:/tmp/cvs-serv5075/lib-index/mbox

Modified Files:
	Makefile.am mbox-index.c mbox-index.h mbox-lock.c mbox-lock.h 
	mbox-open.c mbox-rebuild.c mbox-rewrite.c mbox-sync.c 
Added Files:
	mbox-sync-full.c 
Removed Files:
	mbox-fsck.c 
Log Message:
mbox locking fixes / changes. we now read-lock the mbox file before syncing
so we can be sure no-one corrupts our reads by expunging mailbox. mbox file
is kept open all the time, but re-opened when device/inode for file has
changed (ie. someone overwrote it). File is also kept mmap()ed until lock is
dropped.

we currently create .lock file even when reading the file (ie. being
effectively write-lock), but that'll be made configurable later.



--- NEW FILE: mbox-sync-full.c ---
/* Copyright (C) 2002 Timo Sirainen */

#include "lib.h"
#include "ibuffer.h"
#include "hex-binary.h"
#include "message-parser.h"
#include "message-part-serialize.h"
#include "mbox-index.h"
#include "mbox-lock.h"
#include "mail-index-util.h"

#include <unistd.h>
#include <fcntl.h>

static void skip_line(IBuffer *inbuf)
{
	const unsigned char *msg;
	size_t i, size;

	while (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) {
		for (i = 0; i < size; i++) {
			if (msg[i] == '\n') {
				i_buffer_skip(inbuf, i+1);
				return;
			}
		}

		i_buffer_skip(inbuf, i);
	}
}

static int verify_header_md5sum(MailIndex *index, MailIndexRecord *rec,
				unsigned char current_digest[16])
{
	const unsigned char *old_digest;
	size_t size;

	/* MD5 sums must match */
	old_digest = index->lookup_field_raw(index, rec, FIELD_TYPE_MD5, &size);
	return old_digest != NULL && size >= 16 &&
                memcmp(old_digest, current_digest, 16) == 0;
}

static int mail_update_header_size(MailIndex *index, MailIndexRecord *rec,
				   MailIndexUpdate *update,
				   MessageSize *hdr_size)
{
	const void *part_data;
	void *part_data_copy;
	size_t size;

	/* update index record */
	rec->header_size = hdr_size->physical_size;

	if ((rec->cached_fields & FIELD_TYPE_MESSAGEPART) == 0)
		return TRUE;

	/* update FIELD_TYPE_MESSAGEPART */
	part_data = index->lookup_field_raw(index, rec, FIELD_TYPE_MESSAGEPART,
					    &size);
	if (part_data == NULL) {
		/* well, this wasn't expected but don't bother failing */
		return TRUE;
	}

	t_push();

	/* copy & update the part data */
	part_data_copy = t_malloc(size);
	memcpy(part_data_copy, part_data, size);

	if (!message_part_serialize_update_header(part_data_copy, size,
						  hdr_size)) {
		t_pop();
		return FALSE;
	}

	t_pop();

	index->update_field_raw(update, FIELD_TYPE_MESSAGEPART,
				part_data_copy, size);
	return TRUE;
}

static int match_next_record(MailIndex *index, MailIndexRecord *rec,
			     unsigned int seq, IBuffer *inbuf,
			     MailIndexRecord **next_rec, int *dirty)
{
        MailIndexUpdate *update;
	MessageSize hdr_size;
	MboxHeaderContext ctx;
	uoff_t header_offset, body_offset, offset;
	unsigned char current_digest[16];

	*next_rec = NULL;

	/* skip the From-line */
	skip_line(inbuf);

	header_offset = inbuf->v_offset;

	if (rec->body_size == 0) {
		/* possibly broken message, find the next From-line and make
		   sure header parser won't pass it. */
		mbox_skip_header(inbuf);
		i_buffer_set_read_limit(inbuf, inbuf->v_offset);
		i_buffer_seek(inbuf, header_offset);
	}

	/* get the MD5 sum of fixed headers and the current message flags
	   in Status and X-Status fields */
        mbox_header_init_context(&ctx, index, inbuf);
	message_parse_header(NULL, inbuf, &hdr_size, mbox_header_func, &ctx);
	md5_final(&ctx.md5, current_digest);

	mbox_header_free_context(&ctx);
	i_buffer_set_read_limit(inbuf, 0);

	body_offset = inbuf->v_offset;
	do {
		if (verify_header_md5sum(index, rec, current_digest) &&
		    mbox_verify_end_of_body(inbuf,
					    body_offset + rec->body_size)) {
			/* valid message */
			update = index->update_begin(index, rec);

			/* update flags, unless we've changed them */
			if ((rec->index_flags & INDEX_MAIL_FLAG_DIRTY) == 0) {
				if (!index->update_flags(index, rec, seq,
							 ctx.flags, TRUE))
					return FALSE;

				/* update_flags() sets dirty flag, remove it */
				rec->index_flags &= ~INDEX_MAIL_FLAG_DIRTY;
			} else {
				if (rec->msg_flags != ctx.flags)
					*dirty = TRUE;
			}

			/* update location */
			if (!mbox_mail_get_start_offset(index, rec, &offset))
				return FALSE;
			if (offset != header_offset) {
				index->update_field_raw(update,
							FIELD_TYPE_LOCATION,
							&header_offset,
							sizeof(uoff_t));
			}

			/* update size */
			if (rec->header_size != hdr_size.physical_size ) {
				if (!mail_update_header_size(index, rec,
							     update, &hdr_size))
					return FALSE;
			}

			if (!index->update_end(update))
				return FALSE;

			*next_rec = rec;
			break;
		}

		/* try next message */
		(void)index->expunge(index, rec, seq, TRUE);
		rec = index->next(index, rec);
	} while (rec != NULL);

	return TRUE;
}

static int mbox_sync_buf(MailIndex *index, IBuffer *inbuf)
{
	MailIndexRecord *rec;
	uoff_t from_offset;
	const unsigned char *data;
	size_t size;
	unsigned int seq;
	int dirty;

	if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
		return FALSE;

	mbox_skip_empty_lines(inbuf);

	/* first make sure we start with a "From " line. If file is too
	   small, we'll just treat it as empty mbox file. */
	if (i_buffer_read_data(inbuf, &data, &size, 5) > 0 &&
	    strncmp((const char *) data, "From ", 5) != 0) {
		index_set_error(index, "File isn't in mbox format: %s",
				index->mbox_path);
		return FALSE;
	}

	/* we'll go through the mailbox and index in order matching the
	   messages by their size and Message-ID. old mails aren't remembered,
	   so we handle well only the cases when mail has been deleted. if
	   mails have been reordered (eg. sorted by someone) most of the mails
	   will show up as being new. if we really wanted to support that well,
	   we could save the message-ids into hash but I don't know if it's
	   worth the trouble. */

	seq = 1;
	rec = index->lookup(index, 1);

	dirty = FALSE;
	while (rec != NULL) {
		from_offset = inbuf->v_offset;
		if (inbuf->v_offset != 0) {
			/* we're at the [\r]\n before the From-line,
			   skip it */
			if (!mbox_skip_crlf(inbuf)) {
				/* they just went and broke it, even while
				   we had it locked. */
				return FALSE;
			}
		}

		if (inbuf->v_offset == inbuf->v_size)
			break;

		if (!match_next_record(index, rec, seq, inbuf, &rec, &dirty))
			return FALSE;

		if (rec == NULL) {
			/* Get back to line before From */
			i_buffer_seek(inbuf, from_offset);
			break;
		}

		seq++;
		rec = index->next(index, rec);
	}

	/* delete the rest of the records */
	while (rec != NULL) {
		(void)index->expunge(index, rec, seq, TRUE);

		rec = index->next(index, rec);
	}

	if (!dirty && (index->header->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES)) {
		/* no flags were dirty anymore, no need to rewrite */
		index->header->flags &= ~MAIL_INDEX_FLAG_DIRTY_MESSAGES;
	}

	if (inbuf->v_offset == inbuf->v_size)
		return TRUE;
	else
		return mbox_index_append(index, inbuf);
}

int mbox_sync_full(MailIndex *index)
{
	IBuffer *inbuf;
	int failed, unlock;

	unlock = index->mbox_lock_type == MAIL_LOCK_UNLOCK;
	inbuf = mbox_get_inbuf(index, 0, MAIL_LOCK_SHARED);
	if (inbuf == NULL)
		return FALSE;

	failed = !mbox_sync_buf(index, inbuf);
	i_buffer_unref(inbuf);

	if (unlock)
		(void)mbox_unlock(index);

	return !failed;
}

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Makefile.am	6 Sep 2002 13:43:58 -0000	1.3
+++ Makefile.am	26 Oct 2002 19:38:37 -0000	1.4
@@ -9,13 +9,13 @@
 libstorage_index_mbox_a_SOURCES = \
 	mbox-append.c \
 	mbox-from.c \
-	mbox-fsck.c \
 	mbox-index.c \
 	mbox-lock.c \
 	mbox-open.c \
 	mbox-rebuild.c \
 	mbox-rewrite.c \
-	mbox-sync.c
+	mbox-sync.c \
+	mbox-sync-full.c
 
 noinst_HEADERS = \
 	mbox-index.h \

Index: mbox-index.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-index.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- mbox-index.c	25 Oct 2002 03:29:53 -0000	1.40
+++ mbox-index.c	26 Oct 2002 19:38:37 -0000	1.41
@@ -4,12 +4,14 @@
 #include "ibuffer.h"
 #include "rfc822-tokenize.h"
 #include "mbox-index.h"
+#include "mbox-lock.h"
 #include "mail-index-util.h"
 #include "mail-index-data.h"
 #include "mail-custom-flags.h"
 
-#include <fcntl.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 
 extern MailIndex mbox_index;
 
@@ -22,28 +24,79 @@
 	return FALSE;
 }
 
-IBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen)
+int mbox_file_open(MailIndex *index)
 {
-	i_assert(offset < OFF_T_MAX);
+	struct stat st;
+	int fd;
 
-	if (reopen)
-		mbox_file_close(index);
+	i_assert(index->mbox_fd == -1);
 
-	if (index->mbox_fd == -1) {
-		index->mbox_fd = open(index->mbox_path, O_RDWR);
+	fd = open(index->mbox_path, O_RDWR);
+	if (fd == -1) {
+		mbox_set_syscall_error(index, "open()");
+		return FALSE;
+	}
+
+	if (fstat(fd, &st) < 0) {
+		mbox_set_syscall_error(index, "fstat()");
+		(void)close(fd);
+		return FALSE;
+	}
+
+	index->mbox_fd = fd;
+	index->mbox_dev = st.st_dev;
+	index->mbox_ino = st.st_ino;
+	return TRUE;
+}
+
+IBuffer *mbox_get_inbuf(MailIndex *index, uoff_t offset, MailLockType lock_type)
+{
+	i_assert(offset < OFF_T_MAX);
+
+	switch (lock_type) {
+	case MAIL_LOCK_SHARED:
+	case MAIL_LOCK_EXCLUSIVE:
+		/* don't drop exclusive lock, it may be there for a reason */
+		if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) {
+			if (!mbox_lock(index, lock_type))
+				return NULL;
+		}
+		break;
+	default:
 		if (index->mbox_fd == -1) {
-			mbox_set_syscall_error(index, "open()");
-			return NULL;
+			if (!mbox_file_open(index))
+				return NULL;
 		}
+		break;
 	}
 
-	return i_buffer_create_mmap(index->mbox_fd, default_pool,
-				    MAIL_MMAP_BLOCK_SIZE,
-				    (uoff_t)offset, 0, FALSE);
+	if (index->mbox_inbuf == NULL) {
+		index->mbox_inbuf =
+			i_buffer_create_mmap(index->mbox_fd, default_pool,
+					     MAIL_MMAP_BLOCK_SIZE, 0, 0, FALSE);
+	}
+
+	i_buffer_set_read_limit(index->mbox_inbuf, 0);
+	i_buffer_set_start_offset(index->mbox_inbuf, (uoff_t)offset);
+	i_buffer_seek(index->mbox_inbuf, 0);
+
+	i_buffer_ref(index->mbox_inbuf);
+	return index->mbox_inbuf;
 }
 
-void mbox_file_close(MailIndex *index)
+void mbox_file_close_inbuf(MailIndex *index)
 {
+	if (index->mbox_inbuf != NULL) {
+		i_buffer_close(index->mbox_inbuf);
+		i_buffer_unref(index->mbox_inbuf);
+		index->mbox_inbuf = NULL;
+	}
+}
+
+void mbox_file_close_fd(MailIndex *index)
+{
+	mbox_file_close_inbuf(index);
+
 	if (index->mbox_fd != -1) {
 		close(index->mbox_fd);
 		index->mbox_fd = -1;
@@ -599,6 +652,7 @@
 
 	index->fd = -1;
 	index->mbox_fd = -1;
+	index->mbox_sync_counter = (unsigned int)-1;
 	index->dir = i_strdup(dir);
 
 	len = strlen(index->dir);
@@ -611,7 +665,7 @@
 
 static void mbox_index_free(MailIndex *index)
 {
-        mbox_file_close(index);
+        mbox_file_close_fd(index);
 	mail_index_close(index);
 	i_free(index->dir);
 	i_free(index);
@@ -638,7 +692,7 @@
 	mail_index_set_lock,
 	mail_index_try_lock,
 	mbox_index_rebuild,
-	mbox_index_fsck,
+	mail_index_fsck,
 	mbox_index_sync,
 	mail_index_get_header,
 	mail_index_lookup,

Index: mbox-index.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-index.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- mbox-index.h	20 Oct 2002 00:17:21 -0000	1.17
+++ mbox-index.h	26 Oct 2002 19:38:37 -0000	1.18
@@ -21,8 +21,11 @@
 /* Make sure the mbox is opened. If reopen is TRUE, the file is closed first,
    which is useful when you want to be sure you're not accessing a deleted
    mbox file. */
-IBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen);
-void mbox_file_close(MailIndex *index);
+int mbox_file_open(MailIndex *index);
+IBuffer *mbox_get_inbuf(MailIndex *index, uoff_t offset,
+			MailLockType lock_type);
+void mbox_file_close_inbuf(MailIndex *index);
+void mbox_file_close_fd(MailIndex *index);
 
 void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index,
 			      IBuffer *inbuf);
@@ -46,7 +49,7 @@
 MailIndex *mbox_index_alloc(const char *dir, const char *mbox_path);
 int mbox_index_rebuild(MailIndex *index);
 int mbox_index_sync(MailIndex *index);
-int mbox_index_fsck(MailIndex *index);
+int mbox_sync_full(MailIndex *index);
 IBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec, int *deleted);
 
 int mbox_index_append(MailIndex *index, IBuffer *inbuf);

Index: mbox-lock.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-lock.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- mbox-lock.c	6 Oct 2002 11:35:13 -0000	1.8
+++ mbox-lock.c	26 Oct 2002 19:38:37 -0000	1.9
@@ -147,67 +147,83 @@
 	return FALSE;
 }
 
-static int mbox_lock(MailIndex *index, int exclusive)
+int mbox_lock(MailIndex *index, MailLockType lock_type)
 {
-	i_assert(index->mbox_fd != -1);
+	struct stat st;
 
-	if (++index->mbox_locks > 1)
-		return TRUE;
+	i_assert(lock_type == MAIL_LOCK_SHARED ||
+		 lock_type == MAIL_LOCK_EXCLUSIVE);
+	i_assert(lock_type != MAIL_LOCK_EXCLUSIVE ||
+		 index->mbox_lock_type != MAIL_LOCK_SHARED);
 
-        index->mbox_lock_type = exclusive ? F_WRLCK : F_RDLCK;
-	if (!mbox_lock_fcntl(index, index->mbox_lock_type)) {
-		(void)mbox_lock_dotlock(index, index->mbox_path, FALSE);
-		return FALSE;
-	}
-#ifdef HAVE_FLOCK
-	if (!mbox_lock_flock(index, index->mbox_lock_type)) {
-		(void)mbox_lock_dotlock(index, index->mbox_path, FALSE);
-		return FALSE;
-	}
-#endif
+	if (index->mbox_lock_type == lock_type)
+		return TRUE;
 
-	if (exclusive) {
+	/* make .lock file first to protect overwriting the file */
+	if (index->mbox_lock_type == MAIL_LOCK_UNLOCK) {
 		if (!mbox_lock_dotlock(index, index->mbox_path, TRUE))
 			return FALSE;
 	}
 
+	/* now we need to have the file itself locked. open it if needed. */
+	do {
+		if (stat(index->mbox_path, &st) < 0)
+			return mbox_set_syscall_error(index, "stat()");
 
-	return TRUE;
-}
+		if (st.st_dev != index->mbox_dev ||
+		    st.st_ino != index->mbox_ino)
+			mbox_file_close_fd(index);
 
-int mbox_lock_read(MailIndex *index)
-{
-	return mbox_lock(index, FALSE);
-}
+		if (index->mbox_fd == -1) {
+			if (!mbox_file_open(index))
+				break;
+		}
 
-int mbox_lock_write(MailIndex *index)
-{
-	i_assert(index->mbox_locks == 0 || index->mbox_lock_type != F_RDLCK);
-	return mbox_lock(index, TRUE);
+		if (!mbox_lock_fcntl(index, index->mbox_lock_type))
+			break;
+#ifdef HAVE_FLOCK
+		if (!mbox_lock_flock(index, index->mbox_lock_type))
+			break;
+#endif
+		index->mbox_lock_type = lock_type;
+		return TRUE;
+	} while (0);
+
+	if (index->mbox_lock_type == MAIL_LOCK_UNLOCK)
+		(void)mbox_lock_dotlock(index, index->mbox_path, FALSE);
+
+	return FALSE;
 }
 
 int mbox_unlock(MailIndex *index)
 {
 	int failed;
 
-	i_assert(index->mbox_fd != -1);
-	i_assert(index->mbox_locks > 0);
+	index->mbox_lock_counter++;
+	index->mbox_lock_next_sync = MAIL_LOCK_UNLOCK;
 
-	if (--index->mbox_locks > 0)
+	if (index->mbox_lock_type == MAIL_LOCK_UNLOCK)
 		return TRUE;
 
 	failed = FALSE;
+	if (index->mbox_fd != -1) {
 #ifdef HAVE_FLOCK
-	if (!mbox_lock_flock(index, F_UNLCK))
-		failed = TRUE;
+		if (!mbox_lock_flock(index, F_UNLCK))
+			failed = TRUE;
 #endif
-	if (!mbox_lock_fcntl(index, F_UNLCK))
-		failed = TRUE;
-
-	if (index->mbox_lock_type == F_WRLCK) {
-		if (!mbox_lock_dotlock(index, index->mbox_path, FALSE))
+		if (!mbox_lock_fcntl(index, F_UNLCK))
 			failed = TRUE;
 	}
 
+	if (!mbox_lock_dotlock(index, index->mbox_path, FALSE))
+		failed = TRUE;
+
+	/* make sure we don't keep mmap() between locks - there could have
+	   been changes to file size which would break things. or actually
+	   it'd break only if file was shrinked+grown back to exact size,
+	   but still possible :) */
+	mbox_file_close_inbuf(index);
+
+	index->mbox_lock_type = MAIL_LOCK_UNLOCK;
 	return !failed;
 }

Index: mbox-lock.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-lock.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mbox-lock.h	6 Oct 2002 05:52:43 -0000	1.3
+++ mbox-lock.h	26 Oct 2002 19:38:37 -0000	1.4
@@ -1,8 +1,9 @@
 #ifndef __MBOX_LOCK_H
 #define __MBOX_LOCK_H
 
-int mbox_lock_read(MailIndex *index);
-int mbox_lock_write(MailIndex *index);
+/* NOTE: if mbox file is not open, it's opened. if it is open but file has
+   been overwritten (ie. inode has changed), it's reopened. */
+int mbox_lock(MailIndex *index, MailLockType lock_type);
 int mbox_unlock(MailIndex *index);
 
 #endif

Index: mbox-open.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-open.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mbox-open.c	20 Oct 2002 00:17:21 -0000	1.16
+++ mbox-open.c	26 Oct 2002 19:38:37 -0000	1.17
@@ -12,10 +12,7 @@
 IBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec, int *deleted)
 {
 	IBuffer *inbuf;
-	uoff_t offset, v_stop_offset;
-	const unsigned char *data;
-	size_t size;
-	int failed;
+	uoff_t offset;
 
 	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
 
@@ -28,60 +25,12 @@
 	if (!mbox_mail_get_start_offset(index, rec, &offset))
 		return NULL;
 
-	v_stop_offset = rec->header_size + rec->body_size;
-
-	inbuf = mbox_file_open(index, offset, FALSE);
+	inbuf = mbox_get_inbuf(index, offset, MAIL_LOCK_SHARED);
 	if (inbuf == NULL)
 		return NULL;
 
-	/* make sure message size is valid - it must end with
-	   either EOF or "\nFrom "*/
-	if (!i_buffer_seek(inbuf, v_stop_offset)) {
-		errno = inbuf->buf_errno;
-		mbox_set_syscall_error(index, "i_buffer_seek()");
-		i_buffer_unref(inbuf);
-		return NULL;
-	}
-
-	(void)i_buffer_read_data(inbuf, &data, &size, 6);
-	if (size >= 6) {
-		/* "[\r]\nFrom " expected */
-		if (data[0] == '\r') {
-			data++;
-			size--;
-		}
-
-		failed = size < 6 ||
-			strncmp((const char *) data, "\nFrom ", 6) != 0;
-	} else {
-		if (size > 0 && data[0] == '\r') {
-			data++;
-			size--;
-		}
-		if (size > 0 && data[0] == '\n')
-			size--;
-
-                /* we should be at end of file now */
-		failed = size != 0;
-	}
-
-	if (!i_buffer_seek(inbuf, 0)) {
-		errno = inbuf->buf_errno;
-		mbox_set_syscall_error(index, "i_buffer_seek()");
-		failed = TRUE;
-	}
-
-	if (failed) {
-		/* file has been updated, rescan it */
-		index->set_flags |= MAIL_INDEX_FLAG_FSCK;
-
-		index_set_error(index,
-			"mbox file %s was modified unexpectedly, fscking",
-			index->mbox_path);
-		i_buffer_unref(inbuf);
-		return NULL;
-	}
+	i_assert(index->mbox_sync_counter == index->mbox_lock_counter);
 
-	i_buffer_set_read_limit(inbuf, v_stop_offset);
+	i_buffer_set_read_limit(inbuf, rec->header_size + rec->body_size);
 	return inbuf;
 }

Index: mbox-rebuild.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-rebuild.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- mbox-rebuild.c	20 Oct 2002 02:35:51 -0000	1.16
+++ mbox-rebuild.c	26 Oct 2002 19:38:37 -0000	1.17
@@ -43,15 +43,9 @@
 	if (!mail_index_data_reset(index->data))
 		return FALSE;
 
-	inbuf = mbox_file_open(index, 0, TRUE);
+	inbuf = mbox_get_inbuf(index, 0, MAIL_LOCK_SHARED);
 	if (inbuf == NULL)
 		return FALSE;
-
-	/* lock the mailbox so we can be sure no-one interrupts us. */
-	if (!mbox_lock_read(index)) {
-		i_buffer_unref(inbuf);
-		return FALSE;
-	}
 
 	mbox_skip_empty_lines(inbuf);
 	failed = !mbox_index_append(index, inbuf);

Index: mbox-rewrite.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-rewrite.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- mbox-rewrite.c	23 Oct 2002 17:02:42 -0000	1.30
+++ mbox-rewrite.c	26 Oct 2002 19:38:37 -0000	1.31
@@ -405,7 +405,7 @@
 	uoff_t offset, dirty_offset;
 	const char *path;
 	unsigned int seq;
-	int tmp_fd, failed, dirty_found, locked, rewrite;
+	int tmp_fd, failed, dirty_found, rewrite;
 
 	i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
 
@@ -414,20 +414,16 @@
 		return TRUE;
 	}
 
-	tmp_fd = -1; locked = FALSE;
+	tmp_fd = -1;
 	failed = TRUE; rewrite = FALSE;
 	do {
 		/* lock before fscking to prevent race conditions between
 		   fsck's unlock and our lock. */
-		inbuf = mbox_file_open(index, 0, TRUE);
+		inbuf = mbox_get_inbuf(index, 0, MAIL_LOCK_EXCLUSIVE);
 		if (inbuf == NULL)
 			break;
 
-		if (!mbox_lock_write(index))
-			break;
-		locked = TRUE;
-
-		if (!mbox_index_fsck(index))
+		if (!index->sync(index))
 			break;
 
 		if ((index->header->flags &
@@ -446,8 +442,7 @@
 	} while (0);
 
 	if (!rewrite) {
-		if (locked)
-			(void)mbox_unlock(index);
+		(void)mbox_unlock(index);
 		if (inbuf != NULL)
 			i_buffer_unref(inbuf);
 		return !failed;

Index: mbox-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-sync.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mbox-sync.c	25 Oct 2002 01:01:18 -0000	1.14
+++ mbox-sync.c	26 Oct 2002 19:38:37 -0000	1.15
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "mbox-index.h"
+#include "mbox-lock.h"
 #include "mail-index-util.h"
 
 #include <stdlib.h>
@@ -45,11 +46,16 @@
 int mbox_index_sync(MailIndex *index)
 {
 	struct stat st;
+	MailLockType lock_type;
 	time_t index_mtime;
 	uoff_t filesize;
 
 	i_assert(index->lock_type != MAIL_LOCK_SHARED);
 
+	lock_type = index->mbox_lock_next_sync;
+	index->mbox_lock_next_sync = MAIL_LOCK_UNLOCK;
+	index->mbox_sync_counter = index->mbox_lock_counter;
+
 	if (index->fd == -1) {
 		/* anon-mmaped */
 		index_mtime = index->file_sync_stamp;
@@ -63,9 +69,25 @@
 		return mbox_set_syscall_error(index, "stat()");
 	filesize = st.st_size;
 
+	if (index->mbox_dev != st.st_dev || index->mbox_ino != st.st_ino) {
+		/* mbox file was overwritten, close it if it was open */
+		index->mbox_dev = st.st_dev;
+		index->mbox_ino = st.st_ino;
+		index->mbox_size = (uoff_t)-1;
+
+                mbox_file_close_fd(index);
+	}
+
+	if (lock_type != MAIL_LOCK_UNLOCK) {
+		if (!mbox_lock(index, lock_type))
+			return FALSE;
+	}
+
 	if (index_mtime == st.st_mtime && index->mbox_size == filesize)
 		return TRUE;
 
+	mbox_file_close_inbuf(index);
+
 	/* problem .. index->mbox_size points to data after the last message.
 	   that should be \n, \r\n, or end of file. modify filesize
 	   accordingly to allow any of the extra 0-2 bytes. Don't actually
@@ -85,5 +107,5 @@
 	index->file_sync_stamp = st.st_mtime;
 
 	/* file has changed, scan through the whole mbox */
-	return mbox_index_fsck(index);
+	return mbox_sync_full(index);
 }

--- mbox-fsck.c DELETED ---




More information about the dovecot-cvs mailing list