index-storage.c revision b83deefd2cf1e293373673eefb4d5cf60907978c
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "lib.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "array.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "istream.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "ioloop.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "str.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "imap-parser.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mkdir-parents.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mail-index-alloc-cache.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mail-index-private.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mail-index-modseq.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mailbox-log.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mailbox-list-private.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "index-storage.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "index-mail.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "index-thread-private.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <stdlib.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <time.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <unistd.h>
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina#include <sys/stat.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina#define LOCK_NOTIFY_INTERVAL 30
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastruct index_storage_module index_storage_module =
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MODULE_CONTEXT_INIT(&mail_storage_module_register);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinaint index_list_create_missing_index_dir(struct mailbox_list *list,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina const char *name)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina const char *root_dir, *index_dir, *parent_dir, *p, *origin;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mode_t mode;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina gid_t gid;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina unsigned int n = 0;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina root_dir = mailbox_list_get_path(list, name,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina MAILBOX_LIST_PATH_TYPE_MAILBOX);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina index_dir = mailbox_list_get_path(list, name,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina MAILBOX_LIST_PATH_TYPE_INDEX);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (*index_dir == '\0' || strcmp(index_dir, root_dir) == 0)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina return 0;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina mailbox_list_get_dir_permissions(list, name, &mode, &gid, &origin);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina while (mkdir_chgrp(index_dir, mode, gid, origin) < 0) {
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (errno == EEXIST)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina p = strrchr(index_dir, '/');
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (errno != ENOENT || p == NULL || ++n == 2) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_list_set_critical(list,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina "mkdir(%s) failed: %m", index_dir);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* create the parent directory first */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina parent_dir = t_strdup_until(index_dir, p);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mailbox_list_mkdir(list, parent_dir,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina MAILBOX_LIST_PATH_TYPE_INDEX) < 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic struct mail_index *
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaindex_storage_alloc(struct mailbox_list *list, const char *name,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina enum mailbox_flags flags, const char *prefix)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char *index_dir, *mailbox_path;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_path = mailbox_list_get_path(list, name,
afdc0179af0ad8ddbedd67422193ef02dcd2bf84Lukas Slebodnik MAILBOX_LIST_PATH_TYPE_MAILBOX);
afdc0179af0ad8ddbedd67422193ef02dcd2bf84Lukas Slebodnik index_dir = (flags & MAILBOX_FLAG_NO_INDEX_FILES) != 0 ? "" :
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (*index_dir == '\0')
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_dir = NULL;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return mail_index_alloc_cache_get(mailbox_path, index_dir, prefix);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic void set_cache_decisions(const char *set, const char *fields,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina enum mail_cache_decision_type dec)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char *const *arr;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek int i;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (fields == NULL || *fields == '\0')
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek for (arr = t_strsplit_spaces(fields, " ,"); *arr != NULL; arr++) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek for (i = 0; i < MAIL_INDEX_CACHE_FIELD_COUNT; i++) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (strcasecmp(global_cache_fields[i].name,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek *arr) == 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek global_cache_fields[i].decision = dec;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek break;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (i == MAIL_INDEX_CACHE_FIELD_COUNT) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek i_error("%s: Invalid cache field name '%s', ignoring ",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek set, *arr);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic void index_cache_register_defaults(struct mailbox *box)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const struct mail_storage_settings *set = box->storage->set;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina static bool initialized = FALSE;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct mail_cache *cache = box->cache;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (!initialized) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina initialized = TRUE;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina set_cache_decisions("mail_cache_fields",
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina set->mail_cache_fields,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MAIL_CACHE_DECISION_TEMP);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina set_cache_decisions("mail_never_cache_fields",
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina set->mail_never_cache_fields,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MAIL_CACHE_DECISION_NO |
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MAIL_CACHE_DECISION_FORCED);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->cache_fields = i_malloc(sizeof(global_cache_fields));
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina memcpy(ibox->cache_fields, global_cache_fields,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina sizeof(global_cache_fields));
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_cache_register_fields(cache, ibox->cache_fields,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MAIL_INDEX_CACHE_FIELD_COUNT);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinavoid index_storage_lock_notify(struct mailbox *box,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina enum mailbox_lock_notify_type notify_type,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina unsigned int secs_left)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct mail_storage *storage = box->storage;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *str;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina time_t now;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* if notify type changes, print the message immediately */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina now = time(NULL);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (ibox->last_notify_type == MAILBOX_LOCK_NOTIFY_NONE ||
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->last_notify_type == notify_type) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (ibox->last_notify_type == MAILBOX_LOCK_NOTIFY_NONE &&
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina notify_type == MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* first override notification, show it */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina } else {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (now < ibox->next_lock_notify || secs_left < 15)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->next_lock_notify = now + LOCK_NOTIFY_INTERVAL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->last_notify_type = notify_type;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina switch (notify_type) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina case MAILBOX_LOCK_NOTIFY_NONE:
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina case MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT:
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (storage->callbacks.notify_no == NULL)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina str = t_strdup_printf("Mailbox is locked, will abort in "
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "%u seconds", secs_left);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina storage->callbacks.
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina notify_no(box, str, storage->callback_context);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina case MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE:
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (storage->callbacks.notify_ok == NULL)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina str = t_strdup_printf("Stale mailbox lock file detected, "
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "will override in %u seconds", secs_left);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina storage->callbacks.
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina notify_ok(box, str, storage->callback_context);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinavoid index_storage_lock_notify_reset(struct mailbox *box)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->last_notify_type = MAILBOX_LOCK_NOTIFY_NONE;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinaint index_storage_mailbox_open(struct mailbox *box, bool move_to_memory)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina enum file_lock_method lock_method =
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina box->storage->set->parsed_lock_method;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina enum mail_index_open_flags index_flags;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina int ret;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina i_assert(!box->opened);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina index_flags = ibox->index_flags;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (move_to_memory)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->index_flags &= ~MAIL_INDEX_OPEN_FLAG_CREATE;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (mail_index_is_in_memory(box->index)) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_storage_set_critical(box->storage,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "Couldn't create index file");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (index_list_create_missing_index_dir(box->list, box->name) < 0) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_storage_set_internal_error(box->storage);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ret = mail_index_open(box->index, index_flags, lock_method);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (ret <= 0 || move_to_memory) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina i_assert(ret <= 0);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_storage_set_index_error(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (mail_index_move_to_memory(box->index) < 0) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* try opening once more. it should be created
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina directly into memory now. */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (mail_index_open_or_create(box->index,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina index_flags,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina lock_method) < 0)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina i_panic("in-memory index creation failed");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina box->cache = mail_index_get_cache(box->index);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina index_cache_register_defaults(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina box->view = mail_index_view_open(box->index);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->keyword_names = mail_index_get_keywords(box->index);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ibox->vsize_hdr_ext_id =
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_index_ext_register(box->index, "hdr-vsize",
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina sizeof(struct index_vsize_header), 0,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina sizeof(uint64_t));
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina box->opened = TRUE;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina index_thread_mailbox_opened(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (hook_mailbox_opened != NULL)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek hook_mailbox_opened(box);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if ((box->flags & MAILBOX_FLAG_OPEN_DELETED) == 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (mail_index_is_deleted(box->index)) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mailbox_set_deleted(box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekvoid index_storage_mailbox_alloc(struct mailbox *box, const char *name,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek enum mailbox_flags flags,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *index_prefix)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct index_mailbox_context *ibox;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *path;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek string_t *vname;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek i_assert(name != NULL);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->name = p_strdup(box->pool, name);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek vname = t_str_new(128);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_namespace_get_vname(box->list->ns, vname, name);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->vname = p_strdup(box->pool, str_c(vname));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->flags = flags;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek p_array_init(&box->search_results, box->pool, 16);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_create(&box->module_contexts,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->pool, sizeof(void *), 5);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox = p_new(box->pool, struct index_mailbox_context, 1);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox->index_flags = MAIL_INDEX_OPEN_FLAG_CREATE |
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_settings_to_index_flags(box->storage->set);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek MODULE_CONTEXT_SET(box, index_storage_module, ibox);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek path = mailbox_list_get_path(box->list, name,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek MAILBOX_LIST_PATH_TYPE_MAILBOX);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->path = p_strdup(box->pool, path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->index = index_storage_alloc(box->list, name, flags, index_prefix);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina box->inbox = strcmp(name, "INBOX") == 0 &&
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (box->file_create_mode == 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_refresh_permissions(box);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_index_set_permissions(box->index, box->file_create_mode,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->file_create_gid,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->file_create_gid_origin);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekint index_storage_mailbox_enable(struct mailbox *box,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek enum mailbox_feature feature)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if ((feature & MAILBOX_FEATURE_CONDSTORE) != 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->enabled_features |= MAILBOX_FEATURE_CONDSTORE;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (mailbox_open(box) < 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek T_BEGIN {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_index_modseq_enable(box->index);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek } T_END;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekvoid index_storage_mailbox_close(struct mailbox *box)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek index_mailbox_check_remove_all(box);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (box->input != NULL)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek i_stream_unref(&box->input);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_index_view_close(&box->view);
877b92e80bde510d5cd9f03dbf01e2bcf73ab072Michal Židek mail_index_close(box->index);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek box->cache = NULL;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox->keyword_names = NULL;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek i_free_and_null(ibox->cache_fields);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (array_is_created(&ibox->recent_flags))
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_free(&ibox->recent_flags);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox->recent_flags_prev_uid = 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox->recent_flags_count = 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ibox->sync_last_check = 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekvoid index_storage_mailbox_free(struct mailbox *box)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_index_alloc_cache_unref(&box->index);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekvoid index_storage_mailbox_update_cache_fields(struct mailbox *box,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const struct mailbox_update *update)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *const *field_names = update->cache_fields;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ARRAY_DEFINE(new_fields, struct mail_cache_field);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const struct mail_cache_field *old_fields;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct mail_cache_field field;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina unsigned int i, j, old_count;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina old_fields = mail_cache_register_get_list(box->cache,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek pool_datastack_create(),
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek &old_count);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* There shouldn't be many fields, so don't worry about O(n^2). */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek t_array_init(&new_fields, 32);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek for (i = 0; field_names[i] != NULL; i++) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* see if it's an existing field */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek for (j = 0; j < old_count; j++) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (strcmp(field_names[i], old_fields[j].name) == 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek break;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (j != old_count) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek field = old_fields[j];
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (field.decision == MAIL_CACHE_DECISION_NO)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek field.decision = MAIL_CACHE_DECISION_TEMP;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_append(&new_fields, &field, 1);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek } else if (strncmp(field_names[i], "hdr.", 4) == 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* new header */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek memset(&field, 0, sizeof(field));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek field.name = field_names[i];
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek field.type = MAIL_CACHE_FIELD_HEADER;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek field.decision = MAIL_CACHE_DECISION_TEMP;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_append(&new_fields, &field, 1);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina } else {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* new unknown field. we can't do anything about
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina this since we don't know its type */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (array_count(&new_fields) > 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_cache_register_fields(box->cache,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_idx_modifiable(&new_fields, 0),
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_count(&new_fields));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekint index_storage_mailbox_update(struct mailbox *box,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const struct mailbox_update *update)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const struct mail_index_header *hdr;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct mail_index_view *view;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct mail_index_transaction *trans;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek int ret;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (mailbox_open(box) < 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (update->cache_fields != NULL)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek index_storage_mailbox_update_cache_fields(box, update);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* make sure we get the latest index info */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek (void)mail_index_refresh(box->index);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek view = mail_index_view_open(box->index);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek hdr = mail_index_get_header(view);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek trans = mail_index_transaction_begin(view,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (update->uid_validity != 0 &&
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek hdr->uid_validity != update->uid_validity) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek uint32_t uid_validity = update->uid_validity;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (hdr->uid_validity != 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* UIDVALIDITY change requires index to be reset */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_index_reset(trans);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_index_update_header(trans,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek offsetof(struct mail_index_header, uid_validity),
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek &uid_validity, sizeof(uid_validity), TRUE);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (update->min_next_uid != 0 &&
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek hdr->next_uid < update->min_next_uid) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina uint32_t next_uid = update->min_next_uid;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_update_header(trans,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina offsetof(struct mail_index_header, next_uid),
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina &next_uid, sizeof(next_uid), FALSE);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (update->min_highest_modseq != 0 &&
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_modseq_get_highest(view) < update->min_highest_modseq) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_update_highest_modseq(trans,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina update->min_highest_modseq);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if ((ret = mail_index_transaction_commit(&trans)) < 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_set_internal_error(box->storage);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_view_close(&view);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return ret;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaint index_storage_mailbox_delete_dir(struct mailbox *box, bool mailbox_deleted)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina uint8_t dir_sha128[MAIL_GUID_128_SIZE];
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina enum mail_error error;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mailbox_list_delete_dir(box->list, box->name) == 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina (void)mailbox_list_get_last_error(box->list, &error);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (error != MAIL_ERROR_NOTFOUND || !mailbox_deleted) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_copy_list_error(box->storage, box->list);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* failed directory deletion, but mailbox deletion succeeded.
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina this was probably maildir++, which internally deleted the
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina directory as well. add changelog record about that too. */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_name_get_sha128(box->name, dir_sha128);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_list_add_change(box->list, MAILBOX_LOG_RECORD_DELETE_DIR,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina dir_sha128);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaint index_storage_mailbox_delete(struct mailbox *box)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (!box->opened) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* \noselect mailbox, try deleting only the directory */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return index_storage_mailbox_delete_dir(box, FALSE);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mailbox_mark_index_deleted(box, TRUE) < 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mailbox_get_guid(box, mailbox_guid) < 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* Make sure the indexes are closed before trying to delete the
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina directory that contains them. It can still fail with some NFS
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina implementations if indexes are opened by another session, but
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina that can't really be helped. */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_close(box);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_alloc_cache_destroy_unrefed();
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (box->list->v.delete_mailbox(box->list, box->name) < 0) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_copy_list_error(box->storage, box->list);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_list_add_change(box->list, MAILBOX_LOG_RECORD_DELETE_MAILBOX,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_guid);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return index_storage_mailbox_delete_dir(box, TRUE);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaint index_storage_mailbox_rename(struct mailbox *src, struct mailbox *dest,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina bool rename_children)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina uint8_t guid[MAIL_GUID_128_SIZE];
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (src->list->v.rename_mailbox(src->list, src->name,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina dest->list, dest->name,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina rename_children) < 0) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_copy_list_error(src->storage, src->list);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* we'll track mailbox names, instead of GUIDs. We may be renaming a
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina non-selectable mailbox (directory), which doesn't even have a GUID */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_name_get_sha128(dest->name, guid);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mailbox_list_add_change(src->list, MAILBOX_LOG_RECORD_RENAME, guid);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinabool index_storage_is_readonly(struct mailbox *box)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if ((box->flags & MAILBOX_FLAG_READONLY) != 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return TRUE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (box->backend_readonly) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* return read-only only if there are no private flags
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina (that are stored in index files) */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (box->private_flags_mask == 0)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return TRUE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return FALSE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinabool index_storage_allow_new_keywords(struct mailbox *box)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* FIXME: return FALSE if we're full */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return !index_storage_is_readonly(box);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinabool index_storage_is_inconsistent(struct mailbox *box)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return mail_index_view_is_inconsistent(box->view);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinabool index_keyword_is_valid(struct mailbox *box, const char *keyword,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char **error_r)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina unsigned int i, idx;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* if it already exists, skip validity checks */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mail_index_keyword_lookup(box->index, keyword, &idx))
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return TRUE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (*keyword == '\0') {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *error_r = "Empty keywords not allowed";
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return FALSE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* these are IMAP-specific restrictions, but for now IMAP is all we
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina care about */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina for (i = 0; keyword[i] != '\0'; i++) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (IS_ATOM_SPECIAL((unsigned char)keyword[i])) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *error_r = "Invalid characters in keyword";
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return FALSE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if ((unsigned char)keyword[i] >= 0x80) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *error_r = "8bit characters in keyword";
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return FALSE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (i > box->storage->set->mail_max_keyword_length) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *error_r = "Keyword length too long";
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return FALSE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return TRUE;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic struct mail_keywords *
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaindex_keywords_create_skip(struct mailbox *box,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char *const keywords[])
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina ARRAY_DEFINE(valid_keywords, const char *);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char *error;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina t_array_init(&valid_keywords, 32);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina for (; *keywords != NULL; keywords++) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mailbox_keyword_is_valid(box, *keywords, &error))
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina array_append(&valid_keywords, keywords, 1);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina (void)array_append_space(&valid_keywords); /* NULL-terminate */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return mail_index_keywords_create(box->index, keywords);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaint index_keywords_create(struct mailbox *box, const char *const keywords[],
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct mail_keywords **keywords_r, bool skip_invalid)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char *error;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina unsigned int i;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina for (i = 0; keywords[i] != NULL; i++) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (mailbox_keyword_is_valid(box, keywords[i], &error))
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina continue;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (!skip_invalid) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_set_error(box->storage,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina MAIL_ERROR_PARAMS, error);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* found invalid keywords, do this the slow way */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina T_BEGIN {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *keywords_r = index_keywords_create_skip(box, keywords);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina } T_END;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *keywords_r = mail_index_keywords_create(box->index, keywords);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastruct mail_keywords *
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinaindex_keywords_create_from_indexes(struct mailbox *_box,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const ARRAY_TYPE(keyword_indexes) *idx)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return mail_index_keywords_create_from_indexes(_box->index, idx);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavoid index_keywords_ref(struct mail_keywords *keywords)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_keywords_ref(keywords);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavoid index_keywords_unref(struct mail_keywords *keywords)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_index_keywords_unref(&keywords);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavoid index_save_context_free(struct mail_save_context *ctx)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina i_free_and_null(ctx->from_envelope);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina i_free_and_null(ctx->guid);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina i_free_and_null(ctx->pop3_uidl);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina