mail-storage.c revision f86e4521d7864d385e3397a58eaa4b9c8ed178d8
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "lib.h"
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen#include "ioloop.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "array.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "str.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "var-expand.h"
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen#include "mail-index-private.h"
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen#include "mailbox-list-private.h"
c4cfee078c4a185b5ba8f0c55f51275b7e885b2cTimo Sirainen#include "mail-storage-private.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "mail-namespace.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include "mail-search.h"
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen#include <stdlib.h>
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen#include <time.h>
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen#include <ctype.h>
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen/* Message to show to users when critical error occurs */
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen#define CRITICAL_MSG \
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen "Internal error occurred. Refer to server log for more information."
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen#define DEFAULT_MAX_KEYWORD_LENGTH 50
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstruct mail_storage_module_register mail_storage_module_register = { 0 };
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstruct mail_module_register mail_module_register = { 0 };
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstruct mail_storage_mail_index_module mail_storage_mail_index_module =
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen MODULE_CONTEXT_INIT(&mail_index_module_register);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainenvoid (*hook_mail_storage_created)(struct mail_storage *storage);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenvoid (*hook_mailbox_opened)(struct mailbox *box) = NULL;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenstatic ARRAY_DEFINE(storages, struct mail_storage *);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenvoid mail_storage_init(void)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mailbox_lists_init();
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen i_array_init(&storages, 8);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen}
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainenvoid mail_storage_deinit(void)
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen{
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen if (array_is_created(&storages))
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen array_free(&storages);
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen mailbox_lists_deinit();
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen}
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainenvoid mail_storage_class_register(struct mail_storage *storage_class)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen if (storage_class->v.class_init != NULL)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen storage_class->v.class_init();
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen /* append it after the list, so the autodetection order is correct */
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen array_append(&storages, &storage_class, 1);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen}
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenvoid mail_storage_class_unregister(struct mail_storage *storage_class)
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen{
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen struct mail_storage *const *classes;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen unsigned int i, count;
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen classes = array_get(&storages, &count);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen for (i = 0; i < count; i++) {
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen if (classes[i] == storage_class) {
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen array_delete(&storages, i, 1);
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen break;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen }
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen }
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen storage_class->v.class_deinit();
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen}
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainenvoid mail_storage_parse_env(enum mail_storage_flags *flags_r,
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen enum file_lock_method *lock_method_r)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen{
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen const char *str;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r = 0;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("FULL_FILESYSTEM_ACCESS") != NULL)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_FULL_FS_ACCESS;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("DEBUG") != NULL)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_DEBUG;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("MMAP_DISABLE") != NULL)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_MMAP_DISABLE;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("MMAP_NO_WRITE") != NULL)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_MMAP_NO_WRITE;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("DOTLOCK_USE_EXCL") != NULL)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_DOTLOCK_USE_EXCL;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("MAIL_SAVE_CRLF") != NULL)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_SAVE_CRLF;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (getenv("FSYNC_DISABLE") != NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_FSYNC_DISABLE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (getenv("MAIL_NFS_STORAGE") != NULL)
9d3ccd79130199ffdb19a688027d49bf20a4aaaaTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (getenv("MAIL_NFS_INDEX") != NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_NFS_FLUSH_INDEX;
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen if ((*flags_r & MAIL_STORAGE_FLAG_MMAP_DISABLE) == 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_fatal("mail_nfs_index=yes requires mmap_disable=yes");
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen if ((*flags_r & MAIL_STORAGE_FLAG_FSYNC_DISABLE) != 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_fatal("mail_nfs_index=yes requires fsync_disable=no");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen str = getenv("POP3_UIDL_FORMAT");
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen if (str != NULL && (str = strchr(str, '%')) != NULL &&
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen str != NULL && var_get_key(str + 1) == 'm')
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *flags_r |= MAIL_STORAGE_FLAG_KEEP_HEADER_MD5;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen str = getenv("LOCK_METHOD");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (str == NULL || strcmp(str, "fcntl") == 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *lock_method_r = FILE_LOCK_METHOD_FCNTL;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen else if (strcmp(str, "flock") == 0)
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen *lock_method_r = FILE_LOCK_METHOD_FLOCK;
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen else if (strcmp(str, "dotlock") == 0)
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen *lock_method_r = FILE_LOCK_METHOD_DOTLOCK;
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen else
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen i_fatal("Unknown lock_method: %s", str);
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen}
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainenstatic struct mail_storage *mail_storage_find(const char *name)
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen{
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen struct mail_storage *const *classes;
be889d9b142fbb5604a922c6955bd7f6ea32f163Timo Sirainen unsigned int i, count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(name != NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen classes = array_get(&storages, &count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < count; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (strcasecmp(classes[i]->name, name) == 0)
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen return classes[i];
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return NULL;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
0cea9b1f4fa0495a48f5f097e40492517d67e1baTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic struct mail_storage *
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenmail_storage_autodetect(const char *data, enum mail_storage_flags flags)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_storage *const *classes;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int i, count;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen classes = array_get(&storages, &count);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (i = 0; i < count; i++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (classes[i]->v.autodetect != NULL &&
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen classes[i]->v.autodetect(data, flags))
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen return classes[i];
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen return NULL;
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainenmail_storage_set_autodetection(const char **data, const char **driver,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen enum mail_storage_flags *flags)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen const char *p;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* check if data is in driver:data format (eg. mbox:~/mail) */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen p = *data;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen while (i_isalnum(*p)) p++;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (*p == ':' && p != *data) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* no autodetection if the storage format is given. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *flags |= MAIL_STORAGE_FLAG_NO_AUTODETECTION;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *driver = t_strdup_until(*data, p);
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen *data = p + 1;
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenint mail_storage_create(struct mail_namespace *ns, const char *driver,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *data, const char *user,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen enum mail_storage_flags flags,
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen enum file_lock_method lock_method,
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen const char **error_r)
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen{
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen struct mail_storage *storage_class, *storage;
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen struct mail_storage *const *classes;
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen const char *home, *value;
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen unsigned int i, count;
e2e105f6182f550efa82f77d2a46b3e8a2d4da10Timo Sirainen
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen if (data == NULL)
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen data = "";
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen else if (driver == NULL)
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen mail_storage_set_autodetection(&data, &driver, &flags);
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen if (*data == '\0' && driver == NULL) {
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen /* use the first driver that works */
bc793bfcee945ce8871edfa298fe7235744425b6Timo Sirainen classes = array_get(&storages, &count);
bc793bfcee945ce8871edfa298fe7235744425b6Timo Sirainen } else if (driver == NULL) {
bc793bfcee945ce8871edfa298fe7235744425b6Timo Sirainen storage_class = mail_storage_autodetect(data, flags);
32c24eab7111799d880139634144ba8aea5a666eTimo Sirainen if (storage_class == NULL) {
32c24eab7111799d880139634144ba8aea5a666eTimo Sirainen *error_r = t_strdup_printf(
ea4ca37ec14913354f3a0deebc0df96097eb9468Timo Sirainen "Ambiguous mail location setting, "
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen "don't know what to do with it: %s "
ea4ca37ec14913354f3a0deebc0df96097eb9468Timo Sirainen "(try prefixing it with mbox: or maildir:)",
ea4ca37ec14913354f3a0deebc0df96097eb9468Timo Sirainen data);
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen return -1;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen }
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen classes = &storage_class;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen count = 1;
16598a1fb870ae40d6177755a4306216e4d6a4cdTimo Sirainen } else {
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen storage_class = mail_storage_find(driver);
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen if (storage_class == NULL) {
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen *error_r = t_strdup_printf(
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen "Unknown mail storage driver %s", driver);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen classes = &storage_class;
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen count = 1;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen }
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen
e4423c16a4f798ecf75ca2b0c3ef834000faed4bTimo Sirainen for (i = 0; i < count; i++) {
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen storage = classes[i]->v.alloc();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen storage->flags = flags;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen storage->lock_method = lock_method;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen storage->user = p_strdup(storage->pool, user);
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen storage->ns = ns;
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen storage->callbacks =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen p_new(storage->pool, struct mail_storage_callbacks, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen p_array_init(&storage->module_contexts, storage->pool, 5);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (classes[i]->v.create(storage, data, error_r) == 0)
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen break;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen if ((flags & MAIL_STORAGE_FLAG_DEBUG) != 0 && count > 1) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_info("%s: Couldn't create mail storage %s: %s",
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen classes[i]->name, data, *error_r);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen }
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen /* try the next one */
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen pool_unref(&storage->pool);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e4423c16a4f798ecf75ca2b0c3ef834000faed4bTimo Sirainen if (i == count) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (count <= 1) {
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen *error_r = t_strdup_printf("%s: %s", classes[0]->name,
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen *error_r);
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen return -1;
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen }
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen home = getenv("HOME");
73b251f13abfbd8e06c8c78784eb570d28fe7e40Timo Sirainen if (home == NULL || *home == '\0') home = "(not set)";
73b251f13abfbd8e06c8c78784eb570d28fe7e40Timo Sirainen
73b251f13abfbd8e06c8c78784eb570d28fe7e40Timo Sirainen *error_r = t_strdup_printf(
73b251f13abfbd8e06c8c78784eb570d28fe7e40Timo Sirainen "Mail storage autodetection failed with home=%s", home);
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen return -1;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen }
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen value = getenv("MAIL_MAX_KEYWORD_LENGTH");
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen storage->keyword_max_len = value != NULL ?
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen atoi(value) : DEFAULT_MAX_KEYWORD_LENGTH;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen if (hook_mail_storage_created != NULL) {
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen T_BEGIN {
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen hook_mail_storage_created(storage);
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen } T_END;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen }
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
73b251f13abfbd8e06c8c78784eb570d28fe7e40Timo Sirainen ns->storage = storage;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen mail_namespace_init_storage(ns);
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen return 0;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen}
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen
c4cfee078c4a185b5ba8f0c55f51275b7e885b2cTimo Sirainenvoid mail_storage_destroy(struct mail_storage **_storage)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen struct mail_storage *storage = *_storage;
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(storage != NULL);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen *_storage = NULL;
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen storage->v.destroy(storage);
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen mailbox_list_deinit(storage->list);
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen i_free(storage->error_string);
6e235046e1d8e9d89fc948f5c623676c20421a28Timo Sirainen pool_unref(&storage->pool);
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen}
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainen
abb83d133dd082527d500916fca66a72fbbbaa8dTimo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage)
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen{
e4423c16a4f798ecf75ca2b0c3ef834000faed4bTimo Sirainen i_free_and_null(storage->error_string);
e4423c16a4f798ecf75ca2b0c3ef834000faed4bTimo Sirainen
e4423c16a4f798ecf75ca2b0c3ef834000faed4bTimo Sirainen storage->error = MAIL_ERROR_NONE;
e4423c16a4f798ecf75ca2b0c3ef834000faed4bTimo Sirainen}
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen enum mail_error error, const char *string)
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen{
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen i_free(storage->error_string);
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen storage->error_string = i_strdup(string);
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen storage->error = error;
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen}
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage)
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen{
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen struct tm *tm;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen char str[256];
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen tm = localtime(&ioloop_time);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_free(storage->error_string);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen storage->error_string =
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen i_strdup(str) : i_strdup(CRITICAL_MSG);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen storage->error = MAIL_ERROR_TEMP;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const char *fmt, ...)
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen{
2bfc60a0c890585f1c9d75d721dc78d86d65f6caTimo Sirainen va_list va;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_storage_clear_error(storage);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (fmt != NULL) {
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen va_start(va, fmt);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen va_end(va);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* critical errors may contain sensitive data, so let user
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen see only "Internal error" with a timestamp to make it
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen easier to look from log files the actual error message. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_storage_set_internal_error(storage);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenchar mail_storage_get_hierarchy_sep(struct mail_storage *storage)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return mailbox_list_get_hierarchy_sep(storage->list);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainenstruct mailbox_list *mail_storage_get_list(struct mail_storage *storage)
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen{
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen return storage->list;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen}
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainenstruct mail_namespace *mail_storage_get_namespace(struct mail_storage *storage)
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainen{
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen return storage->ns;
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen}
265e9d8457aa5ce01b7aad954632aed8c36deeb8Timo Sirainen
11768c622a8e5aaf0e5d9b3c9a872867b62b4830Timo Sirainenvoid mail_storage_set_callbacks(struct mail_storage *storage,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_storage_callbacks *callbacks,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen void *context)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *storage->callbacks = *callbacks;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen storage->callback_context = context;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenint mail_storage_mailbox_create(struct mail_storage *storage, const char *name,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen bool directory)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_storage_clear_error(storage);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (!mailbox_list_is_valid_create_name(storage->list, name)) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen "Invalid mailbox name");
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
6ebcdea168735ee76e32b871c1f50f3526690447Timo Sirainen }
6ebcdea168735ee76e32b871c1f50f3526690447Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen return storage->v.mailbox_create(storage, name, directory);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenconst char *mail_storage_get_last_error(struct mail_storage *storage,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen enum mail_error *error_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* We get here only in error situations, so we have to return some
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen error. If storage->error is NONE, it means we forgot to set it at
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen some point.. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (storage->error == MAIL_ERROR_NONE) {
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen *error_r = MAIL_ERROR_TEMP;
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen return storage->error_string != NULL ? storage->error_string :
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen "BUG: Unknown internal error";
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen }
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen if (storage->error_string == NULL) {
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen /* This shouldn't happen.. */
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen storage->error_string =
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen i_strdup_printf("BUG: Unknown 0x%x error",
5c0034beb9933bca2a8b7d83d11dface1ea3b7faTimo Sirainen storage->error);
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen }
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen *error_r = storage->error;
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen return storage->error_string;
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen}
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenconst char *mail_storage_get_mailbox_path(struct mail_storage *storage,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const char *name, bool *is_file_r)
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen{
9bf2dc275ec21bff3d468ab1bc4fddc8874f7d1bTimo Sirainen *is_file_r = storage->mailbox_is_file;
7bb939ef70752f2731d27b18c944ea94e5b23eb5Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (*name == '\0')
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen name = NULL;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return mailbox_list_get_path(storage->list, name,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenconst char *mail_storage_get_mailbox_control_dir(struct mail_storage *storage,
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen const char *name)
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen{
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen if (*name == '\0')
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen name = NULL;
8e574a603c2c02105b073906a7ca91904271b80eTimo Sirainen
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen return mailbox_list_get_path(storage->list, name,
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL);
a04b6515c20b431294626400e173d81f3d25889bTimo Sirainen}
2b68f50813fe2bda94f227fc0144e4823b614474Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenconst char *mail_storage_get_mailbox_index_dir(struct mail_storage *storage,
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const char *name)
7dd73e056c7d9976080393d9cd731f69111818eeTimo Sirainen{
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen if (*name == '\0')
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen name = NULL;
2bfc60a0c890585f1c9d75d721dc78d86d65f6caTimo Sirainen
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen return mailbox_list_get_path(storage->list, name,
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
2bfc60a0c890585f1c9d75d721dc78d86d65f6caTimo Sirainen}
2bfc60a0c890585f1c9d75d721dc78d86d65f6caTimo Sirainen
9c4c535b86e9473ad97c6e9242ed84f3d9d69d0dTimo Sirainenenum mailbox_list_flags
9c4c535b86e9473ad97c6e9242ed84f3d9d69d0dTimo Sirainenmail_storage_get_list_flags(enum mail_storage_flags storage_flags)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen{
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen enum mailbox_list_flags list_flags = 0;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if ((storage_flags & MAIL_STORAGE_FLAG_DEBUG) != 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_DEBUG;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((storage_flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_FULL_FS_ACCESS;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if ((storage_flags & MAIL_STORAGE_FLAG_DOTLOCK_USE_EXCL) != 0)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen list_flags |= MAILBOX_LIST_FLAG_DOTLOCK_USE_EXCL;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if ((storage_flags & MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen list_flags |= MAILBOX_LIST_FLAG_NFS_FLUSH;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return list_flags;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen const char *error_string;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen enum mail_error error;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return FALSE;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mail_storage_set_error(storage, error, error_string);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return TRUE;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenstruct mailbox *mailbox_open(struct mail_storage *storage, const char *name,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct istream *input,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen enum mailbox_open_flags flags)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen struct mailbox *box;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen mail_storage_clear_error(storage);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen if (!mailbox_list_is_valid_existing_name(storage->list, name)) {
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen "Invalid mailbox name");
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen return NULL;
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen }
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen T_BEGIN {
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen box = storage->v.mailbox_open(storage, name, input, flags);
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen if (hook_mailbox_opened != NULL && box != NULL)
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen hook_mailbox_opened(box);
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen } T_END;
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen return box;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenint mailbox_close(struct mailbox **_box)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen struct mailbox *box = *_box;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen if (box->transaction_count != 0) {
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen i_panic("Trying to close mailbox %s with open transactions",
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen box->name);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen }
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen *_box = NULL;
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen return box->v.close(box);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenstruct mail_storage *mailbox_get_storage(struct mailbox *box)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return box->storage;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainenconst char *mailbox_get_name(struct mailbox *box)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return box->name;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenbool mailbox_is_readonly(struct mailbox *box)
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return box->v.is_readonly(box);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
dbd9604da561399cc6255289d5b6f6f662ab2d00Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenbool mailbox_allow_new_keywords(struct mailbox *box)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen return box->v.allow_new_keywords(box);
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mailbox_get_status(struct mailbox *box,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen enum mailbox_status_items items,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mailbox_status *status_r)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen box->v.get_status(box, items, status_r);
2c20ffcb5bb1ccdfdcd0b0ff0c7296f65b990362Timo Sirainen}
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenstruct mailbox_sync_context *
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenmailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
114a0f74e0f825c6bd8aeadfafb248a030762a1fTimo Sirainen return box->v.sync_init(box, flags);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainenbool mailbox_sync_next(struct mailbox_sync_context *ctx,
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen struct mailbox_sync_rec *sync_rec_r)
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen{
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen return ctx->box->v.sync_next(ctx, sync_rec_r);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen}
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenint mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen enum mailbox_status_items status_items,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct mailbox_status *status_r)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct mailbox_sync_context *ctx = *_ctx;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen *_ctx = NULL;
39e8567467cfe8eb63c00708a8653e92758908b9Timo Sirainen return ctx->box->v.sync_deinit(ctx, status_items, status_r);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen}
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenint mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen enum mailbox_status_items status_items,
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen struct mailbox_status *status_r)
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen{
a817fdcc43aedf423e2134091d5f83f91d64bcc9Timo Sirainen struct mailbox_sync_context *ctx;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen struct mailbox_sync_rec sync_rec;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* we don't care about mailbox's current state, so we might as well
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen fix inconsistency state */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx = mailbox_sync_init(box, flags);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen while (mailbox_sync_next(ctx, &sync_rec))
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen ;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return mailbox_sync_deinit(&ctx, status_items, status_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen#undef mailbox_notify_changes
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mailbox_notify_changes(struct mailbox *box, unsigned int min_interval,
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen mailbox_notify_callback_t *callback, void *context)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->notify_min_interval = min_interval;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->notify_callback = callback;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->notify_context = context;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
008a83e9f680f04f69789fb702232416eab2a86cTimo Sirainen box->v.notify_changes(box);
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen}
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenvoid mailbox_notify_changes_stop(struct mailbox *box)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen mailbox_notify_changes(box, 0, NULL, NULL);
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen}
e96fb85799dc95603bb1a6b4d3685df2d042a2f8Timo Sirainen
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainenint mailbox_keywords_create(struct mailbox *box, const char *const keywords[],
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mail_keywords **keywords_r)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *empty_keyword_list = NULL;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (keywords == NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen keywords = &empty_keyword_list;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen return box->v.keywords_create(box, keywords, keywords_r, FALSE);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainenstruct mail_keywords *
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenmailbox_keywords_create_valid(struct mailbox *box,
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen const char *const keywords[])
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen{
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen const char *empty_keyword_list = NULL;
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen struct mail_keywords *kw;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (keywords == NULL)
8c02331f9f569d8b30e74b6bc8550734d65f9daeTimo Sirainen keywords = &empty_keyword_list;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (box->v.keywords_create(box, keywords, &kw, TRUE) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_unreached();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return kw;
d5ac54ef50db16b50689b5c8b7bb64d344190832Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mailbox_keywords_free(struct mailbox *box,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_keywords **_keywords)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_keywords *keywords = *_keywords;
8b681dae1e8fa564649e703ab17398dcfaf896e4Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen *_keywords = NULL;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->v.keywords_free(keywords);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mailbox_get_uids(struct mailbox *box, uint32_t uid1, uint32_t uid2,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen uint32_t *seq1_r, uint32_t *seq2_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen box->v.get_uids(box, uid1, uid2, seq1_r, seq2_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct mailbox_header_lookup_ctx *
mailbox_header_lookup_init(struct mailbox *box, const char *const headers[])
{
return box->v.header_lookup_init(box, headers);
}
void mailbox_header_lookup_deinit(struct mailbox_header_lookup_ctx **_ctx)
{
struct mailbox_header_lookup_ctx *ctx = *_ctx;
*_ctx = NULL;
ctx->box->v.header_lookup_deinit(ctx);
}
struct mail_search_context *
mailbox_search_init(struct mailbox_transaction_context *t,
const char *charset, struct mail_search_arg *args,
const enum mail_sort_type *sort_program)
{
mail_search_args_simplify(args);
return t->box->v.search_init(t, charset, args, sort_program);
}
int mailbox_search_deinit(struct mail_search_context **_ctx)
{
struct mail_search_context *ctx = *_ctx;
*_ctx = NULL;
return ctx->transaction->box->v.search_deinit(ctx);
}
int mailbox_search_next(struct mail_search_context *ctx, struct mail *mail)
{
bool tryagain;
int ret;
while ((ret = mailbox_search_next_nonblock(ctx, mail,
&tryagain)) == 0) {
if (!tryagain)
break;
}
return ret;
}
int mailbox_search_next_nonblock(struct mail_search_context *ctx,
struct mail *mail, bool *tryagain_r)
{
return ctx->transaction->box->v.
search_next_nonblock(ctx, mail, tryagain_r);
}
struct mailbox_transaction_context *
mailbox_transaction_begin(struct mailbox *box,
enum mailbox_transaction_flags flags)
{
struct mailbox_transaction_context *trans;
box->transaction_count++;
trans = box->v.transaction_begin(box, flags);
trans->flags = flags;
return trans;
}
int mailbox_transaction_commit(struct mailbox_transaction_context **t)
{
uint32_t tmp;
return mailbox_transaction_commit_get_uids(t, &tmp, &tmp, &tmp);
}
int mailbox_transaction_commit_get_uids(struct mailbox_transaction_context **_t,
uint32_t *uid_validity_r,
uint32_t *first_saved_uid_r,
uint32_t *last_saved_uid_r)
{
struct mailbox_transaction_context *t = *_t;
t->box->transaction_count--;
*_t = NULL;
return t->box->v.transaction_commit(t, uid_validity_r,
first_saved_uid_r,
last_saved_uid_r);
}
void mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
{
struct mailbox_transaction_context *t = *_t;
t->box->transaction_count--;
*_t = NULL;
t->box->v.transaction_rollback(t);
}
unsigned int mailbox_transaction_get_count(struct mailbox *box)
{
return box->transaction_count;
}
struct mailbox *
mailbox_transaction_get_mailbox(struct mailbox_transaction_context *t)
{
return t->box;
}
int mailbox_save_init(struct mailbox_transaction_context *t,
enum mail_flags flags, struct mail_keywords *keywords,
time_t received_date, int timezone_offset,
const char *from_envelope, struct istream *input,
struct mail *dest_mail, struct mail_save_context **ctx_r)
{
if (t->box->v.save_init == NULL) {
mail_storage_set_error(t->box->storage, MAIL_ERROR_NOTPOSSIBLE,
"Saving messages not supported");
return -1;
}
if (t->box->v.save_init(t, flags, keywords,
received_date, timezone_offset,
from_envelope, input, dest_mail, ctx_r) < 0)
return -1;
(*ctx_r)->dest_mail = dest_mail;
return 0;
}
int mailbox_save_continue(struct mail_save_context *ctx)
{
return ctx->transaction->box->v.save_continue(ctx);
}
int mailbox_save_finish(struct mail_save_context **_ctx)
{
struct mail_save_context *ctx = *_ctx;
*_ctx = NULL;
return ctx->transaction->box->v.save_finish(ctx);
}
void mailbox_save_cancel(struct mail_save_context **_ctx)
{
struct mail_save_context *ctx = *_ctx;
*_ctx = NULL;
ctx->transaction->box->v.save_cancel(ctx);
}
int mailbox_copy(struct mailbox_transaction_context *t, struct mail *mail,
enum mail_flags flags, struct mail_keywords *keywords,
struct mail *dest_mail)
{
return t->box->v.copy(t, mail, flags, keywords, dest_mail);
}
bool mailbox_is_inconsistent(struct mailbox *box)
{
return box->mailbox_deleted || box->v.is_inconsistent(box);
}
void mailbox_set_deleted(struct mailbox *box)
{
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
"Mailbox was deleted under us");
box->mailbox_deleted = TRUE;
}
const char *mail_storage_eacces_msg(const char *func, const char *path)
{
const char *prev_path = path, *dir = "/", *p;
string_t *errmsg = t_str_new(256);
struct stat st;
int ret = -1;
str_printfa(errmsg, "%s(%s) failed: Permission denied (euid=%s egid=%s",
func, path, dec2str(geteuid()), dec2str(getegid()));
while ((p = strrchr(prev_path, '/')) != NULL) {
dir = t_strdup_until(prev_path, p);
ret = stat(dir, &st);
if (ret == 0 || errno != EACCES)
break;
prev_path = dir;
dir = "/";
}
if (ret == 0) {
if (access(dir, X_OK) < 0 && errno == EACCES)
str_printfa(errmsg, " missing +x perm: %s", dir);
else if (prev_path == path &&
access(path, R_OK) < 0 && errno == EACCES)
str_printfa(errmsg, " missing +r perm: %s", path);
}
str_append_c(errmsg, ')');
return str_c(errmsg);
}