bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen#include "lib.h"
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen#include "module-dir.h"
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen#include "quota-plugin.h"
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen#include "quota-private.h"
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen#include "doveadm-print.h"
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen#include "doveadm-mail.h"
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *doveadm_quota_plugin_version = DOVECOT_ABI_VERSION;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainenvoid doveadm_quota_plugin_init(struct module *module);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainenvoid doveadm_quota_plugin_deinit(void);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvistatic int cmd_quota_get_root(struct quota_root *root)
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen{
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen const char *const *res;
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi const char *error;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen uint64_t value, limit;
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi enum quota_get_result qret;
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi int ret = 0;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen res = quota_root_get_resources(root);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen for (; *res != NULL; res++) {
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi qret = quota_get_resource(root, "", *res, &value, &limit, &error);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print(root->set->name);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print(*res);
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi if (qret == QUOTA_GET_RESULT_LIMITED) {
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_num(value);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_num(limit);
73a913fe54721ff0bd5000c54d17225944cd2a61Timo Sirainen if (limit > 0)
73a913fe54721ff0bd5000c54d17225944cd2a61Timo Sirainen doveadm_print_num(value*100 / limit);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen else
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print("0");
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi } else if (qret == QUOTA_GET_RESULT_UNLIMITED) {
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_num(value);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print("-");
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print("0");
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen } else {
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi i_error("Failed to get quota resource %s: %s",
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi *res, error);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print("error");
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print("error");
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print("error");
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi ret = -1;
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen }
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen }
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi return ret;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen}
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenstatic int
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvicmd_quota_get_run(struct doveadm_mail_cmd_context *ctx,
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen struct mail_user *user)
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen{
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen struct quota_user *quser = QUOTA_USER_CONTEXT(user);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen struct quota_root *const *root;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (quser == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Quota not enabled");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_NOTFOUND);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return -1;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
a5da67c3720c98da722ec5e3c7fed13d15cfec72Timo Sirainen
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi int ret = 0;
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen array_foreach(&quser->quota->roots, root)
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi if (cmd_quota_get_root(*root) < 0)
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi ret = -1;
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi if (ret < 0)
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi doveadm_mail_failed_error(ctx, MAIL_ERROR_TEMP);
f4bc02a62f7f0c6e08f84a2b0e535466c012df04Martti Rannanjärvi return ret;
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen}
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen
f24b881d73ecb71938c9f46faa607529c0c58cd5Timo Sirainenstatic void cmd_quota_get_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen const char *const args[] ATTR_UNUSED)
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen{
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_header("root", "Quota name", 0);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_header("type", "Type", 0);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_header("value", "Value",
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_RIGHT_JUSTIFY);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_header("limit", "Limit",
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_RIGHT_JUSTIFY);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_header("percent", "%",
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_RIGHT_JUSTIFY);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen}
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainenstatic struct doveadm_mail_cmd_context *
bc10373fc050eb9dd23f6ed5ee8207d0e4d142eeTimo Sirainencmd_quota_get_alloc(void)
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen{
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen struct doveadm_mail_cmd_context *ctx;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
bc10373fc050eb9dd23f6ed5ee8207d0e4d142eeTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
9a54cc7fc2aee1e329082af1d562e5dfefa40e7fTimo Sirainen ctx->v.run = cmd_quota_get_run;
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen ctx->v.init = cmd_quota_get_init;
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen return ctx;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen}
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenstatic int
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainencmd_quota_recalc_run(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen struct mail_user *user)
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen{
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen struct quota_user *quser = QUOTA_USER_CONTEXT(user);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen struct quota_root *const *root;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen struct quota_transaction_context trans;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen if (quser == NULL) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_error("Quota not enabled");
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen doveadm_mail_failed_error(ctx, MAIL_ERROR_NOTFOUND);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return -1;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
a5da67c3720c98da722ec5e3c7fed13d15cfec72Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&trans);
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen trans.quota = quser->quota;
39dea5f2e78f6bfc3adc0655176f596ee211938fTimo Sirainen trans.recalculate = QUOTA_RECALCULATE_FORCED;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
9d3f82fe687d9ca62ed501fa741730c50c6714c4Aki Tuomi array_foreach(&quser->quota->roots, root) {
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi const char *error;
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi if ((*root)->backend.v.update(*root, &trans, &error) < 0)
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi i_error("Recalculating quota failed: %s", error);
9d3f82fe687d9ca62ed501fa741730c50c6714c4Aki Tuomi if ((*root)->backend.v.flush != NULL)
9d3f82fe687d9ca62ed501fa741730c50c6714c4Aki Tuomi (*root)->backend.v.flush(*root);
9d3f82fe687d9ca62ed501fa741730c50c6714c4Aki Tuomi }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return 0;
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen}
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainenstatic struct doveadm_mail_cmd_context *
bc10373fc050eb9dd23f6ed5ee8207d0e4d142eeTimo Sirainencmd_quota_recalc_alloc(void)
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen{
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen struct doveadm_mail_cmd_context *ctx;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
bc10373fc050eb9dd23f6ed5ee8207d0e4d142eeTimo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
9a54cc7fc2aee1e329082af1d562e5dfefa40e7fTimo Sirainen ctx->v.run = cmd_quota_recalc_run;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen return ctx;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen}
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomistatic struct doveadm_cmd_ver2 quota_commands[] = {
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi {
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi .name = "quota get",
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi .usage = "",
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi .mail_cmd = cmd_quota_get_alloc,
e6e5687226dc976061bffac9e7410ff14244e54fAki TuomiDOVEADM_CMD_PARAMS_START
e6e5687226dc976061bffac9e7410ff14244e54fAki TuomiDOVEADM_CMD_MAIL_COMMON
e6e5687226dc976061bffac9e7410ff14244e54fAki TuomiDOVEADM_CMD_PARAMS_END
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi },
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi {
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi .name = "quota recalc",
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi .usage = "",
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi .mail_cmd = cmd_quota_recalc_alloc,
e6e5687226dc976061bffac9e7410ff14244e54fAki TuomiDOVEADM_CMD_PARAMS_START
e6e5687226dc976061bffac9e7410ff14244e54fAki TuomiDOVEADM_CMD_MAIL_COMMON
e6e5687226dc976061bffac9e7410ff14244e54fAki TuomiDOVEADM_CMD_PARAMS_END
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi }
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen};
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainenvoid doveadm_quota_plugin_init(struct module *module ATTR_UNUSED)
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen{
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen unsigned int i;
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen
bc85bdcdebb2224e45e6c2bbc288e9ce59f651d9Timo Sirainen for (i = 0; i < N_ELEMENTS(quota_commands); i++)
e6e5687226dc976061bffac9e7410ff14244e54fAki Tuomi doveadm_cmd_register_ver2(&quota_commands[i]);
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen}
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainenvoid doveadm_quota_plugin_deinit(void)
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen{
9563e6542b7a8a13b13a0ef62ec68b0383b99293Timo Sirainen}