dovecot-2.0: maildir_copy_preserve_filename=yes could have cause...

dovecot at dovecot.org dovecot at dovecot.org
Thu Dec 3 18:39:01 EET 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/2277467334fb
changeset: 10407:2277467334fb
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Dec 03 10:38:54 2009 -0600
description:
maildir_copy_preserve_filename=yes could have caused crashes.

diffstat:

1 file changed, 30 insertions(+), 14 deletions(-)
src/lib-storage/index/maildir/maildir-copy.c |   44 +++++++++++++++++---------

diffs (61 lines):

diff -r ad3fb3f929fc -r 2277467334fb src/lib-storage/index/maildir/maildir-copy.c
--- a/src/lib-storage/index/maildir/maildir-copy.c	Wed Dec 02 15:35:51 2009 -0600
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Thu Dec 03 10:38:54 2009 -0600
@@ -124,6 +124,34 @@ static int do_hardlink(struct maildir_ma
 	return 1;
 }
 
+static const char *
+maildir_copy_get_preserved_fname(struct maildir_mailbox *src_mbox,
+				 struct maildir_mailbox *dest_mbox,
+				 uint32_t uid)
+{
+	enum maildir_uidlist_rec_flag flags;
+	const char *fname;
+
+	/* see if the filename exists in destination maildir's
+	   uidlist. if it doesn't, we can use it. otherwise generate
+	   a new filename. FIXME: There's a race condition here if
+	   another process is just doing the same copy. */
+	if (maildir_uidlist_lookup(src_mbox->uidlist, uid, &flags,
+				   &fname) <= 0)
+		return NULL;
+
+	if (maildir_uidlist_refresh(dest_mbox->uidlist) <= 0)
+		return NULL;
+	if (maildir_uidlist_get_full_filename(dest_mbox->uidlist,
+					      fname) != NULL) {
+		/* already exists in destination */
+		return NULL;
+	}
+	/* fname may be freed by a later uidlist sync. make sure it gets
+	   strduped. */
+	return t_strcut(t_strdup(fname), ':');
+}
+
 static int
 maildir_copy_hardlink(struct mail_save_context *ctx, struct mail *mail)
 {
@@ -148,20 +176,8 @@ maildir_copy_hardlink(struct mail_save_c
 
 	if (dest_mbox->storage->set->maildir_copy_preserve_filename &&
 	    src_mbox != NULL) {
-		enum maildir_uidlist_rec_flag src_flags;
-		const char *src_fname;
-
-		/* see if the filename exists in destination maildir's
-		   uidlist. if it doesn't, we can use it. otherwise generate
-		   a new filename. FIXME: There's a race condition here if
-		   another process is just doing the same copy. */
-		if (maildir_uidlist_lookup(src_mbox->uidlist,
-					   mail->uid, &src_flags,
-					   &src_fname) > 0 &&
-		    maildir_uidlist_refresh(dest_mbox->uidlist) >= 0 &&
-		    maildir_uidlist_get_full_filename(dest_mbox->uidlist,
-						      src_fname) == NULL)
-			filename = t_strcut(src_fname, ':');
+		filename = maildir_copy_get_preserved_fname(src_mbox, dest_mbox,
+							    mail->uid);
 	}
 	if (filename == NULL) {
 		/* the generated filename is _always_ unique, so we don't


More information about the dovecot-cvs mailing list