bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen/* Quota reporting based on simply summing sizes of all files in mailbox
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen together. */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "lib.h"
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen#include "array.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "str.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota-private.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <unistd.h>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <dirent.h>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <sys/stat.h>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstruct quota_count_path {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen const char *path;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen bool is_file;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo SirainenARRAY_DEFINE_TYPE(quota_count_path, struct quota_count_path);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenextern struct quota_backend quota_backend_dirsize;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic struct quota_root *dirsize_quota_alloc(void)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return i_new(struct quota_root, 1);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainenstatic int dirsize_quota_init(struct quota_root *root, const char *args,
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen const char **error_r)
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen{
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen root->auto_updating = TRUE;
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen return quota_root_default_init(root, args, error_r);
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen}
e2e64c109827f782e9e20b50a15c7489479bcadaTimo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstatic void dirsize_quota_deinit(struct quota_root *_root)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_free(_root);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic const char *const *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendirsize_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen static const char *resources[] = { QUOTA_NAME_STORAGE_KILOBYTES, NULL };
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return resources;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvistatic int get_dir_usage(const char *dir, uint64_t *value,
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi const char **error_r)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen DIR *dirp;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen string_t *path;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct dirent *d;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct stat st;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen unsigned int path_pos;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen dirp = opendir(dir);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (dirp == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (errno == ENOENT)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi *error_r = t_strdup_printf("opendir(%s) failed: %m", dir);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen path = t_str_new(128);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(path, dir);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append_c(path, '/');
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen path_pos = str_len(path);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ret = 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen while ((d = readdir(dirp)) != NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (d->d_name[0] == '.' &&
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (d->d_name[1] == '\0' ||
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* skip . and .. */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen continue;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_truncate(path, path_pos);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(path, d->d_name);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (lstat(str_c(path), &st) < 0) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (errno == ENOENT)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen continue;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi *error_r = t_strdup_printf("lstat(%s) failed: %m", dir);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ret = -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen break;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen } else if (S_ISDIR(st.st_mode)) {
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi if (get_dir_usage(str_c(path), value, error_r) < 0) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen ret = -1;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen break;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen } else {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen *value += st.st_size;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (void)closedir(dirp);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvistatic int get_usage(const char *path, bool is_file, uint64_t *value_r,
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi const char **error_r)
d735048af768fcac51aff26931b9887182a13554Timo Sirainen{
d735048af768fcac51aff26931b9887182a13554Timo Sirainen struct stat st;
d735048af768fcac51aff26931b9887182a13554Timo Sirainen
d735048af768fcac51aff26931b9887182a13554Timo Sirainen if (is_file) {
d735048af768fcac51aff26931b9887182a13554Timo Sirainen if (lstat(path, &st) < 0) {
d735048af768fcac51aff26931b9887182a13554Timo Sirainen if (errno == ENOENT)
d735048af768fcac51aff26931b9887182a13554Timo Sirainen return 0;
d735048af768fcac51aff26931b9887182a13554Timo Sirainen
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi *error_r = t_strdup_printf("lstat(%s) failed: %m", path);
d735048af768fcac51aff26931b9887182a13554Timo Sirainen return -1;
d735048af768fcac51aff26931b9887182a13554Timo Sirainen }
d735048af768fcac51aff26931b9887182a13554Timo Sirainen *value_r += st.st_size;
d735048af768fcac51aff26931b9887182a13554Timo Sirainen } else {
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi if (get_dir_usage(path, value_r, error_r) < 0)
d735048af768fcac51aff26931b9887182a13554Timo Sirainen return -1;
d735048af768fcac51aff26931b9887182a13554Timo Sirainen }
d735048af768fcac51aff26931b9887182a13554Timo Sirainen return 0;
d735048af768fcac51aff26931b9887182a13554Timo Sirainen}
d735048af768fcac51aff26931b9887182a13554Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void quota_count_path_add(ARRAY_TYPE(quota_count_path) *paths,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const char *path, bool is_file)
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen{
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen struct quota_count_path *count_path;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen unsigned int i, count;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t path_len;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen path_len = strlen(path);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen count_path = array_get_modifiable(paths, &count);
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen for (i = 0; i < count; ) {
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen if (strncmp(count_path[i].path, path,
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen strlen(count_path[i].path)) == 0) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* this path has already been counted */
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen return;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen }
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen if (strncmp(count_path[i].path, path, path_len) == 0 &&
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen count_path[i].path[path_len] == '/') {
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen /* the new path contains the existing path.
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen drop it and see if there are more to drop. */
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen array_delete(paths, i, 1);
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen count_path = array_get_modifiable(paths, &count);
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen } else {
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen i++;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen }
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen }
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen
9912076f6653ddfa04f5c4208c1cfc9f83d1dc04Timo Sirainen count_path = array_append_space(paths);
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen count_path->path = t_strdup(path);
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen count_path->is_file = is_file;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen}
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic int
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärviget_quota_root_usage(struct quota_root *root, uint64_t *value_r,
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi const char **error_r)
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_namespace *const *namespaces;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_TYPE(quota_count_path) paths;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen const struct quota_count_path *count_paths;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen unsigned int i, count;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen const char *path;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen bool is_file;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen t_array_init(&paths, 8);
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]))
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen continue;
2d8b23805db6f06b8b38174fb6e135386694f429Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen is_file = mail_storage_is_mailbox_file(namespaces[i]->storage);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_root_path(namespaces[i]->list,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &path))
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen quota_count_path_add(&paths, path, FALSE);
d735048af768fcac51aff26931b9887182a13554Timo Sirainen
d735048af768fcac51aff26931b9887182a13554Timo Sirainen /* INBOX may be in different path. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(namespaces[i]->list, "INBOX",
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) > 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen quota_count_path_add(&paths, path, is_file);
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen }
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen /* now sum up the found paths */
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainen *value_r = 0;
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen count_paths = array_get(&paths, &count);
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen for (i = 0; i < count; i++) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (get_usage(count_paths[i].path, count_paths[i].is_file,
3f0ef4a2861bcc9e9e4b193c8412c8119bf5c37aMartti Rannanjärvi value_r, error_r) < 0)
f632ecfcabd7c701ab2b14f4eacb78117a31109dTimo Sirainen return -1;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen }
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen return 0;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen}
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvistatic enum quota_get_result
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainendirsize_quota_get_resource(struct quota_root *_root, const char *name,
a525be16a69367f43765d20c873b5f168c5b7ea3Martti Rannanjärvi uint64_t *value_r, const char **error_r)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen int ret;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
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;
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
12d7f667b636405ae54dcc4cb3031f4ba52aff04Martti Rannanjärvi ret = get_quota_root_usage(_root, value_r, error_r);
a525be16a69367f43765d20c873b5f168c5b7ea3Martti Rannanjärvi
1379bb74c2855aaf3415fdfe965164a44ac3c001Martti Rannanjärvi return ret < 0 ? QUOTA_GET_RESULT_INTERNAL_ERROR : QUOTA_GET_RESULT_LIMITED;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic int
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainendirsize_quota_update(struct quota_root *root ATTR_UNUSED,
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi struct quota_transaction_context *ctx ATTR_UNUSED,
7b3b617e946d5b32078baa821f5fc05f775e1dfeMartti Rannanjärvi const char **error_r ATTR_UNUSED)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenstruct quota_backend quota_backend_dirsize = {
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .name = "dirsize",
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .v = {
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .alloc = dirsize_quota_alloc,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .init = dirsize_quota_init,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .deinit = dirsize_quota_deinit,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .get_resources = dirsize_quota_root_get_resources,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .get_resource = dirsize_quota_get_resource,
5997118fa7aee2535edac28092261ca085a958aeMartti Rannanjärvi .update = dirsize_quota_update,
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen};