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