sdbox-storage.c revision 1127f3e1ad7135b6ee5d5e13f8fd1e72f85a76f8
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen/* Copyright (c) 2007-2013 Dovecot authors, see the included COPYING file */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "lib.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "fs-api.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "master-service.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "mail-index-modseq.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "mail-search-build.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "mailbox-list-private.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "dbox-mail.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "dbox-save.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "sdbox-file.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "sdbox-sync.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen#include "sdbox-storage.h"
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenextern struct mail_storage dbox_storage, sdbox_storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenextern struct mailbox sdbox_mailbox;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenextern struct dbox_storage_vfuncs sdbox_dbox_storage_vfuncs;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic struct mail_storage *sdbox_storage_alloc(void)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct sdbox_storage *storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen pool_t pool;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen pool = pool_alloconly_create("sdbox storage", 512+256);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen storage = p_new(pool, struct sdbox_storage, 1);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen storage->storage.v = sdbox_dbox_storage_vfuncs;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen storage->storage.storage = sdbox_storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen storage->storage.storage.pool = pool;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return &storage->storage.storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic int sdbox_storage_create(struct mail_storage *_storage,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct mail_namespace *ns,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const char **error_r)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct dbox_storage *storage = (struct dbox_storage *)_storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen enum fs_properties props;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (dbox_storage_create(_storage, ns, error_r) < 0)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return -1;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (storage->attachment_fs != NULL) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen props = fs_get_properties(storage->attachment_fs);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if ((props & FS_PROPERTY_RENAME) == 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen *error_r = "mail_attachment_fs: "
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen "Backend doesn't support renaming";
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return -1;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return 0;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic const char *
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainensdbox_storage_find_root_dir(const struct mail_namespace *ns)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen bool debug = ns->mail_set->mail_debug;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const char *home, *path;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (ns->owner != NULL &&
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_user_get_home(ns->owner, &home) > 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen path = t_strconcat(home, "/sdbox", NULL);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (access(path, R_OK|W_OK|X_OK) == 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (debug)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_debug("sdbox: root exists (%s)", path);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return path;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (debug)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_debug("sdbox: access(%s, rwx): failed: %m", path);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return NULL;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic bool sdbox_storage_autodetect(const struct mail_namespace *ns,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct mailbox_list_settings *set)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen bool debug = ns->mail_set->mail_debug;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct stat st;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const char *path, *root_dir;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (set->root_dir != NULL)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen root_dir = set->root_dir;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen else {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen root_dir = sdbox_storage_find_root_dir(ns);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (root_dir == NULL) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (debug)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_debug("sdbox: couldn't find root dir");
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return FALSE;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* NOTE: this check works for mdbox as well. we'll rely on the
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen autodetect ordering to catch mdbox before we get here. */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen path = t_strconcat(root_dir, "/"DBOX_MAILBOX_DIR_NAME, NULL);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (stat(path, &st) < 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (debug)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_debug("sdbox autodetect: stat(%s) failed: %m", path);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return FALSE;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (!S_ISDIR(st.st_mode)) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (debug)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_debug("sdbox autodetect: %s not a directory", path);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return FALSE;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen set->root_dir = root_dir;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen dbox_storage_get_list_settings(ns, set);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return TRUE;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic struct mailbox *
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainensdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const char *vname, enum mailbox_flags flags)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct sdbox_mailbox *mbox;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct index_mailbox_context *ibox;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen pool_t pool;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* dbox can't work without index files */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen pool = pool_alloconly_create("sdbox mailbox", 1024*3);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox = p_new(pool, struct sdbox_mailbox, 1);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->box = sdbox_mailbox;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->box.pool = pool;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->box.storage = storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->box.list = list;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->box.mail_vfuncs = &sdbox_mail_vfuncs;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS |
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->storage = (struct sdbox_storage *)storage;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return &mbox->box;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenint sdbox_read_header(struct sdbox_mailbox *mbox,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct sdbox_index_header *hdr, bool log_error,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen bool *need_resize_r)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct mail_index_view *view;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const void *data;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen size_t data_size;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen int ret = 0;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_assert(mbox->box.opened);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen view = mail_index_view_open(mbox->box.index);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_get_header_ext(view, mbox->hdr_ext_id,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen &data, &data_size);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE &&
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen (!mbox->box.creating || data_size != 0)) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (log_error) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_storage_set_critical(
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen &mbox->storage->storage.storage,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen "sdbox %s: Invalid dbox header size",
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mailbox_get_path(&mbox->box));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen ret = -1;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen } else {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen memset(hdr, 0, sizeof(*hdr));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (guid_128_is_empty(hdr->mailbox_guid))
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen ret = -1;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen else {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* data is valid. remember it in case mailbox
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen is being reset */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_set_ext_init_data(mbox->box.index,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mbox->hdr_ext_id,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen hdr, sizeof(*hdr));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_view_close(&view);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen *need_resize_r = data_size < sizeof(*hdr);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return ret;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic void sdbox_update_header(struct sdbox_mailbox *mbox,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct mail_index_transaction *trans,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const struct mailbox_update *update)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct sdbox_index_header hdr, new_hdr;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen bool need_resize;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen memset(&hdr, 0, sizeof(hdr));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen need_resize = TRUE;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen new_hdr = hdr;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (update != NULL && !guid_128_is_empty(update->mailbox_guid)) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen memcpy(new_hdr.mailbox_guid, update->mailbox_guid,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen sizeof(new_hdr.mailbox_guid));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen } else if (guid_128_is_empty(new_hdr.mailbox_guid)) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen guid_128_generate(new_hdr.mailbox_guid);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (need_resize) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_ext_resize_hdr(trans, mbox->hdr_ext_id,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen sizeof(new_hdr));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen &new_hdr, sizeof(new_hdr));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen memcpy(mbox->mailbox_guid, new_hdr.mailbox_guid,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen sizeof(mbox->mailbox_guid));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic int ATTR_NULL(2, 3)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainensdbox_mailbox_create_indexes(struct mailbox *box,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const struct mailbox_update *update,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct mail_index_transaction *trans)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct mail_index_transaction *new_trans = NULL;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen const struct mail_index_header *hdr;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen uint32_t uid_validity, uid_next;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (trans == NULL) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen new_trans = mail_index_transaction_begin(box->view, 0);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen trans = new_trans;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen hdr = mail_index_get_header(box->view);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (update != NULL && update->uid_validity != 0)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen uid_validity = update->uid_validity;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen else if (hdr->uid_validity != 0)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen uid_validity = hdr->uid_validity;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen else {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* set uidvalidity */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen uid_validity = dbox_get_uidvalidity_next(box->list);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (hdr->uid_validity != uid_validity) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_update_header(trans,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen offsetof(struct mail_index_header, uid_validity),
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen &uid_validity, sizeof(uid_validity), TRUE);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (update != NULL && hdr->next_uid < update->min_next_uid) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen uid_next = update->min_next_uid;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_update_header(trans,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen offsetof(struct mail_index_header, next_uid),
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen &uid_next, sizeof(uid_next), TRUE);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (update != NULL && update->min_first_recent_uid != 0 &&
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen hdr->first_recent_uid < update->min_first_recent_uid) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen uint32_t first_recent_uid = update->min_first_recent_uid;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_update_header(trans,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen offsetof(struct mail_index_header, first_recent_uid),
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen &first_recent_uid, sizeof(first_recent_uid), FALSE);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (update != NULL && update->min_highest_modseq != 0 &&
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_modseq_get_highest(box->view) <
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen update->min_highest_modseq) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_modseq_enable(box->index);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mail_index_update_highest_modseq(trans,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen update->min_highest_modseq);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen sdbox_update_header(mbox, trans, update);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (new_trans != NULL) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (mail_index_transaction_commit(&new_trans) < 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen mailbox_set_index_error(box);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return -1;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen }
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen return 0;
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen}
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic const char *
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainensdbox_get_attachment_path_suffix(struct dbox_file *_file)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen{
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen struct sdbox_file *file = (struct sdbox_file *)_file;
return t_strdup_printf("-%s-%u",
guid_128_to_string(file->mbox->mailbox_guid),
file->uid);
}
void sdbox_set_mailbox_corrupted(struct mailbox *box)
{
struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
struct sdbox_index_header hdr;
bool need_resize;
if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0 ||
hdr.rebuild_count == 0)
mbox->corrupted_rebuild_count = 1;
else
mbox->corrupted_rebuild_count = hdr.rebuild_count;
}
static void sdbox_set_file_corrupted(struct dbox_file *_file)
{
struct sdbox_file *file = (struct sdbox_file *)_file;
sdbox_set_mailbox_corrupted(&file->mbox->box);
}
static int sdbox_mailbox_alloc_index(struct sdbox_mailbox *mbox)
{
struct sdbox_index_header hdr;
if (index_storage_mailbox_alloc_index(&mbox->box) < 0)
return -1;
mbox->hdr_ext_id =
mail_index_ext_register(mbox->box.index, "dbox-hdr",
sizeof(struct sdbox_index_header), 0, 0);
/* set the initialization data in case the mailbox is created */
memset(&hdr, 0, sizeof(hdr));
guid_128_generate(hdr.mailbox_guid);
mail_index_set_ext_init_data(mbox->box.index, mbox->hdr_ext_id,
&hdr, sizeof(hdr));
return 0;
}
static int sdbox_mailbox_open(struct mailbox *box)
{
struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
struct sdbox_index_header hdr;
bool need_resize;
if (sdbox_mailbox_alloc_index(mbox) < 0)
return -1;
if (dbox_mailbox_open(box) < 0)
return -1;
if (box->creating) {
/* wait for mailbox creation to initialize the index */
return 0;
}
if (box->creating) {
/* wait for mailbox creation to initialize the index */
return 0;
}
/* get/generate mailbox guid */
if (sdbox_read_header(mbox, &hdr, FALSE, &need_resize) < 0) {
/* looks like the mailbox is corrupted */
(void)sdbox_sync(mbox, SDBOX_SYNC_FLAG_FORCE);
if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0)
memset(&hdr, 0, sizeof(hdr));
}
if (guid_128_is_empty(hdr.mailbox_guid)) {
/* regenerate it */
if (sdbox_mailbox_create_indexes(box, NULL, NULL) < 0 ||
sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0)
return -1;
}
memcpy(mbox->mailbox_guid, hdr.mailbox_guid,
sizeof(mbox->mailbox_guid));
return 0;
}
static void sdbox_mailbox_close(struct mailbox *box)
{
struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
if (mbox->corrupted_rebuild_count != 0)
(void)sdbox_sync(mbox, 0);
index_storage_mailbox_close(box);
}
static int
sdbox_mailbox_get_metadata(struct mailbox *box,
enum mailbox_metadata_items items,
struct mailbox_metadata *metadata_r)
{
struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
return -1;
if ((items & MAILBOX_METADATA_GUID) != 0) {
memcpy(metadata_r->guid, mbox->mailbox_guid,
sizeof(metadata_r->guid));
}
return 0;
}
static int
dbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
{
if (!box->opened) {
if (mailbox_open(box) < 0)
return -1;
}
if (sdbox_mailbox_create_indexes(box, update, NULL) < 0)
return -1;
return index_storage_mailbox_update_common(box, update);
}
struct mail_storage sdbox_storage = {
.name = SDBOX_STORAGE_NAME,
.class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG |
MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS |
MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS |
MAIL_STORAGE_CLASS_FLAG_BINARY_DATA,
.v = {
NULL,
sdbox_storage_alloc,
sdbox_storage_create,
dbox_storage_destroy,
NULL,
dbox_storage_get_list_settings,
sdbox_storage_autodetect,
sdbox_mailbox_alloc,
NULL
}
};
struct mail_storage dbox_storage = {
.name = "dbox", /* alias */
.class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG,
.v = {
NULL,
sdbox_storage_alloc,
sdbox_storage_create,
dbox_storage_destroy,
NULL,
dbox_storage_get_list_settings,
sdbox_storage_autodetect,
sdbox_mailbox_alloc,
NULL
}
};
struct mailbox sdbox_mailbox = {
.v = {
index_storage_is_readonly,
index_storage_mailbox_enable,
index_storage_mailbox_exists,
sdbox_mailbox_open,
sdbox_mailbox_close,
index_storage_mailbox_free,
dbox_mailbox_create,
dbox_mailbox_update,
index_storage_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
sdbox_mailbox_get_metadata,
index_storage_set_subscribed,
index_storage_attribute_set,
index_storage_attribute_get,
index_storage_attribute_iter_init,
index_storage_attribute_iter_next,
index_storage_attribute_iter_deinit,
index_storage_list_index_has_changed,
index_storage_list_index_update_sync,
sdbox_storage_sync_init,
index_mailbox_sync_next,
index_mailbox_sync_deinit,
NULL,
dbox_notify_changes,
index_transaction_begin,
index_transaction_commit,
index_transaction_rollback,
NULL,
dbox_mail_alloc,
index_storage_search_init,
index_storage_search_deinit,
index_storage_search_next_nonblock,
index_storage_search_next_update_seq,
sdbox_save_alloc,
sdbox_save_begin,
dbox_save_continue,
sdbox_save_finish,
sdbox_save_cancel,
sdbox_copy,
sdbox_transaction_save_commit_pre,
sdbox_transaction_save_commit_post,
sdbox_transaction_save_rollback,
index_storage_is_inconsistent
}
};
struct dbox_storage_vfuncs sdbox_dbox_storage_vfuncs = {
sdbox_file_free,
sdbox_file_create_fd,
sdbox_mail_open,
sdbox_mailbox_create_indexes,
sdbox_get_attachment_path_suffix,
sdbox_set_mailbox_corrupted,
sdbox_set_file_corrupted
};