sdbox-copy.c revision e8762c2b4914db7997fa9eb644a91586952d1876
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "nfs-workarounds.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "dbox-save.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "sdbox-storage.h"
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen#include "sdbox-file.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-copy.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainensdbox_copy_hardlink(struct mail_save_context *_ctx, struct mail *mail)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct sdbox_mailbox *dest_mbox =
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen (struct sdbox_mailbox *)_ctx->transaction->box;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen struct sdbox_mailbox *src_mbox;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct dbox_file *src_file, *dest_file;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *src_path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strcmp(mail->box->storage->name, SDBOX_STORAGE_NAME) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen src_mbox = (struct sdbox_mailbox *)mail->box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen /* Source storage isn't sdbox, can't hard link */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen src_file = sdbox_file_init(src_mbox, mail->uid);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen dest_file = sdbox_file_init(dest_mbox, 0);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen src_path = src_file->primary_path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = nfs_safe_link(src_path, dest_file->cur_path, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0 && errno == ENOENT && src_file->alt_path != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen src_path = src_file->alt_path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = nfs_safe_link(src_path, dest_file->cur_path, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen if (ret < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ECANTLINK(errno))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (errno == ENOENT)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_set_expunged(mail);
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen else {
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen mail_storage_set_critical(
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen _ctx->transaction->box->storage,
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen "link(%s, %s) failed: %m",
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen src_path, dest_file->cur_path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen dbox_save_add_to_index(ctx);
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen sdbox_save_add_file(_ctx, dest_file);
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen if (_ctx->dest_mail != NULL)
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen mail_set_seq(_ctx->dest_mail, ctx->seq);
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen return 1;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen}
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainensdbox_compatible_file_modes(struct mailbox *box1, struct mailbox *box2)
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return box1->file_create_mode == box2->file_create_mode &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen box1->file_create_gid == box2->file_create_gid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint sdbox_copy(struct mail_save_context *_ctx, struct mail *mail)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_transaction_context *_t = _ctx->transaction;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)_t->box;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen int ret;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen
e9d29ae46d435aee85514decfe6ee27399ebf794Timo Sirainen i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen ctx->finished = TRUE;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (sdbox_compatible_file_modes(&mbox->box, mail->box)) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen T_BEGIN {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ret = sdbox_copy_hardlink(_ctx, mail);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen } T_END;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (ret != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_save_context_free(_ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret > 0 ? 0 : -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen /* non-fatal hardlinking failure, try the slow way */
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mail_storage_copy(_ctx, mail);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen