diff options
Diffstat (limited to 'imap4d/quota.c')
-rw-r--r-- | imap4d/quota.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/imap4d/quota.c b/imap4d/quota.c new file mode 100644 index 000000000..b39f0d8e9 --- /dev/null +++ b/imap4d/quota.c @@ -0,0 +1,203 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010 Free Software Foundation, Inc. + + GNU Mailutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Mailutils is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +#include "imap4d.h" + +struct imap4d_sizeinfo +{ + mu_off_t size; + mu_off_t nfiles; + mu_off_t ndirs; + mu_off_t nerrs; +}; + +static int +addsize (mu_folder_t folder, struct mu_list_response *resp, void *data) +{ + struct imap4d_sizeinfo *si = data; + + if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) + si->ndirs++; + + if (resp->type & MU_FOLDER_ATTRIBUTE_FILE) + { + mu_off_t size; + mu_mailbox_t mbox; + int rc; + + si->nfiles++; + + rc = mu_mailbox_create_from_record (&mbox, resp->format, resp->name); + + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_from_record", + resp->name, rc); + si->nerrs++; + return 0; + } + + rc = mu_mailbox_open (mbox, MU_STREAM_READ); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", + resp->name, rc); + si->nerrs++; + mu_mailbox_destroy (&mbox); + return 0; + } + + rc = mu_mailbox_get_size (mbox, &size); + mu_mailbox_destroy (&mbox); + + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", + resp->name, rc); + si->nerrs++; + return 0; + } + si->size += size; + } + return 0; +} + +void +directory_size (const char *dirname, mu_off_t *size) +{ + mu_folder_t folder; + struct imap4d_sizeinfo sizeinfo; + int status; + + status = mu_folder_create (&folder, dirname); + if (status) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", dirname, status); + return; + } + + status = mu_folder_open (folder, MU_STREAM_READ); + if (status) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", dirname, status); + mu_folder_destroy (&folder); + return; + } + + memset (&sizeinfo, 0, sizeof (sizeinfo)); + status = mu_folder_enumerate (folder, NULL, "*", 0, 0, NULL, + addsize, &sizeinfo); + if (status) + mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_enumerate", dirname, status); + else + { + mu_diag_output (MU_DIAG_INFO, + _("%s statistics: size=%lu, ndirs=%lu, nfiles=%lu, nerrs=%lu"), + dirname, + (unsigned long)sizeinfo.size, + (unsigned long)sizeinfo.ndirs, + (unsigned long)sizeinfo.nfiles, + (unsigned long)sizeinfo.nerrs); + } + *size = sizeinfo.size; +} + + +mu_off_t used_size; + +void +quota_setup () +{ + directory_size (imap4d_homedir, &used_size); +} + +int +quota_check (mu_off_t size) +{ + char *mailbox_name; + mu_mailbox_t mbox; + mu_off_t total; + int rc; + + if (auth_data->quota == 0) + return RESP_OK; + + total = used_size; + + mailbox_name = namespace_getfullpath ("INBOX", "/", NULL); + rc = mu_mailbox_create (&mbox, mailbox_name); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc); + free (mailbox_name); + } + else + { + do + { + mu_off_t mbsize; + + rc = mu_mailbox_open (mbox, MU_STREAM_READ); + if (rc) + { + if (rc != ENOENT) + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", + mailbox_name, rc); + break; + } + + rc = mu_mailbox_get_size (mbox, &mbsize); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_size", + mailbox_name, rc); + mu_mailbox_close (mbox); + break; + } + total += mbsize; + mu_mailbox_close (mbox); + } + while (0); + mu_mailbox_destroy (&mbox); + } + free (mailbox_name); + + if (rc) + return RESP_BAD; + + if (total > auth_data->quota) + { + mu_diag_output (MU_DIAG_NOTICE, + _("user %s is out of mailbox quota"), + auth_data->name); + return RESP_NO; + } + else if (total + size > auth_data->quota) + { + mu_diag_output (MU_DIAG_NOTICE, + _("user %s: adding %lu bytes would exceed mailbox quota"), + auth_data->name, (unsigned long) size); + return RESP_NO; + } + return RESP_OK; +} + +void +quota_update (mu_off_t size) +{ + used_size += size; +} |