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