Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4967:1104fc097321 HEAD
Use rename() instead of link() + unlink() when moving a mail from tmp/ to new/.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 28 Dec 2006 18:07:19 +0200 |
parents | 5df66ce64c0c |
children | 1baf9dd3fc40 |
files | src/lib-storage/index/maildir/maildir-save.c |
diffstat | 1 files changed, 16 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-save.c Thu Dec 28 17:21:55 2006 +0200 +++ b/src/lib-storage/index/maildir/maildir-save.c Thu Dec 28 18:07:19 2006 +0200 @@ -63,6 +63,7 @@ const char *tmpname, const char *destname, bool newdir) { + struct mail_storage *storage = STORAGE(ctx->mbox->storage); const char *tmp_path, *new_path; int ret; @@ -77,23 +78,29 @@ t_strconcat(ctx->newdir, "/", destname, NULL) : t_strconcat(ctx->curdir, "/", destname, NULL); - if (link(tmp_path, new_path) == 0) + /* maildir spec says we should use link() + unlink() here. however + since our filename is guaranteed to be unique, rename() works just + as well, except faster. even if the filename wasn't unique, the + problem could still happen if the file was already moved from + new/ to cur/, so link() doesn't really provide any safety anyway. + + Besides the small temporary performance benefits, this rename() is + almost required with OSX's HFS+ filesystem, since it implements + hard links in a pretty ugly way, which makes the performance crawl + when a lot of hard links are used. */ + if (rename(tmp_path, new_path) == 0) ret = 0; else { ret = -1; if (ENOSPACE(errno)) { - mail_storage_set_error(STORAGE(ctx->mbox->storage), + mail_storage_set_error(storage, "Not enough disk space"); } else { - mail_storage_set_critical(STORAGE(ctx->mbox->storage), - "link(%s, %s) failed: %m", tmp_path, new_path); + mail_storage_set_critical(storage, + "rename(%s, %s) failed: %m", + tmp_path, new_path); } } - - if (unlink(tmp_path) < 0 && errno != ENOENT) { - mail_storage_set_critical(STORAGE(ctx->mbox->storage), - "unlink(%s) failed: %m", tmp_path); - } t_pop(); return ret; }