maildir-save.c revision b5a123eab92bd1fc959e07e6b180a53d9324b409
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
10c5fd417af4ee30b68c967f5e7d5a49f4f149b5Timo Sirainen /* unsigned int keywords[]; */
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct maildir_keywords_sync_ctx *keywords_sync_ctx;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct maildir_filename *files, **files_tail, *file_last;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen#define MAILDIR_SAVECTX(s) container_of(s, struct maildir_save_context, ctx)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic int maildir_file_move(struct maildir_save_context *ctx,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct maildir_filename *mf, const char *destname,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct mail_storage *storage = &ctx->mbox->storage->storage;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen /* if we have flags, we'll move it to cur/ directly, because files in
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen new/ directory can't have flags. alternative would be to write it
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen in new/ and set the flags dirty in index file, but in that case
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen external MUAs would see wrong flags. */
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen tmp_path = t_strconcat(ctx->tmpdir, "/", mf->tmp_name, NULL);
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen t_strconcat(ctx->newdir, "/", destname, NULL) :
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen t_strconcat(ctx->curdir, "/", destname, NULL);
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen /* maildir spec says we should use link() + unlink() here. however
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen since our filename is guaranteed to be unique, rename() works just
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen as well, except faster. even if the filename wasn't unique, the
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen problem could still happen if the file was already moved from
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen new/ to cur/, so link() doesn't really provide any safety anyway.
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen Besides the small temporary performance benefits, this rename() is
0d7d27765267594a5870892268ab345148306d49Timo Sirainen almost required with OSX's HFS+ filesystem, since it implements
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen hard links in a pretty ugly way, which makes the performance crawl
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen when a lot of hard links are used. */
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_NOQUOTA,
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen mail_storage_set_critical(storage, "rename(%s, %s) failed: %m",
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenmaildir_save_transaction_init(struct mailbox_transaction_context *t)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct maildir_mailbox *mbox = MAILDIR_MAILBOX(t->box);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen pool = pool_alloconly_create("maildir_save_context", 4096);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ctx = p_new(pool, struct maildir_save_context, 1);
struct maildir_filename *
unsigned int keyword_count;
sizeof(unsigned int) * keyword_count);
return mf;
const char *basename)
const char **fname_r)
return TRUE;
return FALSE;
return FALSE;
static struct maildir_filename *
while (seq > 0) {
seq--;
return mf;
const char **fname_r)
const char *tmp_fname;
int fd;
return fd;
struct mail_save_context *
return t->save_ctx;
T_BEGIN {
const char *fname;
} T_END;
const char *path)
int output_errno;
} else if (output_errno != 0) {
int ret;
T_BEGIN {
} T_END;
return ret;
} T_END;
if (new_changed) {
if (cur_changed) {
static uint32_t
unsigned int i, count;
if (count == 0)
for (i = 0; i < count; i++) {
int ret;
if (ret == 0) {
T_BEGIN {
} T_END;
first_recent_uid = 0;
if (first_recent_uid != 0) {
return TRUE;
return TRUE;
return FALSE;
int ret;
T_BEGIN {
const char *dest;
prev_mf);
if (newdir)
} T_END;
if (ret < 0)
int ret;
const char *dest;
if (newdir)
} T_END;
int ret;
if (ret > 0) {
} else if (ret == 0 &&
T_BEGIN {
} T_END;
if (ret == 0) {
ret == 0) < 0)
if (ret < 0)
if (ret < 0) {