[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-save.c,1.31,1.32 mbox-storage.c,1.33,1.34 mbox-storage.h,1.13,1.14

cras at procontrol.fi cras at procontrol.fi
Wed Jan 22 21:23:30 EET 2003


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

Modified Files:
	mbox-save.c mbox-storage.c mbox-storage.h 
Log Message:
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
fails, none of the messages are copied. maildir_copy_with_hardlinks didn't
actually work.



Index: mbox-save.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-save.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- mbox-save.c	20 Jan 2003 14:52:52 -0000	1.31
+++ mbox-save.c	22 Jan 2003 19:23:28 -0000	1.32
@@ -14,68 +14,82 @@
 #include <sys/stat.h>
 #include <netdb.h>
 
+struct mail_save_context {
+	pool_t pool;
+
+	struct index_mailbox *ibox;
+	int transaction;
+
+	struct ostream *output;
+	uoff_t sync_offset;
+};
+
 static char my_hostdomain[256] = "";
 
-static int write_error(struct mail_storage *storage, const char *mbox_path)
+static int write_error(struct mail_save_context *ctx)
 {
-	if (errno == ENOSPC)
-		mail_storage_set_error(storage, "Not enough disk space");
-	else {
-		mail_storage_set_critical(storage,
-			"Error writing to mbox file %s: %m", mbox_path);
+	if (errno == ENOSPC) {
+		mail_storage_set_error(ctx->ibox->box.storage,
+				       "Not enough disk space");
+	} else {
+		mail_storage_set_critical(ctx->ibox->box.storage,
+			"Error writing to mbox file %s: %m",
+			ctx->ibox->index->mailbox_path);
 	}
 
 	return FALSE;
 }
 
-static int mbox_seek_to_end(struct mail_storage *storage, int fd,
-			    const char *mbox_path, off_t *pos)
+static int mbox_seek_to_end(struct mail_save_context *ctx, off_t *offset)
 {
 	struct stat st;
 	char ch;
+	int fd;
 
+	fd = ctx->ibox->index->mbox_fd;
 	if (fstat(fd, &st) < 0) {
-		mail_storage_set_critical(storage,
-			"fstat() failed for mbox file %s: %m", mbox_path);
+		mail_storage_set_critical(ctx->ibox->box.storage,
+					  "fstat() failed for mbox file %s: %m",
+					  ctx->ibox->index->mailbox_path);
 		return FALSE;
 	}
 
-	*pos = st.st_size;
+	*offset = st.st_size;
 	if (st.st_size == 0)
 		return TRUE;
 
 	if (lseek(fd, st.st_size-1, SEEK_SET) < 0) {
-		mail_storage_set_critical(storage,
-			"lseek() failed for mbox file %s: %m", mbox_path);
+		mail_storage_set_critical(ctx->ibox->box.storage,
+					  "lseek() failed for mbox file %s: %m",
+					 ctx->ibox->index->mailbox_path);
 		return FALSE;
 	}
 
 	if (read(fd, &ch, 1) != 1) {
-		mail_storage_set_critical(storage,
-			"read() failed for mbox file %s: %m", mbox_path);
+		mail_storage_set_critical(ctx->ibox->box.storage,
+					  "read() failed for mbox file %s: %m",
+					  ctx->ibox->index->mailbox_path);
 		return FALSE;
 	}
 
 	if (ch != '\n') {
 		if (write_full(fd, "\n", 1) < 0)
-			return write_error(storage, mbox_path);
-		*pos += 1;
+			return write_error(ctx);
+		*offset += 1;
 	}
 
 	return TRUE;
 }
 
-static int mbox_append_lf(struct mail_storage *storage, struct ostream *output,
-			  const char *mbox_path)
+static int mbox_append_lf(struct mail_save_context *ctx)
 {
-	if (o_stream_send(output, "\n", 1) < 0)
-		return write_error(storage, mbox_path);
+	if (o_stream_send(ctx->output, "\n", 1) < 0)
+		return write_error(ctx);
 
 	return TRUE;
 }
 
-static int write_from_line(struct mail_storage *storage, struct ostream *output,
-			   const char *mbox_path, time_t internal_date)
+static int write_from_line(struct mail_save_context *ctx, time_t received_date)
 {
 	const char *sender, *line, *name;
 
@@ -94,19 +108,19 @@
 		strocpy(my_hostdomain, name, sizeof(my_hostdomain));
 	}
 
-	sender = t_strconcat(storage->user, "@", my_hostdomain, NULL);
+	sender = t_strconcat(ctx->ibox->box.storage->user, "@",
+			     my_hostdomain, NULL);
 
 	/* save in local timezone, no matter what it was given with */
-	line = mbox_from_create(sender, internal_date);
+	line = mbox_from_create(sender, received_date);
 
-	if (o_stream_send_str(output, line) < 0)
-		return write_error(storage, mbox_path);
+	if (o_stream_send_str(ctx->output, line) < 0)
+		return write_error(ctx);
 
 	return TRUE;
 }
 
-static int write_flags(struct mail_storage *storage, struct ostream *output,
-		       const char *mbox_path,
+static int write_flags(struct mail_save_context *ctx,
 		       const struct mail_full_flags *full_flags)
 {
 	enum mail_flags flags = full_flags->flags;
@@ -118,8 +132,8 @@
 		return TRUE;
 
 	if (flags & MAIL_SEEN) {
-		if (o_stream_send_str(output, "Status: R\n") < 0)
-			return write_error(storage, mbox_path);
+		if (o_stream_send_str(ctx->output, "Status: R\n") < 0)
+			return write_error(ctx);
 	}
 
 	if (flags & (MAIL_ANSWERED|MAIL_DRAFT|MAIL_FLAGGED|MAIL_DELETED)) {
@@ -130,100 +144,134 @@
 				  (flags & MAIL_DELETED) ? "T" : "",
 				  "\n", NULL);
 
-		if (o_stream_send_str(output, str) < 0)
-			return write_error(storage, mbox_path);
+		if (o_stream_send_str(ctx->output, str) < 0)
+			return write_error(ctx);
 	}
 
 	if (flags & MAIL_CUSTOM_FLAGS_MASK) {
-		if (o_stream_send_str(output, "X-Keywords:") < 0)
-			return write_error(storage, mbox_path);
+		if (o_stream_send_str(ctx->output, "X-Keywords:") < 0)
+			return write_error(ctx);
 
 		field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
 		for (i = 0; i < full_flags->custom_flags_count; i++) {
 			const char *custom_flag = full_flags->custom_flags[i];
 
 			if ((flags & field) && custom_flag != NULL) {
-				if (o_stream_send(output, " ", 1) < 0)
-					return write_error(storage, mbox_path);
+				if (o_stream_send(ctx->output, " ", 1) < 0)
+					return write_error(ctx);
 
-				if (o_stream_send_str(output, custom_flag) < 0)
-					return write_error(storage, mbox_path);
+				if (o_stream_send_str(ctx->output,
+						      custom_flag) < 0)
+					return write_error(ctx);
 			}
 
                         field <<= 1;
 		}
 
-		if (o_stream_send(output, "\n", 1) < 0)
-			return write_error(storage, mbox_path);
+		if (o_stream_send(ctx->output, "\n", 1) < 0)
+			return write_error(ctx);
 	}
 
 	return TRUE;
 }
 
-int mbox_storage_save(struct mailbox *box, const struct mail_full_flags *flags,
-		      time_t internal_date,
-		      int timezone_offset __attr_unused__,
-		      struct istream *data, uoff_t data_size)
+int mbox_storage_save_next(struct mail_save_context *ctx,
+			   const struct mail_full_flags *flags,
+			   time_t received_date,
+			   int timezone_offset __attr_unused__,
+			   struct istream *data)
 {
-	struct index_mailbox *ibox = (struct index_mailbox *) box;
-	struct mail_index *index;
 	enum mail_flags real_flags;
-	const char *mbox_path;
-	struct ostream *output;
 	int failed;
-	off_t pos;
-
-	if (box->readonly) {
-		mail_storage_set_error(box->storage, "Mailbox is read-only");
-		return FALSE;
-	}
 
 	/* we don't need the real flag positions, easier to keep using our own.
 	   they need to be checked/added though. */
 	real_flags = flags->flags;
-	if (!index_mailbox_fix_custom_flags(ibox, &real_flags,
+	if (!index_mailbox_fix_custom_flags(ctx->ibox, &real_flags,
 					    flags->custom_flags,
 					    flags->custom_flags_count))
 		return FALSE;
 
+	t_push();
+	if (!write_from_line(ctx, received_date) ||
+	    !write_flags(ctx, flags) ||
+	    !index_storage_save(ctx->ibox->box.storage,
+				ctx->ibox->index->mailbox_path,
+				data, ctx->output) ||
+	    !mbox_append_lf(ctx)) {
+		/* failed, truncate file back to original size.
+		   output stream needs to be flushed before truncating
+		   so unref() won't write anything. */
+		o_stream_flush(ctx->output);
+		if (ctx->sync_offset != (uoff_t)-1) {
+			(void)ftruncate(ctx->ibox->index->mbox_fd,
+					ctx->sync_offset);
+			ctx->sync_offset = (uoff_t)-1;
+		}
+		failed = TRUE;
+	} else {
+		if (!ctx->transaction)
+			ctx->sync_offset = ctx->output->offset;
+		failed = FALSE;
+	}
+	t_pop();
+
+	return !failed;
+}
+
+struct mail_save_context *
+mbox_storage_save_init(struct mailbox *box, int transaction)
+{
+	struct index_mailbox *ibox = (struct index_mailbox *) box;
+	struct mail_save_context *ctx;
+	pool_t pool;
+
+	if (box->readonly) {
+		mail_storage_set_error(box->storage, "Mailbox is read-only");
+		return NULL;
+	}
+
 	if (!index_storage_sync_and_lock(ibox, FALSE, MAIL_LOCK_EXCLUSIVE))
-		return FALSE;
+		return NULL;
 
-	index = ibox->index;
-	mbox_path = index->mailbox_path;
-	if (!mbox_seek_to_end(box->storage, index->mbox_fd, mbox_path, &pos))
+	pool = pool_alloconly_create("mail_save_context", 2048);
+	ctx = p_new(pool, struct mail_save_context, 1);
+	ctx->pool = pool;
+	ctx->ibox = ibox;
+	ctx->transaction = transaction;
+
+	if (!mbox_seek_to_end(ctx, &ctx->sync_offset)) {
+		pool_unref(pool);
+		return NULL;
+	}
+
+	ctx->output = o_stream_create_file(ibox->index->mbox_fd,
+					   ctx->pool, 4096, 0, FALSE);
+	o_stream_set_blocking(ctx->output, 60000, NULL, NULL);
+	return ctx;
+}
+
+int mbox_storage_save_deinit(struct mail_save_context *ctx, int rollback)
+{
+	int failed = FALSE;
+
+	if (!index_storage_lock(ctx->ibox, MAIL_LOCK_UNLOCK))
 		failed = TRUE;
-	else {
-		failed = FALSE;
 
-		t_push();
-		output = o_stream_create_file(index->mbox_fd,
-					      data_stack_pool, 4096,
-					      0, FALSE);
-		o_stream_set_blocking(output, 60000, NULL, NULL);
+	if (o_stream_flush(ctx->output) < 0)
+		failed = TRUE;
+	o_stream_unref(ctx->output);
 
-		if (!write_from_line(box->storage, output, mbox_path,
-				     internal_date) ||
-		    !write_flags(box->storage, output, mbox_path, flags) ||
-		    !index_storage_save(box->storage, mbox_path,
-					data, output, data_size) ||
-		    !mbox_append_lf(box->storage, output, mbox_path)) {
-			/* failed, truncate file back to original size.
-			   output stream needs to be flushed before truncating
-			   so unref() won't write anything. */
-			o_stream_flush(output);
-			(void)ftruncate(index->mbox_fd, pos);
+	if (rollback && ctx->sync_offset != (uoff_t)-1) {
+		if (ftruncate(ctx->ibox->index->mbox_fd,
+			      ctx->sync_offset) < 0) {
+			mail_storage_set_critical(ctx->ibox->box.storage,
+				"ftruncate(%s) failed: %m",
+				ctx->ibox->index->mailbox_path);
 			failed = TRUE;
 		}
-		o_stream_unref(output);
-		t_pop();
-	}
-
-	/* kludgy.. for copying inside same mailbox. */
-	if (!ibox->delay_save_unlocking) {
-		if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-			return FALSE;
 	}
 
+	pool_unref(ctx->pool);
 	return !failed;
 }

Index: mbox-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mbox-storage.c	21 Jan 2003 18:33:06 -0000	1.33
+++ mbox-storage.c	22 Jan 2003 19:23:28 -0000	1.34
@@ -630,7 +630,9 @@
 	index_storage_search_init,
 	index_storage_search_deinit,
 	index_storage_search_next,
-	mbox_storage_save,
+	mbox_storage_save_init,
+	mbox_storage_save_deinit,
+	mbox_storage_save_next,
 	mail_storage_is_inconsistency_error,
 
 	FALSE,

Index: mbox-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- mbox-storage.h	20 Jan 2003 14:52:52 -0000	1.13
+++ mbox-storage.h	22 Jan 2003 19:23:28 -0000	1.14
@@ -5,9 +5,14 @@
 
 int mbox_storage_copy(struct mailbox *box, struct mailbox *destbox,
 		      const char *messageset, int uidset);
-int mbox_storage_save(struct mailbox *box, const struct mail_full_flags *flags,
-		      time_t internal_date, int timezone_offset,
-		      struct istream *data, uoff_t data_size);
+
+struct mail_save_context *
+mbox_storage_save_init(struct mailbox *box, int transaction);
+int mbox_storage_save_deinit(struct mail_save_context *ctx, int rollback);
+int mbox_storage_save_next(struct mail_save_context *ctx,
+			   const struct mail_full_flags *flags,
+			   time_t received_date, int timezone_offset,
+			   struct istream *data);
 
 int mbox_find_mailboxes(struct mail_storage *storage, const char *mask,
 			mailbox_list_callback_t callback, void *context);




More information about the dovecot-cvs mailing list