[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-save.c, 1.81, 1.82 maildir-uidlist.c, 1.63, 1.64 maildir-uidlist.h, 1.21, 1.22

tss at dovecot.org tss at dovecot.org
Fri Mar 23 22:23:29 EET 2007


Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv22759

Modified Files:
	maildir-save.c maildir-uidlist.c maildir-uidlist.h 
Log Message:
When saving/copying mails, we must not do any sorting based on the filename
to saved mails when they're added to uidlist, otherwise they could be saved
to index with wrong UID.



Index: maildir-save.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-save.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -d -r1.81 -r1.82
--- maildir-save.c	11 Mar 2007 16:30:05 -0000	1.81
+++ maildir-save.c	23 Mar 2007 20:23:24 -0000	1.82
@@ -137,6 +137,30 @@
 	return ctx;
 }
 
+static void maildir_save_add_existing_to_index(struct maildir_save_context *ctx)
+{
+	struct maildir_filename *mf;
+	struct mail_keywords *kw;
+	uint32_t seq;
+
+	for (mf = ctx->files; mf != NULL; mf = mf->next) {
+		mail_index_append(ctx->trans, 0, &seq);
+		mail_index_update_flags(ctx->trans, seq,
+					MODIFY_REPLACE, mf->flags);
+		if (mf->keywords_count != 0) {
+			t_push();
+			/* @UNSAFE */
+			kw = t_malloc(sizeof(*kw) + sizeof(kw->idx[0]) *
+				      mf->keywords_count);
+			memcpy(kw->idx, mf + 1, sizeof(kw->idx[0]) *
+			       mf->keywords_count);
+			mail_index_update_keywords(ctx->trans, ctx->seq,
+						   MODIFY_REPLACE, kw);
+			t_pop();
+		}
+	}
+}
+
 uint32_t maildir_save_add(struct maildir_transaction_context *t,
 			  const char *base_fname, enum mail_flags flags,
 			  struct mail_keywords *keywords,
@@ -146,8 +170,12 @@
 	struct maildir_filename *mf;
 	struct tee_istream *tee;
 
-	if (dest_mail != NULL)
+	if (dest_mail != NULL && !ctx->want_mails) {
 		ctx->want_mails = TRUE;
+		/* if there are any existing mails, we need to append them
+		   to index here to keep the UIDs correct */
+		maildir_save_add_existing_to_index(ctx);
+	}
 
 	/* now, we want to be able to rollback the whole append session,
 	   so we'll just store the name of this temp file and move it later
@@ -484,7 +512,7 @@
 int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx)
 {
 	struct maildir_filename *mf;
-	uint32_t first_uid, last_uid;
+	uint32_t first_uid, next_uid;
 	enum maildir_uidlist_rec_flag flags;
 	const char *dest;
 	bool newdir, sync_commit = FALSE;
@@ -519,7 +547,7 @@
 
 		first_uid = maildir_uidlist_get_next_uid(ctx->mbox->uidlist);
 		i_assert(first_uid != 0);
-		mail_index_append_assign_uids(ctx->trans, first_uid, &last_uid);
+		mail_index_append_assign_uids(ctx->trans, first_uid, &next_uid);
 	}
 
 	flags = MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |

Index: maildir-uidlist.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-uidlist.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- maildir-uidlist.c	23 Mar 2007 03:07:08 -0000	1.63
+++ maildir-uidlist.c	23 Mar 2007 20:23:24 -0000	1.64
@@ -63,6 +63,7 @@
 
 struct maildir_uidlist_sync_ctx {
 	struct maildir_uidlist *uidlist;
+	enum maildir_uidlist_sync_flags sync_flags;
 
 	pool_t record_pool;
 	buffer_t *record_buf;
@@ -695,7 +696,8 @@
 	}
 }
 
-int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, bool partial,
+int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist,
+			      enum maildir_uidlist_sync_flags sync_flags,
 			      struct maildir_uidlist_sync_ctx **sync_ctx_r)
 {
 	struct maildir_uidlist_sync_ctx *ctx;
@@ -707,9 +709,10 @@
 
 	*sync_ctx_r = ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
 	ctx->uidlist = uidlist;
-	ctx->partial = partial;
+	ctx->sync_flags = sync_flags;
+	ctx->partial = (sync_flags & MAILDIR_UIDLIST_SYNC_PARTIAL) != 0;
 
-	if (partial) {
+	if (ctx->partial) {
 		/* initially mark all nonsynced */
                 maildir_uidlist_mark_all(uidlist, TRUE);
 		return 1;
@@ -879,32 +882,36 @@
 	return t1 < t2 ? -1 : t1 > t2 ? 1 : 0;
 }
 
-static void maildir_uidlist_assign_uids(struct maildir_uidlist *uidlist,
+static void maildir_uidlist_assign_uids(struct maildir_uidlist_sync_ctx *ctx,
 					unsigned int first_new_pos)
 {
 	struct maildir_uidlist_rec **rec_p;
 	unsigned int dest;
 	size_t size;
 
-	i_assert(UIDLIST_IS_LOCKED(uidlist));
+	i_assert(UIDLIST_IS_LOCKED(ctx->uidlist));
 
-	rec_p = buffer_get_modifiable_data(uidlist->record_buf, &size);
+	rec_p = buffer_get_modifiable_data(ctx->uidlist->record_buf, &size);
 	size /= sizeof(*rec_p);
 
 	/* sort new files and assign UIDs for them */
-	qsort(rec_p + first_new_pos, size - first_new_pos,
-	      sizeof(*rec_p), maildir_time_cmp);
+	if ((ctx->sync_flags & MAILDIR_UIDLIST_SYNC_ORDERED) == 0) {
+		qsort(rec_p + first_new_pos, size - first_new_pos,
+		      sizeof(*rec_p), maildir_time_cmp);
+	}
 	for (dest = first_new_pos; dest < size; dest++) {
 		i_assert(rec_p[dest]->uid == (uint32_t)-1);
-		rec_p[dest]->uid = uidlist->next_uid++;
+		rec_p[dest]->uid = ctx->uidlist->next_uid++;
 		rec_p[dest]->flags &= ~MAILDIR_UIDLIST_REC_FLAG_MOVED;
 
 		if ((rec_p[dest]->flags &
-		     MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0)
-			maildir_uidlist_mark_recent(uidlist, rec_p[dest]->uid);
+		     MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0) {
+			maildir_uidlist_mark_recent(ctx->uidlist,
+						    rec_p[dest]->uid);
+		}
 	}
 
-        uidlist->last_seen_uid = uidlist->next_uid-1;
+        ctx->uidlist->last_seen_uid = ctx->uidlist->next_uid-1;
 }
 
 static int maildir_uid_cmp(const void *p1, const void *p2)
@@ -939,10 +946,8 @@
 	uidlist->record_pool = ctx->record_pool;
 	ctx->record_pool = NULL;
 
-	if (ctx->new_files_count != 0) {
-		maildir_uidlist_assign_uids(uidlist,
-					    size - ctx->new_files_count);
-	}
+	if (ctx->new_files_count != 0)
+		maildir_uidlist_assign_uids(ctx, size - ctx->new_files_count);
 }
 
 void maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx)
@@ -951,10 +956,8 @@
 		if (!ctx->failed)
 			maildir_uidlist_swap(ctx);
 	} else {
-		if (ctx->new_files_count != 0) {
-			maildir_uidlist_assign_uids(ctx->uidlist,
-						    ctx->first_new_pos);
-		}
+		if (ctx->new_files_count != 0)
+			maildir_uidlist_assign_uids(ctx, ctx->first_new_pos);
 	}
 
 	ctx->finished = TRUE;

Index: maildir-uidlist.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-uidlist.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- maildir-uidlist.h	21 Mar 2007 19:22:39 -0000	1.21
+++ maildir-uidlist.h	23 Mar 2007 20:23:24 -0000	1.22
@@ -5,6 +5,11 @@
 
 struct maildir_uidlist_sync_ctx;
 
+enum maildir_uidlist_sync_flags {
+	MAILDIR_UIDLIST_SYNC_PARTIAL	= 0x01,
+	MAILDIR_UIDLIST_SYNC_ORDERED	= 0x02
+};
+
 enum maildir_uidlist_rec_flag {
 	MAILDIR_UIDLIST_REC_FLAG_NEW_DIR	= 0x01,
 	MAILDIR_UIDLIST_REC_FLAG_MOVED		= 0x02,
@@ -42,7 +47,8 @@
 
 /* Sync uidlist with what's actually on maildir. Returns same as
    maildir_uidlist_lock(). */
-int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, bool partial,
+int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist,
+			      enum maildir_uidlist_sync_flags sync_flags,
 			      struct maildir_uidlist_sync_ctx **sync_ctx_r);
 /* Returns 1 = ok, -1 = error, 0 = new file and dovecot-uidlist is locked */
 int maildir_uidlist_sync_next_pre(struct maildir_uidlist_sync_ctx *ctx,



More information about the dovecot-cvs mailing list