dovecot-2.0: maildir: Cleaned up filename/guid preserving code o...

dovecot at dovecot.org dovecot at dovecot.org
Thu Sep 23 19:26:24 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/77e71551fe55
changeset: 12158:77e71551fe55
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Sep 23 17:26:20 2010 +0100
description:
maildir: Cleaned up filename/guid preserving code on save/copy.

diffstat:

 src/lib-storage/index/maildir/maildir-copy.c    |  134 ++++++--------------------
 src/lib-storage/index/maildir/maildir-save.c    |   92 +++++++++++++-----
 src/lib-storage/index/maildir/maildir-storage.h |    9 +-
 3 files changed, 107 insertions(+), 128 deletions(-)

diffs (truncated from 451 to 300 lines):

diff -r 4a753371ae73 -r 77e71551fe55 src/lib-storage/index/maildir/maildir-copy.c
--- a/src/lib-storage/index/maildir/maildir-copy.c	Thu Sep 23 16:40:42 2010 +0100
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Thu Sep 23 17:26:20 2010 +0100
@@ -3,7 +3,6 @@
 #include "lib.h"
 #include "array.h"
 #include "ioloop.h"
-#include "str.h"
 #include "nfs-workarounds.h"
 #include "maildir-storage.h"
 #include "maildir-uidlist.h"
@@ -18,85 +17,19 @@
 #include <sys/stat.h>
 
 struct hardlink_ctx {
-	string_t *dest_path;
-	const char *dest_fname;
-	unsigned int base_end_pos;
-
-	unsigned int size_set:1;
-	unsigned int vsize_set:1;
+	const char *dest_path;
 	unsigned int success:1;
-	unsigned int preserve_filename:1;
 };
 
-static int do_save_mail_size(struct maildir_mailbox *mbox, const char *path,
-			     struct hardlink_ctx *ctx)
-{
-	const char *fname, *str;
-	struct stat st;
-	uoff_t size;
-
-	fname = strrchr(path, '/');
-	fname = fname != NULL ? fname + 1 : path;
-
-	if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE,
-				       &size)) {
-		if (stat(path, &st) < 0) {
-			if (errno == ENOENT)
-				return 0;
-			mail_storage_set_critical(&mbox->storage->storage,
-						  "stat(%s) failed: %m", path);
-			return -1;
-		}
-		size = st.st_size;
-	}
-
-	str = t_strdup_printf(",%c=%"PRIuUOFF_T, MAILDIR_EXTRA_FILE_SIZE, size);
-	str_insert(ctx->dest_path, ctx->base_end_pos, str);
-
-	ctx->dest_fname = strrchr(str_c(ctx->dest_path), '/') + 1;
-	ctx->size_set = TRUE;
-	return 1;
-}
-
-static void do_save_mail_vsize(const char *path, struct hardlink_ctx *ctx)
-{
-	const char *fname, *str;
-	uoff_t size;
-
-	fname = strrchr(path, '/');
-	fname = fname != NULL ? fname + 1 : path;
-
-	if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
-				       &size))
-		return;
-
-	str = t_strdup_printf(",%c=%"PRIuUOFF_T,
-			      MAILDIR_EXTRA_VIRTUAL_SIZE, size);
-	str_insert(ctx->dest_path, ctx->base_end_pos, str);
-
-	ctx->dest_fname = strrchr(str_c(ctx->dest_path), '/') + 1;
-	ctx->vsize_set = TRUE;
-}
-
 static int do_hardlink(struct maildir_mailbox *mbox, const char *path,
 		       struct hardlink_ctx *ctx)
 {
 	int ret;
 
-	if (!ctx->preserve_filename) {
-		if (!ctx->size_set) {
-			if ((ret = do_save_mail_size(mbox, path, ctx)) <= 0)
-				return ret;
-		}
-		/* set virtual size if it's in the original file name */
-		if (!ctx->vsize_set)
-			do_save_mail_vsize(path, ctx);
-	}
-
 	if (mbox->storage->storage.set->mail_nfs_storage)
-		ret = nfs_safe_link(path, str_c(ctx->dest_path), FALSE);
+		ret = nfs_safe_link(path, ctx->dest_path, FALSE);
 	else
-		ret = link(path, str_c(ctx->dest_path));
+		ret = link(path, ctx->dest_path);
 	if (ret < 0) {
 		if (errno == ENOENT)
 			return 0;
@@ -115,7 +48,7 @@
 
 		mail_storage_set_critical(&mbox->storage->storage,
 					  "link(%s, %s) failed: %m",
-					  path, str_c(ctx->dest_path));
+					  path, ctx->dest_path);
 		return -1;
 	}
 
@@ -124,13 +57,16 @@
 }
 
 static int
-maildir_copy_hardlink(struct mail_save_context *ctx,
-		      struct hardlink_ctx *do_ctx, struct mail *mail)
+maildir_copy_hardlink(struct mail_save_context *ctx, struct mail *mail)
 {
 	struct maildir_mailbox *dest_mbox =
 		(struct maildir_mailbox *)ctx->transaction->box;
 	struct maildir_mailbox *src_mbox;
-	const char *path, *guid;
+	struct maildir_filename *mf;
+	struct hardlink_ctx do_ctx;
+	const char *path, *guid, *dest_fname;
+	uoff_t vsize, size;
+	enum mail_lookup_abort old_abort;
 
 	if (strcmp(mail->box->storage->name, MAILDIR_STORAGE_NAME) == 0)
 		src_mbox = (struct maildir_mailbox *)mail->box;
@@ -142,45 +78,47 @@
 		return 0;
 	}
 
-	do_ctx->dest_path = str_new(default_pool, 512);
-
-	if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) < 0)
-		guid = "";
-	if (*guid == '\0') {
-		/* 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();
-	} else {
-		do_ctx->dest_fname = guid;
-		do_ctx->preserve_filename = TRUE;
-	}
-
-	/* hard link to tmp/ with basename and later when we
+	/* hard link to tmp/ with a newly generated filename and later when we
 	   have uidlist locked, move it to new/cur. */
-	str_printfa(do_ctx->dest_path, "%s/tmp/%s",
-		    dest_mbox->box.path, do_ctx->dest_fname);
-	do_ctx->base_end_pos = str_len(do_ctx->dest_path);
+	dest_fname = maildir_filename_generate();
+	memset(&do_ctx, 0, sizeof(do_ctx));
+	do_ctx.dest_path =
+		t_strdup_printf("%s/tmp/%s", dest_mbox->box.path, dest_fname);
 	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 / lda */
 		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;
 	}
 
 	/* hardlinked to tmp/, treat as normal copied mail */
-	maildir_save_add(ctx, do_ctx->dest_fname, do_ctx->preserve_filename);
+	mf = maildir_save_add(ctx, dest_fname);
+	if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) == 0) {
+		if (*guid != '\0')
+			maildir_save_set_dest_basename(ctx, mf, guid);
+	}
+
+	/* remember size/vsize if possible */
+	old_abort = mail->lookup_abort;
+	mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL;
+	if (mail_get_physical_size(mail, &size) < 0)
+		size = (uoff_t)-1;
+	if (mail_get_virtual_size(mail, &vsize) < 0)
+		vsize = (uoff_t)-1;
+	maildir_save_set_sizes(mf, size, vsize);
+	mail->lookup_abort = old_abort;
 	return 1;
 }
 
@@ -195,7 +133,6 @@
 {
 	struct mailbox_transaction_context *_t = ctx->transaction;
 	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_t->box;
-	struct hardlink_ctx do_ctx;
 	int ret;
 
 	i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
@@ -203,10 +140,7 @@
 	if (mbox->storage->set->maildir_copy_with_hardlinks &&
 	    maildir_compatible_file_modes(&mbox->box, mail->box)) {
 		T_BEGIN {
-			memset(&do_ctx, 0, sizeof(do_ctx));
-			ret = maildir_copy_hardlink(ctx, &do_ctx, mail);
-			if (do_ctx.dest_path != NULL)
-				str_free(&do_ctx.dest_path);
+			ret = maildir_copy_hardlink(ctx, mail);
 		} T_END;
 
 		if (ret != 0) {
diff -r 4a753371ae73 -r 77e71551fe55 src/lib-storage/index/maildir/maildir-save.c
--- a/src/lib-storage/index/maildir/maildir-save.c	Thu Sep 23 16:40:42 2010 +0100
+++ b/src/lib-storage/index/maildir/maildir-save.c	Thu Sep 23 17:26:20 2010 +0100
@@ -136,8 +136,8 @@
 	return &ctx->ctx;
 }
 
-void maildir_save_add(struct mail_save_context *_ctx, const char *base_fname,
-		      bool preserve_filename)
+struct maildir_filename *
+maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname)
 {
 	struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
 	struct maildir_filename *mf;
@@ -159,13 +159,10 @@
 	keyword_count = _ctx->keywords == NULL ? 0 : _ctx->keywords->count;
 	mf = p_malloc(ctx->pool, sizeof(*mf) +
 		      sizeof(unsigned int) * keyword_count);
-	mf->tmp_name = mf->dest_basename = p_strdup(ctx->pool, base_fname);
+	mf->tmp_name = mf->dest_basename = p_strdup(ctx->pool, tmp_fname);
 	mf->flags = _ctx->flags;
 	mf->size = (uoff_t)-1;
 	mf->vsize = (uoff_t)-1;
-	mf->preserve_filename = preserve_filename;
-	if (preserve_filename)
-		ctx->have_preserved_filenames = TRUE;
 
 	ctx->file_last = mf;
 	i_assert(*ctx->files_tail == NULL);
@@ -220,6 +217,25 @@
 		ctx->input = input;
 		ctx->cur_dest_mail = _ctx->dest_mail;
 	}
+	return mf;
+}
+
+void maildir_save_set_dest_basename(struct mail_save_context *_ctx,
+				    struct maildir_filename *mf,
+				    const char *basename)
+{
+	struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
+
+	mf->preserve_filename = TRUE;
+	mf->dest_basename = p_strdup(ctx->pool, basename);
+	ctx->have_preserved_filenames = TRUE;
+}
+
+void maildir_save_set_sizes(struct maildir_filename *mf,
+			    uoff_t size, uoff_t vsize)
+{
+	mf->size = size;
+	mf->vsize = vsize;
 }
 
 static bool
@@ -297,12 +313,12 @@
 }
 
 static int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
-			      const char **fname)
+			      const char **fname_r)
 {
 	struct mailbox *box = &mbox->box;
 	struct stat st;
 	unsigned int prefix_len;
-	const char *tmp_fname = *fname;
+	const char *tmp_fname;
 	string_t *path;
 	int fd;
 
@@ -312,8 +328,7 @@
 	prefix_len = str_len(path);
 
 	for (;;) {
-		if (tmp_fname == NULL)
-			tmp_fname = maildir_filename_generate();
+		tmp_fname = maildir_filename_generate();
 		str_truncate(path, prefix_len);
 		str_append(path, tmp_fname);
 
@@ -341,7 +356,7 @@
 		tmp_fname = NULL;


More information about the dovecot-cvs mailing list