dovecot-1.2: maildir: Fixed a memory leak when copying with hard...

dovecot at dovecot.org dovecot at dovecot.org
Fri May 14 17:29:30 EEST 2010


details:   http://hg.dovecot.org/dovecot-1.2/rev/2129667cb499
changeset: 9569:2129667cb499
user:      Timo Sirainen <tss at iki.fi>
date:      Fri May 14 16:29:27 2010 +0200
description:
maildir: Fixed a memory leak when copying with hardlinks.

diffstat:

 src/lib-storage/index/maildir/maildir-copy.c |  50 +++++++++++++------------
 1 files changed, 26 insertions(+), 24 deletions(-)

diffs (136 lines):

diff -r 46d3128626b7 -r 2129667cb499 src/lib-storage/index/maildir/maildir-copy.c
--- a/src/lib-storage/index/maildir/maildir-copy.c	Fri May 14 16:18:03 2010 +0200
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Fri May 14 16:29:27 2010 +0200
@@ -155,12 +155,11 @@
 static int
 maildir_copy_hardlink(struct maildir_transaction_context *t, struct mail *mail,
 		      enum mail_flags flags, struct mail_keywords *keywords,
-		      struct mail *dest_mail)
+		      struct mail *dest_mail, struct hardlink_ctx *do_ctx)
 {
 	struct maildir_mailbox *dest_mbox =
 		(struct maildir_mailbox *)t->ictx.ibox;
 	struct maildir_mailbox *src_mbox;
-	struct hardlink_ctx do_ctx;
 	const char *path, *filename = NULL;
 
 	i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
@@ -183,8 +182,7 @@
 	if (dest_mbox->ibox.keep_recent)
 		flags |= MAIL_RECENT;
 
-	memset(&do_ctx, 0, sizeof(do_ctx));
-	do_ctx.dest_path = str_new(default_pool, 512);
+	do_ctx->dest_path = str_new(default_pool, 512);
 
 	if (dest_mbox->storage->copy_preserve_filename && src_mbox != NULL) {
 		filename = maildir_copy_get_preserved_fname(src_mbox, dest_mbox,
@@ -193,10 +191,10 @@
 	if (filename == NULL) {
 		/* the generated filename is _always_ unique, so we don't
 		   bother trying to check if it already exists */
-		do_ctx.dest_fname = maildir_filename_generate();
+		do_ctx->dest_fname = maildir_filename_generate();
 	} else {
-		do_ctx.dest_fname = filename;
-		do_ctx.preserve_filename = TRUE;
+		do_ctx->dest_fname = filename;
+		do_ctx->preserve_filename = TRUE;
 	}
 
 	/* FIXME: We could hardlink the files directly to destination, but
@@ -207,17 +205,17 @@
 	if (keywords == NULL || keywords->count == 0) {
 		/* no keywords, hardlink directly to destination */
 		if (flags == MAIL_RECENT) {
-			str_printfa(do_ctx.dest_path, "%s/new/%s",
-				    dest_mbox->path, do_ctx.dest_fname);
-			do_ctx.base_end_pos = str_len(do_ctx.dest_path);
+			str_printfa(do_ctx->dest_path, "%s/new/%s",
+				    dest_mbox->path, do_ctx->dest_fname);
+			do_ctx->base_end_pos = str_len(do_ctx->dest_path);
 		} else {
-			str_printfa(do_ctx.dest_path, "%s/cur/",
+			str_printfa(do_ctx->dest_path, "%s/cur/",
 				    dest_mbox->path);
-			do_ctx.base_end_pos = str_len(do_ctx.dest_path) +
-				strlen(do_ctx.dest_fname);
-			str_append(do_ctx.dest_path,
+			do_ctx->base_end_pos = str_len(do_ctx->dest_path) +
+				strlen(do_ctx->dest_fname);
+			str_append(do_ctx->dest_path,
 				   maildir_filename_set_flags(NULL,
-							      do_ctx.dest_fname,
+							      do_ctx->dest_fname,
 							      flags, NULL));
 		}
 	} else
@@ -225,25 +223,25 @@
 	{
 		/* keywords, hardlink to tmp/ with basename and later when we
 		   have uidlist locked, move it to new/cur. */
-		str_printfa(do_ctx.dest_path, "%s/tmp/%s",
-			    dest_mbox->path, do_ctx.dest_fname);
-		do_ctx.base_end_pos = str_len(do_ctx.dest_path);
+		str_printfa(do_ctx->dest_path, "%s/tmp/%s",
+			    dest_mbox->path, do_ctx->dest_fname);
+		do_ctx->base_end_pos = str_len(do_ctx->dest_path);
 	}
 	if (src_mbox != NULL) {
 		/* maildir */
 		if (maildir_file_do(src_mbox, mail->uid,
-				    do_hardlink, &do_ctx) < 0)
+				    do_hardlink, do_ctx) < 0)
 			return -1;
 	} else {
 		/* raw / deliver */
 		if (mail_get_special(mail, MAIL_FETCH_UIDL_FILE_NAME,
 				     &path) < 0 || *path == '\0')
 			return 0;
-		if (do_hardlink(dest_mbox, path, &do_ctx) < 0)
+		if (do_hardlink(dest_mbox, path, do_ctx) < 0)
 			return -1;
 	}
 
-	if (!do_ctx.success) {
+	if (!do_ctx->success) {
 		/* couldn't copy with hardlinking, fallback to copying */
 		return 0;
 	}
@@ -251,14 +249,14 @@
 #if 0
 	if (keywords == NULL || keywords->count == 0) {
 		/* hardlinked to destination, set hardlinked-flag */
-		maildir_save_add(t, do_ctx.dest_fname,
+		maildir_save_add(t, do_ctx->dest_fname,
 				 flags | MAILDIR_SAVE_FLAG_HARDLINK, NULL,
 				 dest_mail);
 	} else
 #endif
 {
 		/* hardlinked to tmp/, treat as normal copied mail */
-		maildir_save_add(t, do_ctx.dest_fname, flags, keywords,
+		maildir_save_add(t, do_ctx->dest_fname, flags, keywords,
 				 dest_mail);
 	}
 	return 1;
@@ -276,14 +274,18 @@
 	struct maildir_transaction_context *t =
 		(struct maildir_transaction_context *)ctx->transaction;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)t->ictx.ibox;
+	struct hardlink_ctx do_ctx;
 	int ret;
 
 	if (mbox->storage->copy_with_hardlinks &&
 	    maildir_compatible_file_modes(&mbox->ibox.box, mail->box)) {
 		T_BEGIN {
+			memset(&do_ctx, 0, sizeof(do_ctx));
 			ret = maildir_copy_hardlink(t, mail, ctx->flags,
 						    ctx->keywords,
-						    ctx->dest_mail);
+						    ctx->dest_mail, &do_ctx);
+			if (do_ctx.dest_path != NULL)
+				str_free(&do_ctx.dest_path);
 		} T_END;
 
 		if (ret != 0) {


More information about the dovecot-cvs mailing list