maildir-copy.c revision d22301419109ed4a38351715e6760011421dadec
/* Copyright (c) 2002-2010 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 const char *
struct maildir_mailbox *dest_mbox,
{
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. */
&fname) <= 0)
return NULL;
return NULL;
/* already exists in destination */
return NULL;
}
/* fname may be freed by a later uidlist sync. make sure it gets
strduped. */
}
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;
}
return -1;
}
}
/* 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
{
}
{
int ret;
T_BEGIN {
} T_END;
if (ret != 0) {
return ret > 0 ? 0 : -1;
}
/* non-fatal hardlinking failure, try the slow way */
}
}