int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input) { struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx; struct maildir_filename *mf; /* new mail, new failure state */ ctx->failed = FALSE; T_BEGIN { /* create a new file in tmp/ directory */ const char *fname; ctx->fd = maildir_create_tmp(ctx->mbox, ctx->tmpdir, &fname); if (ctx->fd == -1) ctx->failed = TRUE; else { if (ctx->mbox->storage->storage.set->mail_save_crlf) ctx->input = i_stream_create_crlf(input); else ctx->input = i_stream_create_lf(input); mf = maildir_save_add(_ctx, fname, NULL); if (_ctx->data.guid != NULL) { maildir_save_set_dest_basename(_ctx, mf, _ctx->data.guid); } } } T_END; if (!ctx->failed) { _ctx->data.output = o_stream_create_fd_file(ctx->fd, 0, FALSE); o_stream_cork(_ctx->data.output); ctx->last_save_finished = FALSE; } return ctx->failed ? -1 : 0; }
static int 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; 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; else if (strcmp(mail->box->storage->name, "raw") == 0) { /* lda uses raw format */ src_mbox = NULL; } else { /* Can't hard link files from the source storage */ return 0; } /* hard link to tmp/ with a newly generated filename and later when we have uidlist locked, move it to new/cur. */ dest_fname = maildir_filename_generate(); memset(&do_ctx, 0, sizeof(do_ctx)); do_ctx.dest_path = t_strdup_printf("%s/tmp/%s", mailbox_get_path(&dest_mbox->box), dest_fname); if (src_mbox != NULL) { /* maildir */ if (maildir_file_do(src_mbox, mail->uid, 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) return -1; } if (!do_ctx.success) { /* couldn't copy with hardlinking, fallback to copying */ return 0; } /* hardlinked to tmp/, treat as normal copied mail */ mf = maildir_save_add(ctx, dest_fname, mail); 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; }