]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Maildir: Handle uidlist errors better.
authorTimo Sirainen <tss@iki.fi>
Mon, 4 May 2009 20:40:41 +0000 (16:40 -0400)
committerTimo Sirainen <tss@iki.fi>
Mon, 4 May 2009 20:40:41 +0000 (16:40 -0400)
--HG--
branch : HEAD

src/lib-storage/index/dbox/dbox-file-maildir.c
src/lib-storage/index/maildir/maildir-copy.c
src/lib-storage/index/maildir/maildir-mail.c
src/lib-storage/index/maildir/maildir-sync.c
src/lib-storage/index/maildir/maildir-uidlist.c
src/lib-storage/index/maildir/maildir-uidlist.h
src/lib-storage/index/maildir/maildir-util.c

index 2e7fc280758b6b51481c77730ef2c368f5afe2af..d5f4ea297def7933cc827022e299f7bea0e6392c 100644 (file)
@@ -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;
 }
index 2008473dd0499c8ff2a924237dc9dad0d33dc435..3cfa76e5fd177eae44135d275bb8adc8393ca9c8 100644 (file)
@@ -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)
index 33e22140603a626f27fbe83f9432a2ca4cdc547b..4fa3937e13184663187333e9d5c0c9f0faad401c 100644 (file)
@@ -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 =
index 35c68a1f9f6e5bc4133f8e289acbf034fd740e2a..d29f8c676f71674774242d25702dac6bad3b20b9 100644 (file)
@@ -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) {
index 0e5d2284a4bc6ab046b89c2691fd0841627ac3c8..bccdaddfdb3648690e3db015ecc1f2fd0e8737b3 100644 (file)
@@ -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;
                }
index 0e61884ce2b56b952a919a3e821f6ca5243b1f86..f169a862ced361ab8470ec36ed13e7348f830413 100644 (file)
@@ -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,
index 26793521fcdcd3e6ede0e22f9ba1b6265e8a9b75..0db32c912d19bbaae857e30ef12c0e5fa83c79e9 100644 (file)
@@ -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 */