maildir-copy.c revision 303079fb1b356981de656c9b3d419a925c6e70a3
/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "str.h"
#include "nfs-workarounds.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include "maildir-filename.h"
#include "maildir-keywords.h"
#include "maildir-sync.h"
#include "index-mail.h"
#include "mail-copy.h"
#include <stdlib.h>
#include <unistd.h>
struct hardlink_ctx {
const char *dest_fname;
unsigned int base_end_pos;
unsigned int size_set:1;
unsigned int vsize_set:1;
unsigned int success:1;
unsigned int preserve_filename:1;
};
struct hardlink_ctx *ctx)
{
&size)) {
return 0;
"stat(%s) failed: %m", path);
return -1;
}
}
return 1;
}
{
&size))
return;
}
struct hardlink_ctx *ctx)
{
int ret;
if (!ctx->preserve_filename) {
return ret;
}
/* set virtual size if it's in the original file name */
}
else
if (ret < 0) {
return 0;
return -1;
}
/* we could handle the EEXIST condition by changing the
filename, but it practically never happens so just fallback
to standard copying for the rare cases when it does. */
return 1;
"link(%s, %s) failed: %m",
return -1;
}
return 1;
}
static int
{
struct maildir_mailbox *dest_mbox =
struct maildir_mailbox *src_mbox;
struct hardlink_ctx do_ctx;
/* lda uses raw format */
} else {
/* Can't hard link files from the source storage */
return 0;
}
t->save_ctx = maildir_save_transaction_init(t);
/* don't allow caller to specify recent flag */
flags &= ~MAIL_RECENT;
flags |= MAIL_RECENT;
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. */
&src_fname) > 0 &&
}
/* the generated filename is _always_ unique, so we don't
bother trying to check if it already exists */
} else {
}
/* hard link to tmp/ with basename and later when we
/* maildir */
do_hardlink, &do_ctx) < 0)
return -1;
} else {
/* raw / lda */
return 0;
return -1;
}
/* couldn't copy with hardlinking, fallback to copying */
return 0;
}
/* hardlinked to tmp/, treat as normal copied mail */
return 1;
}
static bool
{
}
{
struct maildir_transaction_context *t =
int ret;
T_BEGIN {
} T_END;
if (ret != 0) {
return ret > 0 ? 0 : -1;
}
/* non-fatal hardlinking failure, try the slow way */
}
}