bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen/* Quota reporting based on simply summing sizes of all files in mailbox
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo SirainenARRAY_DEFINE_TYPE(quota_count_path, struct quota_count_path);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenextern struct quota_backend quota_backend_dirsize;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic struct quota_root *dirsize_quota_alloc(void)
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainenstatic int dirsize_quota_init(struct quota_root *root, const char *args,
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen const char **error_r)
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen return quota_root_default_init(root, args, error_r);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstatic void dirsize_quota_deinit(struct quota_root *_root)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic const char *const *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendirsize_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen static const char *resources[] = { QUOTA_NAME_STORAGE_KILOBYTES, NULL };
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvistatic int get_dir_usage(const char *dir, uint64_t *value,
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi *error_r = t_strdup_printf("opendir(%s) failed: %m", dir);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* skip . and .. */
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi *error_r = t_strdup_printf("lstat(%s) failed: %m", dir);
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi if (get_dir_usage(str_c(path), value, error_r) < 0) {
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvistatic int get_usage(const char *path, bool is_file, uint64_t *value_r,
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi *error_r = t_strdup_printf("lstat(%s) failed: %m", path);
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi if (get_dir_usage(path, value_r, error_r) < 0)
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void quota_count_path_add(ARRAY_TYPE(quota_count_path) *paths,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen count_path = array_get_modifiable(paths, &count);
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen for (i = 0; i < count; ) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* this path has already been counted */
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen if (strncmp(count_path[i].path, path, path_len) == 0 &&
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen /* the new path contains the existing path.
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen drop it and see if there are more to drop. */
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen count_path = array_get_modifiable(paths, &count);
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärviget_quota_root_usage(struct quota_root *root, uint64_t *value_r,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen namespaces = array_get(&root->quota->namespaces, &count);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen for (i = 0; i < count; i++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (!quota_root_is_namespace_visible(root, namespaces[i]))
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen is_file = mail_storage_is_mailbox_file(namespaces[i]->storage);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_root_path(namespaces[i]->list,
d735048af768fcac51aff26931b9887182a13554Timo Sirainen /* INBOX may be in different path. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(namespaces[i]->list, "INBOX",
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen /* now sum up the found paths */
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen for (i = 0; i < count; i++) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (get_usage(count_paths[i].path, count_paths[i].is_file,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainendirsize_quota_get_resource(struct quota_root *_root, const char *name,
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi if (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) != 0) {
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi *error_r = QUOTA_UNKNOWN_RESOURCE_ERROR_STRING;
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi return QUOTA_GET_RESULT_UNKNOWN_RESOURCE;
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi ret = get_quota_root_usage(_root, value_r, error_r);
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi return ret < 0 ? QUOTA_GET_RESULT_INTERNAL_ERROR : QUOTA_GET_RESULT_LIMITED;
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendirsize_quota_update(struct quota_root *root ATTR_UNUSED,
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi struct quota_transaction_context *ctx ATTR_UNUSED,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .get_resources = dirsize_quota_root_get_resources,