Mercurial > dovecot > core-2.2
changeset 11652:ad122febbf26 HEAD
[m]dbox: If alt-dir exists for a mailbox while trying to create it, rebuild mailbox indexes.
This makes sure that if there are any mails in the alt-dir, they become
visible rather than be overwritten.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 28 Jun 2010 22:00:58 +0100 |
parents | 243166e7dd2d |
children | 8c52ebde02a6 |
files | src/lib-storage/index/dbox-common/dbox-storage.c src/lib-storage/index/dbox-common/dbox-storage.h src/lib-storage/index/dbox-multi/mdbox-storage.c src/lib-storage/index/dbox-single/sdbox-storage.c src/lib-storage/list/mailbox-list-fs.c |
diffstat | 5 files changed, 73 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/dbox-common/dbox-storage.c Mon Jun 28 21:58:42 2010 +0100 +++ b/src/lib-storage/index/dbox-common/dbox-storage.c Mon Jun 28 22:00:58 2010 +0100 @@ -10,6 +10,8 @@ #include "dbox-storage.h" #include <stdio.h> +#include <dirent.h> +#include <unistd.h> void dbox_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED, struct mailbox_list_settings *set) @@ -90,6 +92,36 @@ } } +static int dir_is_empty(struct mail_storage *storage, const char *path) +{ + DIR *dir; + struct dirent *d; + int ret = 1; + + dir = opendir(path); + if (dir == NULL) { + if (errno == ENOENT) { + /* race condition with DELETE/RENAME? */ + return 1; + } + mail_storage_set_critical(storage, "opendir(%s) failed: %m", + path); + return -1; + } + while ((d = readdir(dir)) != NULL) { + if (*d->d_name == '.') + continue; + + ret = 0; + } + if (closedir(dir) < 0) { + mail_storage_set_critical(storage, "closedir(%s) failed: %m", + path); + ret = -1; + } + return ret; +} + int dbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update, bool directory) { @@ -97,6 +129,8 @@ struct mail_index_sync_ctx *sync_ctx; struct mail_index_view *view; struct mail_index_transaction *trans; + const char *alt_path; + struct stat st; int ret; if (directory && @@ -106,6 +140,25 @@ if (index_storage_mailbox_open(box, FALSE) < 0) return -1; + /* if alt path already exists and contains files, rebuild storage so + that we don't start overwriting files. */ + alt_path = mailbox_list_get_path(box->list, box->name, + MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX); + if (alt_path != NULL && stat(alt_path, &st) == 0) { + ret = dir_is_empty(box->storage, alt_path); + if (ret < 0) + return -1; + if (ret == 0) { + mail_storage_set_critical(&storage->storage, + "Mailbox %s has existing files in alt path, " + "rebuilding storage to avoid losing messages", + box->vname); + storage->v.set_mailbox_corrupted(box); + return -1; + } + /* dir is empty, ignore it */ + } + /* use syncing as a lock */ ret = mail_index_sync_begin(box->index, &sync_ctx, &view, &trans, 0); if (ret <= 0) {
--- a/src/lib-storage/index/dbox-common/dbox-storage.h Mon Jun 28 21:58:42 2010 +0100 +++ b/src/lib-storage/index/dbox-common/dbox-storage.h Mon Jun 28 22:00:58 2010 +0100 @@ -39,6 +39,8 @@ int (*mailbox_create_indexes)(struct mailbox *box, const struct mailbox_update *update, struct mail_index_transaction *trans); + /* mark the mailbox corrupted */ + void (*set_mailbox_corrupted)(struct mailbox *box); /* mark the file corrupted */ void (*set_file_corrupted)(struct dbox_file *file); };
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c Mon Jun 28 21:58:42 2010 +0100 +++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c Mon Jun 28 22:00:58 2010 +0100 @@ -270,6 +270,13 @@ } } +static void mdbox_set_mailbox_corrupted(struct mailbox *box) +{ + struct mdbox_storage *mstorage = (struct mdbox_storage *)box->storage; + + mdbox_storage_set_corrupted(mstorage); +} + static void mdbox_set_file_corrupted(struct dbox_file *file) { struct mdbox_storage *mstorage = (struct mdbox_storage *)file->storage; @@ -426,5 +433,6 @@ mdbox_file_create_fd, mdbox_mail_open, mdbox_mailbox_create_indexes, + mdbox_set_mailbox_corrupted, mdbox_set_file_corrupted };
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c Mon Jun 28 21:58:42 2010 +0100 +++ b/src/lib-storage/index/dbox-single/sdbox-storage.c Mon Jun 28 22:00:58 2010 +0100 @@ -198,11 +198,18 @@ return ret; } -static void sdbox_set_file_corrupted(struct dbox_file *file ATTR_UNUSED) +static void sdbox_set_mailbox_corrupted(struct mailbox *box ATTR_UNUSED) { /* FIXME */ } +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_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE]) { @@ -309,5 +316,6 @@ sdbox_file_create_fd, sdbox_mail_open, sdbox_mailbox_create_indexes, + sdbox_set_mailbox_corrupted, sdbox_set_file_corrupted };
--- a/src/lib-storage/list/mailbox-list-fs.c Mon Jun 28 21:58:42 2010 +0100 +++ b/src/lib-storage/list/mailbox-list-fs.c Mon Jun 28 22:00:58 2010 +0100 @@ -316,27 +316,12 @@ fs_list_create_mailbox_dir(struct mailbox_list *list, const char *name, bool directory) { - const char *path, *alt_path, *gid_origin, *p; - struct stat st; + const char *path, *gid_origin, *p; mode_t mode; gid_t gid; bool create_parent_dir; int ret; - /* make sure the alt path doesn't exist yet. it shouldn't (except with - race conditions with RENAME/DELETE), but if something crashed and - left it lying around we don't want to start overwriting files in - it. */ - if (!directory) { - alt_path = mailbox_list_get_path(list, name, - MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX); - if (alt_path != NULL && stat(alt_path, &st) == 0) { - mailbox_list_set_error(list, MAIL_ERROR_EXISTS, - "Mailbox already exists"); - return -1; - } - } - path = mailbox_list_get_path(list, name, directory ? MAILBOX_LIST_PATH_TYPE_DIR : MAILBOX_LIST_PATH_TYPE_MAILBOX);