static void maildir_mail_remove_sizes_from_uidlist(struct mail *mail) { struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box; if (maildir_uidlist_lookup_ext(mbox->uidlist, mail->uid, MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) { maildir_uidlist_unset_ext(mbox->uidlist, mail->uid, MAILDIR_UIDLIST_REC_EXT_VSIZE); } if (maildir_uidlist_lookup_ext(mbox->uidlist, mail->uid, MAILDIR_UIDLIST_REC_EXT_PSIZE) != NULL) { maildir_uidlist_unset_ext(mbox->uidlist, mail->uid, MAILDIR_UIDLIST_REC_EXT_PSIZE); } }
static bool maildir_expunge_is_valid_guid(struct maildir_index_sync_context *ctx, uint32_t uid, const char *filename, guid_128_t expunged_guid_128) { guid_128_t guid_128; const char *guid; if (guid_128_is_empty(expunged_guid_128)) { /* no GUID associated with expunge */ return TRUE; } T_BEGIN { guid = maildir_uidlist_lookup_ext(ctx->mbox->uidlist, uid, MAILDIR_UIDLIST_REC_EXT_GUID); if (guid == NULL) guid = t_strcut(filename, ':'); mail_generate_guid_128_hash(guid, guid_128); } T_END; if (memcmp(guid_128, expunged_guid_128, sizeof(guid_128)) == 0) return TRUE; mail_storage_set_critical(&ctx->mbox->storage->storage, "Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s", ctx->mbox->box.vname, ctx->uid, guid_128_to_string(guid_128), guid_128_to_string(expunged_guid_128)); return FALSE; }
static int maildir_quick_size_lookup(struct index_mail *mail, bool vsize, uoff_t *size_r) { struct mail *_mail = &mail->mail.mail; struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box; enum maildir_uidlist_rec_ext_key key; const char *path, *fname, *value; if (!_mail->saving) { if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0) return -1; } else { if (maildir_save_file_get_size(_mail->transaction, _mail->seq, vsize, size_r) == 0) return 1; path = maildir_save_file_get_path(_mail->transaction, _mail->seq); fname = strrchr(path, '/'); fname = fname != NULL ? fname + 1 : path; } /* size can be included in filename */ if (vsize || !mbox->storage->set->maildir_broken_filename_sizes) { if (maildir_filename_get_size(fname, vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE : MAILDIR_EXTRA_FILE_SIZE, size_r)) return 1; } /* size can be included in uidlist entry */ if (!_mail->saving) { key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE : MAILDIR_UIDLIST_REC_EXT_PSIZE; value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, key); if (value != NULL && str_to_uoff(value, size_r) == 0) return 1; } return 0; }
static int maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field, const char **value_r) { struct index_mail *mail = (struct index_mail *)_mail; struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box; const char *path, *fname = NULL, *end, *guid, *uidl, *order; struct stat st; switch (field) { case MAIL_FETCH_GUID: /* use GUID from uidlist if it exists */ i_assert(!_mail->saving); if (mail->data.guid != NULL) { *value_r = mail->data.guid; return 0; } /* first make sure that we have a refreshed uidlist */ if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0) return -1; guid = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, MAILDIR_UIDLIST_REC_EXT_GUID); if (guid != NULL) { if (*guid != '\0') { *value_r = mail->data.guid = p_strdup(mail->mail.data_pool, guid); return 0; } mail_storage_set_critical(_mail->box->storage, "Maildir %s: Corrupted dovecot-uidlist: " "UID %u had empty GUID, clearing it", mailbox_get_path(_mail->box), _mail->uid); maildir_uidlist_unset_ext(mbox->uidlist, _mail->uid, MAILDIR_UIDLIST_REC_EXT_GUID); } /* default to base filename: */ if (maildir_mail_get_special(_mail, MAIL_FETCH_STORAGE_ID, value_r) < 0) return -1; mail->data.guid = mail->data.filename; return 0; case MAIL_FETCH_STORAGE_ID: if (mail->data.filename != NULL) { *value_r = mail->data.filename; return 0; } if (fname != NULL) { /* we came here from MAIL_FETCH_GUID, avoid a second lookup */ } else if (!_mail->saving) { if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0) return -1; } else { path = maildir_save_file_get_path(_mail->transaction, _mail->seq); fname = strrchr(path, '/'); fname = fname != NULL ? fname + 1 : path; } end = strchr(fname, MAILDIR_INFO_SEP); mail->data.filename = end == NULL ? p_strdup(mail->mail.data_pool, fname) : p_strdup_until(mail->mail.data_pool, fname, end); *value_r = mail->data.filename; return 0; case MAIL_FETCH_UIDL_BACKEND: uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, MAILDIR_UIDLIST_REC_EXT_POP3_UIDL); if (uidl == NULL) { /* use the default */ *value_r = ""; } else if (*uidl == '\0') { /* special optimization case: use the base file name */ return maildir_mail_get_special(_mail, MAIL_FETCH_STORAGE_ID, value_r); } else { *value_r = p_strdup(mail->mail.data_pool, uidl); } return 0; case MAIL_FETCH_POP3_ORDER: order = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, MAILDIR_UIDLIST_REC_EXT_POP3_ORDER); if (order == NULL) { *value_r = ""; } else { *value_r = p_strdup(mail->mail.data_pool, order); } return 0; case MAIL_FETCH_REFCOUNT: if (maildir_mail_stat(_mail, &st) < 0) return -1; *value_r = p_strdup_printf(mail->mail.data_pool, "%lu", (unsigned long)st.st_nlink); return 0; default: return index_mail_get_special(_mail, field, value_r); } }