/* locking already does the most important sanity checks for header */
hdr = *index->hdr;
- if (hdr.uid_validity == 0) {
- *error_r = "uid_validity = 0";
+ if (hdr.uid_validity == 0 && hdr.next_uid != 1) {
+ *error_r = "uid_validity = 0 && next_uid != 1";
return 0;
}
}
/* following some extra checks that only take a bit of CPU */
- if (hdr->uid_validity == 0) {
+ if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
mail_index_set_error(index, "Corrupted index file %s: "
- "uid_validity = 0", index->filepath);
+ "uid_validity = 0, next_uid = %u",
+ index->filepath, hdr->next_uid);
return -1;
}
hdr->indexid = now;
- hdr->uid_validity = now;
hdr->next_uid = 1;
}
{
struct index_mailbox *ibox;
struct mail_index *index;
- const struct mail_index_header *hdr;
const char *path, *index_dir, *control_dir;
struct stat st;
if (ibox == NULL)
return NULL;
- if (mail_index_get_header(ibox->view, &hdr) < 0) {
- index_storage_mailbox_free(&ibox->box);
- return NULL;
- }
-
ibox->path = i_strdup(path);
ibox->control_dir = i_strdup(control_dir);
ibox->get_recent_count = maildir_get_recent_count;
ibox->mail_interface = &maildir_mail;
- ibox->uidlist = maildir_uidlist_init(ibox, hdr->uid_validity);
+ ibox->uidlist = maildir_uidlist_init(ibox);
/* for shared mailboxes get the create mode from the
permissions of dovecot-shared file */
i_assert(ret == 0); /* view is locked, can't happen */
uid_validity = maildir_uidlist_get_uid_validity(ibox->uidlist);
- if (uid_validity != hdr->uid_validity && hdr->next_uid != 1) {
+ if (uid_validity != hdr->uid_validity &&
+ uid_validity != 0 && hdr->uid_validity != 0) {
/* uidvalidity changed and mailbox isn't being initialized,
index must be rebuilt */
mail_storage_set_critical(ibox->box.storage,
&sync_stamp, sizeof(sync_stamp));
}
- if (uid_validity != hdr->uid_validity) {
+ if (hdr->uid_validity == 0) {
+ /* get the initial uidvalidity */
+ if (maildir_uidlist_update(ibox->uidlist) < 0)
+ ret = -1;
+ uid_validity = maildir_uidlist_get_uid_validity(ibox->uidlist);
+ if (uid_validity == 0) {
+ uid_validity = ioloop_time;
+ maildir_uidlist_set_uid_validity(ibox->uidlist,
+ uid_validity);
+ }
+ } else if (uid_validity == 0) {
+ maildir_uidlist_set_uid_validity(ibox->uidlist,
+ hdr->uid_validity);
+ }
+
+ if (uid_validity != hdr->uid_validity && uid_validity != 0) {
mail_index_update_header(trans,
offsetof(struct mail_index_header, uid_validity),
&uid_validity, sizeof(uid_validity));
unsigned int initial_read:1;
unsigned int initial_sync:1;
+ unsigned int file_missing:1;
};
struct maildir_uidlist_sync_ctx {
uidlist->lock_fd = -1;
}
-struct maildir_uidlist *
-maildir_uidlist_init(struct index_mailbox *ibox, uint32_t uid_validity)
+struct maildir_uidlist *maildir_uidlist_init(struct index_mailbox *ibox)
{
struct maildir_uidlist *uidlist;
uidlist->files = hash_create(default_pool, default_pool, 4096,
maildir_hash, maildir_cmp);
- uidlist->uid_validity = uid_validity;
uidlist->next_uid = 1;
return uidlist;
"open(%s) failed: %m", uidlist->fname);
return -1;
}
+ uidlist->file_missing = TRUE;
uidlist->initial_read = TRUE;
return 0;
}
+ uidlist->file_missing = FALSE;
if (fstat(fd, &st) < 0) {
mail_storage_set_critical(storage,
return uidlist->uid_validity;
}
+void maildir_uidlist_set_uid_validity(struct maildir_uidlist *uidlist,
+ uint32_t uid_validity)
+{
+ uidlist->uid_validity = uid_validity;
+}
+
uint32_t maildir_uidlist_get_next_uid(struct maildir_uidlist *uidlist)
{
return !uidlist->initial_read ? 0 : uidlist->next_uid;
const char *filename, *flags_str;
int ret = 0;
- uidlist->version = 2;
+ uidlist->version = 2;
+
+ if (uidlist->uid_validity == 0)
+ uidlist->uid_validity = ioloop_time;
str = t_str_new(4096);
str_printfa(str, "%u %u %u\n", uidlist->version,
mail_storage_set_critical(ibox->box.storage,
"file_dotlock_replace(%s) failed: %m", db_path);
ret = -1;
+ } else {
+ uidlist->file_missing = FALSE;
}
} else {
(void)close(uidlist->lock_fd);
}
ctx->new_files_count++;
+ if (uidlist->record_pool == NULL) {
+ uidlist->record_pool =
+ pool_alloconly_create("uidlist record_pool",
+ 1024);
+ }
+
rec = p_new(uidlist->record_pool,
struct maildir_uidlist_rec, 1);
rec->uid = (uint32_t)-1;
int maildir_uidlist_try_lock(struct maildir_uidlist *uidlist);
void maildir_uidlist_unlock(struct maildir_uidlist *uidlist);
-struct maildir_uidlist *
-maildir_uidlist_init(struct index_mailbox *ibox, uint32_t uid_validity);
+struct maildir_uidlist *maildir_uidlist_init(struct index_mailbox *ibox);
void maildir_uidlist_deinit(struct maildir_uidlist *uidlist);
/* Returns -1 if error, 0 if file is broken or lost, 1 if ok. */
uint32_t maildir_uidlist_get_uid_validity(struct maildir_uidlist *uidlist);
uint32_t maildir_uidlist_get_next_uid(struct maildir_uidlist *uidlist);
+void maildir_uidlist_set_uid_validity(struct maildir_uidlist *uidlist,
+ uint32_t uid_validity);
+
/* Sync uidlist with what's actually on maildir. */
struct maildir_uidlist_sync_ctx *
maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, int partial);