mailbox_equals(cmd->client->mailbox, ns, name))
return cmd->client->mailbox;
- box = mailbox_open(ns->list, name, NULL, MAILBOX_OPEN_SAVEONLY |
- MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL) {
- client_send_list_error(cmd, ns->list);
+ box = mailbox_alloc(ns->list, name, NULL, MAILBOX_FLAG_SAVEONLY |
+ MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(box) < 0) {
+ client_send_storage_error(cmd, mailbox_get_storage(box));
+ mailbox_close(&box);
return NULL;
}
if (cmd->client->enabled_features != 0)
if (mailbox_sync(mailbox, 0, 0, NULL) < 0)
client_send_untagged_storage_error(client, storage);
- if (mailbox_close(&mailbox) < 0)
- client_send_untagged_storage_error(client, storage);
+ mailbox_close(&mailbox);
client_update_mailbox_flags(client, NULL);
client_send_tagline(cmd, "OK Close completed.");
if (mailbox_equals(client->mailbox, dest_ns, mailbox))
destbox = client->mailbox;
else {
- destbox = mailbox_open(dest_ns->list, mailbox, NULL,
- MAILBOX_OPEN_SAVEONLY |
- MAILBOX_OPEN_KEEP_RECENT);
- if (destbox == NULL) {
- client_send_list_error(cmd, dest_ns->list);
+ destbox = mailbox_alloc(dest_ns->list, mailbox, NULL,
+ MAILBOX_FLAG_SAVEONLY |
+ MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(destbox) < 0) {
+ client_send_storage_error(cmd,
+ mailbox_get_storage(destbox));
+ mailbox_close(&destbox);
return TRUE;
}
if (client->enabled_features != 0)
storage = mailbox_get_storage(mailbox);
client->mailbox = NULL;
- if (mailbox_close(&mailbox) < 0)
- client_send_untagged_storage_error(client, storage);
+ mailbox_close(&mailbox);
}
if ((client->workarounds & WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
{
struct client *client = ctx->cmd->client;
struct mailbox_status status;
- enum mailbox_open_flags open_flags = 0;
+ enum mailbox_flags flags = 0;
if (readonly)
- open_flags |= MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT;
- ctx->box = mailbox_open(ctx->ns->list, mailbox, NULL, open_flags);
- if (ctx->box == NULL) {
- client_send_list_error(ctx->cmd, ctx->ns->list);
+ flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT;
+ ctx->box = mailbox_alloc(ctx->ns->list, mailbox, NULL, flags);
+ if (mailbox_open(ctx->box) < 0) {
+ client_send_storage_error(ctx->cmd,
+ mailbox_get_storage(ctx->box));
+ mailbox_close(&ctx->box);
return -1;
}
client->mailbox_change_lock = cmd;
if (client->mailbox != NULL) {
- struct mail_storage *old_storage =
- mailbox_get_storage(client->mailbox);
-
client_search_updates_free(client);
box = client->mailbox;
client->mailbox = NULL;
- if (mailbox_close(&box) < 0)
- client_send_untagged_storage_error(client, old_storage);
+ mailbox_close(&box);
/* CLOSED response is required by QRESYNC */
client_send_line(client, "* OK [CLOSED]");
}
client->mailbox = NULL;
storage = mailbox_get_storage(mailbox);
- if (mailbox_close(&mailbox) < 0)
- client_send_untagged_storage_error(client, storage);
+ mailbox_close(&mailbox);
client_update_mailbox_flags(client, NULL);
client_send_tagline(cmd, "OK Unselect completed.");
}
/* open the mailbox */
- box = mailbox_open(ns->list, mailbox, NULL, MAILBOX_OPEN_FAST |
- MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL) {
- *error_r = mailbox_list_get_last_error(ns->list, &error);
- *error_r = imap_get_error_string(*error_r, error);
- return -1;
- }
+ box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_READONLY |
+ MAILBOX_FLAG_KEEP_RECENT);
if ((items & STATUS_HIGHESTMODSEQ) != 0)
client_enable(client, MAILBOX_FEATURE_CONDSTORE);
i_fatal("Couldn't create internal raw storage: %s", errstr);
if (path == NULL) {
input = create_raw_stream(&ctx, 0, &mtime);
- box = mailbox_open(raw_ns->list, "Dovecot Delivery Mail",
- input, MAILBOX_OPEN_NO_INDEX_FILES);
+ box = mailbox_alloc(raw_ns->list, "Dovecot Delivery Mail",
+ input, MAILBOX_FLAG_NO_INDEX_FILES);
i_stream_unref(&input);
} else {
mtime = (time_t)-1;
- box = mailbox_open(raw_ns->list, path, NULL,
- MAILBOX_OPEN_NO_INDEX_FILES);
+ box = mailbox_alloc(raw_ns->list, path, NULL,
+ MAILBOX_FLAG_NO_INDEX_FILES);
}
- if (box == NULL) {
+ if (mailbox_open(box) < 0) {
i_fatal("Can't open delivery mail as raw: %s",
- mailbox_list_get_last_error(raw_ns->list, &error));
+ mail_storage_get_last_error(box->storage, &error));
}
if (mailbox_sync(box, 0, 0, NULL) < 0) {
i_fatal("Can't sync delivery mail: %s",
struct mail_storage *storage;
struct mailbox *box;
enum mail_error error;
- enum mailbox_open_flags open_flags =
- MAILBOX_OPEN_KEEP_RECENT | MAILBOX_OPEN_SAVEONLY |
- MAILBOX_OPEN_POST_SESSION;
+ enum mailbox_flags flags =
+ MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_SAVEONLY |
+ MAILBOX_FLAG_POST_SESSION;
*error_r = NULL;
if (strcasecmp(name, "INBOX") == 0) {
/* deliveries to INBOX must always succeed,
regardless of ACLs */
- open_flags |= MAILBOX_OPEN_IGNORE_ACLS;
+ flags |= MAILBOX_FLAG_IGNORE_ACLS;
}
*ns_r = ns = mail_namespace_find(ctx->dest_user->namespaces, &name);
return NULL;
}
- box = mailbox_open(ns->list, name, NULL, open_flags);
- if (box != NULL)
+ box = mailbox_alloc(ns->list, name, NULL, flags);
+ if (mailbox_open(box) == 0)
return box;
- *error_r = mailbox_list_get_last_error(ns->list, &error);
+ storage = mailbox_get_storage(box);
+ *error_r = mail_storage_get_last_error(storage, &error);
+ mailbox_close(&box);
if (!ctx->set->lda_mailbox_autocreate || error != MAIL_ERROR_NOTFOUND)
return NULL;
/* try creating it. */
- storage = mail_namespace_get_default_storage(ns);
if (mail_storage_mailbox_create(storage, ns, name, FALSE) < 0) {
*error_r = mail_storage_get_last_error(storage, &error);
return NULL;
}
/* and try opening again */
- box = mailbox_open(ns->list, name, NULL, open_flags);
- if (box == NULL) {
- *error_r = mailbox_list_get_last_error(ns->list, &error);
- return NULL;
- }
-
- if (mailbox_sync(box, 0, 0, NULL) < 0) {
+ box = mailbox_alloc(ns->list, name, NULL, flags);
+ storage = mailbox_get_storage(box);
+ if (mailbox_open(box) < 0 ||
+ mailbox_sync(box, 0, 0, NULL) < 0) {
+ *error_r = mail_storage_get_last_error(storage, &error);
mailbox_close(&box);
- *error_r = mail_storage_get_last_error(mailbox_get_storage(box),
- &error);
return NULL;
}
return box;
set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
}
-static int create_cydir(struct mail_storage *storage, struct mail_namespace *ns,
+static int create_cydir(struct mail_storage *storage, struct mailbox_list *list,
const char *path)
{
mode_t mode;
gid_t gid;
- mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid);
+ mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 &&
errno != EEXIST) {
if (!mail_storage_set_error_from_errno(storage)) {
}
static struct mailbox *
-cydir_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, enum mailbox_open_flags flags)
+cydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
struct cydir_mailbox *mbox;
- struct mail_index *index;
- const char *path;
pool_t pool;
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- index = index_storage_alloc(list, name, flags, CYDIR_INDEX_PREFIX);
- mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
- MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+ /* cydir can't work without index files */
+ flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
pool = pool_alloconly_create("cydir mailbox", 1024+512);
mbox = p_new(pool, struct cydir_mailbox, 1);
mbox->ibox.box = cydir_mailbox;
mbox->ibox.box.pool = pool;
mbox->ibox.box.storage = storage;
+ mbox->ibox.box.list = list;
mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
- mbox->ibox.index = index;
- mbox->storage = (struct cydir_storage *)storage;
- mbox->path = p_strdup(pool, path);
+ index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+ CYDIR_INDEX_PREFIX);
+ mail_index_set_fsync_types(mbox->ibox.index,
+ MAIL_INDEX_SYNC_TYPE_APPEND |
+ MAIL_INDEX_SYNC_TYPE_EXPUNGE);
- index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
+ mbox->storage = (struct cydir_storage *)storage;
return &mbox->ibox.box;
}
-static struct mailbox *
-cydir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+static int cydir_mailbox_open(struct mailbox *box)
{
- const char *path;
struct stat st;
- if (input != NULL) {
- mailbox_list_set_critical(list,
+ if (box->input != NULL) {
+ mail_storage_set_critical(box->storage,
"cydir doesn't support streamed mailboxes");
- return NULL;
+ return -1;
}
- /* cydir can't work without index files */
- flags &= ~MAILBOX_OPEN_NO_INDEX_FILES;
-
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (stat(path, &st) == 0)
- return cydir_open(storage, list, name, flags);
- else if (errno == ENOENT) {
- if (strcmp(name, "INBOX") == 0) {
- /* INBOX always exists, create it */
- if (create_cydir(storage, list->ns, path) < 0) {
- mailbox_list_set_error_from_storage(list,
- storage);
- return NULL;
- }
- return cydir_open(storage, list, "INBOX", flags);
- }
- mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+ if (stat(box->path, &st) == 0) {
+ /* exists, open it */
+ } else if (errno == ENOENT && strcmp(box->name, "INBOX") == 0) {
+ /* INBOX always exists, create it */
+ if (create_cydir(box->storage, box->list, box->path) < 0)
+ return -1;
+ } else if (errno == ENOENT) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ return -1;
} else if (errno == EACCES) {
- mail_storage_set_critical(storage, "%s",
- mail_error_eacces_msg("stat", path));
+ mail_storage_set_critical(box->storage, "%s",
+ mail_error_eacces_msg("stat", box->path));
+ return -1;
} else {
- mail_storage_set_critical(storage, "stat(%s) failed: %m",
- path);
+ mail_storage_set_critical(box->storage, "stat(%s) failed: %m",
+ box->path);
+ return -1;
}
- return NULL;
+ return index_storage_mailbox_open(box);
}
static int
return -1;
}
- return create_cydir(storage, list->ns, path);
+ return create_cydir(storage, list, path);
}
static int
if (box->notify_callback == NULL)
index_mailbox_check_remove_all(&mbox->ibox);
else
- index_mailbox_check_add(&mbox->ibox, mbox->path);
+ index_mailbox_check_add(&mbox->ibox, mbox->ibox.box.path);
}
static int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
cydir_storage_add_list,
cydir_storage_get_list_settings,
NULL,
- cydir_mailbox_open,
+ cydir_mailbox_alloc,
cydir_mailbox_create,
NULL
}
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
+ cydir_mailbox_open,
index_storage_mailbox_close,
index_storage_get_status,
NULL,
struct cydir_mailbox {
struct index_mailbox ibox;
struct cydir_storage *storage;
-
- const char *path;
};
struct cydir_transaction_context {
struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
int ret = 0;
- if (!box->opened)
- index_storage_mailbox_open(&mbox->ibox);
+ if (!box->opened) {
+ if (mailbox_open(box) < 0)
+ ret = -1;
+ }
- if (index_mailbox_want_full_sync(&mbox->ibox, flags))
+ if (index_mailbox_want_full_sync(&mbox->ibox, flags) && ret == 0)
ret = cydir_sync(mbox);
return index_mailbox_sync_init(box, flags, ret < 0);
{
const char *dir;
- dir = file->single_mbox != NULL ? file->single_mbox->path :
+ dir = file->single_mbox != NULL ? file->single_mbox->ibox.box.path :
file->storage->storage_dir;
return t_strdup_printf("%s/%s", dir, file->fname);
}
} else {
file->fname = dbox_generate_tmp_filename();
}
- file->current_path = i_strdup_printf("%s/%s", mbox->path, file->fname);
+ file->current_path = i_strdup_printf("%s/%s", mbox->ibox.box.path,
+ file->fname);
return file;
}
if (file->single_mbox != NULL) {
new_fname = dbox_file_uid_get_fname(file->single_mbox,
id, &maildir);
- new_path = i_strdup_printf("%s/%s", file->single_mbox->path,
+ new_path = i_strdup_printf("%s/%s",
+ file->single_mbox->ibox.box.path,
new_fname);
} else {
new_fname = i_strdup_printf(DBOX_MAIL_FILE_MULTI_FORMAT, id);
&data, &data_size);
if (data_size != sizeof(*hdr)) {
mail_storage_set_critical(&mbox->storage->storage,
- "dbox %s: Invalid dbox header size", mbox->path);
+ "dbox %s: Invalid dbox header size",
+ mbox->ibox.box.path);
mbox->storage->sync_rebuild = TRUE;
return -1;
}
if (cur_map_uid_validity != mbox->map_uid_validity) {
mail_storage_set_critical(&mbox->storage->storage,
"dbox %s: map uidvalidity mismatch (%u vs %u)",
- mbox->path, mbox->map_uid_validity,
+ mbox->ibox.box.path, mbox->map_uid_validity,
cur_map_uid_validity);
mbox->storage->sync_rebuild = TRUE;
return -1;
dbox_map_append_free(&ctx->append_ctx);
if (!ctx->mbox->storage->storage.set->fsync_disable) {
- if (fdatasync_path(ctx->mbox->path) < 0) {
+ if (fdatasync_path(ctx->mbox->ibox.box.path) < 0) {
i_error("fdatasync_path(%s) failed: %m",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
}
}
dbox_transaction_save_rollback(ctx);
enum mail_error error;
int ret;
- box = dbox_mailbox_open(&ctx->storage->storage, ns->list, name, NULL,
- MAILBOX_OPEN_READONLY |
- MAILBOX_OPEN_KEEP_RECENT |
- MAILBOX_OPEN_IGNORE_ACLS);
- if (box == NULL) {
- mailbox_list_get_last_error(ns->list, &error);
+ box = dbox_mailbox_alloc(&ctx->storage->storage, ns->list, name, NULL,
+ MAILBOX_FLAG_READONLY |
+ MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_IGNORE_ACLS);
+ if (dbox_mailbox_open(box) < 0) {
+ (void)mail_storage_get_last_error(box->storage, &error);
+ mailbox_close(&box);
if (error == MAIL_ERROR_TEMP)
return -1;
/* non-temporary error, ignore */
if (ret <= 0) {
i_assert(ret != 0);
mail_storage_set_index_error(&mbox->ibox);
- (void)mailbox_close(&box);
+ mailbox_close(&box);
return -1;
}
ret = -1;
}
- (void)mailbox_close(&box);
+ mailbox_close(&box);
return ret < 0 ? -1 : 0;
}
{
if (mail_index_sync_commit(&msg->sync_ctx) < 0)
return -1;
- (void)mailbox_close(&msg->box);
+ mailbox_close(&msg->box);
memset(msg, 0, sizeof(*msg));
return 0;
}
strcmp(mailbox, ctx->prev_msg.box->name) == 0 ?
ctx->prev_msg.box : NULL;
while (box == NULL) {
- box = dbox_mailbox_open(storage, ctx->default_list,
- mailbox, NULL,
- MAILBOX_OPEN_READONLY |
- MAILBOX_OPEN_KEEP_RECENT |
- MAILBOX_OPEN_IGNORE_ACLS);
- if (box != NULL)
+ box = dbox_mailbox_alloc(storage, ctx->default_list,
+ mailbox, NULL,
+ MAILBOX_FLAG_READONLY |
+ MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_IGNORE_ACLS);
+ if (dbox_mailbox_open(box) == 0)
break;
- mail_storage_get_last_error(storage, &error);
+ (void)mail_storage_get_last_error(box->storage, &error);
+ mailbox_close(&box);
if (error == MAIL_ERROR_TEMP)
return -1;
if (ret <= 0) {
i_assert(ret != 0);
mail_storage_set_index_error(&mbox->ibox);
- (void)mailbox_close(&box);
+ mailbox_close(&box);
return -1;
}
ctx->prev_msg.box = box;
return NULL;
}
-static struct mailbox *
-dbox_open(struct dbox_storage *storage, struct mailbox_list *list,
- const char *name, enum mailbox_open_flags flags)
+struct mailbox *
+dbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
- struct mail_storage *_storage = &storage->storage;
struct dbox_mailbox *mbox;
- struct mailbox *box;
- struct mail_index *index;
- const char *path;
pool_t pool;
- int ret;
/* dbox can't work without index files */
- flags &= ~MAILBOX_OPEN_NO_INDEX_FILES;
-
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
- index = index_storage_alloc(list, name, flags, DBOX_INDEX_PREFIX);
- mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
- MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+ flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
pool = pool_alloconly_create("dbox mailbox", 1024+512);
mbox = p_new(pool, struct dbox_mailbox, 1);
mbox->ibox.box = dbox_mailbox;
mbox->ibox.box.pool = pool;
- mbox->ibox.box.storage = _storage;
+ mbox->ibox.box.storage = storage;
mbox->ibox.box.list = list;
mbox->ibox.mail_vfuncs = &dbox_mail_vfuncs;
- mbox->ibox.index = index;
mbox->ibox.keep_index_backups = TRUE;
mbox->ibox.index_never_in_memory = TRUE;
- mbox->path = p_strdup(pool, path);
- mbox->alt_path = p_strdup(pool, dbox_get_alt_path(list, path));
- mbox->storage = storage;
+ index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+ DBOX_INDEX_PREFIX);
+ mail_index_set_fsync_types(mbox->ibox.index,
+ MAIL_INDEX_SYNC_TYPE_APPEND |
+ MAIL_INDEX_SYNC_TYPE_EXPUNGE);
+
+ mbox->storage = (struct dbox_storage *)storage;
+ mbox->alt_path =
+ p_strdup(pool, dbox_get_alt_path(list, mbox->ibox.box.path));
mbox->dbox_ext_id =
- mail_index_ext_register(index, "dbox", 0,
+ mail_index_ext_register(mbox->ibox.index, "dbox", 0,
sizeof(struct dbox_mail_index_record),
sizeof(uint32_t));
mbox->dbox_hdr_ext_id =
- mail_index_ext_register(index, "dbox-hdr",
+ mail_index_ext_register(mbox->ibox.index, "dbox-hdr",
sizeof(struct dbox_index_header), 0, 0);
mbox->guid_ext_id =
- mail_index_ext_register(index, "guid", 0, DBOX_GUID_BIN_LEN, 1);
+ mail_index_ext_register(mbox->ibox.index, "guid",
+ 0, DBOX_GUID_BIN_LEN, 1);
- ret = index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
mbox->maildir_uidlist = maildir_uidlist_init_readonly(&mbox->ibox);
-
- box = &mbox->ibox.box;
- if (ret < 0)
- mailbox_close(&box);
- return box;
+ return &mbox->ibox.box;
}
uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list)
return mailbox_uidvalidity_next(path);
}
-static void dbox_write_index_header(struct mailbox *box)
+static int dbox_write_index_header(struct mailbox *box)
{
struct dbox_mailbox *mbox = (struct dbox_mailbox *)box;
struct mail_index_transaction *trans;
uint32_t uid_validity;
if (dbox_map_open(mbox->storage->map, TRUE) < 0)
- return;
+ return -1;
trans = mail_index_transaction_begin(mbox->ibox.view, 0);
offsetof(struct mail_index_header, uid_validity),
&uid_validity, sizeof(uid_validity), TRUE);
- (void)mail_index_transaction_commit(&trans);
+ return mail_index_transaction_commit(&trans);
}
-static int create_dbox(struct mail_storage *_storage, struct mailbox_list *list,
- const char *path, const char *name, bool directory)
+static int create_dbox(struct mailbox *box)
{
- struct dbox_storage *storage = (struct dbox_storage *)_storage;
- struct mailbox *box;
mode_t mode;
gid_t gid;
- mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
- if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) == 0) {
- if (!directory) {
- /* create indexes immediately with the dbox header */
- box = dbox_open(storage, list, name,
- MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL)
- return -1;
- dbox_write_index_header(box);
- mailbox_close(&box);
- return 0;
- }
+ mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid);
+ if (mkdir_parents_chown(box->path, mode, (uid_t)-1, gid) == 0) {
+ /* create indexes immediately with the dbox header */
+ if (index_storage_mailbox_open(box) < 0)
+ return -1;
+ if (dbox_write_index_header(box) < 0)
+ return -1;
} else if (errno != EEXIST) {
- if (!mail_storage_set_error_from_errno(_storage)) {
- mail_storage_set_critical(_storage,
- "mkdir(%s) failed: %m", path);
+ if (!mail_storage_set_error_from_errno(box->storage)) {
+ mail_storage_set_critical(box->storage,
+ "mkdir(%s) failed: %m", box->path);
}
return -1;
}
return TRUE;
}
-struct mailbox *
-dbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+int dbox_mailbox_open(struct mailbox *box)
{
- struct dbox_storage *storage = (struct dbox_storage *)_storage;
- const char *path;
-
- if (input != NULL) {
- mailbox_list_set_critical(list,
+ if (box->input != NULL) {
+ mail_storage_set_critical(box->storage,
"dbox doesn't support streamed mailboxes");
- return NULL;
+ return -1;
}
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (dbox_cleanup_if_exists(list, path)) {
- return dbox_open(storage, list, name, flags);
+ if (dbox_cleanup_if_exists(box->list, box->path)) {
+ return index_storage_mailbox_open(box);
} else if (errno == ENOENT) {
- if (strcmp(name, "INBOX") == 0 &&
- (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+ if (strcmp(box->name, "INBOX") == 0 &&
+ (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
/* INBOX always exists, create it */
- if (create_dbox(_storage, list, path, name, FALSE) < 0) {
- mailbox_list_set_error_from_storage(list,
- _storage);
- return NULL;
- }
- return dbox_open(storage, list, name, flags);
+ if (create_dbox(box) < 0)
+ return -1;
+ return box->opened ? 0 :
+ index_storage_mailbox_open(box);
}
- mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ return -1;
} else if (errno == EACCES) {
- mailbox_list_set_critical(list, "%s",
- mail_error_eacces_msg("stat", path));
+ mail_storage_set_critical(box->storage, "%s",
+ mail_error_eacces_msg("stat", box->path));
+ return -1;
} else {
- mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
+ mail_storage_set_critical(box->storage,
+ "stat(%s) failed: %m", box->path);
+ return -1;
}
- return NULL;
}
-static int dbox_storage_mailbox_close(struct mailbox *box)
+static void dbox_mailbox_close(struct mailbox *box)
{
struct dbox_mailbox *mbox = (struct dbox_mailbox *)box;
maildir_uidlist_deinit(&mbox->maildir_uidlist);
- return index_storage_mailbox_close(box);
+ index_storage_mailbox_close(box);
}
static int
const char *name, bool directory)
{
const char *path, *alt_path;
+ struct mailbox *box;
struct stat st;
+ int ret;
path = mailbox_list_get_path(list, name,
directory ? MAILBOX_LIST_PATH_TYPE_DIR :
return -1;
}
+ if (directory) {
+ mode_t mode;
+ gid_t gid;
+
+ mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
+ if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) == 0)
+ return 0;
+ else if (errno == EEXIST) {
+ mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
+ "Mailbox already exists");
+ } else if (!mail_storage_set_error_from_errno(storage)) {
+ mail_storage_set_critical(storage,
+ "mkdir(%s) failed: %m", path);
+ }
+ return -1;
+ }
+
/* 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. */
- alt_path = directory ? NULL : dbox_get_alt_path(list, path);
+ alt_path = dbox_get_alt_path(list, path);
if (alt_path != NULL && stat(alt_path, &st) == 0) {
mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
"Mailbox already exists");
return -1;
}
- return create_dbox(storage, list, path, name, directory);
+ box = dbox_mailbox_alloc(storage, list, name, NULL,
+ MAILBOX_FLAG_KEEP_RECENT);
+ ret = create_dbox(box);
+ mailbox_close(&box);
+ return ret;
}
static int
tmp_set = *list->mail_set;
tmp_set.mail_full_filesystem_access = TRUE;
list->mail_set = &tmp_set;
- box = dbox_open(storage, list, path, MAILBOX_OPEN_IGNORE_ACLS |
- MAILBOX_OPEN_KEEP_RECENT);
+ box = dbox_mailbox_alloc(&storage->storage, list, path, NULL,
+ MAILBOX_FLAG_IGNORE_ACLS |
+ MAILBOX_FLAG_KEEP_RECENT);
+ ret = mailbox_open(box);
list->mail_set = old_set;
- if (box == NULL)
+ if (ret < 0) {
+ mailbox_close(&box);
return -1;
+ }
mbox = (struct dbox_mailbox *)box;
/* get a list of all map_uids in this mailbox */
index_mailbox_check_remove_all(&mbox->ibox);
else {
path = t_strdup_printf("%s/"DBOX_INDEX_PREFIX".log",
- mbox->path);
+ mbox->ibox.box.path);
index_mailbox_check_add(&mbox->ibox, path);
}
}
dbox_storage_add_list,
dbox_storage_get_list_settings,
NULL,
- dbox_mailbox_open,
+ dbox_mailbox_alloc,
dbox_mailbox_create,
dbox_sync_purge
}
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
- dbox_storage_mailbox_close,
+ dbox_mailbox_open,
+ dbox_mailbox_close,
index_storage_get_status,
NULL,
NULL,
uint32_t dbox_ext_id, dbox_hdr_ext_id, guid_ext_id;
- const char *path, *alt_path;
+ const char *alt_path;
};
struct dbox_transaction_context {
void dbox_transaction_class_deinit(void);
struct mailbox *
-dbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags);
+dbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags);
+int dbox_mailbox_open(struct mailbox *box);
struct mail *
dbox_mail_alloc(struct mailbox_transaction_context *t,
uid = strtoul(fname, &p, 10);
if (*p != '\0' || uid == 0 || uid >= (uint32_t)-1) {
i_warning("dbox %s: Ignoring invalid filename %s",
- ctx->mbox->path, fname);
+ ctx->mbox->ibox.box.path, fname);
return 0;
}
ret = maildir_uidlist_sync_next(ctx->maildir_sync_ctx, fname, 0);
if (ret == 0) {
i_warning("%s: Ignoring duplicate maildir file: %s",
- ctx->mbox->path, fname);
+ ctx->mbox->ibox.box.path, fname);
}
return ret;
}
while (maildir_uidlist_iter_next(iter, &uid, &flags, &fname)) {
file = dbox_file_init_single(mbox, uid);
file->current_path =
- i_strdup_printf("%s/%s", ctx->mbox->path, fname);
+ i_strdup_printf("%s/%s", ctx->mbox->ibox.box.path,
+ fname);
ret = dbox_sync_add_file_index(ctx, file);
dbox_file_unref(&file);
int ret = 0;
dbox_sync_set_uidvalidity(ctx);
- if (dbox_sync_index_rebuild_dir(ctx, ctx->mbox->path, TRUE) < 0)
+ if (dbox_sync_index_rebuild_dir(ctx, ctx->mbox->ibox.box.path, TRUE) < 0)
ret = -1;
else if (ctx->mbox->alt_path != NULL) {
if (dbox_sync_index_rebuild_dir(ctx, ctx->mbox->alt_path,
data_size=4 is for backwards compatibility */
if (data_size != 0 && data_size != 4) {
i_warning("dbox %s: Invalid dbox header size",
- mbox->path);
+ mbox->ibox.box.path);
}
ret = -1;
} else {
if (mbox->storage->have_multi_msgs) {
mail_storage_set_critical(storage,
"dbox %s: Storage keeps breaking",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
ret = -1;
} else if (i >= DBOX_REBUILD_COUNT) {
mail_storage_set_critical(storage,
"dbox %s: Index keeps breaking",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
ret = -1;
} else {
/* do a full resync and try again. */
i_warning("dbox %s: Rebuilding index",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
ret = dbox_sync_index_rebuild(mbox);
}
}
int ret = 0;
if (!box->opened) {
- if (index_storage_mailbox_open(&mbox->ibox) < 0)
+ if (mailbox_open(box) < 0)
ret = -1;
}
#include "lib.h"
#include "array.h"
-#include "buffer.h"
+#include "istream.h"
#include "ioloop.h"
#include "imap-parser.h"
#include "mkdir-parents.h"
static const char *
get_index_dir(struct mailbox_list *list, const char *name,
- enum mailbox_open_flags flags, struct stat *st_r)
+ enum mailbox_flags flags, struct stat *st_r)
{
const char *index_dir;
- index_dir = (flags & MAILBOX_OPEN_NO_INDEX_FILES) != 0 ? "" :
+ index_dir = (flags & MAILBOX_FLAG_NO_INDEX_FILES) != 0 ? "" :
mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
if (*index_dir == '\0') {
/* disabled */
return index_dir;
}
-struct mail_index *
+static struct mail_index *
index_storage_alloc(struct mailbox_list *list, const char *name,
- enum mailbox_open_flags flags, const char *prefix)
+ enum mailbox_flags flags, const char *prefix)
{
struct index_list **indexp, *rec;
struct mail_index *index;
const char *index_dir, *mailbox_path;
int destroy_count;
+ // FIXME: failure handling when dirs don't exist yet?
mailbox_path = mailbox_list_get_path(list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
index_dir = get_index_dir(list, name, flags, &st);
ibox->last_notify_type = MAILBOX_LOCK_NOTIFY_NONE;
}
-int index_storage_mailbox_open(struct index_mailbox *ibox)
+int index_storage_mailbox_open(struct mailbox *box)
{
- struct mail_storage *storage = ibox->box.storage;
- enum file_lock_method lock_method = storage->set->parsed_lock_method;
+ struct index_mailbox *ibox = (struct index_mailbox *)box;
+ enum file_lock_method lock_method =
+ box->storage->set->parsed_lock_method;
enum mail_index_open_flags index_flags;
+ gid_t dir_gid;
int ret;
- i_assert(!ibox->box.opened);
+ i_assert(!box->opened);
- index_flags = mail_storage_settings_to_index_flags(storage->set);
+ if (box->file_create_mode == 0) {
+ mailbox_list_get_permissions(box->list, box->name,
+ &box->file_create_mode,
+ &box->file_create_gid);
+ mailbox_list_get_dir_permissions(box->list, box->name,
+ &box->dir_create_mode,
+ &dir_gid);
+ mail_index_set_permissions(ibox->index,
+ box->file_create_mode,
+ box->file_create_gid);
+ }
+
+ index_flags = mail_storage_settings_to_index_flags(box->storage->set);
if (!ibox->move_to_memory)
index_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
if (ibox->keep_index_backups)
MODULE_CONTEXT_SET_FULL(ibox->view, mail_storage_mail_index_module,
ibox, &ibox->view_module_ctx);
- ibox->box.opened = TRUE;
+ box->opened = TRUE;
index_thread_mailbox_index_opened(ibox);
if (hook_mailbox_index_opened != NULL)
- hook_mailbox_index_opened(&ibox->box);
+ hook_mailbox_index_opened(box);
return 0;
}
-int index_storage_mailbox_init(struct index_mailbox *ibox, const char *name,
- enum mailbox_open_flags flags,
- bool move_to_memory)
+void index_storage_mailbox_alloc(struct index_mailbox *ibox, const char *name,
+ struct istream *input,
+ enum mailbox_flags flags,
+ const char *index_prefix)
{
- struct mail_storage *storage = ibox->box.storage;
struct mailbox *box = &ibox->box;
- gid_t dir_gid;
+ const char *path;
- i_assert(name != NULL);
+ if (name != NULL)
+ box->name = p_strdup(box->pool, name);
+ else {
+ i_assert(input != NULL);
+ box->name = "(read-only input stream)";
+ }
- box->storage = storage;
- box->name = p_strdup(box->pool, name);
- box->open_flags = flags;
- if (box->file_create_mode == 0) {
- mailbox_list_get_permissions(box->list, name,
- &box->file_create_mode,
- &box->file_create_gid);
- mailbox_list_get_dir_permissions(box->list, name,
- &box->dir_create_mode,
- &dir_gid);
- mail_index_set_permissions(ibox->index, box->file_create_mode,
- box->file_create_gid);
+ if (input != NULL) {
+ flags |= MAILBOX_FLAG_READONLY;
+ box->input = input;
+ i_stream_ref(input);
}
+ box->flags = flags;
p_array_init(&box->search_results, box->pool, 16);
array_create(&box->module_contexts,
box->pool, sizeof(void *), 5);
- ibox->keep_recent = (flags & MAILBOX_OPEN_KEEP_RECENT) != 0;
- ibox->keep_locked = (flags & MAILBOX_OPEN_KEEP_LOCKED) != 0;
- ibox->move_to_memory = move_to_memory;
+ path = mailbox_list_get_path(box->list, name,
+ MAILBOX_LIST_PATH_TYPE_MAILBOX);
+ ibox->box.path = p_strdup(box->pool, path);
+
+ ibox->keep_recent = (flags & MAILBOX_FLAG_KEEP_RECENT) != 0;
+ ibox->keep_locked = (flags & MAILBOX_FLAG_KEEP_LOCKED) != 0;
ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
ibox->commit_log_file_seq = 0;
-
+ ibox->index = index_storage_alloc(box->list, name, flags, index_prefix);
ibox->md5hdr_ext_idx =
mail_index_ext_register(ibox->index, "header-md5", 0, 16, 1);
-
- if ((flags & MAILBOX_OPEN_FAST) == 0)
- return index_storage_mailbox_open(ibox);
- return 0;
}
int index_storage_mailbox_enable(struct mailbox *box,
if ((feature & MAILBOX_FEATURE_CONDSTORE) != 0) {
box->enabled_features |= MAILBOX_FEATURE_CONDSTORE;
if (!box->opened) {
- if (index_storage_mailbox_open(ibox) < 0)
+ if (mailbox_open(box) < 0)
return -1;
}
mail_index_modseq_enable(ibox->index);
return 0;
}
-int index_storage_mailbox_close(struct mailbox *box)
+void index_storage_mailbox_close(struct mailbox *box)
{
struct index_mailbox *ibox = (struct index_mailbox *) box;
mail_index_view_close(&ibox->view);
index_mailbox_check_remove_all(ibox);
+ if (ibox->box.input != NULL)
+ i_stream_unref(&ibox->box.input);
if (ibox->index != NULL)
index_storage_unref(ibox->index);
if (array_is_created(&ibox->recent_flags))
i_free(ibox->cache_fields);
pool_unref(&box->pool);
- return 0;
}
bool index_storage_is_readonly(struct mailbox *box)
{
struct index_mailbox *ibox = (struct index_mailbox *) box;
- return (ibox->box.open_flags & MAILBOX_OPEN_READONLY) != 0 ||
+ return (box->flags & MAILBOX_FLAG_READONLY) != 0 ||
ibox->backend_readonly;
}
unsigned int secs_left);
void index_storage_lock_notify_reset(struct index_mailbox *ibox);
-struct mail_index *
-index_storage_alloc(struct mailbox_list *list, const char *name,
- enum mailbox_open_flags flags, const char *prefix);
void index_storage_unref(struct mail_index *index);
void index_storage_destroy_unrefed(void);
void index_storage_destroy(struct mail_storage *storage ATTR_UNUSED);
-int index_storage_mailbox_init(struct index_mailbox *ibox, const char *name,
- enum mailbox_open_flags flags,
- bool move_to_memory);
-int index_storage_mailbox_open(struct index_mailbox *ibox);
+void index_storage_mailbox_alloc(struct index_mailbox *ibox, const char *name,
+ struct istream *input,
+ enum mailbox_flags flags,
+ const char *index_prefix);
+int index_storage_mailbox_open(struct mailbox *box);
int index_storage_mailbox_enable(struct mailbox *box,
enum mailbox_feature feature);
-int index_storage_mailbox_close(struct mailbox *box);
+void index_storage_mailbox_close(struct mailbox *box);
bool index_storage_is_readonly(struct mailbox *box);
bool index_storage_allow_new_keywords(struct mailbox *box);
thread_type, write_seqs);
}
-static int mail_thread_mailbox_close(struct mailbox *box)
+static void mail_thread_mailbox_close(struct mailbox *box)
{
struct mail_thread_mailbox *tbox = MAIL_THREAD_CONTEXT(box);
- int ret;
i_assert(tbox->ctx == NULL);
array_free(&tbox->cache->thread_nodes);
i_free(tbox->cache);
- ret = tbox->module_ctx.super.close(box);
+ tbox->module_ctx.super.close(box);
i_free(tbox);
- return ret;
}
void index_thread_mailbox_index_opened(struct index_mailbox *ibox)
/* keywords, hardlink to tmp/ with basename and later when we
have uidlist locked, move it to new/cur. */
str_printfa(do_ctx.dest_path, "%s/tmp/%s",
- dest_mbox->path, do_ctx.dest_fname);
+ dest_mbox->ibox.box.path, do_ctx.dest_fname);
do_ctx.base_end_pos = str_len(do_ctx.dest_path);
}
if (src_mbox != NULL) {
}
/* the control dir doesn't exist. create it unless the whole
mailbox was just deleted. */
- if (!maildir_set_deleted(mk->mbox))
+ if (!maildir_set_deleted(&mk->mbox->ibox.box))
return -1;
}
/* either nothing is cached, or only vsize is cached. */
mail->pop3_state = 1;
} else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
- (mail->ibox->box.open_flags &
- MAILBOX_OPEN_POP3_SESSION) == 0) {
+ (mail->ibox->box.flags & MAILBOX_FLAG_POP3_SESSION) == 0) {
/* if virtual size isn't cached permanently,
POP3 isn't being used */
mail->pop3_state = -1;
"new" : "cur";
mail_storage_set_critical(_mail->box->storage,
"Maildir filename has wrong W value: %s/%s/%s",
- mbox->path, subdir, fname);
+ mbox->ibox.box.path, subdir, fname);
} else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
ctx->files_tail = &ctx->files;
ctx->fd = -1;
- ctx->tmpdir = p_strconcat(pool, mbox->path, "/tmp", NULL);
- ctx->newdir = p_strconcat(pool, mbox->path, "/new", NULL);
- ctx->curdir = p_strconcat(pool, mbox->path, "/cur", NULL);
+ ctx->tmpdir = p_strconcat(pool, mbox->ibox.box.path, "/tmp", NULL);
+ ctx->newdir = p_strconcat(pool, mbox->ibox.box.path, "/new", NULL);
+ ctx->curdir = p_strconcat(pool, mbox->ibox.box.path, "/cur", NULL);
ctx->keywords_buffer = buffer_create_const_data(pool, NULL, 0);
array_create_from_buffer(&ctx->keywords_array, ctx->keywords_buffer,
MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE);
} else if (errno != 0) {
mail_storage_set_critical(storage,
- "write(%s) failed: %m", ctx->mbox->path);
+ "write(%s) failed: %m",
+ ctx->mbox->ibox.box.path);
}
/* remove from the linked list */
unsigned int i;
int ret;
- ret = maildir_check_tmp(storage, dir);
- if (ret > 0) {
- if (!verify) {
+ if (!verify) {
+ ret = maildir_check_tmp(storage, dir);
+ if (ret > 0) {
mail_storage_set_error(storage,
MAIL_ERROR_EXISTS, "Mailbox already exists");
return -1;
}
- return 1;
+ if (ret < 0)
+ return -1;
}
- if (ret < 0)
- return -1;
- /* doesn't exist, create */
for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
path = t_strconcat(dir, "/", maildir_subdirs[i], NULL);
if (mkdir_verify(storage, ns, path, mode, gid, verify) < 0)
}
static struct mailbox *
-maildir_open(struct mail_storage *storage, struct mail_namespace *ns,
- const char *name, enum mailbox_open_flags flags)
+maildir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
struct maildir_mailbox *mbox;
- struct mail_index *index;
- const char *path, *control_dir;
- struct stat st;
pool_t pool;
- path = mailbox_list_get_path(ns->list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- control_dir = mailbox_list_get_path(ns->list, name,
- MAILBOX_LIST_PATH_TYPE_CONTROL);
-
pool = pool_alloconly_create("maildir mailbox", 1024+512);
mbox = p_new(pool, struct maildir_mailbox, 1);
mbox->ibox.box = maildir_mailbox;
mbox->ibox.box.pool = pool;
mbox->ibox.box.storage = storage;
- mbox->ibox.box.list = ns->list;
+ mbox->ibox.box.list = list;
mbox->ibox.mail_vfuncs = &maildir_mail_vfuncs;
+ index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+ MAILDIR_INDEX_PREFIX);
+
mbox->storage = (struct maildir_storage *)storage;
- mbox->path = p_strdup(pool, path);
+ mbox->maildir_ext_id =
+ mail_index_ext_register(mbox->ibox.index, "maildir",
+ sizeof(mbox->maildir_hdr), 0, 0);
+ mbox->uidlist = maildir_uidlist_init(mbox);
+ mbox->keywords = maildir_keywords_init(mbox);
+ return &mbox->ibox.box;
+}
- index = index_storage_alloc(ns->list, name, flags,
- MAILDIR_INDEX_PREFIX);
- mbox->ibox.index = index;
+static int maildir_mailbox_open_existing(struct mailbox *box)
+{
+ struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
+ struct stat st;
/* for shared mailboxes get the create mode from the
permissions of dovecot-shared file. */
- if (stat(t_strconcat(path, "/dovecot-shared", NULL), &st) == 0) {
+ if (stat(t_strconcat(box->path, "/dovecot-shared", NULL), &st) == 0) {
if ((st.st_mode & S_ISGID) != 0 ||
(st.st_mode & 0060) == 0) {
/* Ignore GID */
st.st_gid = (gid_t)-1;
}
- mail_index_set_permissions(index, st.st_mode & 0666, st.st_gid);
+ mail_index_set_permissions(mbox->ibox.index,
+ st.st_mode & 0666, st.st_gid);
- mbox->ibox.box.file_create_mode = st.st_mode & 0666;
- mbox->ibox.box.dir_create_mode =
- get_dir_mode(st.st_mode & 0666);
- mbox->ibox.box.file_create_gid = st.st_gid;
- mbox->ibox.box.private_flags_mask = MAIL_SEEN;
+ box->file_create_mode = st.st_mode & 0666;
+ box->dir_create_mode = get_dir_mode(st.st_mode & 0666);
+ box->file_create_gid = st.st_gid;
+ box->private_flags_mask = MAIL_SEEN;
}
- mbox->maildir_ext_id =
- mail_index_ext_register(index, "maildir",
- sizeof(mbox->maildir_hdr), 0, 0);
-
- index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
- mbox->uidlist = maildir_uidlist_init(mbox);
- if ((flags & MAILBOX_OPEN_KEEP_LOCKED) != 0) {
- if (maildir_uidlist_lock(mbox->uidlist) <= 0) {
- struct mailbox *box = &mbox->ibox.box;
-
- mailbox_close(&box);
- mailbox_list_set_error_from_storage(ns->list, storage);
- return NULL;
- }
+ if ((box->flags & MAILBOX_FLAG_KEEP_LOCKED) != 0) {
+ if (maildir_uidlist_lock(mbox->uidlist) <= 0)
+ return -1;
mbox->keep_lock_to = timeout_add(MAILDIR_LOCK_TOUCH_SECS * 1000,
maildir_lock_touch_timeout,
mbox);
}
- if (access(t_strconcat(path, "/cur", NULL), W_OK) < 0 &&
+ if (access(t_strconcat(box->path, "/cur", NULL), W_OK) < 0 &&
errno == EACCES)
mbox->ibox.backend_readonly = TRUE;
-
- mbox->keywords = maildir_keywords_init(mbox);
- return &mbox->ibox.box;
+ return index_storage_mailbox_open(box);
}
-static struct mailbox *
-maildir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+static int maildir_mailbox_open(struct mailbox *box)
{
- const char *path;
struct stat st;
mode_t mode;
gid_t gid;
int ret;
+ bool inbox;
- if (input != NULL) {
- mailbox_list_set_critical(list,
+ if (box->input != NULL) {
+ mail_storage_set_critical(box->storage,
"Maildir doesn't support streamed mailboxes");
- return NULL;
+ return -1;
}
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (strcmp(name, "INBOX") == 0 &&
- (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
- /* INBOX always exists */
- mailbox_list_get_dir_permissions(list, NULL, &mode, &gid);
- if (create_maildir(storage, list->ns, path,
- mode, gid, TRUE) < 0) {
- mailbox_list_set_error_from_storage(list, storage);
- return NULL;
- }
- return maildir_open(storage, list->ns, "INBOX", flags);
- }
+ inbox = strcmp(box->name, "INBOX") == 0 &&
+ (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0;
/* begin by checking if tmp/ directory exists and if it should be
cleaned up. */
- ret = maildir_check_tmp(storage, path);
+ ret = maildir_check_tmp(box->storage, box->path);
if (ret > 0) {
/* exists */
- return maildir_open(storage, list->ns, name, flags);
- }
- if (ret < 0) {
- mailbox_list_set_error_from_storage(list, storage);
- return NULL;
+ return maildir_mailbox_open_existing(box);
}
+ if (ret < 0)
+ return -1;
/* tmp/ directory doesn't exist. does the maildir? */
- if (stat(path, &st) == 0) {
+ if (inbox || stat(box->path, &st) == 0) {
/* yes, we'll need to create the missing dirs */
- mailbox_list_get_dir_permissions(list, name, &mode, &gid);
- if (create_maildir(storage, list->ns, path,
- mode, gid, TRUE) < 0) {
- mailbox_list_set_error_from_storage(list, storage);
- return NULL;
- }
+ mailbox_list_get_dir_permissions(box->list, box->name,
+ &mode, &gid);
+ if (create_maildir(box->storage, box->list->ns, box->path,
+ mode, gid, TRUE) < 0)
+ return -1;
- return maildir_open(storage, list->ns, name, flags);
+ return maildir_mailbox_open_existing(box);
} else if (errno == ENOENT) {
- mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
- return NULL;
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ return -1;
} else {
- mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
- return NULL;
+ mail_storage_set_critical(box->storage,
+ "stat(%s) failed: %m", box->path);
+ return -1;
}
}
rename_children);
}
-static int maildir_storage_mailbox_close(struct mailbox *box)
+static void maildir_mailbox_close(struct mailbox *box)
{
struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
if (mbox->keywords != NULL)
maildir_keywords_deinit(&mbox->keywords);
maildir_uidlist_deinit(&mbox->uidlist);
- return index_storage_mailbox_close(box);
+ index_storage_mailbox_close(box);
}
static void maildir_notify_changes(struct mailbox *box)
index_mailbox_check_remove_all(&mbox->ibox);
else {
index_mailbox_check_add(&mbox->ibox,
- t_strconcat(mbox->path, "/new", NULL));
+ t_strconcat(mbox->ibox.box.path, "/new", NULL));
index_mailbox_check_add(&mbox->ibox,
- t_strconcat(mbox->path, "/cur", NULL));
+ t_strconcat(mbox->ibox.box.path, "/cur", NULL));
}
}
maildir_storage_add_list,
maildir_storage_get_list_settings,
maildir_storage_autodetect,
- maildir_mailbox_open,
+ maildir_mailbox_alloc,
maildir_mailbox_create,
NULL
}
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
- maildir_storage_mailbox_close,
+ maildir_mailbox_open,
+ maildir_mailbox_close,
index_storage_get_status,
maildir_list_index_has_changed,
maildir_list_index_update_sync,
struct maildir_storage *storage;
struct mail_index_view *flags_view;
- const char *path;
struct timeout *keep_lock_to;
/* maildir sync: */
maildir_file_do(mbox, seq, (maildir_file_do_func *)callback, context)
#endif
-bool maildir_set_deleted(struct maildir_mailbox *mbox);
+bool maildir_set_deleted(struct mailbox *box);
uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list);
void maildir_transaction_class_init(void);
maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
- "(old uid=%u, file=%s)", ctx->mbox->path, uid, filename);
+ "(old uid=%u, file=%s)", ctx->mbox->ibox.box.path,
+ uid, filename);
return 0;
}
first time, reset the index so we can add all messages as
new */
i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
- mbox->path, hdr->uid_validity, uid_validity);
+ mbox->ibox.box.path, hdr->uid_validity, uid_validity);
mail_index_reset(trans);
index_mailbox_reset_uidvalidity(&mbox->ibox);
maildir_uidlist_set_next_uid(mbox->uidlist, 1, TRUE);
if (mbox->ibox.box.v.sync_notify != NULL)
mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0);
- if (stat(t_strconcat(mbox->path, "/cur", NULL), &st) == 0) {
+ if (stat(t_strconcat(mbox->ibox.box.path, "/cur", NULL), &st) == 0) {
mbox->maildir_hdr.new_check_time =
I_MAX(st.st_mtime, time_before_sync);
mbox->maildir_hdr.cur_mtime = st.st_mtime;
ctx = t_new(struct maildir_sync_context, 1);
ctx->mbox = mbox;
- ctx->new_dir = t_strconcat(mbox->path, "/new", NULL);
- ctx->cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+ ctx->new_dir = t_strconcat(mbox->ibox.box.path, "/new", NULL);
+ ctx->cur_dir = t_strconcat(mbox->ibox.box.path, "/cur", NULL);
ctx->last_touch = ioloop_time;
ctx->last_notify = ioloop_time;
ctx->flags = flags;
}
new_fname = maildir_filename_generate();
- new_path = t_strconcat(ctx->mbox->path, "/new/", new_fname, NULL);
+ new_path = t_strconcat(ctx->mbox->ibox.box.path, "/new/",
+ new_fname, NULL);
if (rename(path2, new_path) == 0)
i_warning("Fixed a duplicate: %s -> %s", path2, new_fname);
static int
maildir_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st_r)
{
+ struct mailbox *box = &mbox->ibox.box;
int i;
for (i = 0;; i++) {
if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT)
break;
- if (!maildir_set_deleted(mbox))
+ if (!maildir_set_deleted(box))
return -1;
/* try again */
}
- mail_storage_set_critical(mbox->ibox.box.storage,
- "stat(%s) failed: %m", path);
+ mail_storage_set_critical(box->storage, "stat(%s) failed: %m", path);
return -1;
}
return -1;
}
- if (!maildir_set_deleted(ctx->mbox))
+ if (!maildir_set_deleted(&ctx->mbox->ibox.box))
return -1;
/* try again */
}
bool lost_files, force_resync;
int ret = 0;
- if (!box->opened)
- index_storage_mailbox_open(&mbox->ibox);
+ if (!box->opened) {
+ if (mailbox_open(box) < 0)
+ return index_mailbox_sync_init(box, flags, TRUE);
+ }
force_resync = (flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0;
if (index_mailbox_want_full_sync(&mbox->ibox, flags)) {
T_BEGIN {
const char *new_dir, *cur_dir;
- new_dir = t_strconcat(mbox->path, "/new", NULL);
- cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+ new_dir = t_strconcat(mbox->ibox.box.path, "/new", NULL);
+ cur_dir = t_strconcat(mbox->ibox.box.path, "/cur", NULL);
ret = maildir_sync_quick_check(mbox, FALSE, new_dir, cur_dir,
&new_changed, &cur_changed);
}
/* the control dir doesn't exist. create it unless the whole
mailbox was just deleted. */
- if (!maildir_set_deleted(uidlist->mbox))
+ if (!maildir_set_deleted(&uidlist->mbox->ibox.box))
return -1;
}
}
/* the control dir doesn't exist. create it unless the whole
mailbox was just deleted. */
- if (!maildir_set_deleted(uidlist->mbox))
+ if (!maildir_set_deleted(&uidlist->mbox->ibox.box))
return -1;
}
if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
/* probably in new/ dir */
- path = t_strconcat(mbox->path, "/new/", fname, NULL);
+ path = t_strconcat(mbox->ibox.box.path, "/new/", fname, NULL);
ret = callback(mbox, path, context);
if (ret != 0)
return ret;
}
- path = t_strconcat(mbox->path, "/cur/", fname, NULL);
+ path = t_strconcat(mbox->ibox.box.path, "/cur/", fname, NULL);
ret = callback(mbox, path, context);
return ret;
}
}
}
-static int maildir_create_subdirs(struct maildir_mailbox *mbox)
+static int maildir_create_subdirs(struct mailbox *box)
{
static const char *subdirs[] = { "cur", "new", "tmp" };
const char *dirs[N_ELEMENTS(subdirs) + 2];
- struct mailbox *box = &mbox->ibox.box;
struct stat st;
const char *path;
unsigned int i;
/* @UNSAFE: get a list of directories we want to create */
for (i = 0; i < N_ELEMENTS(subdirs); i++)
- dirs[i] = t_strconcat(mbox->path, "/", subdirs[i], NULL);
+ dirs[i] = t_strconcat(box->path, "/", subdirs[i], NULL);
dirs[i++] = mailbox_list_get_path(box->list, box->name,
MAILBOX_LIST_PATH_TYPE_CONTROL);
dirs[i++] = mailbox_list_get_path(box->list, box->name,
return i == N_ELEMENTS(dirs) ? 0 : -1;
}
-bool maildir_set_deleted(struct maildir_mailbox *mbox)
+bool maildir_set_deleted(struct mailbox *box)
{
- struct mailbox *box = &mbox->ibox.box;
struct stat st;
int ret;
- if (stat(mbox->path, &st) < 0) {
+ if (stat(box->path, &st) < 0) {
if (errno == ENOENT)
mailbox_set_deleted(box);
else {
mail_storage_set_critical(box->storage,
- "stat(%s) failed: %m", mbox->path);
+ "stat(%s) failed: %m", box->path);
}
return FALSE;
}
/* maildir itself exists. create all of its subdirectories in case
they got lost. */
T_BEGIN {
- ret = maildir_create_subdirs(mbox);
+ ret = maildir_create_subdirs(box);
} T_END;
return ret < 0 ? FALSE : TRUE;
}
return 0;
}
- fd = open(mbox->path, mbox->ibox.backend_readonly ? O_RDONLY : O_RDWR);
+ fd = open(mbox->ibox.box.path,
+ mbox->ibox.backend_readonly ? O_RDONLY : O_RDWR);
if (fd == -1 && errno == EACCES && !mbox->ibox.backend_readonly) {
mbox->ibox.backend_readonly = TRUE;
- fd = open(mbox->path, O_RDONLY);
+ fd = open(mbox->ibox.box.path, O_RDONLY);
}
if (fd == -1) {
}
mbox->mbox_stream = i_stream_create_raw_mbox(mbox->mbox_file_stream,
- mbox->path);
+ mbox->ibox.box.path);
if (mbox->mbox_lock_type != F_UNLCK)
istream_raw_mbox_set_locked(mbox->mbox_stream);
return 0;
if (st.st_atime >= st.st_mtime) {
buf.modtime = st.st_mtime;
buf.actime = buf.modtime - 1;
- if (utime(mbox->path, &buf) < 0) {
+ if (utime(mbox->ibox.box.path, &buf) < 0) {
mbox_set_syscall_error(mbox, "utimes()");
return;
}
if (data == NULL) {
mail_storage_set_critical(&mbox->storage->storage,
"Cached message offset lost for seq %u in mbox file %s",
- seq, mbox->path);
+ seq, mbox->ibox.box.path);
mbox->mbox_hdr.dirty_flag = TRUE;
mbox->mbox_broken_offsets = TRUE;
return 0;
mail_storage_set_critical(&mbox->storage->storage,
"Cached message offset %s is invalid for mbox file %s",
- dec2str(offset), mbox->path);
+ dec2str(offset), mbox->ibox.box.path);
mbox->mbox_hdr.dirty_flag = TRUE;
mbox->mbox_broken_offsets = TRUE;
return 0;
be sure that the file is latest, but mbox files get rarely
deleted and the flushing might cause errors (e.g. EBUSY for
trying to flush a /var/mail mountpoint) */
- if (nfs_safe_stat(mbox->path, &st) < 0) {
+ if (nfs_safe_stat(mbox->ibox.box.path, &st) < 0) {
if (errno == ENOENT)
mailbox_set_deleted(&mbox->ibox.box);
else
privileged group
- DoS other users by dotlocking their mailboxes infinitely
*/
- fname = strrchr(mbox->path, '/');
+ fname = strrchr(mbox->ibox.box.path, '/');
if (fname == NULL) {
/* already relative */
- fname = mbox->path;
+ fname = mbox->ibox.box.path;
} else {
- dir = t_strdup_until(mbox->path, fname);
+ dir = t_strdup_until(mbox->ibox.box.path, fname);
if (chdir(dir) < 0) {
mail_storage_set_critical(&mbox->storage->storage,
"chdir(%s) failed: %m", dir);
if (op == MBOX_DOTLOCK_OP_LOCK) {
if (access(fname, R_OK) < 0) {
mail_storage_set_critical(&mbox->storage->storage,
- "access(%s) failed: %m", mbox->path);
+ "access(%s) failed: %m", mbox->ibox.box.path);
return -1;
}
}
set.callback = dotlock_callback;
set.context = ctx;
- ret = file_dotlock_create(&set, mbox->path, 0, &mbox->mbox_dotlock);
+ ret = file_dotlock_create(&set, mbox->ibox.box.path, 0,
+ &mbox->mbox_dotlock);
if (ret >= 0) {
/* success / timeout */
} else if (errno == EACCES && restrict_access_have_priv_gid() &&
ret = mbox_dotlock_privileged_op(mbox, &set,
MBOX_DOTLOCK_OP_LOCK);
} else if (errno == EACCES)
- mbox_dotlock_log_eacces_error(mbox, mbox->path);
+ mbox_dotlock_log_eacces_error(mbox, mbox->ibox.box.path);
else
mbox_set_syscall_error(mbox, "file_dotlock_create()");
mail_storage_set_critical(&ctx->mbox->storage->storage,
"fcntl() failed with mbox file %s: "
"File is locked by another process (EACCES)",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
return -1;
}
int mbox_lock(struct mbox_mailbox *mbox, int lock_type,
unsigned int *lock_id_r)
{
+ const char *path = mbox->ibox.box.path;
+ int mbox_fd = mbox->mbox_fd;
bool fcntl_locked;
int ret;
if (mbox->storage->storage.set->mail_nfs_storage) {
if (fcntl_locked) {
- nfs_flush_attr_cache_fd_locked(mbox->path,
- mbox->mbox_fd);
- nfs_flush_read_cache_locked(mbox->path,
- mbox->mbox_fd);
+ nfs_flush_attr_cache_fd_locked(path, mbox_fd);
+ nfs_flush_read_cache_locked(path, mbox_fd);
} else {
- nfs_flush_attr_cache_unlocked(mbox->path);
- nfs_flush_read_cache_unlocked(mbox->path,
- mbox->mbox_fd);
+ nfs_flush_attr_cache_unlocked(path);
+ nfs_flush_read_cache_unlocked(path, mbox_fd);
}
}
if (ret == 0) {
mail_storage_set_critical(&mbox->storage->storage,
"Losing sync for mail uid=%u in mbox file %s",
- mail->mail.mail.uid, mbox->path);
+ mail->mail.mail.uid, mbox->ibox.box.path);
}
return 0;
}
if (ret < 0) {
i_warning("mbox %s: Can't find next message offset "
"for uid=%u",
- mbox->path, mail->mail.mail.uid);
+ mbox->ibox.box.path, mail->mail.mail.uid);
}
}
if (ret <= 0)
buf.modtime = st.st_mtime;
buf.actime = ctx->orig_atime;
- if (utime(mbox->path, &buf) < 0)
+ if (utime(mbox->ibox.box.path, &buf) < 0)
mbox_set_syscall_error(mbox, "utime()");
}
} else {
mail_storage_set_critical(&mbox->storage->storage,
"%s failed with mbox file %s: %m",
- function, mbox->path);
+ function, mbox->ibox.box.path);
}
return -1;
}
return TRUE;
}
+static bool want_memory_indexes(struct mbox_storage *storage, const char *path)
+{
+ struct stat st;
+
+ if (storage->set->mbox_min_index_size == 0)
+ return FALSE;
+
+ if (stat(path, &st) < 0) {
+ if (errno == ENOENT)
+ st.st_size = 0;
+ else {
+ mail_storage_set_critical(&storage->storage,
+ "stat(%s) failed: %m", path);
+ return FALSE;
+ }
+ }
+ return st.st_size / 1024 < storage->set->mbox_min_index_size;
+}
+
+static struct mailbox *
+mbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
+{
+ struct mbox_mailbox *mbox;
+ pool_t pool;
+
+ pool = pool_alloconly_create("mbox mailbox", 1024+512);
+ mbox = p_new(pool, struct mbox_mailbox, 1);
+ mbox->ibox.box = mbox_mailbox;
+ mbox->ibox.box.pool = pool;
+ mbox->ibox.box.storage = storage;
+ mbox->ibox.box.list = list;
+ mbox->ibox.mail_vfuncs = &mbox_mail_vfuncs;
+
+ index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+ MBOX_INDEX_PREFIX);
+
+ mbox->storage = (struct mbox_storage *)storage;
+ mbox->mbox_fd = -1;
+ mbox->mbox_lock_type = F_UNLCK;
+ mbox->mbox_ext_idx =
+ mail_index_ext_register(mbox->ibox.index, "mbox",
+ sizeof(mbox->mbox_hdr),
+ sizeof(uint64_t), sizeof(uint64_t));
+
+ if ((storage->flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0)
+ mbox->mbox_save_md5 = TRUE;
+ return &mbox->ibox.box;
+}
+
static int verify_inbox(struct mailbox_list *list)
{
const char *inbox_path, *rootdir;
return 0;
}
-static bool want_memory_indexes(struct mbox_storage *storage, const char *path)
-{
- struct stat st;
-
- if (storage->set->mbox_min_index_size == 0)
- return FALSE;
-
- if (stat(path, &st) < 0) {
- if (errno == ENOENT)
- st.st_size = 0;
- else {
- mail_storage_set_critical(&storage->storage,
- "stat(%s) failed: %m", path);
- return FALSE;
- }
- }
- return st.st_size / 1024 < storage->set->mbox_min_index_size;
-}
-
static void mbox_lock_touch_timeout(struct mbox_mailbox *mbox)
{
mbox_dotlock_touch(mbox);
}
-static struct mbox_mailbox *
-mbox_alloc_mailbox(struct mbox_storage *storage, struct mail_index *index,
- const char *name, const char *path,
- enum mailbox_open_flags flags)
+static int mbox_mailbox_open_existing(struct mbox_mailbox *mbox)
{
- struct mbox_mailbox *mbox;
- pool_t pool;
+ struct mailbox *box = &mbox->ibox.box;
+ const char *rootdir;
- pool = pool_alloconly_create("mbox mailbox", 1024+512);
- mbox = p_new(pool, struct mbox_mailbox, 1);
- mbox->ibox.box = mbox_mailbox;
- mbox->ibox.box.pool = pool;
- mbox->ibox.box.storage = &storage->storage;
- mbox->ibox.mail_vfuncs = &mbox_mail_vfuncs;
- mbox->ibox.index = index;
-
- mbox->storage = storage;
- mbox->path = p_strdup(mbox->ibox.box.pool, path);
- mbox->mbox_fd = -1;
- mbox->mbox_lock_type = F_UNLCK;
- mbox->mbox_ext_idx =
- mail_index_ext_register(index, "mbox",
- sizeof(mbox->mbox_hdr),
- sizeof(uint64_t), sizeof(uint64_t));
-
- if ((storage->storage.flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0)
- mbox->mbox_save_md5 = TRUE;
-
- index_storage_mailbox_init(&mbox->ibox, name, flags,
- want_memory_indexes(storage, path));
- return mbox;
-}
-
-static struct mailbox *
-mbox_open(struct mbox_storage *storage, struct mailbox_list *list,
- const char *name, enum mailbox_open_flags flags)
-{
- struct mbox_mailbox *mbox;
- struct mail_index *index;
- const char *path, *rootdir;
-
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
-
- index = index_storage_alloc(list, name, flags, MBOX_INDEX_PREFIX);
- mbox = mbox_alloc_mailbox(storage, index, name, path, flags);
-
- if (access(path, R_OK|W_OK) < 0) {
- if (errno < EACCES)
+ if (access(box->path, R_OK|W_OK) < 0) {
+ if (errno != EACCES) {
mbox_set_syscall_error(mbox, "access()");
- else
- mbox->ibox.backend_readonly = TRUE;
+ return -1;
+ }
+ mbox->ibox.backend_readonly = TRUE;
}
+ mbox->ibox.move_to_memory =
+ want_memory_indexes(mbox->storage, box->path);
- if (strcmp(name, "INBOX") == 0) {
+ if (strcmp(box->name, "INBOX") == 0) {
/* if INBOX isn't under the root directory, it's probably in
/var/mail and we want to allow privileged dotlocking */
- rootdir = mailbox_list_get_path(list, NULL,
+ rootdir = mailbox_list_get_path(box->list, NULL,
MAILBOX_LIST_PATH_TYPE_DIR);
- if (strncmp(path, rootdir, strlen(rootdir)) != 0)
+ if (strncmp(box->path, rootdir, strlen(rootdir)) != 0)
mbox->mbox_privileged_locking = TRUE;
}
- if ((flags & MAILBOX_OPEN_KEEP_LOCKED) != 0) {
- if (mbox_lock(mbox, F_WRLCK, &mbox->mbox_global_lock_id) <= 0) {
- struct mailbox *box = &mbox->ibox.box;
-
- mailbox_close(&box);
- mailbox_list_set_error_from_storage(list,
- &storage->storage);
- return NULL;
- }
+ if ((box->flags & MAILBOX_FLAG_KEEP_LOCKED) != 0) {
+ if (mbox_lock(mbox, F_WRLCK, &mbox->mbox_global_lock_id) <= 0)
+ return -1;
if (mbox->mbox_dotlock != NULL) {
mbox->keep_lock_to =
mbox_lock_touch_timeout, mbox);
}
}
- return &mbox->ibox.box;
-}
-
-static struct mailbox *
-mbox_mailbox_open_stream(struct mbox_storage *storage,
- struct mailbox_list *list, const char *name,
- struct istream *input, enum mailbox_open_flags flags)
-{
- struct mail_index *index;
- struct mbox_mailbox *mbox;
- const char *path;
-
- flags |= MAILBOX_OPEN_READONLY;
-
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- index = index_storage_alloc(list, name, flags, MBOX_INDEX_PREFIX);
- mbox = mbox_alloc_mailbox(storage, index, name, path, flags);
-
- i_stream_ref(input);
- mbox->mbox_file_stream = input;
- mbox->ibox.backend_readonly = TRUE;
- mbox->no_mbox_file = TRUE;
-
- mbox->path = "(read-only mbox stream)";
- return &mbox->ibox.box;
+ return index_storage_mailbox_open(box);
}
-static struct mailbox *
-mbox_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+static int mbox_mailbox_open(struct mailbox *box)
{
- struct mbox_storage *storage = (struct mbox_storage *)_storage;
- const char *path;
+ struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
struct stat st;
+ int ret;
- if (input != NULL) {
- return mbox_mailbox_open_stream(storage, list, name,
- input, flags);
+ if (box->input != NULL) {
+ mbox->mbox_file_stream = box->input;
+ mbox->ibox.backend_readonly = TRUE;
+ mbox->no_mbox_file = TRUE;
+ return 0;
}
- if (strcmp(name, "INBOX") == 0 &&
- (list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
+ if (strcmp(box->name, "INBOX") == 0 &&
+ (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
/* make sure INBOX exists */
- if (verify_inbox(list) < 0)
- return NULL;
- return mbox_open(storage, list, "INBOX", flags);
- }
-
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (stat(path, &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
- t_strdup_printf("Mailbox isn't selectable: %s",
- name));
- return NULL;
- }
-
- return mbox_open(storage, list, name, flags);
+ if (verify_inbox(box->list) < 0)
+ return -1;
+ return mbox_mailbox_open_existing(mbox);
}
- if (ENOTFOUND(errno)) {
- mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
- } else if (!mailbox_list_set_error_from_errno(list)) {
- mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
+ if ((ret = stat(box->path, &st)) == 0 && !S_ISDIR(st.st_mode))
+ return mbox_mailbox_open_existing(mbox);
+ else if (ret == 0) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+ t_strdup_printf("Mailbox isn't selectable: %s",
+ box->name));
+ return -1;
+ } else if (ENOTFOUND(errno)) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ return -1;
+ } else if (mail_storage_set_error_from_errno(box->storage)) {
+ return -1;
+ } else {
+ mail_storage_set_critical(box->storage,
+ "stat(%s) failed: %m", box->path);
+ return -1;
}
-
- return NULL;
}
static int
return -1;
}
-static int mbox_storage_mailbox_close(struct mailbox *box)
+static void mbox_mailbox_close(struct mailbox *box)
{
struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
const struct mail_index_header *hdr;
enum mbox_sync_flags sync_flags = 0;
- int ret = 0;
if (mbox->mbox_stream != NULL &&
istream_raw_mbox_is_corrupted(mbox->mbox_stream)) {
sync_flags |= MBOX_SYNC_REWRITE;
}
}
- if (sync_flags != 0 && !mbox->invalid_mbox_file) {
- if (mbox_sync(mbox, sync_flags) < 0)
- ret = -1;
- }
+ if (sync_flags != 0 && !mbox->invalid_mbox_file)
+ (void)mbox_sync(mbox, sync_flags);
if (mbox->mbox_global_lock_id != 0)
(void)mbox_unlock(mbox, mbox->mbox_global_lock_id);
if (mbox->mbox_file_stream != NULL)
i_stream_destroy(&mbox->mbox_file_stream);
- return index_storage_mailbox_close(box) < 0 ? -1 : ret;
+ index_storage_mailbox_close(box);
}
static void mbox_notify_changes(struct mailbox *box)
if (box->notify_callback == NULL)
index_mailbox_check_remove_all(&mbox->ibox);
else if (!mbox->no_mbox_file)
- index_mailbox_check_add(&mbox->ibox, mbox->path);
+ index_mailbox_check_add(&mbox->ibox, mbox->ibox.box.path);
}
static bool
mbox_storage_add_list,
mbox_storage_get_list_settings,
mbox_storage_autodetect,
- mbox_mailbox_open,
+ mbox_mailbox_alloc,
mbox_mailbox_create,
NULL
}
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
- mbox_storage_mailbox_close,
+ mbox_mailbox_open,
+ mbox_mailbox_close,
index_storage_get_status,
NULL,
NULL,
struct index_mailbox ibox;
struct mbox_storage *storage;
- const char *path;
-
int mbox_fd;
struct istream *mbox_stream, *mbox_file_stream;
int mbox_lock_type;
else if (ret >= 0) {
mbox_sync_set_critical(sync_ctx,
"mbox_move(%"PRIuUOFF_T", %"PRIuUOFF_T", %"PRIuUOFF_T
- ") moved only %"PRIuUOFF_T" bytes in mbox file %s",
- dest, source, size, (uoff_t)ret, sync_ctx->mbox->path);
+ ") moved only %"PRIuUOFF_T" bytes",
+ dest, source, size, (uoff_t)ret);
ret = -1;
} else if (ret < 0) {
errno = output->stream_errno;
mbox_sync_file_update_ext_modified(sync_ctx);
mbox_sync_set_critical(sync_ctx,
- "mbox %s: seq=%u uid=%u uid_broken=%d "
+ "seq=%u uid=%u uid_broken=%d "
"originally needed %"PRIuUOFF_T
" bytes, now needs %"PRIuSIZE_T" bytes",
- sync_ctx->mbox->path, seq, mails[idx].uid,
- mails[idx].uid_broken,
+ seq, mails[idx].uid, mails[idx].uid_broken,
(uoff_t)-mails[idx].space, need_space);
}
}
if (sync_ctx->ext_modified) {
mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
"mbox file %s was modified while we were syncing, "
- "check your locking settings", sync_ctx->mbox->path);
+ "check your locking settings",
+ sync_ctx->mbox->ibox.box.path);
}
va_start(va, fmt);
mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
- "%s", t_strdup_vprintf(fmt, va));
+ "Sync failed for mbox file %s: %s",
+ sync_ctx->mbox->ibox.box.path,
+ t_strdup_vprintf(fmt, va));
va_end(va);
}
{
if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
mbox_sync_set_critical(sync_ctx,
- "Unexpectedly lost From-line at offset %"PRIuUOFF_T
- " from mbox file %s", from_offset,
- sync_ctx->mbox->path);
+ "Unexpectedly lost From-line at offset %"PRIuUOFF_T,
+ from_offset);
return -1;
}
return 0;
if (rec == NULL && uid < sync_ctx->idx_next_uid) {
/* this UID was already in index and it was expunged */
mbox_sync_set_critical(sync_ctx,
- "mbox sync: Expunged message reappeared in mailbox %s "
+ "Expunged message reappeared to mailbox "
"(UID %u < %u, seq=%u, idx_msgs=%u)",
- sync_ctx->mbox->path, uid, sync_ctx->idx_next_uid,
+ uid, sync_ctx->idx_next_uid,
sync_ctx->seq, messages_count);
ret = FALSE; rec = NULL;
} else if (rec != NULL && rec->uid != uid) {
/* new UID in the middle of the mailbox - shouldn't happen */
mbox_sync_set_critical(sync_ctx,
- "mbox sync: UID inserted in the middle of mailbox %s "
- "(%u > %u, seq=%u, idx_msgs=%u)", sync_ctx->mbox->path,
+ "UID inserted in the middle of mailbox "
+ "(%u > %u, seq=%u, idx_msgs=%u)",
rec->uid, uid, sync_ctx->seq, messages_count);
ret = FALSE; rec = NULL;
} else {
}
if (ret == 0) {
mbox_sync_set_critical(sync_ctx,
- "X-IMAPbase uid-last unexpectedly points outside "
- "mbox file %s", sync_ctx->mbox->path);
+ "X-IMAPbase uid-last offset unexpectedly outside mbox");
return -1;
}
if (uid_last != sync_ctx->base_uid_last) {
mbox_sync_set_critical(sync_ctx,
- "X-IMAPbase uid-last unexpectedly lost in mbox file %s",
- sync_ctx->mbox->path);
+ "X-IMAPbase uid-last unexpectedly lost");
return -1;
}
if (ret < 0) {
if (deleted) {
mbox_sync_set_critical(sync_ctx,
- "Message was expunged unexpectedly "
- "in mbox file %s", mbox->path);
+ "Message was expunged unexpectedly");
}
return -1;
}
old_offset) < 0) {
mbox_sync_set_critical(sync_ctx,
"Error seeking back to original "
- "offset %s in mbox file %s",
- dec2str(old_offset), mbox->path);
+ "offset %s", dec2str(old_offset));
return -1;
}
return 0;
if (istream_raw_mbox_seek(sync_ctx->mbox->mbox_stream,
size) < 0) {
mbox_sync_set_critical(sync_ctx,
- "Error seeking to end of mbox file %s",
- sync_ctx->mbox->path);
+ "Error seeking to end of mbox");
return -1;
}
sync_ctx->idx_seq =
i_warning("UIDVALIDITY changed (%u -> %u) in mbox file %s",
sync_ctx->hdr->uid_validity,
sync_ctx->base_uid_validity,
- sync_ctx->mbox->path);
+ sync_ctx->mbox->ibox.box.path);
sync_ctx->index_reset = TRUE;
return TRUE;
}
return 0;
mbox_sync_set_critical(sync_ctx,
- "UIDs broken with partial sync in mbox file %s",
- sync_ctx->mbox->path);
+ "UIDs broken with partial sync");
sync_ctx->mbox->mbox_hdr.dirty_flag = TRUE;
return 0;
mail_storage_set_critical(
&sync_ctx->mbox->storage->storage,
"Out of UIDs, renumbering them in mbox "
- "file %s", sync_ctx->mbox->path);
+ "file %s",
+ sync_ctx->mbox->ibox.box.path);
sync_ctx->renumber_uids = TRUE;
return 0;
}
if (file_size < sync_ctx->file_input->v_offset) {
mbox_sync_set_critical(sync_ctx,
- "file size unexpectedly shrank in mbox file %s "
- "(%"PRIuUOFF_T" vs %"PRIuUOFF_T")",
- sync_ctx->mbox->path, file_size,
+ "file size unexpectedly shrank "
+ "(%"PRIuUOFF_T" vs %"PRIuUOFF_T")", file_size,
sync_ctx->file_input->v_offset);
return -1;
}
quite minimal (an extra logged error message). */
while (sync_ctx->orig_mtime == st->st_mtime) {
usleep(500000);
- if (utime(sync_ctx->mbox->path, NULL) < 0) {
+ if (utime(sync_ctx->mbox->ibox.box.path, NULL) < 0) {
mbox_set_syscall_error(sync_ctx->mbox,
"utime()");
return -1;
return -1;
}
} else {
- if (stat(mbox->path, &statbuf) < 0) {
+ if (stat(mbox->ibox.box.path, &statbuf) < 0) {
if (errno == ENOENT) {
mailbox_set_deleted(&mbox->ibox.box);
return 0;
else {
buf.modtime = st.st_mtime;
buf.actime = sync_ctx.orig_atime;
- if (utime(mbox->path, &buf) < 0)
+ if (utime(mbox->ibox.box.path, &buf) < 0)
mbox_set_syscall_error(mbox, "utime()");
}
}
enum mbox_sync_flags mbox_sync_flags = 0;
int ret = 0;
- if (!box->opened)
- index_storage_mailbox_open(&mbox->ibox);
+ if (!box->opened) {
+ if (mailbox_open(box) < 0)
+ ret = -1;
+ }
- if (index_mailbox_want_full_sync(&mbox->ibox, flags)) {
+ if (index_mailbox_want_full_sync(&mbox->ibox, flags) && ret == 0) {
if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
!mbox->storage->set->mbox_very_dirty_syncs)
mbox_sync_flags |= MBOX_SYNC_UNDIRTY;
return mail_set_aborted(mail);
p->stats_fstat_lookup_count++;
- st = i_stream_stat(mbox->input, TRUE);
+ st = i_stream_stat(mail->box->input, TRUE);
if (st == NULL) {
mail_storage_set_critical(mail->box->storage,
- "stat(%s) failed: %m", mbox->path);
+ "stat(%s) failed: %m", mail->box->path);
return -1;
}
struct message_size *body_size, struct istream **stream_r)
{
struct index_mail *mail = (struct index_mail *)_mail;
- struct raw_mailbox *mbox = (struct raw_mailbox *)_mail->box;
if (mail->data.stream == NULL) {
/* we can't just reference mbox->input, because
index_mail_close() expects to be able to free the stream */
mail->data.stream =
- i_stream_create_limit(mbox->input, (uoff_t)-1);
+ i_stream_create_limit(_mail->box->input, (uoff_t)-1);
}
return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
*value_r = mbox->envelope_sender;
return 0;
case MAIL_FETCH_UIDL_FILE_NAME:
- *value_r = mbox->have_filename ? mbox->path : "";
+ *value_r = mbox->have_filename ? _mail->box->path : "";
return 0;
default:
return index_mail_get_special(_mail, field, value_r);
#include "raw-sync.h"
#include "raw-storage.h"
-struct raw_mailbox_list {
- union mailbox_list_module_context module_ctx;
-};
-
extern struct mail_storage raw_storage;
extern struct mailbox raw_mailbox;
set->subscription_fname = RAW_SUBSCRIPTION_FILE_NAME;
}
-static int
-raw_mailbox_open_input(struct mailbox_list *list, const char *name,
- const char *path, struct istream **input_r)
-{
- int fd;
-
- fd = open(path, O_RDONLY);
- if (fd == -1) {
- if (ENOTFOUND(errno)) {
- mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
- } else if (!mailbox_list_set_error_from_errno(list)) {
- mailbox_list_set_critical(list, "open(%s) failed: %m",
- path);
- }
- return -1;
- }
- *input_r = i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
- return 0;
-}
-
static struct mailbox *
-raw_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+raw_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
struct raw_mailbox *mbox;
- const char *path;
pool_t pool;
- bool stream = input != NULL;
-
- flags |= MAILBOX_OPEN_READONLY | MAILBOX_OPEN_NO_INDEX_FILES;
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (input != NULL)
- i_stream_ref(input);
- else {
- if (raw_mailbox_open_input(list, name, path, &input) < 0)
- return NULL;
- }
+ flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_NO_INDEX_FILES;
pool = pool_alloconly_create("raw mailbox", 1024+512);
mbox = p_new(pool, struct raw_mailbox, 1);
mbox->ibox.box = raw_mailbox;
mbox->ibox.box.pool = pool;
mbox->ibox.box.storage = storage;
+ mbox->ibox.box.list = list;
mbox->ibox.mail_vfuncs = &raw_mail_vfuncs;
- mbox->ibox.index = index_storage_alloc(list, name, flags, NULL);
+
+ index_storage_mailbox_alloc(&mbox->ibox, name, input, flags, NULL);
mbox->storage = (struct raw_storage *)storage;
- mbox->path = p_strdup(pool, path);
- mbox->input = input;
- if (stream)
+ if (input != NULL)
mbox->mtime = mbox->ctime = ioloop_time;
else {
mbox->mtime = mbox->ctime = (time_t)-1;
mbox->have_filename = TRUE;
}
mbox->size = (uoff_t)-1;
-
- index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
return &mbox->ibox.box;
}
-static int raw_mailbox_close(struct mailbox *box)
+static int raw_mailbox_open(struct mailbox *box)
{
- struct raw_mailbox *mbox = (struct raw_mailbox *)box;
+ int fd;
+
+ if (box->input != NULL)
+ return index_storage_mailbox_open(box);
- i_stream_unref(&mbox->input);
- return index_storage_mailbox_close(box);
+ fd = open(box->path, O_RDONLY);
+ if (fd == -1) {
+ if (ENOTFOUND(errno)) {
+ mail_storage_set_error(box->storage,
+ MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ } else if (!mail_storage_set_error_from_errno(box->storage)) {
+ mail_storage_set_critical(box->storage,
+ "open(%s) failed: %m", box->path);
+ }
+ return -1;
+ }
+ box->input = i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
+ return index_storage_mailbox_open(box);
}
static int
raw_storage_add_list,
raw_storage_get_list_settings,
NULL,
- raw_mailbox_open,
+ raw_mailbox_alloc,
raw_mailbox_create,
NULL
}
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
- raw_mailbox_close,
+ raw_mailbox_open,
+ index_storage_mailbox_close,
index_storage_get_status,
NULL,
NULL,
struct index_mailbox ibox;
struct raw_storage *storage;
- const char *path;
- struct istream *input;
-
time_t mtime, ctime;
uoff_t size;
const char *envelope_sender;
struct raw_mailbox *mbox = (struct raw_mailbox *)box;
int ret = 0;
- if (!box->opened)
- index_storage_mailbox_open(&mbox->ibox);
+ if (!box->opened) {
+ if (mailbox_open(box) < 0)
+ ret = -1;
+ }
- if (!mbox->synced)
+ if (!mbox->synced && ret == 0)
ret = raw_sync(mbox);
return index_mailbox_sync_init(box, flags, ret < 0);
static MODULE_CONTEXT_DEFINE_INIT(index_list_storage_module,
&mail_storage_module_register);
-static int index_list_box_close(struct mailbox *box)
+static void index_list_box_close(struct mailbox *box)
{
struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
- return ibox->module_ctx.super.close(box);
+ ibox->module_ctx.super.close(box);
}
static int index_list_update_mail_index(struct index_mailbox_list *ilist,
return 0;
}
-static void index_list_mail_mailbox_opened(struct mailbox *box)
+static void index_list_mail_mailbox_allocated(struct mailbox *box)
{
struct index_mailbox_list *ilist =
INDEX_LIST_CONTEXT(box->list);
void index_mailbox_list_sync_init(void)
{
- index_list_next_hook_mailbox_created = hook_mailbox_opened;
- hook_mailbox_opened = index_list_mail_mailbox_opened;
+ index_list_next_hook_mailbox_created = hook_mailbox_allocated;
+ hook_mailbox_allocated = index_list_mail_mailbox_allocated;
}
/* Called after mail storage has been created */
extern void (*hook_mail_storage_created)(struct mail_storage *storage);
-/* Called after mailbox has been opened */
-extern void (*hook_mailbox_opened)(struct mailbox *box);
+/* Called after mailbox has been allocated */
+extern void (*hook_mailbox_allocated)(struct mailbox *box);
/* Called after mailbox index has been opened */
extern void (*hook_mailbox_index_opened)(struct mailbox *box);
bool (*autodetect)(const struct mail_namespace *ns,
struct mailbox_list_settings *set);
- struct mailbox *(*mailbox_open)(struct mail_storage *storage,
- struct mailbox_list *list,
- const char *name,
- struct istream *input,
- enum mailbox_open_flags flags);
+ struct mailbox *(*mailbox_alloc)(struct mail_storage *storage,
+ struct mailbox_list *list,
+ const char *name,
+ struct istream *input,
+ enum mailbox_flags flags);
int (*mailbox_create)(struct mail_storage *storage,
struct mailbox_list *list, const char *name,
bool (*allow_new_keywords)(struct mailbox *box);
int (*enable)(struct mailbox *box, enum mailbox_feature features);
- int (*close)(struct mailbox *box);
+ int (*open)(struct mailbox *box);
+ void (*close)(struct mailbox *box);
void (*get_status)(struct mailbox *box, enum mailbox_status_items items,
struct mailbox_status *status_r);
};
struct mailbox {
- char *name;
+ const char *name;
struct mail_storage *storage;
struct mailbox_list *list;
/* private: */
pool_t pool;
- enum mailbox_open_flags open_flags;
+ /* mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX */
+ const char *path;
+ struct istream *input;
+ enum mailbox_flags flags;
unsigned int transaction_count;
enum mailbox_feature enabled_features;
MODULE_CONTEXT_INIT(&mail_index_module_register);
void (*hook_mail_storage_created)(struct mail_storage *storage);
-void (*hook_mailbox_opened)(struct mailbox *box) = NULL;
+void (*hook_mailbox_allocated)(struct mailbox *box) = NULL;
void (*hook_mailbox_index_opened)(struct mailbox *box) = NULL;
ARRAY_TYPE(mail_storage) mail_storage_classes;
return TRUE;
}
-struct mailbox *mailbox_open(struct mailbox_list *list, const char *name,
- struct istream *input,
- enum mailbox_open_flags flags)
+struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
+ struct istream *input,
+ enum mailbox_flags flags)
{
struct mailbox_list *new_list = list;
struct mail_storage *storage;
struct mailbox *box;
- if (mailbox_list_get_storage(&new_list, &name, &storage) < 0)
- return NULL;
+ if (mailbox_list_get_storage(&new_list, &name, &storage) < 0) {
+ /* just use the first storage. FIXME: does this break? */
+ storage = list->ns->storage;
+ }
+
+ T_BEGIN {
+ box = storage->v.mailbox_alloc(storage, new_list,
+ name, input, flags);
+ if (hook_mailbox_allocated != NULL)
+ hook_mailbox_allocated(box);
+ } T_END;
+ return box;
+}
- mailbox_list_clear_error(list);
+int mailbox_open(struct mailbox *box)
+{
+ int ret;
- if (!mailbox_list_is_valid_existing_name(new_list, name)) {
- mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
+ mail_storage_clear_error(box->storage);
+
+ if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
"Invalid mailbox name");
- return NULL;
+ return -1;
}
T_BEGIN {
- box = storage->v.mailbox_open(storage, new_list,
- name, input, flags);
- if (hook_mailbox_opened != NULL && box != NULL)
- hook_mailbox_opened(box);
+ ret = box->v.open(box);
} T_END;
- if (box != NULL)
- box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
- else if (new_list != list) {
- const char *str;
- enum mail_error error;
+ if (ret < 0)
+ return -1;
- str = mailbox_list_get_last_error(new_list, &error);
- mailbox_list_set_error(list, error, str);
- }
- return box;
+ box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
+ return 0;
}
int mailbox_enable(struct mailbox *box, enum mailbox_feature features)
return box->enabled_features;
}
-int mailbox_close(struct mailbox **_box)
+void mailbox_close(struct mailbox **_box)
{
struct mailbox *box = *_box;
}
*_box = NULL;
- return box->v.close(box);
+ box->v.close(box);
}
struct mail_storage *mailbox_get_storage(const struct mailbox *box)
MAIL_STORAGE_FLAG_NO_AUTOCREATE = 0x04
};
-enum mailbox_open_flags {
+enum mailbox_flags {
/* Mailbox must not be modified even if asked */
- MAILBOX_OPEN_READONLY = 0x01,
+ MAILBOX_FLAG_READONLY = 0x01,
/* Only saving/copying mails to mailbox works. */
- MAILBOX_OPEN_SAVEONLY = 0x02,
- /* Delay opening index files (and possibly other files) until mailbox
- is being synchronized. */
- MAILBOX_OPEN_FAST = 0x04,
+ MAILBOX_FLAG_SAVEONLY = 0x02,
/* Don't reset MAIL_RECENT flags when syncing */
- MAILBOX_OPEN_KEEP_RECENT = 0x08,
+ MAILBOX_FLAG_KEEP_RECENT = 0x08,
/* Don't create index files for the mailbox */
- MAILBOX_OPEN_NO_INDEX_FILES = 0x10,
+ MAILBOX_FLAG_NO_INDEX_FILES = 0x10,
/* Keep mailbox exclusively locked all the time while it's open */
- MAILBOX_OPEN_KEEP_LOCKED = 0x20,
+ MAILBOX_FLAG_KEEP_LOCKED = 0x20,
/* Enable if mailbox is used for serving POP3. This allows making
better caching decisions. */
- MAILBOX_OPEN_POP3_SESSION = 0x40,
+ MAILBOX_FLAG_POP3_SESSION = 0x40,
/* Enable if mailbox is used for saving a mail delivery using MDA.
This causes ACL plugin to use POST right rather than INSERT. */
- MAILBOX_OPEN_POST_SESSION = 0x80,
+ MAILBOX_FLAG_POST_SESSION = 0x80,
/* Force opening mailbox and ignoring any ACLs */
- MAILBOX_OPEN_IGNORE_ACLS = 0x100
+ MAILBOX_FLAG_IGNORE_ACLS = 0x100
};
enum mailbox_feature {
/* Returns TRUE if mailboxes are files. */
bool mail_storage_is_mailbox_file(struct mail_storage *storage) ATTR_PURE;
-/* Open a mailbox. If input stream is given, mailbox is opened read-only
- using it as a backend. If storage doesn't support stream backends and its
- tried to be used, NULL is returned.
+/* Initialize mailbox without actually opening any files or verifying that
+ it exists. If input stream is given, mailbox is opened read-only
+ using it as a backend.
Note that append and copy may open the selected mailbox again
with possibly different readonly-state. */
-struct mailbox *mailbox_open(struct mailbox_list *list, const char *name,
- struct istream *input,
- enum mailbox_open_flags flags);
-/* Close the box. Returns -1 if some cleanup errors occurred, but
- the mailbox was closed anyway. */
-int mailbox_close(struct mailbox **box);
+struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
+ struct istream *input,
+ enum mailbox_flags flags);
+/* Open the mailbox. If this function isn't called explicitly, it's also called
+ internally by lib-storage when necessary. */
+int mailbox_open(struct mailbox *box);
+/* Close the box. */
+void mailbox_close(struct mailbox **box);
/* Enable the given feature for the mailbox. */
int mailbox_enable(struct mailbox *box, enum mailbox_feature features);
ATTR_FORMAT(2, 3);
void mailbox_list_set_internal_error(struct mailbox_list *list);
bool mailbox_list_set_error_from_errno(struct mailbox_list *list);
-void mailbox_list_set_error_from_storage(struct mailbox_list *list,
- struct mail_storage *storage);
#endif
i_info("Namespace %s: Permission lookup failed from %s",
list->ns->prefix, path);
}
+ if (name != NULL) {
+ /* return defaults */
+ mailbox_list_get_permissions_full(list, NULL,
+ file_mode_r,
+ dir_mode_r, gid_r);
+ return;
+ }
/* return safe defaults */
*file_mode_r = 0600;
*dir_mode_r = 0700;
mailbox_list_set_error(list, error, error_string);
return TRUE;
}
-
-void mailbox_list_set_error_from_storage(struct mailbox_list *list,
- struct mail_storage *storage)
-{
- const char *str;
- enum mail_error error;
-
- str = mail_storage_get_last_error(storage, &error);
- mailbox_list_set_error(list, error, str);
-}
NULL,
test_storage_get_list_settings,
NULL,
- test_mailbox_open,
+ test_mailbox_alloc,
test_mailbox_create,
NULL
}
struct mail_storage *test_mail_storage_create(void);
struct mailbox *
-test_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags);
+test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags);
struct mail *
test_mailbox_mail_alloc(struct mailbox_transaction_context *t,
return 0;
}
-static int test_mailbox_close(struct mailbox *box ATTR_UNUSED)
+static int test_mailbox_open(struct mailbox *box ATTR_UNUSED)
{
return 0;
}
+static void test_mailbox_close(struct mailbox *box ATTR_UNUSED)
+{
+}
+
static void test_mailbox_get_status(struct mailbox *box ATTR_UNUSED,
enum mailbox_status_items items ATTR_UNUSED,
struct mailbox_status *status_r)
test_mailbox_is_readonly,
test_mailbox_allow_new_keywords,
test_mailbox_enable,
+ test_mailbox_open,
test_mailbox_close,
test_mailbox_get_status,
NULL,
};
struct mailbox *
-test_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input ATTR_UNUSED,
- enum mailbox_open_flags flags)
+test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input ATTR_UNUSED,
+ enum mailbox_flags flags)
{
struct mailbox *box;
pool_t pool;
box->list = list;
box->pool = pool;
- box->open_flags = flags;
+ box->flags = flags;
p_array_init(&box->search_results, pool, 16);
p_array_init(&box->module_contexts, pool, 5);
client->state.mail_data->used);
}
client->state.raw_box = box =
- mailbox_open(raw_list, "Dovecot Delivery Mail", input,
- MAILBOX_OPEN_NO_INDEX_FILES);
+ mailbox_alloc(raw_list, "Dovecot Delivery Mail", input,
+ MAILBOX_FLAG_NO_INDEX_FILES);
i_stream_unref(&input);
- if (box == NULL) {
+ if (mailbox_open(box) < 0 ||
+ mailbox_sync(box, 0, 0, NULL) < 0) {
i_error("Can't open delivery mail as raw: %s",
- mailbox_list_get_last_error(raw_list, &error));
- client_rcpt_fail_all(client);
- return -1;
- }
- if (mailbox_sync(box, 0, 0, NULL) < 0) {
- i_error("Can't sync delivery mail: %s",
- mailbox_list_get_last_error(raw_list, &error));
+ mail_storage_get_last_error(box->storage, &error));
+ mailbox_close(&box);
client_rcpt_fail_all(client);
return -1;
}
if (abox->module_ctx.super.is_readonly(box))
return TRUE;
- save_right = (box->open_flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
+ save_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
if (acl_mailbox_right_lookup(box, save_right) > 0)
return FALSE;
return acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_WRITE) > 0;
}
-static int acl_mailbox_close(struct mailbox *box)
+static void acl_mailbox_close(struct mailbox *box)
{
struct acl_mailbox *abox = ACL_CONTEXT(box);
acl_object_deinit(&abox->aclobj);
- return abox->module_ctx.super.close(box);
+ abox->module_ctx.super.close(box);
}
static int
struct acl_mailbox *abox = ACL_CONTEXT(box);
enum acl_storage_rights save_right;
- save_right = (box->open_flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
+ save_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
if (acl_mailbox_right_lookup(box, save_right) <= 0)
return -1;
struct acl_mailbox *abox = ACL_CONTEXT(t->box);
enum acl_storage_rights save_right;
- save_right = (t->box->open_flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
+ save_right = (t->box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
if (acl_mailbox_right_lookup(t->box, save_right) <= 0)
return -1;
keywords_r, skip_invalid);
}
-struct mailbox *acl_mailbox_open_box(struct mailbox *box)
+static int acl_mailbox_open_check_acl(struct mailbox *box)
{
+ struct acl_mailbox *abox = ACL_CONTEXT(box);
struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
+ const unsigned int *idx_arr = alist->rights.acl_storage_right_idx;
+ enum acl_storage_rights open_right;
+ int ret;
+
+ /* mailbox can be opened either for reading or appending new messages */
+ if ((box->flags & MAILBOX_FLAG_IGNORE_ACLS) != 0 ||
+ (box->list->ns->flags & NAMESPACE_FLAG_NOACL) != 0)
+ return 0;
+
+ if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0) {
+ open_right = (box->flags & MAILBOX_FLAG_POST_SESSION) != 0 ?
+ ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
+ } else {
+ open_right = ACL_STORAGE_RIGHT_READ;
+ }
+
+ ret = acl_object_have_right(abox->aclobj, idx_arr[open_right]);
+ if (ret > 0)
+ return 0;
+ if (ret < 0)
+ return -1;
+
+ /* no access. */
+ ret = acl_object_have_right(abox->aclobj,
+ idx_arr[ACL_STORAGE_RIGHT_LOOKUP]);
+ if (ret < 0)
+ return -1;
+ if (ret > 0) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
+ MAIL_ERRSTR_NO_PERMISSION);
+ } else {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ }
+ return -1;
+}
+
+static int acl_mailbox_open(struct mailbox *box)
+{
+ struct acl_mailbox *abox = ACL_CONTEXT(box);
+
+ if (acl_mailbox_open_check_acl(box) < 0)
+ return -1;
+
+ return abox->module_ctx.super.open(box);
+}
+
+struct mailbox *
+acl_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
+{
+ union mail_storage_module_context *astorage = ACL_CONTEXT(storage);
+ struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
struct acl_mailbox *abox;
+ struct mailbox *box;
+
+ box = astorage->super.mailbox_alloc(storage, list, name, input, flags);
abox = p_new(box->pool, struct acl_mailbox, 1);
abox->module_ctx.super = box->v;
abox->aclobj = acl_object_init_from_name(alist->rights.backend,
mailbox_get_name(box));
- if ((box->open_flags & MAILBOX_OPEN_IGNORE_ACLS) == 0) {
+ if ((box->flags & MAILBOX_FLAG_IGNORE_ACLS) == 0) {
box->v.is_readonly = acl_is_readonly;
box->v.allow_new_keywords = acl_allow_new_keywords;
+ box->v.open = acl_mailbox_open;
box->v.close = acl_mailbox_close;
box->v.mail_alloc = acl_mail_alloc;
box->v.save_begin = acl_save_begin;
void acl_mailbox_list_created(struct mailbox_list *list);
void acl_mail_user_created(struct mail_user *list);
-struct mailbox *acl_mailbox_open_box(struct mailbox *box);
+struct mailbox *
+acl_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags);
struct acl_backend *acl_mailbox_list_get_backend(struct mailbox_list *list);
int acl_mailbox_list_have_right(struct mailbox_list *list, const char *name,
struct acl_user_module acl_user_module =
MODULE_CONTEXT_INIT(&mail_user_module_register);
-static struct mailbox *
-acl_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
-{
- union mail_storage_module_context *astorage = ACL_CONTEXT(storage);
- struct mailbox *box;
- enum acl_storage_rights save_right;
- bool can_see;
- int ret;
-
- /* mailbox can be opened either for reading or appending new messages */
- if ((flags & MAILBOX_OPEN_IGNORE_ACLS) != 0 ||
- (list->ns->flags & NAMESPACE_FLAG_NOACL) != 0) {
- ret = 1;
- } else if ((flags & MAILBOX_OPEN_SAVEONLY) == 0) {
- ret = acl_mailbox_list_have_right(list, name, FALSE,
- ACL_STORAGE_RIGHT_READ,
- &can_see);
- } else {
- save_right = (flags & MAILBOX_OPEN_POST_SESSION) != 0 ?
- ACL_STORAGE_RIGHT_POST : ACL_STORAGE_RIGHT_INSERT;
- ret = acl_mailbox_list_have_right(list, name, FALSE,
- save_right, &can_see);
- }
- if (ret <= 0) {
- if (ret < 0)
- return NULL;
- if (can_see) {
- mailbox_list_set_error(list, MAIL_ERROR_PERM,
- MAIL_ERRSTR_NO_PERMISSION);
- } else {
- mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
- }
- return NULL;
- }
-
- box = astorage->super.mailbox_open(storage, list, name, input, flags);
- if (box == NULL)
- return NULL;
-
- return acl_mailbox_open_box(box);
-}
-
static int
acl_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
const char *name, bool directory)
astorage = p_new(storage->pool,
union mail_storage_module_context, 1);
astorage->super = storage->v;
- storage->v.mailbox_open = acl_mailbox_open;
+ storage->v.mailbox_alloc = acl_mailbox_alloc;
storage->v.mailbox_create = acl_mailbox_create;
MODULE_CONTEXT_SET_SELF(storage, acl_storage_module, astorage);
return mail_storage_get_last_error(storage, &error);
}
-static const char *list_error(struct mailbox_list *list)
-{
- enum mail_error error;
-
- return mailbox_list_get_last_error(list, &error);
-}
-
static int mailbox_copy_mails(struct mailbox *srcbox, struct mailbox *destbox,
struct dotlock *dotlock, const char **error_r)
{
/* First open the source mailbox. If we can't open it, don't create
the destination mailbox either. */
- srcbox = mailbox_open(source_ns->list, name, NULL,
- MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
- if (srcbox == NULL) {
+ srcbox = mailbox_alloc(source_ns->list, name, NULL,
+ MAILBOX_FLAG_READONLY |
+ MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(srcbox) < 0) {
if (set->skip_broken_mailboxes)
return 0;
i_error("Mailbox conversion: "
"Couldn't open source mailbox %s: %s",
- name, list_error(source_ns->list));
+ name, storage_error(mailbox_get_storage(srcbox)));
+ mailbox_close(&srcbox);
return -1;
}
}
}
- destbox = mailbox_open(dest_ns->list, dest_name, NULL,
- MAILBOX_OPEN_KEEP_RECENT);
- if (destbox == NULL) {
+ destbox = mailbox_alloc(dest_ns->list, dest_name, NULL,
+ MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(destbox) < 0) {
i_error("Mailbox conversion: Couldn't open dest mailbox %s: %s",
- dest_name, list_error(dest_ns->list));
+ dest_name, storage_error(mailbox_get_storage(destbox)));
mailbox_close(&srcbox);
+ mailbox_close(&destbox);
return -1;
}
const char *expire_plugin_version = PACKAGE_VERSION;
-static void (*next_hook_mail_storage_created)(struct mail_storage *storage);
+static void (*next_hook_mailbox_allocated)(struct mailbox *box);
static void (*next_hook_mail_user_created)(struct mail_user *user);
static MODULE_CONTEXT_DEFINE_INIT(expire_storage_module,
MODULE_CONTEXT_SET(box, expire_storage_module, xpr_box);
}
-static struct mailbox *
-expire_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+static void expire_mailbox_allocated(struct mailbox *box)
{
- struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->user);
- union mail_storage_module_context *xpr_storage =
- EXPIRE_CONTEXT(storage);
- struct mailbox *box;
+ struct expire_mail_user *euser =
+ EXPIRE_USER_CONTEXT(box->storage->user);
+ struct mail_namespace *ns = mailbox_list_get_namespace(box->list);
string_t *vname;
unsigned int secs;
bool altmove;
- box = xpr_storage->super.mailbox_open(storage, list, name, input, flags);
- if (box != NULL) {
+ if (euser != NULL) {
vname = t_str_new(128);
- (void)mail_namespace_get_vname(mailbox_list_get_namespace(list),
- vname, name);
+ (void)mail_namespace_get_vname(ns, vname, box->name);
secs = expire_box_find_min_secs(euser->env, str_c(vname),
&altmove);
if (secs != 0)
mailbox_expire_hook(box, secs, altmove);
}
- return box;
-}
-
-static void expire_mail_storage_created(struct mail_storage *storage)
-{
- struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->user);
- union mail_storage_module_context *xpr_storage;
-
- if (euser != NULL) {
- xpr_storage = p_new(storage->pool,
- union mail_storage_module_context, 1);
- xpr_storage->super = storage->v;
- storage->v.mailbox_open = expire_mailbox_open;
-
- MODULE_CONTEXT_SET_SELF(storage, expire_storage_module,
- xpr_storage);
- }
- if (next_hook_mail_storage_created != NULL)
- next_hook_mail_storage_created(storage);
+ if (next_hook_mailbox_allocated != NULL)
+ next_hook_mailbox_allocated(box);
}
static void expire_mail_user_deinit(struct mail_user *user)
void expire_plugin_init(void)
{
- next_hook_mail_storage_created = hook_mail_storage_created;
- hook_mail_storage_created = expire_mail_storage_created;
+ next_hook_mailbox_allocated = hook_mailbox_allocated;
+ hook_mailbox_allocated = expire_mailbox_allocated;
next_hook_mail_user_created = hook_mail_user_created;
hook_mail_user_created = expire_mail_user_created;
void expire_plugin_deinit(void)
{
- hook_mail_storage_created = next_hook_mail_storage_created;
+ hook_mailbox_allocated = next_hook_mailbox_allocated;
hook_mail_user_created = next_hook_mail_user_created;
}
return 0;
}
- box = mailbox_open(ns->list, ns_mailbox, NULL, 0);
- if (box == NULL) {
- errstr = mailbox_list_get_last_error(ns->list, &error);
+ box = mailbox_alloc(ns->list, ns_mailbox, NULL, 0);
+ if (mailbox_open(box) < 0) {
+ errstr = mail_storage_get_last_error(mailbox_get_storage(box),
+ &error);
+ mailbox_close(&box);
if (error != MAIL_ERROR_NOTFOUND) {
i_error("%s: Opening mailbox %s failed: %s",
user, mailbox, errstr);
void fts_plugin_init(void)
{
- fts_next_hook_mailbox_opened = hook_mailbox_opened;
- hook_mailbox_opened = fts_mailbox_opened;
+ fts_next_hook_mailbox_allocated = hook_mailbox_allocated;
+ hook_mailbox_allocated = fts_mailbox_allocated;
}
void fts_plugin_deinit(void)
{
- hook_mailbox_opened = fts_next_hook_mailbox_opened;
+ hook_mailbox_allocated = fts_next_hook_mailbox_allocated;
}
#ifndef FTS_PLUGIN_H
#define FTS_PLUGIN_H
-extern void (*fts_next_hook_mailbox_opened)(struct mailbox *box);
+extern void (*fts_next_hook_mailbox_allocated)(struct mailbox *box);
-void fts_mailbox_opened(struct mailbox *box);
+void fts_mailbox_allocated(struct mailbox *box);
void fts_plugin_init(void);
void fts_plugin_deinit(void);
&mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(fts_mail_module, &mail_module_register);
-static int fts_mailbox_close(struct mailbox *box)
+static void fts_mailbox_close(struct mailbox *box)
{
struct fts_mailbox *fbox = FTS_CONTEXT(box);
- int ret;
if (fbox->backend_substr != NULL)
fts_backend_deinit(&fbox->backend_substr);
if (fbox->backend_fast != NULL)
fts_backend_deinit(&fbox->backend_fast);
- ret = fbox->module_ctx.super.close(box);
+ fbox->module_ctx.super.close(box);
i_free(fbox);
- return ret;
}
static int fts_build_mail_flush_headers(struct fts_storage_build_context *ctx)
MODULE_CONTEXT_SET(box, fts_storage_module, fbox);
}
-void fts_mailbox_opened(struct mailbox *box)
+void fts_mailbox_allocated(struct mailbox *box)
{
const char *env;
if (env != NULL)
fts_mailbox_init(box, env);
- if (fts_next_hook_mailbox_opened != NULL)
- fts_next_hook_mailbox_opened(box);
+ if (fts_next_hook_mailbox_allocated != NULL)
+ fts_next_hook_mailbox_allocated(box);
}
#define ERROR_NOT_ADMIN "["IMAP_RESP_CODE_NOPERM"] " \
"You lack administrator privileges on this mailbox."
-#define ACL_MAILBOX_OPEN_FLAGS \
- (MAILBOX_OPEN_READONLY | MAILBOX_OPEN_FAST | MAILBOX_OPEN_KEEP_RECENT)
+#define ACL_MAILBOX_FLAGS \
+ (MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT)
#define IMAP_ACL_ANYONE "anyone"
#define IMAP_ACL_AUTHENTICATED "authenticated"
/* Force opening the mailbox so that we can give a nicer error message
if mailbox isn't selectable but is listable. */
- box = mailbox_open(ns->list, name, NULL, ACL_MAILBOX_OPEN_FLAGS |
- MAILBOX_OPEN_IGNORE_ACLS);
- if (box == NULL) {
- client_send_list_error(cmd, ns->list);
- return NULL;
- }
-
+ box = mailbox_alloc(ns->list, name, NULL, ACL_MAILBOX_FLAGS |
+ MAILBOX_FLAG_IGNORE_ACLS);
ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
if (ret > 0)
return box;
if (ns == NULL)
return TRUE;
- box = mailbox_open(ns->list, real_mailbox, NULL,
- ACL_MAILBOX_OPEN_FLAGS | MAILBOX_OPEN_IGNORE_ACLS);
- if (box == NULL) {
- client_send_list_error(cmd, ns->list);
- return TRUE;
- }
-
+ box = mailbox_alloc(ns->list, real_mailbox, NULL,
+ ACL_MAILBOX_FLAGS | MAILBOX_FLAG_IGNORE_ACLS);
if (acl_object_get_my_rights(acl_mailbox_get_aclobj(box),
pool_datastack_create(), &rights) < 0) {
client_send_tagline(cmd, "NO "MAIL_ERRSTR_CRITICAL_MSG);
if (ns == NULL)
return TRUE;
- box = mailbox_open(ns->list, mailbox, NULL, (MAILBOX_OPEN_READONLY |
- MAILBOX_OPEN_FAST |
- MAILBOX_OPEN_KEEP_RECENT));
- if (box == NULL) {
- client_send_list_error(cmd, ns->list);
- return TRUE;
- }
-
if (quser == NULL) {
- mailbox_close(&box);
client_send_tagline(cmd, "OK No quota.");
return TRUE;
}
if (ns->owner != NULL && ns->owner != client->user &&
!client->user->admin) {
- mailbox_close(&box);
client_send_tagline(cmd, "NO Not showing other users' quota.");
return TRUE;
}
+ box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_READONLY |
+ MAILBOX_FLAG_KEEP_RECENT);
+
/* send QUOTAROOT reply */
str = t_str_new(128);
str_append(str, "* QUOTAROOT ");
bool internal_namespace;
};
-struct lazy_expunge_mail_storage {
- union mail_storage_module_context module_ctx;
-};
-
struct lazy_expunge_transaction {
union mailbox_transaction_module_context module_ctx;
static void (*lazy_expunge_next_hook_mail_namespaces_created)
(struct mail_namespace *namespaces);
-static void (*lazy_expunge_next_hook_mail_storage_created)
- (struct mail_storage *storage);
+static void (*lazy_expunge_next_hook_mailbox_allocated)(struct mailbox *box);
static void (*lazy_expunge_next_hook_mailbox_list_created)
(struct mailbox_list *list);
static void (*lazy_expunge_next_hook_mail_user_created)(struct mail_user *user);
struct mail_storage *storage;
enum mail_error error;
- box = mailbox_open(list, name, NULL, MAILBOX_OPEN_FAST |
- MAILBOX_OPEN_KEEP_RECENT |
- MAILBOX_OPEN_NO_INDEX_FILES);
- if (box != NULL)
+ box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_NO_INDEX_FILES);
+ if (mailbox_open(box) == 0) {
+ *error_r = NULL;
return box;
+ }
- *error_r = mailbox_list_get_last_error(list, &error);
+ *error_r = mail_storage_get_last_error(mailbox_get_storage(box),
+ &error);
+ mailbox_close(&box);
if (error != MAIL_ERROR_NOTFOUND)
return NULL;
}
/* and try opening again */
- box = mailbox_open(list, name, NULL, MAILBOX_OPEN_FAST |
- MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL)
- *error_r = mailbox_list_get_last_error(list, &error);
+ box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(box) < 0) {
+ *error_r = mail_storage_get_last_error(mailbox_get_storage(box),
+ &error);
+ mailbox_close(&box);
+ return NULL;
+ }
return box;
}
return _mail;
}
-static struct mailbox *
-lazy_expunge_mailbox_open(struct mail_storage *storage,
- struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+static void lazy_expunge_mailbox_allocated(struct mailbox *box)
{
- struct lazy_expunge_mail_storage *lstorage =
- LAZY_EXPUNGE_CONTEXT(storage);
struct lazy_expunge_mailbox_list *llist =
- LAZY_EXPUNGE_LIST_CONTEXT(list);
- struct mailbox *box;
+ LAZY_EXPUNGE_LIST_CONTEXT(box->list);
union mailbox_module_context *mbox;
- box = lstorage->module_ctx.super.
- mailbox_open(storage, list, name, input, flags);
- if (box == NULL || llist == NULL || llist->internal_namespace)
- return box;
+ if (llist != NULL && !llist->internal_namespace) {
+ mbox = p_new(box->pool, union mailbox_module_context, 1);
+ mbox->super = box->v;
- mbox = p_new(box->pool, union mailbox_module_context, 1);
- mbox->super = box->v;
+ box->v.transaction_begin = lazy_expunge_transaction_begin;
+ box->v.transaction_commit = lazy_expunge_transaction_commit;
+ box->v.transaction_rollback = lazy_expunge_transaction_rollback;
+ box->v.mail_alloc = lazy_expunge_mail_alloc;
+ MODULE_CONTEXT_SET_SELF(box, lazy_expunge_mail_storage_module,
+ mbox);
+ }
- box->v.transaction_begin = lazy_expunge_transaction_begin;
- box->v.transaction_commit = lazy_expunge_transaction_commit;
- box->v.transaction_rollback = lazy_expunge_transaction_rollback;
- box->v.mail_alloc = lazy_expunge_mail_alloc;
- MODULE_CONTEXT_SET_SELF(box, lazy_expunge_mail_storage_module, mbox);
- return box;
+ if (lazy_expunge_next_hook_mailbox_allocated != NULL)
+ lazy_expunge_next_hook_mailbox_allocated(box);
}
static int
return 0;
}
-static void lazy_expunge_mail_storage_init(struct mail_storage *storage)
-{
- struct lazy_expunge_mail_storage *lstorage;
-
- lstorage = p_new(storage->pool, struct lazy_expunge_mail_storage, 1);
- lstorage->module_ctx.super = storage->v;
- storage->v.mailbox_open = lazy_expunge_mailbox_open;
-
- MODULE_CONTEXT_SET(storage, lazy_expunge_mail_storage_module, lstorage);
-}
-
-static void lazy_expunge_mail_storage_created(struct mail_storage *storage)
-{
- lazy_expunge_mail_storage_init(storage);
-
- if (lazy_expunge_next_hook_mail_storage_created != NULL)
- lazy_expunge_next_hook_mail_storage_created(storage);
-}
-
static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
{
struct lazy_expunge_mail_user *luser =
hook_mail_namespaces_created =
lazy_expunge_hook_mail_namespaces_created;
- lazy_expunge_next_hook_mail_storage_created = hook_mail_storage_created;
- hook_mail_storage_created = lazy_expunge_mail_storage_created;
+ lazy_expunge_next_hook_mailbox_allocated = hook_mailbox_allocated;
+ hook_mailbox_allocated = lazy_expunge_mailbox_allocated;
lazy_expunge_next_hook_mailbox_list_created = hook_mailbox_list_created;
hook_mailbox_list_created = lazy_expunge_mailbox_list_created;
{
hook_mail_namespaces_created =
lazy_expunge_hook_mail_namespaces_created;
- hook_mail_storage_created = lazy_expunge_next_hook_mail_storage_created;
+ hook_mailbox_allocated = lazy_expunge_next_hook_mailbox_allocated;
hook_mailbox_list_created = lazy_expunge_next_hook_mailbox_list_created;
hook_mail_user_created = lazy_expunge_next_hook_mail_user_created;
}
}
static struct mailbox *
-listescape_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+listescape_mailbox_alloc(struct mail_storage *storage,
+ struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
struct listescape_mail_storage *mstorage = LIST_ESCAPE_CONTEXT(storage);
struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
if (!mlist->name_escaped && list->hierarchy_sep != list->ns->sep)
name = list_escape(list->ns, name, TRUE);
return mstorage->module_ctx.super.
- mailbox_open(storage, list, name, input, flags);
+ mailbox_alloc(storage, list, name, input, flags);
}
static int
mstorage = p_new(storage->pool, struct listescape_mail_storage, 1);
mstorage->module_ctx.super = storage->v;
- storage->v.mailbox_open = listescape_mailbox_open;
+ storage->v.mailbox_alloc = listescape_mailbox_alloc;
storage->v.mailbox_create = listescape_mailbox_create;
MODULE_CONTEXT_SET(storage, listescape_storage_module, mstorage);
}
static struct mailbox *
-mail_log_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+mail_log_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
union mail_storage_module_context *lstorage = MAIL_LOG_CONTEXT(storage);
struct mailbox *box;
union mailbox_module_context *lbox;
- box = lstorage->super.mailbox_open(storage, list, name, input, flags);
- if (box == NULL)
- return NULL;
+ box = lstorage->super.mailbox_alloc(storage, list, name, input, flags);
lbox = p_new(box->pool, union mailbox_module_context, 1);
lbox->super = box->v;
lstorage = p_new(storage->pool, union mail_storage_module_context, 1);
lstorage->super = storage->v;
- storage->v.mailbox_open = mail_log_mailbox_open;
+ storage->v.mailbox_alloc = mail_log_mailbox_alloc;
MODULE_CONTEXT_SET_SELF(storage, mail_log_storage_module, lstorage);
/* try to open the spool mbox */
mstorage->open_spool_inbox = TRUE;
mbox->spool_mbox =
- mailbox_open(box->list, "INBOX", NULL,
- MAILBOX_OPEN_KEEP_RECENT |
- MAILBOX_OPEN_NO_INDEX_FILES);
+ mailbox_alloc(box->list, "INBOX", NULL,
+ MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_NO_INDEX_FILES);
mstorage->open_spool_inbox = FALSE;
}
-
- if (mbox->spool_mbox != NULL)
- mbox_snarf(mbox->spool_mbox, box);
+ (void)mbox_snarf(mbox->spool_mbox, box);
return mbox->module_ctx.super.sync_init(box, flags);
}
-static int mbox_snarf_close(struct mailbox *box)
+static void mbox_snarf_close(struct mailbox *box)
{
struct mbox_snarf_mailbox *mbox = MBOX_SNARF_CONTEXT(box);
if (mbox->spool_mbox != NULL)
mailbox_close(&mbox->spool_mbox);
- return mbox->module_ctx.super.close(box);
+ mbox->module_ctx.super.close(box);
}
static struct mailbox *
-mbox_snarf_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+mbox_snarf_mailbox_alloc(struct mail_storage *storage,
+ struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
struct mbox_snarf_mail_storage *mstorage =
MBOX_SNARF_CONTEXT(storage);
}
box = mstorage->module_ctx.super.
- mailbox_open(storage, list, name, input, flags);
+ mailbox_alloc(storage, list, name, input, flags);
storage->flags = old_flags;
list->flags = old_list_flags;
mstorage = p_new(storage->pool, struct mbox_snarf_mail_storage, 1);
mstorage->snarf_inbox_path = p_strdup(storage->pool, path);
mstorage->module_ctx.super = storage->v;
- storage->v.mailbox_open = mbox_snarf_mailbox_open;
+ storage->v.mailbox_alloc = mbox_snarf_mailbox_alloc;
MODULE_CONTEXT_SET(storage, mbox_snarf_storage_module, mstorage);
}
return 0;
}
- box = mailbox_open(ns->list, name, NULL,
- MAILBOX_OPEN_READONLY | MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL) {
- mailbox_list_get_last_error(ns->list, &error);
+ box = mailbox_alloc(ns->list, name, NULL,
+ MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(box) < 0) {
+ mail_storage_get_last_error(mailbox_get_storage(box), &error);
+ mailbox_close(&box);
if (error == MAIL_ERROR_TEMP)
return -1;
/* non-temporary error, e.g. ACLs denied access. */
return ret;
}
-static int quota_mailbox_close(struct mailbox *box)
+static void quota_mailbox_close(struct mailbox *box)
{
struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
i_assert(qbox->expunge_qt == NULL ||
qbox->expunge_qt->tmp_mail == NULL);
- return qbox->module_ctx.super.close(box);
+ qbox->module_ctx.super.close(box);
}
static struct mailbox *
-quota_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+quota_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
struct mailbox *box;
struct quota_mailbox *qbox;
- box = qstorage->super.mailbox_open(storage, list, name, input, flags);
+ box = qstorage->super.mailbox_alloc(storage, list, name, input, flags);
if (box == NULL || QUOTA_LIST_CONTEXT(list) == NULL)
return box;
and free the quota for all the messages existing in it. Open the
mailbox locked so that other processes can't mess up the quota
calculations by adding/removing mails while we're doing this. */
- box = mailbox_open(list, name, NULL, MAILBOX_OPEN_KEEP_RECENT |
- MAILBOX_OPEN_KEEP_LOCKED);
- if (box == NULL) {
- str = mailbox_list_get_last_error(list, &error);
+ box = mailbox_alloc(list, name, NULL, MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_KEEP_LOCKED);
+ if (mailbox_open(box) < 0) {
+ str = mail_storage_get_last_error(mailbox_get_storage(box),
+ &error);
if (error != MAIL_ERROR_NOTPOSSIBLE) {
ret = -1;
} else {
qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
qstorage->super = storage->v;
- storage->v.mailbox_open = quota_mailbox_open;
+ storage->v.mailbox_alloc = quota_mailbox_alloc;
MODULE_CONTEXT_SET_SELF(storage, quota_storage_module, qstorage);
quota_maildir_storage_set(storage);
{
struct mail_search_args *search_args;
- trash->box = mailbox_open(trash->ns->list, trash->name, NULL,
- MAILBOX_OPEN_KEEP_RECENT);
- if (trash->box == NULL)
+ trash->box = mailbox_alloc(trash->ns->list, trash->name, NULL,
+ MAILBOX_FLAG_KEEP_RECENT);
+ if (mailbox_open(trash->box) < 0) {
+ mailbox_close(&trash->box);
return 0;
+ }
if (mailbox_sync(trash->box, MAILBOX_SYNC_FLAG_FULL_READ, 0, NULL) < 0)
return -1;
i_array_init(&mbox->backend_boxes, 8);
mbox->search_args_crc32 = (uint32_t)-1;
- path = t_strconcat(mbox->path, "/"VIRTUAL_CONFIG_FNAME, NULL);
+ path = t_strconcat(mbox->ibox.box.path, "/"VIRTUAL_CONFIG_FNAME, NULL);
fd = open(path, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
}
static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
- enum mailbox_open_flags open_flags)
+ enum mailbox_flags flags)
{
struct mail_user *user = mbox->storage->storage.user;
struct virtual_backend_box *const *bboxes;
+ struct mail_storage *storage;
struct mail_namespace *ns;
unsigned int i, count;
enum mail_error error;
const char *str, *mailbox;
- open_flags |= MAILBOX_OPEN_KEEP_RECENT;
+ flags |= MAILBOX_FLAG_KEEP_RECENT;
bboxes = array_get(&mbox->backend_boxes, &count);
for (i = 0; i < count; ) {
mailbox = bboxes[i]->name;
ns = mail_namespace_find(user->namespaces, &mailbox);
- bboxes[i]->box = mailbox_open(ns->list, mailbox,
- NULL, open_flags);
+ bboxes[i]->box = mailbox_alloc(ns->list, mailbox, NULL, flags);
- if (bboxes[i]->box == NULL) {
- str = mailbox_list_get_last_error(ns->list, &error);
+ if (mailbox_open(bboxes[i]->box) < 0) {
+ storage = mailbox_get_storage(bboxes[i]->box);
+ str = mail_storage_get_last_error(storage, &error);
if (bboxes[i]->wildcard &&
(error == MAIL_ERROR_PERM ||
error == MAIL_ERROR_NOTFOUND)) {
bboxes = array_get(&mbox->backend_boxes, &count);
continue;
}
- if (ns->list != mbox->ibox.box.list) {
- /* copy the error */
- mailbox_list_set_error(mbox->ibox.box.list,
- error, str);
- }
+ /* copy the error */
+ mail_storage_set_error(mbox->ibox.box.storage,
+ error, str);
break;
}
i_array_init(&bboxes[i]->uids, 64);
else {
/* failed */
for (; i > 0; i--) {
- (void)mailbox_close(&bboxes[i-1]->box);
+ mailbox_close(&bboxes[i-1]->box);
array_free(&bboxes[i-1]->uids);
}
return -1;
}
static struct mailbox *
-virtual_open(struct virtual_storage *storage, struct mailbox_list *list,
- const char *name, enum mailbox_open_flags flags)
+virtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
- struct mail_storage *_storage = &storage->storage;
+ struct virtual_storage *storage = (struct virtual_storage *)storage;
struct virtual_mailbox *mbox;
- struct mail_index *index;
- const char *path;
pool_t pool;
- bool failed;
-
- if (virtual_mailbox_is_in_open_stack(storage, name)) {
- mail_storage_set_critical(_storage,
- "Virtual mailbox loops: %s", name);
- return NULL;
- }
-
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- index = index_storage_alloc(list, name, flags, VIRTUAL_INDEX_PREFIX);
pool = pool_alloconly_create("virtual mailbox", 1024+512);
mbox = p_new(pool, struct virtual_mailbox, 1);
mbox->ibox.box = virtual_mailbox;
mbox->ibox.box.pool = pool;
mbox->ibox.box.storage = _storage;
+ mbox->ibox.box.list = list;
mbox->ibox.mail_vfuncs = &virtual_mail_vfuncs;
- mbox->ibox.index = index;
+
+ index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
+ VIRTUAL_INDEX_PREFIX);
mbox->storage = storage;
- mbox->path = p_strdup(pool, path);
mbox->vseq_lookup_prev_mailbox = i_strdup("");
mbox->virtual_ext_id =
- mail_index_ext_register(index, "virtual", 0,
+ mail_index_ext_register(mbox->ibox.index, "virtual", 0,
sizeof(struct virtual_mail_index_record),
sizeof(uint32_t));
-
- array_append(&storage->open_stack, &name, 1);
- failed = virtual_config_read(mbox) < 0 ||
- virtual_mailboxes_open(mbox, flags) < 0;
- array_delete(&storage->open_stack,
- array_count(&storage->open_stack)-1, 1);
- if (failed) {
- virtual_config_free(mbox);
- index_storage_mailbox_close(&mbox->ibox.box);
- return NULL;
- }
-
- index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
return &mbox->ibox.box;
}
-static struct mailbox *
-virtual_mailbox_open(struct mail_storage *_storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+static int virtual_mailbox_open(struct mailbox *box)
{
- struct virtual_storage *storage = (struct virtual_storage *)_storage;
- const char *path;
+ struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
struct stat st;
+ bool failed;
- if (input != NULL) {
- mailbox_list_set_critical(list,
+ if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) {
+ mail_storage_set_critical(box->storage,
+ "Virtual mailbox loops: %s", box->name);
+ return -1;
+ }
+
+ if (box->input != NULL) {
+ mail_storage_set_critical(box->storage,
"virtual doesn't support streamed mailboxes");
- return NULL;
+ return -1;
}
- path = mailbox_list_get_path(list, name,
- MAILBOX_LIST_PATH_TYPE_MAILBOX);
- if (stat(path, &st) == 0)
- return virtual_open(storage, list, name, flags);
- else if (errno == ENOENT) {
- mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
- T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+ if (stat(box->path, &st) == 0) {
+ /* exists, open it */
+ } else if (errno == ENOENT) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+ T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+ return -1;
} else if (errno == EACCES) {
- mailbox_list_set_critical(list, "%s",
- mail_error_eacces_msg("stat", path));
+ mail_storage_set_critical(box->storage, "%s",
+ mail_error_eacces_msg("stat", box->path));
+ return -1;
} else {
- mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
+ mail_storage_set_critical(box->storage,
+ "stat(%s) failed: %m", box->path);
+ return -1;
}
- return NULL;
+
+ array_append(&mbox->storage->open_stack, &box->name, 1);
+ failed = virtual_config_read(mbox) < 0 ||
+ virtual_mailboxes_open(mbox, box->flags) < 0;
+ array_delete(&mbox->storage->open_stack,
+ array_count(&mbox->storage->open_stack)-1, 1);
+ return failed ? -1 : 0;
}
-static int virtual_storage_mailbox_close(struct mailbox *box)
+static void virtual_mailbox_close(struct mailbox *box)
{
struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
struct mail_storage *storage;
struct virtual_backend_box **bboxes;
unsigned int i, count;
- int ret = 0;
virtual_config_free(mbox);
mailbox_search_result_free(&bboxes[i]->search_result);
storage = bboxes[i]->box->storage;
- if (mailbox_close(&bboxes[i]->box) < 0) {
- const char *str;
- enum mail_error error;
-
- str = mail_storage_get_last_error(storage, &error);
- mail_storage_set_error(box->storage, error, str);
- ret = -1;
- }
+ mailbox_close(&bboxes[i]->box);
if (array_is_created(&bboxes[i]->sync_outside_expunges))
array_free(&bboxes[i]->sync_outside_expunges);
array_free(&bboxes[i]->sync_pending_removes);
array_free(&mbox->backend_boxes);
i_free(mbox->vseq_lookup_prev_mailbox);
- return index_storage_mailbox_close(box) < 0 ? -1 : ret;
+ index_storage_mailbox_close(box);
}
static int virtual_mailbox_create(struct mail_storage *_storage,
virtual_storage_add_list,
virtual_storage_get_list_settings,
NULL,
- virtual_mailbox_open,
+ virtual_mailbox_alloc,
virtual_mailbox_create,
NULL
}
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
- virtual_storage_mailbox_close,
+ virtual_mailbox_open,
+ virtual_mailbox_close,
index_storage_get_status,
NULL,
NULL,
struct index_mailbox ibox;
struct virtual_storage *storage;
- const char *path;
uint32_t virtual_ext_id;
uint32_t prev_uid_validity;
if (ext_name_offset >= ext_size ||
ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) {
i_error("virtual index %s: Broken mailbox_count header",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
ctx->index_broken = TRUE;
ext_mailbox_count = 0;
ret = FALSE;
if (mailboxes[i].id > ext_hdr->highest_mailbox_id ||
mailboxes[i].id <= prev_mailbox_id) {
i_error("virtual index %s: Broken mailbox id",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
break;
}
if (mailboxes[i].name_len == 0 ||
mailboxes[i].name_len > ext_size) {
i_error("virtual index %s: Broken mailbox name_len",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
break;
}
if (ext_name_offset + mailboxes[i].name_len > ext_size) {
i_error("virtual index %s: Broken mailbox list",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
break;
}
T_BEGIN {
struct mailbox_status status;
int ret;
- if (!bbox->box->opened)
- index_storage_mailbox_open(ibox);
+ if (!bbox->box->opened) {
+ if (mailbox_open(bbox->box) < 0)
+ return -1;
+ }
/* if we already did some changes to index, commit them before
syncing starts. */
if (mail_index_unlink(ctx->index) < 0) {
i_error("virtual index %s: Failed to unlink() "
"broken indexes: %m",
- ctx->mbox->path);
+ ctx->mbox->ibox.box.path);
}
}
mail_index_sync_rollback(&ctx->index_sync_ctx);
struct mailbox_sync_context *sync_ctx;
int ret = 0;
- if (!box->opened)
- index_storage_mailbox_open(&mbox->ibox);
+ if (!box->opened) {
+ if (mailbox_open(box) < 0)
+ ret = -1;
+ }
- if (index_mailbox_want_full_sync(&mbox->ibox, flags))
+ if (index_mailbox_want_full_sync(&mbox->ibox, flags) && ret == 0)
ret = virtual_sync(mbox, flags);
sync_ctx = index_mailbox_sync_init(box, flags, ret < 0);
}
static struct mailbox *
-zlib_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
- const char *name, struct istream *input,
- enum mailbox_open_flags flags)
+zlib_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
{
union mail_storage_module_context *qstorage = ZLIB_CONTEXT(storage);
struct mailbox *box;
zlib_mailbox_open_input(storage, list, name);
}
- box = qstorage->super.mailbox_open(storage, list, name, input, flags);
+ box = qstorage->super.mailbox_alloc(storage, list, name, input, flags);
if (zlib_input != NULL)
i_stream_unref(&zlib_input);
- if (box != NULL && strcmp(storage->name, "maildir") == 0)
+ if (strcmp(box->storage->name, "maildir") == 0)
zlib_maildir_open_init(box);
return box;
}
qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
qstorage->super = storage->v;
- storage->v.mailbox_open = zlib_mailbox_open;
+ storage->v.mailbox_alloc = zlib_mailbox_alloc;
MODULE_CONTEXT_SET_SELF(storage, zlib_storage_module, qstorage);
struct mail_storage *storage;
const char *inbox, *ident;
struct client *client;
- enum mailbox_open_flags flags;
+ enum mailbox_flags flags;
const char *errmsg;
enum mail_error error;
}
client->inbox_ns = ns;
- flags = MAILBOX_OPEN_POP3_SESSION;
+ flags = MAILBOX_FLAG_POP3_SESSION;
if (set->pop3_no_flag_updates)
- flags |= MAILBOX_OPEN_KEEP_RECENT;
+ flags |= MAILBOX_FLAG_KEEP_RECENT;
if (set->pop3_lock_session)
- flags |= MAILBOX_OPEN_KEEP_LOCKED;
- client->mailbox = mailbox_open(ns->list, "INBOX", NULL, flags);
- if (client->mailbox == NULL) {
+ flags |= MAILBOX_FLAG_KEEP_LOCKED;
+ client->mailbox = mailbox_alloc(ns->list, "INBOX", NULL, flags);
+ storage = mailbox_get_storage(client->mailbox);
+ if (mailbox_open(client->mailbox) < 0) {
errmsg = t_strdup_printf("Couldn't open INBOX: %s",
- mailbox_list_get_last_error(ns->list,
+ mail_storage_get_last_error(storage,
&error));
i_error("%s", errmsg);
client_send_line(client, "-ERR [IN-USE] %s", errmsg);
client_destroy(client, "Couldn't open INBOX");
return NULL;
}
- storage = mailbox_get_storage(client->mailbox);
client->mail_set = mail_storage_get_settings(storage);
if (!init_mailbox(client, &errmsg)) {
if (ns == NULL)
i_fatal("Can't find namespace for mailbox %s", mailbox);
- box = mailbox_open(ns->list, mailbox, NULL, MAILBOX_OPEN_KEEP_RECENT |
- MAILBOX_OPEN_IGNORE_ACLS);
- if (box == NULL) {
+ box = mailbox_alloc(ns->list, mailbox, NULL, MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_IGNORE_ACLS);
+ if (mailbox_open(box) < 0) {
i_fatal("Opening mailbox %s failed: %s", orig_mailbox,
- mailbox_list_get_last_error(ns->list, NULL));
+ mail_storage_get_last_error(mailbox_get_storage(box),
+ NULL));
}
return box;
}