]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dbox: Check mailbox existence from index directory with ITERINDEX
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 26 Jun 2017 16:06:26 +0000 (19:06 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 3 Jul 2017 12:25:27 +0000 (15:25 +0300)
src/lib-storage/index/dbox-common/dbox-storage.c

index 463fdb18e829fbd1841a732ac1ba9d803da1e19a..8d890cb58266ff82b51f3e41c3dd00ab3bcdbf89 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <dirent.h>
 #include <unistd.h>
+#include <utime.h>
 
 void dbox_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
                                    struct mailbox_list_settings *set)
@@ -178,10 +179,25 @@ dbox_cleanup_temp_files(struct mailbox_list *list, const char *path,
                /* not the time to scan it yet */
                return FALSE;
        } else {
+               bool stated = FALSE;
+               if (last_change_time == (time_t)-1) {
+                       /* Don't know the ctime yet - look it up. */
+                       struct stat st;
+
+                       if (stat(path, &st) < 0) {
+                               if (errno == ENOENT)
+                                       i_error("stat(%s) failed: %m", path);
+                               return FALSE;
+                       }
+                       last_change_time = st.st_ctime;
+                       stated = TRUE;
+               }
                if (last_scan_time > last_change_time + DBOX_TMP_DELETE_SECS) {
                        /* there haven't been any changes to this directory
-                          since we last checked it. */
-                       return FALSE;
+                          since we last checked it. If we did an extra stat(),
+                          we need to update the last_scan_time to avoid
+                          stat()ing the next time. */
+                       return stated;
                }
                const char *prefix =
                        mailbox_list_get_global_temp_prefix(list);
@@ -189,15 +205,41 @@ dbox_cleanup_temp_files(struct mailbox_list *list, const char *path,
                                       ioloop_time - DBOX_TMP_DELETE_SECS);
                return TRUE;
        }
+       return FALSE;
 }
 
 int dbox_mailbox_check_existence(struct mailbox *box, time_t *path_ctime_r)
 {
-       const char *box_path = mailbox_get_path(box);
+       const char *index_path, *box_path = mailbox_get_path(box);
        struct stat st;
+       int ret = -1;
+
+       *path_ctime_r = (time_t)-1;
+
+       if (box->list->set.iter_from_index_dir) {
+               /* Just because the index directory exists, it doesn't mean
+                  that the mailbox is selectable. Check that by seeing if
+                  dovecot.index.log exists. If it doesn't, fallback to
+                  checking for the dbox-Mails in the mail root directory.
+                  So this also means that if a mailbox is \NoSelect, listing
+                  it will always do a stat() for dbox-Mails in the mail root
+                  directory. That's not ideal, but this makes the behavior
+                  safer and \NoSelect mailboxes are somewhat rare. */
+               if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
+                                       &index_path) < 0)
+                       return -1;
+               i_assert(index_path != NULL);
+               index_path = t_strconcat(index_path, "/", box->index_prefix,
+                                        ".log", NULL);
+               ret = stat(index_path, &st);
+       }
+       if (ret < 0) {
+               ret = stat(box_path, &st);
+               if (ret == 0)
+                       *path_ctime_r = st.st_ctime;
+       }
 
-       if (stat(box_path, &st) == 0) {
-               *path_ctime_r = st.st_ctime;
+       if (ret == 0) {
                return 0;
        } else if (errno == ENOENT || errno == ENAMETOOLONG) {
                mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,