changeset 3245:6491dab63e54 HEAD

Added input stream parameter to mailbox_open(). With mbox it now allows opening a read-only mbox using a stream.
author Timo Sirainen <tss@iki.fi>
date Tue, 29 Mar 2005 16:33:07 +0300
parents f104e4197ac1
children 3957eece913f
files src/imap/cmd-append.c src/imap/cmd-copy.c src/imap/cmd-select.c src/imap/cmd-status.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-file.c src/lib-storage/index/mbox/mbox-lock.c src/lib-storage/index/mbox/mbox-save.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/pop3/client.c
diffstat 14 files changed, 164 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-append.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/imap/cmd-append.c	Tue Mar 29 16:33:07 2005 +0300
@@ -360,7 +360,7 @@
 	    mailbox_equals(cmd->client->mailbox, storage, name))
 		return cmd->client->mailbox;
 
-	box = mailbox_open(storage, name, MAILBOX_OPEN_FAST |
+	box = mailbox_open(storage, name, NULL, MAILBOX_OPEN_FAST |
 			   MAILBOX_OPEN_KEEP_RECENT);
 	if (box == NULL) {
 		client_send_storage_error(cmd, storage);
--- a/src/imap/cmd-copy.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/imap/cmd-copy.c	Tue Mar 29 16:33:07 2005 +0300
@@ -74,7 +74,8 @@
 	if (mailbox_equals(client->mailbox, storage, mailbox))
 		destbox = client->mailbox;
 	else {
-		destbox = mailbox_open(storage, mailbox, MAILBOX_OPEN_FAST |
+		destbox = mailbox_open(storage, mailbox, NULL,
+				       MAILBOX_OPEN_FAST |
 				       MAILBOX_OPEN_KEEP_RECENT);
 		if (destbox == NULL) {
 			client_send_storage_error(cmd, storage);
--- a/src/imap/cmd-select.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/imap/cmd-select.c	Tue Mar 29 16:33:07 2005 +0300
@@ -29,7 +29,7 @@
 	if (storage == NULL)
 		return TRUE;
 
-	box = mailbox_open(storage, mailbox, !readonly ? 0 :
+	box = mailbox_open(storage, mailbox, NULL, !readonly ? 0 :
 			   (MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT));
 	if (box == NULL) {
 		client_send_storage_error(cmd, storage);
--- a/src/imap/cmd-status.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/imap/cmd-status.c	Tue Mar 29 16:33:07 2005 +0300
@@ -58,7 +58,7 @@
 		box = client->mailbox;
 	} else {
 		/* open the mailbox */
-		box = mailbox_open(storage, mailbox, MAILBOX_OPEN_FAST |
+		box = mailbox_open(storage, mailbox, NULL, MAILBOX_OPEN_FAST |
 				   MAILBOX_OPEN_READONLY |
 				   MAILBOX_OPEN_KEEP_RECENT);
 		if (box == NULL)
--- a/src/lib-storage/index/maildir/maildir-storage.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Tue Mar 29 16:33:07 2005 +0300
@@ -446,8 +446,8 @@
 }
 
 static struct mailbox *
-maildir_mailbox_open(struct mail_storage *_storage,
-		     const char *name, enum mailbox_open_flags flags)
+maildir_mailbox_open(struct mail_storage *_storage, const char *name,
+		     struct istream *input, enum mailbox_open_flags flags)
 {
 	struct index_storage *storage = (struct index_storage *)_storage;
 	const char *path;
@@ -455,6 +455,12 @@
 
 	mail_storage_clear_error(_storage);
 
+	if (input != NULL) {
+		mail_storage_set_critical(_storage,
+			"Maildir doesn't support streamed mailboxes");
+		return NULL;
+	}
+
 	if (strcmp(name, "INBOX") == 0) {
 		if (verify_inbox(storage) < 0)
 			return NULL;
--- a/src/lib-storage/index/mbox/mbox-file.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/index/mbox/mbox-file.c	Tue Mar 29 16:33:07 2005 +0300
@@ -16,6 +16,12 @@
 
 	i_assert(ibox->mbox_fd == -1);
 
+	if (ibox->mbox_file_stream != NULL) {
+		/* read-only mbox stream */
+		i_assert(ibox->mbox_readonly);
+		return 0;
+	}
+
 	fd = open(ibox->path, ibox->mbox_readonly ? O_RDONLY : O_RDWR);
 	if (fd == -1 && errno == EACCES && !ibox->mbox_readonly) {
                 ibox->mbox_readonly = TRUE;
@@ -56,7 +62,15 @@
 	if (ibox->mbox_stream != NULL)
 		return 0;
 
-	i_assert(ibox->mbox_file_stream == NULL);
+	if (ibox->mbox_file_stream != NULL) {
+		/* read-only mbox stream */
+		i_assert(ibox->mbox_fd == -1 && ibox->mbox_readonly);
+
+		ibox->mbox_stream =
+			i_stream_create_raw_mbox(default_pool,
+						 ibox->mbox_file_stream);
+		return 0;
+	}
 
 	if (ibox->mbox_fd == -1) {
 		if (mbox_file_open(ibox) < 0)
@@ -85,13 +99,20 @@
 void mbox_file_close_stream(struct index_mailbox *ibox)
 {
 	if (ibox->mbox_stream != NULL) {
-		i_stream_close(ibox->mbox_file_stream);
-		i_stream_unref(ibox->mbox_file_stream);
-		ibox->mbox_file_stream = NULL;
-
 		i_stream_unref(ibox->mbox_stream);
 		ibox->mbox_stream = NULL;
 	}
+
+	if (ibox->mbox_file_stream != NULL) {
+		if (ibox->mbox_fd == -1) {
+			/* read-only mbox stream */
+			i_assert(ibox->mbox_readonly);
+		} else {
+			i_stream_close(ibox->mbox_file_stream);
+			i_stream_unref(ibox->mbox_file_stream);
+			ibox->mbox_file_stream = NULL;
+		}
+	}
 }
 
 int mbox_file_seek(struct index_mailbox *ibox, struct mail_index_view *view,
--- a/src/lib-storage/index/mbox/mbox-lock.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Tue Mar 29 16:33:07 2005 +0300
@@ -455,6 +455,13 @@
 	if (!lock_settings_initialized)
                 mbox_init_lock_settings();
 
+	if (ibox->mbox_fd == -1 && ibox->mbox_file_stream != NULL) {
+		/* read-only mbox stream. no need to lock. */
+		i_assert(ibox->mbox_readonly);
+		ibox->mbox_lock_type = lock_type;
+		return TRUE;
+	}
+
 	max_wait_time = time(NULL) + lock_timeout;
 
 	memset(&ctx, 0, sizeof(ctx));
--- a/src/lib-storage/index/mbox/mbox-save.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/index/mbox/mbox-save.c	Tue Mar 29 16:33:07 2005 +0300
@@ -251,6 +251,12 @@
 	struct index_mailbox *ibox = ctx->ibox;
 	int ret;
 
+	if (ctx->ibox->mbox_readonly || ctx->ibox->readonly) {
+		mail_storage_set_error(&ctx->ibox->storage->storage,
+				       "Read-only mbox");
+		return -1;
+	}
+
 	if (ctx->append_offset == (uoff_t)-1) {
 		/* first appended mail in this transaction */
 		if (ibox->mbox_lock_type != F_WRLCK) {
--- a/src/lib-storage/index/mbox/mbox-storage.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Tue Mar 29 16:33:07 2005 +0300
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "istream.h"
 #include "home-expand.h"
 #include "mkdir-parents.h"
 #include "unlink-directory.h"
@@ -478,6 +479,43 @@
 	return FALSE;
 }
 
+static struct index_mailbox *
+mbox_alloc(struct index_storage *storage, struct mail_index *index,
+	   const char *name, enum mailbox_open_flags flags)
+{
+	struct index_mailbox *ibox;
+	pool_t pool;
+
+	pool = pool_alloconly_create("mailbox", 256);
+	ibox = p_new(pool, struct index_mailbox, 1);
+	ibox->box = mbox_mailbox;
+	ibox->box.pool = pool;
+	ibox->storage = storage;
+
+	if (index_storage_mailbox_init(ibox, index, name, flags) < 0) {
+		/* the memory is already freed here, no need to deinit */
+		return NULL;
+	}
+
+	ibox->mbox_fd = -1;
+	ibox->mbox_lock_type = F_UNLCK;
+	ibox->mbox_ext_idx =
+		mail_index_ext_register(index, "mbox", 0,
+					sizeof(uint64_t), sizeof(uint64_t));
+
+	ibox->is_recent = mbox_mail_is_recent;
+	ibox->mail_vfuncs = &mbox_mail_vfuncs;
+        ibox->mbox_very_dirty_syncs = getenv("MBOX_VERY_DIRTY_SYNCS") != NULL;
+	ibox->mbox_do_dirty_syncs = ibox->mbox_very_dirty_syncs ||
+		getenv("MBOX_DIRTY_SYNCS") != NULL;
+
+	ibox->md5hdr_ext_idx =
+		mail_index_ext_register(ibox->index, "header-md5", 0, 16, 1);
+	if ((flags & MAILBOX_OPEN_KEEP_HEADER_MD5) != 0)
+		ibox->mbox_save_md5 = TRUE;
+	return ibox;
+}
+
 static struct mailbox *
 mbox_open(struct index_storage *storage, const char *name,
 	  enum mailbox_open_flags flags)
@@ -485,8 +523,6 @@
 	struct index_mailbox *ibox;
 	struct mail_index *index;
 	const char *path, *index_dir;
-	uint32_t mbox_ext_idx;
-	pool_t pool;
 
 	if (strcmp(name, "INBOX") == 0) {
 		/* name = "INBOX"
@@ -503,36 +539,11 @@
 	}
 
 	index = index_storage_alloc(index_dir, path, MBOX_INDEX_PREFIX);
-	mbox_ext_idx = mail_index_ext_register(index, "mbox", 0,
-					       sizeof(uint64_t),
-					       sizeof(uint64_t));
-
-	pool = pool_alloconly_create("mailbox", 256);
-	ibox = p_new(pool, struct index_mailbox, 1);
-	ibox->box = mbox_mailbox;
-	ibox->box.pool = pool;
-	ibox->storage = storage;
-
-	if (index_storage_mailbox_init(ibox, index, name, flags) < 0) {
-		/* the memory was already freed */
+	ibox = mbox_alloc(storage, index, name, flags);
+	if (ibox == NULL)
 		return NULL;
-	}
 
-	ibox->path = p_strdup(pool, path);
-	ibox->mbox_fd = -1;
-	ibox->mbox_lock_type = F_UNLCK;
-	ibox->mbox_ext_idx = mbox_ext_idx;
-
-	ibox->is_recent = mbox_mail_is_recent;
-	ibox->mail_vfuncs = &mbox_mail_vfuncs;
-        ibox->mbox_very_dirty_syncs = getenv("MBOX_VERY_DIRTY_SYNCS") != NULL;
-	ibox->mbox_do_dirty_syncs = ibox->mbox_very_dirty_syncs ||
-		getenv("MBOX_DIRTY_SYNCS") != NULL;
-
-	ibox->md5hdr_ext_idx =
-		mail_index_ext_register(ibox->index, "header-md5", 0, 16, 1);
-	if ((flags & MAILBOX_OPEN_KEEP_HEADER_MD5) != 0)
-		ibox->mbox_save_md5 = TRUE;
+	ibox->path = p_strdup(ibox->box.pool, path);
 
 	if (access(path, R_OK|W_OK) < 0) {
 		if (errno < EACCES)
@@ -547,8 +558,30 @@
 }
 
 static struct mailbox *
-mbox_mailbox_open(struct mail_storage *_storage,
-		  const char *name, enum mailbox_open_flags flags)
+mbox_mailbox_open_stream(struct index_storage *storage, const char *name,
+			 struct istream *input, enum mailbox_open_flags flags)
+{
+	struct mail_index *index;
+	struct index_mailbox *ibox;
+
+	flags |= MAILBOX_OPEN_READONLY;
+
+	index = mail_index_alloc(NULL, NULL);
+	ibox = mbox_alloc(storage, index, name, flags);
+	if (ibox == NULL)
+		return NULL;
+
+	i_stream_ref(input);
+	ibox->mbox_file_stream = input;
+	ibox->mbox_readonly = TRUE;
+
+	ibox->path = "(read-only mbox stream)";
+	return &ibox->box;
+}
+
+static struct mailbox *
+mbox_mailbox_open(struct mail_storage *_storage, const char *name,
+		  struct istream *input, enum mailbox_open_flags flags)
 {
 	struct index_storage *storage = (struct index_storage *)_storage;
 	const char *path;
@@ -556,6 +589,9 @@
 
 	mail_storage_clear_error(_storage);
 
+	if (input != NULL)
+		return mbox_mailbox_open_stream(storage, name, input, flags);
+
 	if (strcmp(name, "INBOX") == 0) {
 		/* make sure INBOX exists */
 		if (verify_inbox(storage) < 0)
@@ -916,7 +952,11 @@
 	}
 
         mbox_file_close(ibox);
-        index_storage_mailbox_free(box);
+	if (ibox->mbox_file_stream != NULL) {
+		i_stream_unref(ibox->mbox_file_stream);
+                ibox->mbox_file_stream = NULL;
+	}
+	index_storage_mailbox_free(box);
 	return ret;
 }
 
--- a/src/lib-storage/index/mbox/mbox-sync.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Tue Mar 29 16:33:07 2005 +0300
@@ -1257,17 +1257,28 @@
 int mbox_sync_has_changed(struct index_mailbox *ibox, int leave_dirty)
 {
 	const struct mail_index_header *hdr;
-	struct stat st;
+	const struct stat *st;
+	struct stat statbuf;
+
+	if (ibox->mbox_file_stream != NULL && ibox->mbox_fd == -1) {
+		/* read-only stream */
+		st = i_stream_stat(ibox->mbox_file_stream);
+		if (st == NULL) {
+			mbox_set_syscall_error(ibox, "i_stream_stat()");
+			return -1;
+		}
+	} else {
+		if (stat(ibox->path, &statbuf) < 0) {
+			mbox_set_syscall_error(ibox, "stat()");
+			return -1;
+		}
+		st = &statbuf;
+	}
 
 	hdr = mail_index_get_header(ibox->view);
 
-	if (stat(ibox->path, &st) < 0) {
-		mbox_set_syscall_error(ibox, "stat()");
-		return -1;
-	}
-
-	if ((uint32_t)st.st_mtime == hdr->sync_stamp &&
-	    (uint64_t)st.st_size == hdr->sync_size) {
+	if ((uint32_t)st->st_mtime == hdr->sync_stamp &&
+	    (uint64_t)st->st_size == hdr->sync_size) {
 		/* fully synced */
 		ibox->mbox_sync_dirty = FALSE;
 		return 0;
@@ -1276,8 +1287,8 @@
 	if (!ibox->mbox_sync_dirty || !leave_dirty)
 		return 1;
 
-	return st.st_mtime != ibox->mbox_dirty_stamp ||
-		st.st_size != ibox->mbox_dirty_size;
+	return st->st_mtime != ibox->mbox_dirty_stamp ||
+		st->st_size != ibox->mbox_dirty_size;
 }
 
 static int mbox_sync_update_imap_base(struct mbox_sync_context *sync_ctx)
--- a/src/lib-storage/mail-storage-private.h	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/mail-storage-private.h	Tue Mar 29 16:33:07 2005 +0300
@@ -20,6 +20,7 @@
 
 	struct mailbox *(*mailbox_open)(struct mail_storage *storage,
 					const char *name,
+					struct istream *input,
 					enum mailbox_open_flags flags);
 
 	int (*mailbox_create)(struct mail_storage *storage, const char *name,
--- a/src/lib-storage/mail-storage.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/mail-storage.c	Tue Mar 29 16:33:07 2005 +0300
@@ -288,10 +288,11 @@
 	return storage->v.get_last_error(storage, syntax_error_r);
 }
 
-struct mailbox *mailbox_open(struct mail_storage *storage,
-			     const char *name, enum mailbox_open_flags flags)
+struct mailbox *mailbox_open(struct mail_storage *storage, const char *name,
+			     struct istream *input,
+			     enum mailbox_open_flags flags)
 {
-	return storage->v.mailbox_open(storage, name, flags);
+	return storage->v.mailbox_open(storage, name, input, flags);
 }
 
 int mailbox_close(struct mailbox *box)
--- a/src/lib-storage/mail-storage.h	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/lib-storage/mail-storage.h	Tue Mar 29 16:33:07 2005 +0300
@@ -13,10 +13,15 @@
 };
 
 enum mailbox_open_flags {
+	/* Mailbox must not be modified even if asked */
 	MAILBOX_OPEN_READONLY		= 0x01,
+	/* Any extra time consuming operations shouldn't be performed
+	   (eg. when opening mailbox just for STATUS). */
 	MAILBOX_OPEN_FAST		= 0x02,
+	/* Don't reset MAIL_RECENT flags when syncing */
 	MAILBOX_OPEN_KEEP_RECENT	= 0x04,
-	MAILBOX_OPEN_KEEP_HEADER_MD5	= 0x04
+	/* Remember message headers' MD5 sum */
+	MAILBOX_OPEN_KEEP_HEADER_MD5	= 0x08
 };
 
 enum mailbox_list_flags {
@@ -266,15 +271,15 @@
 const char *mail_storage_get_last_error(struct mail_storage *storage,
 					int *syntax_error_r);
 
-/* Open a mailbox. If readonly is TRUE, mailbox must not be
-   modified in any way even when it's asked. If fast is TRUE,
-   any extra time consuming operations shouldn't be performed
-   (eg. when opening mailbox just for STATUS).
+/* Open a mailbox. If input stream is given, mailbox is opened read-only
+   using it as a backend. If storage doesn't support stream backends and its
+   tried to be used, NULL is returned.
 
    Note that append and copy may open the selected mailbox again
    with possibly different readonly-state. */
-struct mailbox *mailbox_open(struct mail_storage *storage,
-			     const char *name, enum mailbox_open_flags flags);
+struct mailbox *mailbox_open(struct mail_storage *storage, const char *name,
+			     struct istream *input,
+			     enum mailbox_open_flags flags);
 /* Close the box. Returns FALSE if some cleanup errors occured, but
    the mailbox was closed anyway. */
 int mailbox_close(struct mailbox *box);
--- a/src/pop3/client.c	Tue Mar 29 16:30:55 2005 +0300
+++ b/src/pop3/client.c	Tue Mar 29 16:33:07 2005 +0300
@@ -153,7 +153,7 @@
 		flags |= MAILBOX_OPEN_KEEP_RECENT;
 	if ((uidl_keymask & UIDL_MD5) != 0)
 		flags |= MAILBOX_OPEN_KEEP_HEADER_MD5;
-	client->mailbox = mailbox_open(storage, "INBOX", flags);
+	client->mailbox = mailbox_open(storage, "INBOX", NULL, flags);
 	if (client->mailbox == NULL) {
 		i_error("Couldn't open INBOX: %s",
 			mail_storage_get_last_error(storage, &syntax_error));