mail-storage.c revision 099a6b509dc3fc68e662b6736f03b73eb575c527
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "lib.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "ioloop.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "array.h"
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen#include "llist.h"
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen#include "istream.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "eacces-error.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mkdir-parents.h"
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen#include "var-expand.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-index-private.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-index-alloc-cache.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mailbox-list-private.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-storage-private.h"
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen#include "mail-storage-settings.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-namespace.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-search.h"
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen#include "mailbox-search-result-private.h"
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <stdlib.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <ctype.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_module_register mail_module_register = { 0 };
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo SirainenARRAY_TYPE(mail_storage) mail_storage_classes;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mail_storage_init(void)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_lists_init();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_hooks_init();
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen i_array_init(&mail_storage_classes, 8);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainenvoid mail_storage_deinit(void)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen{
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (array_is_created(&mail_storage_classes))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_free(&mail_storage_classes);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_hooks_deinit();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_lists_deinit();
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen i_assert(mail_storage_find_class(storage_class->name) == NULL);
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen /* append it after the list, so the autodetection order is correct */
9eef11df882f9c14d164f42cb438f32fe724041cTimo Sirainen array_append(&mail_storage_classes, &storage_class, 1);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen}
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_storage *const *classes;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int i, count;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen classes = array_get(&mail_storage_classes, &count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (classes[i] == storage_class) {
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen array_delete(&mail_storage_classes, i, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen break;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_storage *mail_storage_find_class(const char *name)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen struct mail_storage *const *classes;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int i, count;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen i_assert(name != NULL);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen classes = array_get(&mail_storage_classes, &count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen if (strcasecmp(classes[i]->name, name) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return classes[i];
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen return NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct mail_storage *
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenmail_storage_autodetect(const struct mail_namespace *ns,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_list_settings *set)
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen{
8b3a4836da0b032673918941cb49c956d3b89b25Timo Sirainen struct mail_storage *const *classes;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int i, count;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen classes = array_get(&mail_storage_classes, &count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (classes[i]->v.autodetect != NULL) {
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen if (classes[i]->v.autodetect(ns, set))
47255691575e06a1c95ce78ff0a1b502199de3abTimo Sirainen return classes[i];
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
307ec6c2c319e3335ddb1a7aca2d2884fe17fae0Timo Sirainen return NULL;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *p;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen p = *data;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen while (i_isalnum(*p)) p++;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (*p == ':' && p != *data) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen /* no autodetection if the storage driver is given. */
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *driver = t_strdup_until(*data, p);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen *data = p + 1;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen }
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainenstatic struct mail_storage *
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainenmail_storage_get_class(struct mail_namespace *ns, const char *driver,
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen struct mailbox_list_settings *list_set,
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen const char **error_r)
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen{
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen struct mail_storage *storage_class;
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen const char *home;
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen if (driver != NULL) {
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen storage_class = mail_storage_find_class(driver);
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen if (storage_class == NULL) {
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen *error_r = t_strdup_printf(
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen "Unknown mail storage driver %s", driver);
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen return NULL;
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(list_set->root_dir != NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen storage_class->v.get_list_settings(ns, list_set);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return storage_class;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen storage_class = mail_storage_autodetect(ns, list_set);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (storage_class != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return storage_class;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ns->set->location == NULL || *ns->set->location == '\0') {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (void)mail_user_get_home(ns->user, &home);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *error_r = t_strdup_printf(
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Mail storage autodetection failed with home=%s", home);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *error_r = t_strdup_printf(
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Ambiguous mail location setting, "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "don't know what to do with it: %s "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "(try prefixing it with mbox: or maildir:)",
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen ns->set->location);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return NULL;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen}
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainenstatic int
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainenmail_storage_create_root(struct mailbox_list *list,
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen enum mail_storage_flags flags, const char **error_r)
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen{
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen const char *root_dir, *origin;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen struct stat st;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen mode_t mode;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen gid_t gid;
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen root_dir = mailbox_list_get_path(list, NULL,
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen if (root_dir == NULL) {
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen /* storage doesn't use directories (e.g. shared root) */
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (stat(root_dir, &st) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* ok */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (errno == EACCES) {
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen *error_r = mail_error_eacces_msg("stat", root_dir);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (errno != ENOENT && errno != ENOTDIR) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (list->ns->type == NAMESPACE_SHARED) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* can't create a new user, but we don't want to fail
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen the storage creation. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *error_r = t_strdup_printf(
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Root mail directory doesn't exist: %s", root_dir);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* we need to create the root directory. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mkdir_parents_chgrp(root_dir, mode, gid, origin) < 0 &&
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen errno != EEXIST) {
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen *error_r = mail_error_create_eacces_msg("mkdir", root_dir);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* created */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct mail_storage *
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenmail_storage_find(struct mail_user *user,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen const struct mail_storage *storage_class,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct mailbox_list_settings *set)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_storage *storage = user->storages;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen for (; storage != NULL; storage = storage->next) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strcmp(storage->name, storage_class->name) == 0 &&
ec0cc8fa647794e44a1afaa448f495a713048dc4Timo Sirainen ((storage->class_flags &
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0 ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen strcmp(storage->unique_root_dir, set->root_dir) == 0))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return storage;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen enum mail_storage_flags flags, const char **error_r)
307ec6c2c319e3335ddb1a7aca2d2884fe17fae0Timo Sirainen{
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen struct mail_storage *storage_class, *storage = NULL;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen struct mailbox_list_settings list_set;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mailbox_list_flags list_flags = 0;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen const char *data = ns->set->location;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen const char *p;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ns->mail_set->pop3_uidl_format != NULL) {
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen /* if pop3_uidl_format contains %m, we want to keep the
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen header MD5 sums stored even if we're not running POP3
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen right now. */
08e9fec5ba9e1a26e658c4224207d666b6ced27dTimo Sirainen p = ns->mail_set->pop3_uidl_format;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen while ((p = strchr(p, '%')) != NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (p[1] == '%')
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen p += 2;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else if (var_get_key(++p) == 'm') {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen flags |= MAIL_STORAGE_FLAG_KEEP_HEADER_MD5;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen break;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen memset(&list_set, 0, sizeof(list_set));
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (data == NULL) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen /* autodetect */
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen } else if (driver != NULL && strcmp(driver, "shared") == 0) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen /* internal shared namespace */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen list_set.root_dir = ns->user->set->base_dir;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen } else {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (driver == NULL)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen mail_storage_set_autodetection(&data, &driver);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (mailbox_list_settings_parse(data, &list_set, ns,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen error_r) < 0)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return -1;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0 &&
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen list_set.root_dir == NULL) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen *error_r = "Root mail directory not given";
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return -1;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen storage_class = mail_storage_get_class(ns, driver, &list_set, error_r);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (storage_class == NULL)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return -1;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen i_assert(list_set.layout != NULL);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (ns->list == NULL) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen /* first storage for namespace */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (mail_storage_is_mailbox_file(storage_class))
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (mailbox_list_create(list_set.layout, ns, &list_set,
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen list_flags, error_r) < 0) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen *error_r = t_strdup_printf("Mailbox list driver %s: %s",
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen list_set.layout, *error_r);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return -1;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (mail_storage_create_root(ns->list, flags, error_r) < 0)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return -1;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage = mail_storage_find(ns->user, storage_class, &list_set);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (storage != NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* using an existing storage */
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->refcount++;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mail_namespace_add_storage(ns, storage);
5e32f3d9e2c58b6db53cc3b063c9ee73949207caTimo Sirainen return 0;
5e32f3d9e2c58b6db53cc3b063c9ee73949207caTimo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage = storage_class->v.alloc();
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->refcount = 1;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->storage_class = storage_class;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->user = ns->user;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->set = ns->mail_set;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->flags = flags;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (storage->v.create != NULL &&
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->v.create(storage, ns, error_r) < 0) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen pool_unref(&storage->pool);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return -1;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen }
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen T_BEGIN {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen hook_mail_storage_created(storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen } T_END;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen DLLIST_PREPEND(&ns->user->storages, storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mail_namespace_add_storage(ns, storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return 0;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenvoid mail_storage_ref(struct mail_storage *storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->refcount++;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenvoid mail_storage_unref(struct mail_storage **_storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen struct mail_storage *storage = *_storage;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_assert(storage->refcount > 0);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen *_storage = NULL;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (--storage->refcount > 0)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen DLLIST_REMOVE(&storage->user->storages, storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (storage->v.destroy != NULL)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->v.destroy(storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_free(storage->error_string);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen pool_unref(&storage->pool);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mail_index_alloc_cache_destroy_unrefed();
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_free_and_null(storage->error_string);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->error = MAIL_ERROR_NONE;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen enum mail_error error, const char *string)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_free(storage->error_string);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->error_string = i_strdup(string);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->error = error;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen struct tm *tm;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen char str[256];
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen
ab3c52cff40218f248fac2bd7c93125cc2ae4c9dTimo Sirainen tm = localtime(&ioloop_time);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen i_free(storage->error_string);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->error_string =
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen strftime(str, sizeof(str),
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen MAIL_ERRSTR_CRITICAL_MSG_STAMP, tm) > 0 ?
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen i_strdup(str) : i_strdup(MAIL_ERRSTR_CRITICAL_MSG);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen storage->error = MAIL_ERROR_TEMP;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen const char *fmt, ...)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen va_list va;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen mail_storage_clear_error(storage);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (fmt != NULL) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen va_start(va, fmt);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen va_end(va);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* critical errors may contain sensitive data, so let user
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen see only "Internal error" with a timestamp to make it
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen easier to look from log files the actual error message. */
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen mail_storage_set_internal_error(storage);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen}
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen struct mailbox_list *list)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen{
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen const char *str;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen enum mail_error error;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen str = mailbox_list_get_last_error(list, &error);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen mail_storage_set_error(storage, error, str);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenvoid mail_storage_set_index_error(struct mailbox *box)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen{
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (mail_index_is_deleted(box->index))
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mailbox_set_deleted(box);
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen else
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen mail_storage_set_internal_error(box->storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen mail_index_reset_error(box->index);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenconst struct mail_storage_settings *
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenmail_storage_get_settings(struct mail_storage *storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return storage->set;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainenstruct mail_user *mail_storage_get_user(struct mail_storage *storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return storage->user;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen struct mail_storage_callbacks *callbacks,
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen void *context)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen storage->callbacks = *callbacks;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->callback_context = context;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainenint mail_storage_purge(struct mail_storage *storage)
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return storage->v.purge == NULL ? 0 :
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen storage->v.purge(storage);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen}
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen enum mail_error *error_r)
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen{
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* We get here only in error situations, so we have to return some
9307e4f91ea313a303b5473d9c53a3a2f383300fTimo Sirainen error. If storage->error is NONE, it means we forgot to set it at
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen some point.. */
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen if (storage->error == MAIL_ERROR_NONE) {
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen if (error_r != NULL)
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen *error_r = MAIL_ERROR_TEMP;
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen return storage->error_string != NULL ? storage->error_string :
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen "BUG: Unknown internal error";
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen }
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (storage->error_string == NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen /* This shouldn't happen.. */
719123a3ec5aeb45ef1c50c265039666c71981d7Timo Sirainen storage->error_string =
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen i_strdup_printf("BUG: Unknown 0x%x error",
55d33f807765482eb47374aaaced1fe714e0b256Timo Sirainen storage->error);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen }
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (error_r != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *error_r = storage->error;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return storage->error_string;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mail_storage_is_mailbox_file(struct mail_storage *storage)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return (storage->class_flags &
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen const char *error_string;
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen enum mail_error error;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen return FALSE;
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen if (storage->set->mail_debug && error != MAIL_ERROR_NOTFOUND) {
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen /* debugging is enabled - admin may be debugging a
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen (permission) problem, so return FALSE to get the caller to
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen log the full error message. */
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen return FALSE;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen }
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen mail_storage_set_error(storage, error, error_string);
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen return TRUE;
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen}
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainenstruct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen enum mailbox_flags flags)
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen{
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen struct mailbox_list *new_list = list;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen struct mail_storage *storage;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen struct mailbox *box;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen if (mailbox_list_get_storage(&new_list, &name, &storage) < 0) {
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen /* just use the first storage. FIXME: does this break? */
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen storage = list->ns->storage;
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen }
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen T_BEGIN {
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen box = storage->v.mailbox_alloc(storage, new_list, name, flags);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen hook_mailbox_allocated(box);
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen } T_END;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen return box;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int mailbox_open_full(struct mailbox *box, struct istream *input)
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->opened)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Invalid mailbox name");
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (input != NULL) {
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen if ((box->storage->class_flags &
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_critical(box->storage,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Storage doesn't support streamed mailboxes");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen }
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen box->input = input;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->flags |= MAILBOX_FLAG_READONLY;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_stream_ref(box->input);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen T_BEGIN {
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen ret = box->v.open(box);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen } T_END;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen if (ret < 0) {
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen if (box->input != NULL)
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen i_stream_unref(&box->input);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen return -1;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen }
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen return 0;
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen}
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainenint mailbox_open(struct mailbox *box)
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen{
a1893588a73d32a322153f5a2f7a16ef2c724979Timo Sirainen return mailbox_open_full(box, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_open_stream(struct mailbox *box, struct istream *input)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen return mailbox_open_full(box, input);
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen}
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainenint mailbox_enable(struct mailbox *box, enum mailbox_feature features)
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen{
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen return box->v.enable(box, features);
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen}
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainenenum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen{
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen return box->enabled_features;
d52f5dcb05092e126058874772f2c367499e650aTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_close(struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!box->opened)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->transaction_count != 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_panic("Trying to close mailbox %s with open transactions",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.close(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->opened = FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->mailbox_deleted = FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->backend_readonly = FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_clear(&box->search_results);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_free(struct mailbox **_box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox *box = *_box;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_box = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_close(box);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen mail_index_alloc_cache_unref(&box->index);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen pool_unref(&box->pool);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_create(struct mailbox *box, const struct mailbox_update *update,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen bool directory)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!mailbox_list_is_valid_create_name(box->list, box->name)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Invalid mailbox name");
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->list->v.create_mailbox_dir(box->list, box->name,
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen directory) < 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen mail_storage_copy_list_error(box->storage, box->list);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen mailbox_refresh_permissions(box);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->v.create(box, update, directory);
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_update(struct mailbox *box, const struct mailbox_update *update)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen return box->v.update(box, update);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int mailbox_mark_index_deleted(struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_index_transaction *trans;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen trans = mail_index_transaction_begin(box->view, 0);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen mail_index_set_deleted(trans);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mail_index_transaction_commit(&trans) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_index_error(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* sync the mailbox. this finishes the index deletion and it can
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen succeed only for a single session. we do it here, so the rest of
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen the deletion code doesn't have to worry about race conditions. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_delete(struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mail_error error;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (*box->name == '\0') {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Storage root can't be deleted");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strcmp(box->name, "INBOX") == 0 &&
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
8576eb5abb66178f251c00209e564c7673c0e4cfTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen "INBOX can't be deleted.");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->deleting = TRUE;
8576eb5abb66178f251c00209e564c7673c0e4cfTimo Sirainen if (mailbox_open(box) < 0) {
8576eb5abb66178f251c00209e564c7673c0e4cfTimo Sirainen (void)mail_storage_get_last_error(box->storage, &error);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (error != MAIL_ERROR_NOTFOUND)
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* \noselect mailbox */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_mark_index_deleted(box) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen ret = box->v.delete(box);
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen box->deleting = FALSE;
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen mailbox_close(box);
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen return ret;
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen}
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainenstatic bool nullequals(const void *p1, const void *p2)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return (p1 == NULL && p2 == NULL) || (p1 != NULL && p2 != NULL);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_rename(struct mailbox *src, struct mailbox *dest,
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen bool rename_children)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!mailbox_list_is_valid_existing_name(src->list, src->name) ||
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen *src->name == '\0' ||
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen !mailbox_list_is_valid_create_name(dest->list, dest->name)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_list_set_error(src->list, MAIL_ERROR_PARAMS,
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen "Invalid mailbox name");
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strcmp(src->storage->name, dest->storage->name) != 0) {
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen mailbox_list_set_error(src->list, MAIL_ERROR_NOTPOSSIBLE,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Can't rename mailbox to another storage type.");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen if (!nullequals(src->list->set.index_dir, dest->list->set.index_dir) ||
3ea86ed7cf06ba04e4aa6cd1c4df9be336c06cd3Timo Sirainen !nullequals(src->list->set.control_dir, dest->list->set.control_dir)) {
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen mailbox_list_set_error(src->list, MAIL_ERROR_NOTPOSSIBLE,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Can't rename mailboxes across specified storages.");
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen if (src->list->ns->type != NAMESPACE_PRIVATE ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dest->list->ns->type != NAMESPACE_PRIVATE) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_list_set_error(src->list, MAIL_ERROR_NOTPOSSIBLE,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Renaming not supported across non-private namespaces.");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return src->v.rename(src, dest, rename_children);
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_storage *mailbox_get_storage(const struct mailbox *box)
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen{
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen return box->storage;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainenstruct mail_namespace *
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainenmailbox_get_namespace(const struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->list->ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenconst struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->storage->set;
471a6b2b4e64eca5d5779ae20a477312b32c89eeTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenconst char *mailbox_get_name(const struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenconst char *mailbox_get_vname(const struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->vname;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_is_readonly(struct mailbox *box)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen{
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return box->v.is_readonly(box);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainenbool mailbox_allow_new_keywords(struct mailbox *box)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen{
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return box->v.allow_new_keywords(box);
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainenbool mailbox_backends_equal(const struct mailbox *box1,
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen const struct mailbox *box2)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen{
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen struct mail_namespace *ns1 = box1->list->ns, *ns2 = box2->list->ns;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strcmp(box1->name, box2->name) != 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (ns1->alias_for != NULL)
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen ns1 = ns1->alias_for;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (ns2->alias_for != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ns2 = ns2->alias_for;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ns1 == ns2;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_get_status(struct mailbox *box,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mailbox_status_items items,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_status *status_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.get_status(box, items, status_r);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->v.get_guid == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Storage doesn't support mailbox GUIDs");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!box->opened) {
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen if (mailbox_open(box) < 0)
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen return -1;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen }
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen return box->v.get_guid(box, guid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mailbox_sync_context *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenmailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_sync_context *ctx;
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen if (box->transaction_count != 0) {
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen i_panic("Trying to sync mailbox %s with open transactions",
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen box->name);
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen }
34b8b14ce06c0939932b60f22f61aea124198438Timo Sirainen T_BEGIN {
34b8b14ce06c0939932b60f22f61aea124198438Timo Sirainen ctx = box->v.sync_init(box, flags);
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen } T_END;
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen return ctx;
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen}
d9b9687bf8cae9cfb070b1b7aadefa683220269fTimo Sirainen
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainenbool mailbox_sync_next(struct mailbox_sync_context *ctx,
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen struct mailbox_sync_rec *sync_rec_r)
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen{
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen return ctx->box->v.sync_next(ctx, sync_rec_r);
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen}
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainenint mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_sync_status *status_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_sync_context *ctx = *_ctx;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen *_ctx = NULL;
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memset(status_r, 0, sizeof(*status_r));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ctx->box->v.sync_deinit(ctx, status_r);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_sync_context *ctx;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen struct mailbox_sync_status status;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (array_count(&box->search_results) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* we don't care about mailbox's current state, so we might
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen as well fix inconsistency state */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen }
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen ctx = mailbox_sync_init(box, flags);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen return mailbox_sync_deinit(&ctx, &status);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
2e86ce0239b4bc88c94d7edb5813d38ab080627eTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#undef mailbox_notify_changes
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainenvoid mailbox_notify_changes(struct mailbox *box, unsigned int min_interval,
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen mailbox_notify_callback_t *callback, void *context)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->notify_min_interval = min_interval;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->notify_callback = callback;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->notify_context = context;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen box->v.notify_changes(box);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen}
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_notify_changes_stop(struct mailbox *box)
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_notify_changes(box, 0, NULL, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_keywords_create(struct mailbox *box, const char *const keywords[],
cf848255bf65a5e2382c59c093da72f877f7535aTimo Sirainen struct mail_keywords **keywords_r)
cf848255bf65a5e2382c59c093da72f877f7535aTimo Sirainen{
cf848255bf65a5e2382c59c093da72f877f7535aTimo Sirainen const char *empty_keyword_list = NULL;
cf848255bf65a5e2382c59c093da72f877f7535aTimo Sirainen
cf848255bf65a5e2382c59c093da72f877f7535aTimo Sirainen if (keywords == NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen keywords = &empty_keyword_list;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->v.keywords_create(box, keywords, keywords_r, FALSE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_keywords *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenmailbox_keywords_create_valid(struct mailbox *box,
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen const char *const keywords[])
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen const char *empty_keyword_list = NULL;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen struct mail_keywords *kw;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen if (keywords == NULL)
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen keywords = &empty_keyword_list;
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen if (box->v.keywords_create(box, keywords, &kw, TRUE) < 0)
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen i_unreached();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return kw;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_keywords *
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainenmailbox_keywords_create_from_indexes(struct mailbox *box,
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen const ARRAY_TYPE(keyword_indexes) *idx)
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen{
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen return box->v.keywords_create_from_indexes(box, idx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_keywords_ref(struct mailbox *box, struct mail_keywords *keywords)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.keywords_ref(keywords);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_keywords_unref(struct mailbox *box,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_keywords **_keywords)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_keywords *keywords = *_keywords;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_keywords = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.keywords_unref(keywords);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_keyword_is_valid(struct mailbox *box, const char *keyword,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char **error_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->v.keyword_is_valid(box, keyword, error_r);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_get_seq_range(struct mailbox *box, uint32_t uid1, uint32_t uid2,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint32_t *seq1_r, uint32_t *seq2_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.get_seq_range(box, uid1, uid2, seq1_r, seq2_r);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_get_uid_range(struct mailbox *box,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const ARRAY_TYPE(seq_range) *seqs,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_TYPE(seq_range) *uids)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.get_uid_range(box, seqs, uids);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_get_expunges(struct mailbox *box, uint64_t prev_modseq,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const ARRAY_TYPE(seq_range) *uids_filter,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_TYPE(mailbox_expunge_rec) *expunges)
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen{
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen return box->v.get_expunges(box, prev_modseq,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uids_filter, expunges);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint32_t backend_uidvalidity,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint32_t backend_uid, uint32_t *uid_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->v.get_virtual_uid == NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->v.get_virtual_uid(box, backend_mailbox, backend_uidvalidity,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen backend_uid, uid_r);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_get_virtual_backend_boxes(struct mailbox *box,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_TYPE(mailboxes) *mailboxes,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen bool only_with_msgs)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->v.get_virtual_backend_boxes == NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_append(mailboxes, &box, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.get_virtual_backend_boxes(box, mailboxes, only_with_msgs);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_get_virtual_box_patterns(struct mailbox *box,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_TYPE(mailbox_virtual_patterns) *includes,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY_TYPE(mailbox_virtual_patterns) *excludes)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->v.get_virtual_box_patterns == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_virtual_pattern pat;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memset(&pat, 0, sizeof(pat));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen pat.ns = box->list->ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen pat.pattern = box->name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_append(includes, &pat, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->v.get_virtual_box_patterns(box, includes, excludes);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mailbox_header_lookup_ctx *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenmailbox_header_lookup_init(struct mailbox *box, const char *const headers[])
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->v.header_lookup_init(box, headers);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_header_lookup_ref(struct mailbox_header_lookup_ctx *ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(ctx->refcount > 0);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->refcount++;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_header_lookup_unref(struct mailbox_header_lookup_ctx **_ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_header_lookup_ctx *ctx = *_ctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_ctx = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen i_assert(ctx->refcount > 0);
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen if (--ctx->refcount > 0)
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen return;
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen ctx->box->v.header_lookup_deinit(ctx);
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen}
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_search_context *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenmailbox_search_init(struct mailbox_transaction_context *t,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_search_args *args,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const enum mail_sort_type *sort_program)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_search_args_ref(args);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!args->simplified)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_search_args_simplify(args);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return t->box->v.search_init(t, args, sort_program);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_search_deinit(struct mail_search_context **_ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_search_context *ctx = *_ctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_search_args *args = ctx->args;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_ctx = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_search_results_initial_done(ctx);
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen ret = ctx->transaction->box->v.search_deinit(ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_search_args_unref(&args);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_search_next(struct mail_search_context *ctx, struct mail *mail)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen bool tryagain;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (!mailbox_search_next_nonblock(ctx, mail, &tryagain)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!tryagain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_search_next_nonblock(struct mail_search_context *ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail *mail, bool *tryagain_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox *box = ctx->transaction->box;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!box->v.search_next_nonblock(ctx, mail, tryagain_r))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_search_results_add(ctx, mail->uid);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen return TRUE;
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen }
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool mailbox_search_seen_lost_data(struct mail_search_context *ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ctx->seen_lost_data;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
59bf1df59552b6898749a87ae28476debd9b77d8Timo Sirainenint mailbox_search_result_build(struct mailbox_transaction_context *t,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_search_args *args,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mailbox_search_result_flags flags,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_search_result **result_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_search_context *ctx;
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen struct mail *mail;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx = mailbox_search_init(t, args, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *result_r = mailbox_search_result_save(ctx, flags);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail = mail_alloc(t, 0, NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (mailbox_search_next(ctx, mail)) ;
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen mail_free(&mail);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = mailbox_search_deinit(&ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_search_result_free(result_r);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainenstruct mailbox_transaction_context *
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainenmailbox_transaction_begin(struct mailbox *box,
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen enum mailbox_transaction_flags flags)
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen{
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen struct mailbox_transaction_context *trans;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen box->transaction_count++;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen trans = box->v.transaction_begin(box, flags);
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen trans->flags = flags;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen return trans;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen}
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainenint mailbox_transaction_commit(struct mailbox_transaction_context **t)
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen{
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen struct mail_transaction_commit_changes changes;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen int ret;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen /* Store changes temporarily so that plugins overriding
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen transaction_commit() can look at them. */
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen ret = mailbox_transaction_commit_get_changes(t, &changes);
252f5c6a63878e7a8a7ffb5847eecbad7f8737e8Timo Sirainen pool_unref(&changes.pool);
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen return ret;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen}
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainenint mailbox_transaction_commit_get_changes(
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen struct mailbox_transaction_context **_t,
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen struct mail_transaction_commit_changes *changes_r)
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen{
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen struct mailbox_transaction_context *t = *_t;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen t->box->transaction_count--;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen *_t = NULL;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen return t->box->v.transaction_commit(t, changes_r);
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen}
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
ccd7b4e0a5f09058a59cc4b3f878254e93e7cb0aTimo Sirainenvoid mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
ccd7b4e0a5f09058a59cc4b3f878254e93e7cb0aTimo Sirainen{
ccd7b4e0a5f09058a59cc4b3f878254e93e7cb0aTimo Sirainen struct mailbox_transaction_context *t = *_t;
ccd7b4e0a5f09058a59cc4b3f878254e93e7cb0aTimo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen t->box->transaction_count--;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_t = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen t->box->v.transaction_rollback(t);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenunsigned int mailbox_transaction_get_count(const struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->transaction_count;
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen uint64_t max_modseq,
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen ARRAY_TYPE(seq_range) *seqs)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen t->box->v.transaction_set_max_modseq(t, max_modseq, seqs);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainenstruct mailbox *
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainenmailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return t->box;
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct mail_save_context *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenmailbox_save_alloc(struct mailbox_transaction_context *t)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_save_context *ctx;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen ctx = t->box->v.save_alloc(t);
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen ctx->received_date = (time_t)-1;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen ctx->save_date = (time_t)-1;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen return ctx;
efeb13303798b47d2c4295468d233c1bcfd79c94Timo Sirainen}
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainenvoid mailbox_save_set_flags(struct mail_save_context *ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum mail_flags flags,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_keywords *keywords)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->flags = flags;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->keywords = keywords;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (keywords != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_keywords_ref(ctx->transaction->box, keywords);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_copy_flags(struct mail_save_context *ctx, struct mail *mail)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *const *keywords_list;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen keywords_list = mail_get_keywords(mail);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->keywords = str_array_length(keywords_list) == 0 ? NULL :
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_keywords_create_valid(ctx->transaction->box,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen keywords_list);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->flags = mail_get_flags(mail);
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen}
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainenvoid mailbox_save_set_min_modseq(struct mail_save_context *ctx,
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen uint64_t min_modseq)
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen{
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen ctx->min_modseq = min_modseq;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_set_received_date(struct mail_save_context *ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen time_t received_date, int timezone_offset)
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen{
6abf66a3731d52889517bd644595c540e3a9b3ecTimo Sirainen ctx->received_date = received_date;
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen ctx->received_tz_offset = timezone_offset;
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_set_save_date(struct mail_save_context *ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen time_t save_date)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->save_date = save_date;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_set_from_envelope(struct mail_save_context *ctx,
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen const char *envelope)
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen{
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen i_free(ctx->from_envelope);
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen ctx->from_envelope = i_strdup(envelope);
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen}
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainenvoid mailbox_save_set_uid(struct mail_save_context *ctx, uint32_t uid)
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen{
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen ctx->uid = uid;
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen}
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainenvoid mailbox_save_set_guid(struct mail_save_context *ctx, const char *guid)
5446576156fbe26e07a5cb964a900281d283f387Timo Sirainen{
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen i_assert(guid == NULL || *guid != '\0');
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen
53c384be5f8f27945fd61b8a0d731a93a261628fTimo Sirainen i_free(ctx->guid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->guid = i_strdup(guid);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_set_pop3_uidl(struct mail_save_context *ctx, const char *uidl)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_free(ctx->pop3_uidl);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->pop3_uidl = i_strdup(uidl);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_set_dest_mail(struct mail_save_context *ctx,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail *mail)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->dest_mail = mail;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox *box = (*ctx)->transaction->box;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mail_index_is_deleted(box->index)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_set_deleted(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->v.save_begin == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Saving messages not supported");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen ret = box->v.save_begin(*ctx, input);
0c47c2096714b50880d48d00ce0bf28349eb4aceTimo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ret < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_save_cancel(ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_save_continue(struct mail_save_context *ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ctx->transaction->box->v.save_continue(ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_save_finish(struct mail_save_context **_ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
d8504a5ac72efb86a8da852c8d814ccaf0ae8625Timo Sirainen struct mail_save_context *ctx = *_ctx;
d8504a5ac72efb86a8da852c8d814ccaf0ae8625Timo Sirainen struct mailbox *box = ctx->transaction->box;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_keywords *keywords = ctx->keywords;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_ctx = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = box->v.save_finish(ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (keywords != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_keywords_unref(box, &keywords);
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen return ret;
cd70f7aec3bf49147fa80b77dd7ede7d7697202eTimo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_save_cancel(struct mail_save_context **_ctx)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_save_context *ctx = *_ctx;
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen struct mailbox *box = ctx->transaction->box;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_keywords *keywords = ctx->keywords;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_ctx = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx->transaction->box->v.save_cancel(ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (keywords != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_keywords_unref(box, &keywords);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenint mailbox_copy(struct mail_save_context **_ctx, struct mail *mail)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_save_context *ctx = *_ctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox *box = ctx->transaction->box;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_keywords *keywords = ctx->keywords;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
975a784c2e02ecdcb56efb7a1db5e4769c7756d8Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *_ctx = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (mail_index_is_deleted(box->index)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_set_deleted(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_save_cancel(_ctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ret = ctx->transaction->box->v.copy(ctx, mail);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (keywords != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_keywords_unref(box, &keywords);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainenbool mailbox_is_inconsistent(struct mailbox *box)
31d32d39dd09be0625a6d92ee715155f5d679515Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return box->mailbox_deleted || box->v.is_inconsistent(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_set_deleted(struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Mailbox was deleted under us");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->mailbox_deleted = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid mailbox_refresh_permissions(struct mailbox *box)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *origin, *dir_origin;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen gid_t dir_gid;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (box->input != NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->file_create_mode = 0600;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->dir_create_mode = 0700;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->file_create_gid = (gid_t)-1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->file_create_gid_origin = "defaults";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_list_get_permissions(box->list, box->name,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &box->file_create_mode,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &box->file_create_gid, &origin);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen box->file_create_gid_origin = p_strdup(box->pool, origin);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_list_get_dir_permissions(box->list, box->name,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &box->dir_create_mode,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &dir_gid, &dir_origin);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainenint mailbox_create_fd(struct mailbox *box, const char *path, int flags,
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen int *fd_r)
9bbfe7f5ff821cac11d1d2550a91b148f389d82cTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mode_t old_mask;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int fd;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(box->file_create_mode != 0);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert((flags & O_CREAT) != 0);
173fc9ed37637e4609b1ecc9415a9b92067eeeb2Timo Sirainen
173fc9ed37637e4609b1ecc9415a9b92067eeeb2Timo Sirainen *fd_r = -1;
173fc9ed37637e4609b1ecc9415a9b92067eeeb2Timo Sirainen
173fc9ed37637e4609b1ecc9415a9b92067eeeb2Timo Sirainen old_mask = umask(0);
173fc9ed37637e4609b1ecc9415a9b92067eeeb2Timo Sirainen fd = open(path, flags, box->file_create_mode);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen umask(old_mask);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (fd != -1) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* ok */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (errno == EEXIST) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* O_EXCL used, caller will handle this error */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (errno == ENOENT) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mailbox_set_deleted(box);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (mail_storage_set_error_from_errno(box->storage)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen mail_storage_set_critical(box->storage,
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen "open(%s, O_CREAT) failed: %m", path);
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen return -1;
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen }
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen if (box->file_create_gid != (gid_t)-1) {
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen if (fchown(fd, (uid_t)-1, box->file_create_gid) == 0) {
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen /* ok */
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen } else if (errno == EPERM) {
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen mail_storage_set_critical(box->storage, "%s",
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen eperm_error_get_chgrp("fchown", path,
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen box->file_create_gid,
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen box->file_create_gid_origin));
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen } else {
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen mail_storage_set_critical(box->storage,
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen "fchown(%s) failed: %m", path);
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen }
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen }
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen *fd_r = fd;
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen return 1;
f3053c3637f64633c8ef642e1b9b689b333ebf73Timo Sirainen}
03936179f87aebde358dbe1ca8c34e5b5551db45Timo Sirainen