quota-clone-plugin.c revision 0d1b8b6bec79746c5d89d57dd8c1688946bd9237
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2015-2017 Dovecot authors, see the included COPYING file */
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#include "lib.h"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#include "module-context.h"
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen#include "ioloop.h"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#include "dict.h"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#include "mail-storage-private.h"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#include "quota.h"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#include "quota-clone-plugin.h"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen/* If mailbox is kept open for this many milliseconds after quota update,
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen flush quota-clone. */
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen#define QUOTA_CLONE_FLUSH_DELAY_MSECS (10*1000)
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#define DICT_QUOTA_CLONE_PATH DICT_PATH_PRIVATE"quota/"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#define DICT_QUOTA_CLONE_BYTES_PATH DICT_QUOTA_CLONE_PATH"storage"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#define DICT_QUOTA_CLONE_COUNT_PATH DICT_QUOTA_CLONE_PATH"messages"
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#define QUOTA_CLONE_USER_CONTEXT(obj) \
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen MODULE_CONTEXT(obj, quota_clone_user_module)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen#define QUOTA_CLONE_CONTEXT(obj) \
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen MODULE_CONTEXT(obj, quota_clone_storage_module)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(quota_clone_user_module,
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen &mail_user_module_register);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(quota_clone_storage_module,
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen &mail_storage_module_register);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstruct quota_clone_user {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen union mail_user_module_context module_ctx;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct dict *dict;
5da08ab71623953f248b24a21d45b02555bbb24bTimo Sirainen bool quota_flushing;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen};
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstruct quota_clone_mailbox {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen union mailbox_module_context module_ctx;
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen struct timeout *to_quota_flush;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen bool quota_changed;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen};
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainenstatic void quota_clone_flush_real(struct mailbox *box)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_user *quser =
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen QUOTA_CLONE_USER_CONTEXT(box->storage->user);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct dict_transaction_context *trans;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_root_iter *iter;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_root *root;
d861bc0977b229cdaeb3fb77377e2a2bd9d40d3dTimo Sirainen uint64_t bytes_value, count_value, limit;
661998e2ccd772ad92a9d4a75cb712692a8c94b3Timo Sirainen const char *error;
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen int ret_bytes, ret_count;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen /* we'll clone the first quota root */
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen iter = quota_root_iter_init(box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen root = quota_root_iter_next(iter);
f39a06c378f6ea80a4ae9d257f0d79221a945a57Timo Sirainen quota_root_iter_deinit(&iter);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen if (root == NULL) {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen /* no quota roots defined for this mailbox - ignore */
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen qbox->quota_changed = FALSE;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen return;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen }
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
d861bc0977b229cdaeb3fb77377e2a2bd9d40d3dTimo Sirainen /* get new values first */
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen ret_bytes = quota_get_resource(root, "", QUOTA_NAME_STORAGE_BYTES,
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen &bytes_value, &limit);
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen if (ret_bytes < 0) {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen i_error("quota_clone_plugin: Failed to lookup current quota bytes");
d861bc0977b229cdaeb3fb77377e2a2bd9d40d3dTimo Sirainen return;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen }
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen ret_count = quota_get_resource(root, "", QUOTA_NAME_MESSAGES,
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen &count_value, &limit);
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen if (ret_count < 0) {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen i_error("quota_clone_plugin: Failed to lookup current quota count");
d861bc0977b229cdaeb3fb77377e2a2bd9d40d3dTimo Sirainen return;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen }
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen if (ret_bytes == 0 && ret_count == 0) {
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen /* quota isn't enabled - no point in updating it */
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen return;
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen }
d861bc0977b229cdaeb3fb77377e2a2bd9d40d3dTimo Sirainen
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen /* Then update the resources that exist. The resources can't really
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen change unless the quota backend is changed, so we don't worry about
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen the special case of ret_count changing between 1 and 0. Note that
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen ret_count==1 also when quota is unlimited. */
d861bc0977b229cdaeb3fb77377e2a2bd9d40d3dTimo Sirainen trans = dict_transaction_begin(quser->dict);
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen if (ret_bytes > 0) {
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen dict_set(trans, DICT_QUOTA_CLONE_BYTES_PATH,
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen t_strdup_printf("%llu", (unsigned long long)bytes_value));
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen }
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen if (ret_count > 0) {
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen dict_set(trans, DICT_QUOTA_CLONE_COUNT_PATH,
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen t_strdup_printf("%llu", (unsigned long long)count_value));
a022e47f45597650f71f00c3af3fa783982a65adTimo Sirainen }
661998e2ccd772ad92a9d4a75cb712692a8c94b3Timo Sirainen if (dict_transaction_commit(&trans, &error) < 0)
661998e2ccd772ad92a9d4a75cb712692a8c94b3Timo Sirainen i_error("quota_clone_plugin: Failed to commit dict update: %s", error);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen else
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen qbox->quota_changed = FALSE;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainenstatic void quota_clone_flush(struct mailbox *box)
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen{
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen struct quota_clone_user *quser =
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen QUOTA_CLONE_USER_CONTEXT(box->storage->user);
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&qbox->to_quota_flush);
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen if (quser->quota_flushing) {
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen /* recursing back from quota recalculation */
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen } else if (qbox->quota_changed) {
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen quser->quota_flushing = TRUE;
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen quota_clone_flush_real(box);
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen quser->quota_flushing = FALSE;
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen }
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen}
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainenstatic void quota_clone_changed(struct mailbox *box)
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen{
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen qbox->quota_changed = TRUE;
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen if (qbox->to_quota_flush == NULL) {
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen qbox->to_quota_flush = timeout_add(QUOTA_CLONE_FLUSH_DELAY_MSECS,
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen quota_clone_flush, box);
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen }
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen}
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic int quota_clone_save_finish(struct mail_save_context *ctx)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_mailbox *qbox =
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen QUOTA_CLONE_CONTEXT(ctx->transaction->box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen quota_clone_changed(ctx->transaction->box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen return qbox->module_ctx.super.save_finish(ctx);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic int
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenquota_clone_copy(struct mail_save_context *ctx, struct mail *mail)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_mailbox *qbox =
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen QUOTA_CLONE_CONTEXT(ctx->transaction->box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen quota_clone_changed(ctx->transaction->box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen return qbox->module_ctx.super.copy(ctx, mail);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic void
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenquota_clone_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen enum mailbox_sync_type sync_type)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen if (qbox->module_ctx.super.sync_notify != NULL)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen qbox->module_ctx.super.sync_notify(box, uid, sync_type);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen if (sync_type == MAILBOX_SYNC_TYPE_EXPUNGE)
5de0c65da362236080fa699af3da03e45e480ab8Timo Sirainen quota_clone_changed(box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic void quota_clone_mailbox_close(struct mailbox *box)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen qbox->module_ctx.super.close(box);
8705e45564a2e87d32bd825e0e997a8177846f77Timo Sirainen
588a0579058849aed9f7b59d8259e0c58d9fd23cTimo Sirainen quota_clone_flush(box);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic void quota_clone_mailbox_allocated(struct mailbox *box)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_user *quser =
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen QUOTA_CLONE_USER_CONTEXT(box->storage->user);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct mailbox_vfuncs *v = box->vlast;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_mailbox *qbox;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen if (quser == NULL)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen return;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen qbox = p_new(box->pool, struct quota_clone_mailbox, 1);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen qbox->module_ctx.super = *v;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen box->vlast = &qbox->module_ctx.super;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen v->save_finish = quota_clone_save_finish;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen v->copy = quota_clone_copy;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen v->sync_notify = quota_clone_mailbox_sync_notify;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen v->close = quota_clone_mailbox_close;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen MODULE_CONTEXT_SET(box, quota_clone_storage_module, qbox);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic void quota_clone_mail_user_deinit(struct mail_user *user)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_user *quser = QUOTA_CLONE_USER_CONTEXT(user);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen dict_deinit(&quser->dict);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen quser->module_ctx.super.deinit(user);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic void quota_clone_mail_user_created(struct mail_user *user)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct quota_clone_user *quser;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct dict_settings dict_set;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen struct dict *dict;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen const char *uri, *error;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen uri = mail_user_plugin_getenv(user, "quota_clone_dict");
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen if (uri == NULL || uri[0] == '\0') {
0d1d485939b9b7f1a0f588aea40c504e3d26e35bJ. Nick Koston if (user->mail_debug) {
0d1d485939b9b7f1a0f588aea40c504e3d26e35bJ. Nick Koston i_debug("The quota_clone_dict setting is missing from configuration");
0d1d485939b9b7f1a0f588aea40c504e3d26e35bJ. Nick Koston }
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen return;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen }
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&dict_set);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen dict_set.username = user->username;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen dict_set.base_dir = user->set->base_dir;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen (void)mail_user_get_home(user, &dict_set.home_dir);
20e04227229970d148801c507946666e2a9bd838Timo Sirainen if (dict_init(uri, &dict_set, &dict, &error) < 0) {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen i_error("quota_clone_dict: Failed to initialize '%s': %s",
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen uri, error);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen return;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen }
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen quser = p_new(user->pool, struct quota_clone_user, 1);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen quser->module_ctx.super = *v;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen user->vlast = &quser->module_ctx.super;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen v->deinit = quota_clone_mail_user_deinit;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen quser->dict = dict;
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen MODULE_CONTEXT_SET(user, quota_clone_user_module, quser);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenstatic struct mail_storage_hooks quota_clone_mail_storage_hooks = {
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen .mailbox_allocated = quota_clone_mailbox_allocated,
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen .mail_user_created = quota_clone_mail_user_created
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen};
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenvoid quota_clone_plugin_init(struct module *module ATTR_UNUSED)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen mail_storage_hooks_add(module, &quota_clone_mail_storage_hooks);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenvoid quota_clone_plugin_deinit(void)
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen{
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen mail_storage_hooks_remove(&quota_clone_mail_storage_hooks);
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen}
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainen
1f2f38f518ea14d1042c98ab039e6df053f7b285Timo Sirainenconst char *quota_clone_plugin_dependencies[] = { "quota", NULL };