maildir-copy.c revision ea4c984d8097f24aa18ed5bb364ebaf3b01bc2a3
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int do_save_mail_size(struct maildir_mailbox *mbox, const char *path,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen str = t_strdup_printf(",%c=%"PRIuUOFF_T, MAILDIR_EXTRA_FILE_SIZE, size);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen str_insert(ctx->dest_path, ctx->base_end_pos, str);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ctx->dest_fname = strrchr(str_c(ctx->dest_path), '/') + 1;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic void do_save_mail_vsize(const char *path, struct hardlink_ctx *ctx)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (!maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen str_insert(ctx->dest_path, ctx->base_end_pos, str);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ctx->dest_fname = strrchr(str_c(ctx->dest_path), '/') + 1;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic int do_hardlink(struct maildir_mailbox *mbox, const char *path,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if ((ret = do_save_mail_size(mbox, path, ctx)) <= 0)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* set virtual size if it's in the original file name */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (mbox->storage->storage.set->mail_nfs_storage)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen ret = nfs_safe_link(path, str_c(ctx->dest_path), FALSE);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen mail_storage_set_error(&mbox->storage->storage,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* we could handle the EEXIST condition by changing the
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen filename, but it practically never happens so just fallback
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen to standard copying for the rare cases when it does. */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (errno == EACCES || ECANTLINK(errno) || errno == EEXIST)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen "link(%s, %s) failed: %m",
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenstatic const char *
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenmaildir_copy_get_preserved_fname(struct maildir_mailbox *src_mbox,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (maildir_uidlist_lookup(src_mbox->uidlist, uid, &flags,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* fname may be freed by a later uidlist sync. make sure it gets
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenmaildir_copy_hardlink(struct mail_save_context *ctx, struct mail *mail)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen (struct maildir_mailbox *)ctx->transaction->box;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (strcmp(mail->box->storage->name, MAILDIR_STORAGE_NAME) == 0)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen src_mbox = (struct maildir_mailbox *)mail->box;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen else if (strcmp(mail->box->storage->name, "raw") == 0) {
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* lda uses raw format */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* Can't hard link files from the source storage */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen do_ctx.dest_path = str_new(default_pool, 512);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (dest_mbox->storage->set->maildir_copy_preserve_filename &&
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen filename = maildir_copy_get_preserved_fname(src_mbox,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* the generated filename is _always_ unique, so we don't
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen bother trying to check if it already exists */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen do_ctx.dest_fname = maildir_filename_generate();
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* hard link to tmp/ with basename and later when we
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen have uidlist locked, move it to new/cur. */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen do_ctx.base_end_pos = str_len(do_ctx.dest_path);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* maildir */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* raw / lda */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (mail_get_special(mail, MAIL_FETCH_UIDL_FILE_NAME,
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (do_hardlink(dest_mbox, path, &do_ctx) < 0)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* couldn't copy with hardlinking, fallback to copying */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen /* hardlinked to tmp/, treat as normal copied mail */
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen maildir_save_add(ctx, do_ctx.dest_fname, do_ctx.preserve_filename);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenmaildir_compatible_file_modes(struct mailbox *box1, struct mailbox *box2)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen return box1->file_create_mode == box2->file_create_mode &&
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen box1->file_create_gid == box2->file_create_gid;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainenint maildir_copy(struct mail_save_context *ctx, struct mail *mail)
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct mailbox_transaction_context *_t = ctx->transaction;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)_t->box;
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen i_assert((_t->flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
51f750db859e62e2c58a61806b53e0adb13e0775Timo Sirainen if (mbox->storage->set->maildir_copy_with_hardlinks &&