Mercurial > dovecot > original-hg > dovecot-1.2
changeset 1454:80f82c6a3250 HEAD
We have to sync dovecot-uidlist before indexing mails in new/ dir or we'll
get UID conflicts.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 08 May 2003 21:59:38 +0300 |
parents | 30e8a75d7842 |
children | 4f7d146f6201 |
files | src/lib-index/maildir/maildir-build.c src/lib-index/maildir/maildir-index.h src/lib-index/maildir/maildir-sync.c |
diffstat | 3 files changed, 80 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/maildir/maildir-build.c Thu May 08 18:53:07 2003 +0300 +++ b/src/lib-index/maildir/maildir-build.c Thu May 08 21:59:38 2003 +0300 @@ -2,15 +2,11 @@ #include "lib.h" #include "istream.h" -#include "str.h" #include "maildir-index.h" -#include "mail-index-data.h" #include "mail-index-util.h" -#include <stdio.h> #include <unistd.h> #include <fcntl.h> -#include <dirent.h> #include <sys/stat.h> static int maildir_record_update(struct mail_index *index, @@ -127,70 +123,3 @@ return index_file_set_syscall_error(index, path, "close()"); return ret; } - -int maildir_index_build_dir(struct mail_index *index, - const char *source_dir, const char *dest_dir, - DIR *dirp, struct dirent *d) -{ - const char *final_dir; - string_t *sourcepath, *destpath; - int failed; - - i_assert(index->maildir_lock_fd != -1); - i_assert(index->lock_type != MAIL_LOCK_SHARED); - - sourcepath = t_str_new(PATH_MAX); - destpath = t_str_new(PATH_MAX); - - final_dir = dest_dir != NULL ? dest_dir : source_dir; - - failed = FALSE; - for (; d != NULL && !failed; d = readdir(dirp)) { - if (d->d_name[0] == '.') - continue; - - if (dest_dir != NULL) { - /* rename() has the problem that it might overwrite - some mails, but that happens only with a broken - client that has created non-unique base name. - - Alternative would be link() + unlink(), but that's - racy when multiple clients try to move the mail from - new/ to cur/: - - a) One of the clients uses slightly different - filename (eg. sets flags) - - b) Third client changes mail's flag between - client1's unlink() and client2's link() calls. - - Checking first if file exists with stat() is pretty - useless as well. It requires that we also stat the - file in new/, to make sure that the dest file isn't - actually the same file which someone _just_ had - rename()d. */ - str_truncate(sourcepath, 0); - str_truncate(destpath, 0); - - str_printfa(sourcepath, "%s/%s", source_dir, d->d_name); - str_printfa(destpath, "%s/%s", dest_dir, d->d_name); - - if (rename(str_c(sourcepath), str_c(destpath)) < 0 && - errno != ENOENT) { - index_set_error(index, "maildir build: " - "rename(%s, %s) failed: %m", - str_c(sourcepath), - str_c(destpath)); - failed = TRUE; - break; - } - } - - t_push(); - failed = !maildir_index_append_file(index, final_dir, - d->d_name); - t_pop(); - } - - return !failed; -}
--- a/src/lib-index/maildir/maildir-index.h Thu May 08 18:53:07 2003 +0300 +++ b/src/lib-index/maildir/maildir-index.h Thu May 08 21:59:38 2003 +0300 @@ -28,9 +28,6 @@ int maildir_index_append_file(struct mail_index *index, const char *dir, const char *fname); -int maildir_index_build_dir(struct mail_index *index, - const char *source_dir, const char *dest_dir, - DIR *dirp, struct dirent *d); struct istream *maildir_open_mail(struct mail_index *index, struct mail_index_record *rec,
--- a/src/lib-index/maildir/maildir-sync.c Thu May 08 18:53:07 2003 +0300 +++ b/src/lib-index/maildir/maildir-sync.c Thu May 08 21:59:38 2003 +0300 @@ -4,11 +4,13 @@ #include "buffer.h" #include "hash.h" #include "ioloop.h" +#include "str.h" #include "maildir-index.h" #include "maildir-uidlist.h" #include "mail-index-data.h" #include "mail-index-util.h" +#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> @@ -437,6 +439,74 @@ return TRUE; } +static int maildir_sync_new(struct mail_index *index, + const char *source_dir, const char *dest_dir, + DIR *dirp, struct dirent *d, int append_index) +{ + const char *final_dir; + string_t *sourcepath, *destpath; + int failed; + + i_assert(index->maildir_lock_fd != -1); + i_assert(index->lock_type != MAIL_LOCK_SHARED); + + sourcepath = t_str_new(PATH_MAX); + destpath = t_str_new(PATH_MAX); + + final_dir = dest_dir != NULL ? dest_dir : source_dir; + + failed = FALSE; + for (; d != NULL && !failed; d = readdir(dirp)) { + if (d->d_name[0] == '.') + continue; + + if (dest_dir != NULL) { + /* rename() has the problem that it might overwrite + some mails, but that happens only with a broken + client that has created non-unique base name. + + Alternative would be link() + unlink(), but that's + racy when multiple clients try to move the mail from + new/ to cur/: + + a) One of the clients uses slightly different + filename (eg. sets flags) + + b) Third client changes mail's flag between + client1's unlink() and client2's link() calls. + + Checking first if file exists with stat() is pretty + useless as well. It requires that we also stat the + file in new/, to make sure that the dest file isn't + actually the same file which someone _just_ had + rename()d. */ + str_truncate(sourcepath, 0); + str_truncate(destpath, 0); + + str_printfa(sourcepath, "%s/%s", source_dir, d->d_name); + str_printfa(destpath, "%s/%s", dest_dir, d->d_name); + + if (rename(str_c(sourcepath), str_c(destpath)) < 0 && + errno != ENOENT) { + index_set_error(index, "maildir build: " + "rename(%s, %s) failed: %m", + str_c(sourcepath), + str_c(destpath)); + failed = TRUE; + break; + } + } + + if (append_index) { + t_push(); + failed = !maildir_index_append_file(index, final_dir, + d->d_name); + t_pop(); + } + } + + return !failed; +} static int maildir_index_lock_and_sync(struct mail_index *index, int *changes, DIR *new_dirp, struct dirent *new_dent, struct maildir_uidlist **uidlist_r) @@ -533,15 +603,18 @@ /* move mail from new/ to cur/ */ if (new_dirp != NULL && INDEX_IS_UIDLIST_LOCKED(index)) { new_dir = t_strconcat(index->mailbox_path, "/new", NULL); - if (!maildir_index_build_dir(index, new_dir, cur_dir, - new_dirp, new_dent)) + if (!maildir_sync_new(index, new_dir, cur_dir, + new_dirp, new_dent, FALSE)) return FALSE; if (uidlist != NULL) uidlist->rewrite = TRUE; /* set cur/ directory's timestamp into past to make sure we - notice if new mail is moved there */ + notice if new mail is moved there. FIXME: is this such a + good idea? Works fine only as long as others don't try + the same thing.. But alternative is to wait a second or + potentially lose some mails. */ ut.actime = ut.modtime = ioloop_time-60; if (utime(cur_dir, &ut) < 0) { index_file_set_syscall_error(index, cur_dir, "utime()"); @@ -550,8 +623,10 @@ /* We have to always scan the cur/ directory to make sure we don't miss any mails some other non-Dovecot - client may have moved there. FIXME: make it - optional, it's unnecessary with Dovecot-only setup */ + client may have moved there. FIXME: in Dovecot-only setup + we could just skip checking cur/ changes. In that case the + new/ dir has to be be synced after uidlist is first synced + or there could be some problems with conflicting UIDs */ cur_changed = TRUE; /* set the cur/ directory's timestamp */