From: Timo Sirainen Date: Mon, 4 May 2009 20:40:41 +0000 (-0400) Subject: Maildir: Handle uidlist errors better. X-Git-Tag: 2.0.alpha1~845 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7ede6554e451ec039a67beec7d6ee4aff61d386e;p=thirdparty%2Fdovecot%2Fcore.git Maildir: Handle uidlist errors better. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/dbox/dbox-file-maildir.c b/src/lib-storage/index/dbox/dbox-file-maildir.c index 2e7fc28075..d5f4ea297d 100644 --- a/src/lib-storage/index/dbox/dbox-file-maildir.c +++ b/src/lib-storage/index/dbox/dbox-file-maildir.c @@ -84,6 +84,8 @@ bool dbox_maildir_uid_get_fname(struct dbox_mailbox *mbox, uint32_t uid, { enum maildir_uidlist_rec_flag flags; - *fname_r = maildir_uidlist_lookup(mbox->maildir_uidlist, uid, &flags); - return *fname_r != NULL; + if (maildir_uidlist_lookup(mbox->maildir_uidlist, uid, &flags, + fname_r) <= 0) + return FALSE; + return TRUE; } diff --git a/src/lib-storage/index/maildir/maildir-copy.c b/src/lib-storage/index/maildir/maildir-copy.c index 2008473dd0..3cfa76e5fd 100644 --- a/src/lib-storage/index/maildir/maildir-copy.c +++ b/src/lib-storage/index/maildir/maildir-copy.c @@ -167,9 +167,9 @@ maildir_copy_hardlink(struct maildir_transaction_context *t, struct mail *mail, uidlist. if it doesn't, we can use it. otherwise generate a new filename. FIXME: There's a race condition here if another process is just doing the same copy. */ - src_fname = maildir_uidlist_lookup(src_mbox->uidlist, - mail->uid, &src_flags); - if (src_fname != NULL && + if (maildir_uidlist_lookup(src_mbox->uidlist, + mail->uid, &src_flags, + &src_fname) > 0 && maildir_uidlist_refresh(dest_mbox->uidlist) >= 0 && maildir_uidlist_get_full_filename(dest_mbox->uidlist, src_fname) == NULL) diff --git a/src/lib-storage/index/maildir/maildir-mail.c b/src/lib-storage/index/maildir/maildir-mail.c index 33e2214060..4fa3937e13 100644 --- a/src/lib-storage/index/maildir/maildir-mail.c +++ b/src/lib-storage/index/maildir/maildir-mail.c @@ -147,7 +147,7 @@ static int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r) return data->save_date; } -static bool +static int maildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail, const char **fname_r) { @@ -155,10 +155,11 @@ maildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail, struct mail_index_view *view; uint32_t seq; bool exists; + int ret; - *fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags); - if (*fname_r != NULL) - return TRUE; + ret = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags, fname_r); + if (ret != 0) + return ret; /* file exists in index file, but not in dovecot-uidlist anymore. */ mail_set_expunged(mail); @@ -177,7 +178,7 @@ maildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail, the same as in index. fix this by forcing a resync. */ (void)maildir_storage_sync_force(mbox, mail->uid); } - return FALSE; + return 0; } static int maildir_get_pop3_state(struct index_mail *mail) @@ -252,7 +253,7 @@ static int maildir_quick_size_lookup(struct index_mail *mail, bool vsize, char *p; if (_mail->uid != 0) { - if (!maildir_mail_get_fname(mbox, _mail, &fname)) + if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0) return -1; } else { path = maildir_save_file_get_path(_mail->transaction, @@ -428,7 +429,7 @@ maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field, case MAIL_FETCH_UIDL_FILE_NAME: case MAIL_FETCH_GUID: if (_mail->uid != 0) { - if (!maildir_mail_get_fname(mbox, _mail, &fname)) + if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0) return -1; } else { path = maildir_save_file_get_path(_mail->transaction, @@ -488,12 +489,15 @@ static void maildir_mail_set_cache_corrupted(struct mail *_mail, enum maildir_uidlist_rec_flag flags; const char *fname; uoff_t size; + int ret; if (field == MAIL_FETCH_VIRTUAL_SIZE) { /* make sure it gets removed from uidlist. if it's in file name, we can't really do more than log it. */ - fname = maildir_uidlist_lookup(mbox->uidlist, - _mail->uid, &flags); + ret = maildir_uidlist_lookup(mbox->uidlist, _mail->uid, + &flags, &fname); + if (ret <= 0) + return; if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE, &size)) { const char *subdir = diff --git a/src/lib-storage/index/maildir/maildir-sync.c b/src/lib-storage/index/maildir/maildir-sync.c index 35c68a1f9f..d29f8c676f 100644 --- a/src/lib-storage/index/maildir/maildir-sync.c +++ b/src/lib-storage/index/maildir/maildir-sync.c @@ -692,6 +692,7 @@ static int maildir_sync_context(struct maildir_sync_context *ctx, bool forced, enum maildir_uidlist_sync_flags sync_flags; enum maildir_uidlist_rec_flag flags; bool new_changed, cur_changed, lock_failure; + const char *fname; int ret; *lost_files_r = FALSE; @@ -854,8 +855,11 @@ static int maildir_sync_context(struct maildir_sync_context *ctx, bool forced, } if (find_uid != NULL && *find_uid != 0) { - if (maildir_uidlist_lookup_nosync(ctx->mbox->uidlist, *find_uid, - &flags) == NULL) { + ret = maildir_uidlist_lookup_nosync(ctx->mbox->uidlist, + *find_uid, &flags, &fname); + if (ret < 0) + return -1; + if (ret == 0) { /* UID is expunged */ *find_uid = 0; } else if ((flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) == 0) { diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c index 0e5d2284a4..bccdaddfdb 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.c +++ b/src/lib-storage/index/maildir/maildir-uidlist.c @@ -860,9 +860,10 @@ int maildir_uidlist_refresh_fast_init(struct maildir_uidlist *uidlist) } } -static struct maildir_uidlist_rec * +static int maildir_uidlist_lookup_rec(struct maildir_uidlist *uidlist, uint32_t uid, - unsigned int *idx_r) + unsigned int *idx_r, + struct maildir_uidlist_rec **rec_r) { struct maildir_uidlist_rec *const *recs; unsigned int idx, left_idx, right_idx; @@ -870,7 +871,7 @@ maildir_uidlist_lookup_rec(struct maildir_uidlist *uidlist, uint32_t uid, if (!uidlist->initial_read) { /* first time we need to read uidlist */ if (maildir_uidlist_refresh(uidlist) < 0) - return NULL; + return -1; } idx = left_idx = 0; @@ -884,66 +885,72 @@ maildir_uidlist_lookup_rec(struct maildir_uidlist *uidlist, uint32_t uid, right_idx = idx; else { *idx_r = idx; - return recs[idx]; + *rec_r = recs[idx]; + return 1; } } if (idx > 0) idx--; *idx_r = idx; - return NULL; + return 0; } -const char * -maildir_uidlist_lookup(struct maildir_uidlist *uidlist, uint32_t uid, - enum maildir_uidlist_rec_flag *flags_r) +int maildir_uidlist_lookup(struct maildir_uidlist *uidlist, uint32_t uid, + enum maildir_uidlist_rec_flag *flags_r, + const char **fname_r) { - const char *fname; + int ret; - fname = maildir_uidlist_lookup_nosync(uidlist, uid, flags_r); - if (fname == NULL) { + ret = maildir_uidlist_lookup_nosync(uidlist, uid, flags_r, fname_r); + if (ret <= 0) { + if (ret < 0) + return -1; if (uidlist->fd != -1 || uidlist->mbox == NULL) { /* refresh uidlist and check again in case it was added after the last mailbox sync */ if (maildir_uidlist_refresh(uidlist) < 0) - return NULL; + return -1; } else { /* the uidlist doesn't exist. */ if (maildir_storage_sync_force(uidlist->mbox, uid) < 0) - return NULL; + return -1; } /* try again */ - fname = maildir_uidlist_lookup_nosync(uidlist, uid, flags_r); + ret = maildir_uidlist_lookup_nosync(uidlist, uid, + flags_r, fname_r); } - return fname; + return ret; } -const char * -maildir_uidlist_lookup_nosync(struct maildir_uidlist *uidlist, uint32_t uid, - enum maildir_uidlist_rec_flag *flags_r) +int maildir_uidlist_lookup_nosync(struct maildir_uidlist *uidlist, uint32_t uid, + enum maildir_uidlist_rec_flag *flags_r, + const char **fname_r) { - const struct maildir_uidlist_rec *rec; + struct maildir_uidlist_rec *rec; unsigned int idx; + int ret; - rec = maildir_uidlist_lookup_rec(uidlist, uid, &idx); - if (rec == NULL) - return NULL; + if ((ret = maildir_uidlist_lookup_rec(uidlist, uid, &idx, &rec)) <= 0) + return ret; *flags_r = rec->flags; - return rec->filename; + *fname_r = rec->filename; + return 1; } const char * maildir_uidlist_lookup_ext(struct maildir_uidlist *uidlist, uint32_t uid, enum maildir_uidlist_rec_ext_key key) { - const struct maildir_uidlist_rec *rec; + struct maildir_uidlist_rec *rec; unsigned int idx; const unsigned char *p; + int ret; - rec = maildir_uidlist_lookup_rec(uidlist, uid, &idx); - if (rec == NULL || rec->extensions == NULL) + ret = maildir_uidlist_lookup_rec(uidlist, uid, &idx, &rec); + if (ret <= 0 || rec->extensions == NULL) return NULL; p = rec->extensions; @@ -992,14 +999,17 @@ maildir_uidlist_set_ext_real(struct maildir_uidlist *uidlist, uint32_t uid, const unsigned char *p; buffer_t *buf; unsigned int len; + int ret; + + ret = maildir_uidlist_lookup_rec(uidlist, uid, &idx, &rec); + if (ret <= 0) { + if (ret < 0) + return; - rec = maildir_uidlist_lookup_rec(uidlist, uid, &idx); - if (rec == NULL) { /* maybe it's a new message */ if (maildir_uidlist_refresh(uidlist) < 0) return; - rec = maildir_uidlist_lookup_rec(uidlist, uid, &idx); - if (rec == NULL) { + if (maildir_uidlist_lookup_rec(uidlist, uid, &idx, &rec) <= 0) { /* message is already expunged, ignore */ return; } diff --git a/src/lib-storage/index/maildir/maildir-uidlist.h b/src/lib-storage/index/maildir/maildir-uidlist.h index 0e61884ce2..f169a862ce 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.h +++ b/src/lib-storage/index/maildir/maildir-uidlist.h @@ -64,13 +64,14 @@ int maildir_uidlist_refresh(struct maildir_uidlist *uidlist); fill in the uidvalidity/nextuid from index file instead. */ int maildir_uidlist_refresh_fast_init(struct maildir_uidlist *uidlist); -/* Returns uidlist record for given filename, or NULL if not found. */ -const char * -maildir_uidlist_lookup(struct maildir_uidlist *uidlist, uint32_t uid, - enum maildir_uidlist_rec_flag *flags_r); -const char * -maildir_uidlist_lookup_nosync(struct maildir_uidlist *uidlist, uint32_t uid, - enum maildir_uidlist_rec_flag *flags_r); +/* Look up uidlist record for given filename. Returns 1 if found, + 0 if not found, -1 if error */ +int maildir_uidlist_lookup(struct maildir_uidlist *uidlist, uint32_t uid, + enum maildir_uidlist_rec_flag *flags_r, + const char **fname_r); +int maildir_uidlist_lookup_nosync(struct maildir_uidlist *uidlist, uint32_t uid, + enum maildir_uidlist_rec_flag *flags_r, + const char **fname_r); /* Returns extension's value or NULL if it doesn't exist. */ const char * maildir_uidlist_lookup_ext(struct maildir_uidlist *uidlist, uint32_t uid, diff --git a/src/lib-storage/index/maildir/maildir-util.c b/src/lib-storage/index/maildir/maildir-util.c index 26793521fc..0db32c912d 100644 --- a/src/lib-storage/index/maildir/maildir-util.c +++ b/src/lib-storage/index/maildir/maildir-util.c @@ -59,9 +59,9 @@ static int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid, bool have_flags; int ret; - fname = maildir_uidlist_lookup(mbox->uidlist, uid, &flags); - if (fname == NULL) - return -2; /* expunged */ + ret = maildir_uidlist_lookup(mbox->uidlist, uid, &flags, &fname); + if (ret <= 0) + return ret == 0 ? -2 : -1; if ((flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) { /* let's see if we can guess the filename based on index */