quota-storage.c revision 76b43e4417bab52e913da39b5f5bc2a130d3f149
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (c) 2005-2008 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "array.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "istream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-search.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-storage-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mailbox-list-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "quota-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "quota-plugin.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <sys/stat.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define QUOTA_CONTEXT(obj) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT(obj, quota_storage_module)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#define QUOTA_MAIL_CONTEXT(obj) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT(obj, quota_mail_module)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define QUOTA_LIST_CONTEXT(obj) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT(obj, quota_mailbox_list_module)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct quota_mailbox_list {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen union mailbox_list_module_context module_ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_storage *storage;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct quota_mailbox {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen union mailbox_module_context module_ctx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mailbox_transaction_context *expunge_trans;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_transaction_context *expunge_qt;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ARRAY_DEFINE(expunge_uids, uint32_t);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ARRAY_DEFINE(expunge_sizes, uoff_t);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int save_hack:1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int recalculate:1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(quota_storage_module,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &mail_storage_module_register);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(quota_mail_module, &mail_module_register);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(quota_mailbox_list_module,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &mailbox_list_module_register);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void quota_mail_expunge(struct mail *_mail)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(_mail->box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen union mail_module_context *qmail = QUOTA_MAIL_CONTEXT(mail);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* We need to handle the situation where multiple transactions expunged
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen the mail at the same time. In here we'll just save the message's
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen physical size and do the quota freeing later when the message was
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen known to be expunged. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_get_physical_size(_mail, &size) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!array_is_created(&qbox->expunge_uids)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_array_init(&qbox->expunge_uids, 64);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_array_init(&qbox->expunge_sizes, 64);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_append(&qbox->expunge_uids, &_mail->uid, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_append(&qbox->expunge_sizes, &size, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qmail->super.expunge(_mail);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct mailbox_transaction_context *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenquota_mailbox_transaction_begin(struct mailbox *box,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mailbox_transaction_flags flags)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen{
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct mailbox_transaction_context *t;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct quota_transaction_context *qt;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen t = qbox->module_ctx.super.transaction_begin(box, flags);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen qt = quota_transaction_begin(quota_set, box);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen MODULE_CONTEXT_SET(t, quota_storage_module, qt);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return t;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenquota_mailbox_transaction_commit(struct mailbox_transaction_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t *uid_validity_r,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t *first_saved_uid_r,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uint32_t *last_saved_uid_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_transaction_context *qt = QUOTA_CONTEXT(ctx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (qt->tmp_mail != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_free(&qt->tmp_mail);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (qbox->module_ctx.super.transaction_commit(ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uid_validity_r,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen first_saved_uid_r,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen last_saved_uid_r) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen quota_transaction_rollback(&qt);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (void)quota_transaction_commit(&qt);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenquota_mailbox_transaction_rollback(struct mailbox_transaction_context *ctx)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen{
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->box);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct quota_transaction_context *qt = QUOTA_CONTEXT(ctx);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (qt->tmp_mail != NULL)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen mail_free(&qt->tmp_mail);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qbox->module_ctx.super.transaction_rollback(ctx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen quota_transaction_rollback(&qt);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct mail *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenquota_mail_alloc(struct mailbox_transaction_context *t,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_fetch_field wanted_fields,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen union mail_module_context *qmail;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail *_mail;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_private *mail;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen _mail = qbox->module_ctx.super.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_alloc(t, wanted_fields, wanted_headers);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail = (struct mail_private *)_mail;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qmail = p_new(mail->pool, union mail_module_context, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qmail->super = mail->v;
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen mail->v.expunge = quota_mail_expunge;
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, quota_mail_module, qmail);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen return _mail;
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int quota_check(struct mailbox_transaction_context *t, struct mail *mail)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_transaction_context *qt = QUOTA_CONTEXT(t);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen bool too_large;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = quota_try_alloc(qt, mail, &too_large);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else if (ret == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_set_error(t->box->storage, MAIL_ERROR_NOSPACE,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Quota exceeded");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_set_critical(t->box->storage,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Internal quota calculation error");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenquota_copy(struct mailbox_transaction_context *t, struct mail *mail,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail *dest_mail)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_transaction_context *qt = QUOTA_CONTEXT(t);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (dest_mail == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we always want to know the mail size */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (qt->tmp_mail == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qt->tmp_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest_mail = qt->tmp_mail;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qbox->save_hack = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (qbox->module_ctx.super.copy(t, mail, flags, keywords,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dest_mail) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* if copying used saving internally, we already checked the quota
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen and set qbox->save_hack = TRUE. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return qbox->save_hack ? 0 : quota_check(t, dest_mail);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenquota_save_init(struct mailbox_transaction_context *t,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen time_t received_date, int timezone_offset,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *from_envelope, struct istream *input,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail *dest_mail, struct mail_save_context **ctx_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_transaction_context *qt = QUOTA_CONTEXT(t);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(t->box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct stat *st;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen st = i_stream_stat(input, TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (st != NULL && st->st_size != -1) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Input size is known, check for quota immediately. This
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen check isn't perfect, especially because input stream's
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen linefeeds may contain CR+LFs while physical message would
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen only contain LFs. With mbox some headers might be skipped
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen entirely.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen I think these don't really matter though compared to the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen benefit of giving "out of quota" error before sending the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen full mail. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen bool too_large;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = quota_test_alloc(qt, st->st_size, &too_large);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_set_error(t->box->storage,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAIL_ERROR_NOSPACE, "Quota exceeded");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else if (ret < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_set_critical(t->box->storage,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Internal quota calculation error");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (dest_mail == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we always want to know the mail size */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qt->tmp_mail == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qt->tmp_mail = mail_alloc(t, MAIL_FETCH_PHYSICAL_SIZE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen dest_mail = qt->tmp_mail;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return qbox->module_ctx.super.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen save_init(t, flags, keywords, received_date,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen timezone_offset, from_envelope,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen input, dest_mail, ctx_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int quota_save_finish(struct mail_save_context *ctx)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_transaction_context *qt = QUOTA_CONTEXT(ctx->transaction);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->transaction->box);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qbox->module_ctx.super.save_finish(ctx) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->save_hack = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return quota_check(ctx->transaction, ctx->dest_mail != NULL ?
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->dest_mail : qt->tmp_mail);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void quota_mailbox_sync_finish(struct quota_mailbox *qbox)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (array_is_created(&qbox->expunge_uids)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_clear(&qbox->expunge_uids);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_clear(&qbox->expunge_sizes);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qbox->expunge_qt != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qbox->expunge_qt->tmp_mail != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_free(&qbox->expunge_qt->tmp_mail);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mailbox_transaction_rollback(&qbox->expunge_trans);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (void)quota_transaction_commit(&qbox->expunge_qt);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->recalculate = FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void quota_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mailbox_sync_type sync_type)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const uint32_t *uids;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const uoff_t *sizep;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i, count;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen uoff_t size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (qbox->module_ctx.super.sync_notify != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen qbox->module_ctx.super.sync_notify(box, uid, sync_type);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (sync_type != MAILBOX_SYNC_TYPE_EXPUNGE || qbox->recalculate) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (uid == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen quota_mailbox_sync_finish(qbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we're in the middle of syncing the mailbox, so it's a bad idea to
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen try and get the message sizes at this point. Rely on sizes that
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen we saved earlier, or recalculate the whole quota if we don't know
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen the size. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!array_is_created(&qbox->expunge_uids)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i = count = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uids = array_get(&qbox->expunge_uids, &count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0; i < count; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (uids[i] == uid)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qbox->expunge_qt == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->expunge_qt = quota_transaction_begin(quota_set, box);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (i != count) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we already know the size */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sizep = array_idx(&qbox->expunge_sizes, i);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_free_bytes(qbox->expunge_qt, *sizep);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* try to look up the size. this works only if it's cached. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qbox->expunge_qt->tmp_mail == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->expunge_trans = mailbox_transaction_begin(box, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->expunge_qt->tmp_mail =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_alloc(qbox->expunge_trans,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAIL_FETCH_PHYSICAL_SIZE, NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_set_uid(qbox->expunge_qt->tmp_mail, uid) &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_get_physical_size(qbox->expunge_qt->tmp_mail, &size) == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_free_bytes(qbox->expunge_qt, size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* there's no way to get the size. recalculate the quota. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_recalculate(qbox->expunge_qt);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->recalculate = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int quota_mailbox_sync_deinit(struct mailbox_sync_context *ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mailbox_status_items status_items,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mailbox_status *status_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->box);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* just in case sync_notify() wasn't called with uid=0 */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen quota_mailbox_sync_finish(qbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return qbox->module_ctx.super.sync_deinit(ctx, status_items, status_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int quota_mailbox_close(struct mailbox *box)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct quota_mailbox *qbox = QUOTA_CONTEXT(box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (array_is_created(&qbox->expunge_uids)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_free(&qbox->expunge_uids);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_free(&qbox->expunge_sizes);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(qbox->expunge_qt == NULL ||
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qbox->expunge_qt->tmp_mail == NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return qbox->module_ctx.super.close(box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct mailbox *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenquota_mailbox_open(struct mail_storage *storage, const char *name,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *input, enum mailbox_open_flags flags)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct mailbox *box;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct quota_mailbox *qbox;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen box = qstorage->super.mailbox_open(storage, name, input, flags);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (box == NULL)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return NULL;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen qbox = p_new(box->pool, struct quota_mailbox, 1);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen qbox->module_ctx.super = box->v;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen box->v.transaction_begin = quota_mailbox_transaction_begin;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen box->v.transaction_commit = quota_mailbox_transaction_commit;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen box->v.transaction_rollback = quota_mailbox_transaction_rollback;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen box->v.mail_alloc = quota_mail_alloc;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen box->v.save_init = quota_save_init;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen box->v.save_finish = quota_save_finish;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen box->v.copy = quota_copy;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen box->v.sync_notify = quota_mailbox_sync_notify;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen box->v.sync_deinit = quota_mailbox_sync_deinit;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen box->v.close = quota_mailbox_close;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MODULE_CONTEXT_SET(box, quota_storage_module, qbox);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return box;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenquota_mailbox_list_delete(struct mailbox_list *list, const char *name)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(list);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mailbox *box;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_search_context *ctx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mailbox_transaction_context *t;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_transaction_context *qt;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail *mail;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_search_arg search_arg;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_error error;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* This is a bit annoying to handle. We'll have to open the mailbox
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen and free the quota for all the messages existing in it. Open the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mailbox locked so that other processes can't mess up the quota
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen calculations by adding/removing mails while we're doing this. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen box = mailbox_open(qlist->storage, name, NULL, MAILBOX_OPEN_FAST |
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAILBOX_OPEN_KEEP_RECENT | MAILBOX_OPEN_KEEP_LOCKED);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (box == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (void)mail_storage_get_last_error(qlist->storage, &error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (error != MAIL_ERROR_NOTPOSSIBLE)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* mailbox isn't selectable */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return qlist->module_ctx.super.delete_mailbox(list, name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ, 0, NULL) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox_close(&box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memset(&search_arg, 0, sizeof(search_arg));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen search_arg.type = SEARCH_ALL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen t = mailbox_transaction_begin(box, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qt = QUOTA_CONTEXT(t);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx = mailbox_search_init(t, NULL, &search_arg, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail = mail_alloc(t, 0, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen while (mailbox_search_next(ctx, mail) > 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen quota_free(qt, mail);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_free(&mail);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = mailbox_search_deinit(&ctx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mailbox_transaction_rollback(&t);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = mailbox_transaction_commit(&t);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mailbox_close(&box);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* FIXME: here's an unfortunate race condition */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret < 0 ? -1 :
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qlist->module_ctx.super.delete_mailbox(list, name);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void quota_storage_destroy(struct mail_storage *storage)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_remove_user_storage(quota_set, storage);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (qstorage->super.destroy != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qstorage->super.destroy(storage);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid quota_mail_storage_created(struct mail_storage *storage)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(storage->list);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen union mail_storage_module_context *qstorage;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (quota_next_hook_mail_storage_created != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_next_hook_mail_storage_created(storage);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qlist->storage = storage;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qstorage = p_new(storage->pool, union mail_storage_module_context, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qstorage->super = storage->v;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen storage->v.destroy = quota_storage_destroy;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen storage->v.mailbox_open = quota_mailbox_open;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MODULE_CONTEXT_SET_SELF(storage, quota_storage_module, qstorage);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (storage->ns->type == NAMESPACE_PRIVATE &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (storage->ns->flags & NAMESPACE_FLAG_INTERNAL) == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* register to user's quota roots */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_add_user_storage(quota_set, storage);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid quota_mailbox_list_created(struct mailbox_list *list)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct quota_mailbox_list *qlist;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (quota_next_hook_mailbox_list_created != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen quota_next_hook_mailbox_list_created(list);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qlist = p_new(list->pool, struct quota_mailbox_list, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen qlist->module_ctx.super = list->v;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen list->v.delete_mailbox = quota_mailbox_list_delete;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen MODULE_CONTEXT_SET(list, quota_mailbox_list_module, qlist);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen