/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 1999-2019 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 . */ #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 (void) { directory_size (real_homedir, &used_size); } int quota_check (mu_off_t size) { char *mailbox_name; mu_mailbox_t mbox; mu_off_t total; int rc; mu_record_t record; if (auth_data->quota == 0) return RESP_OK; total = used_size; mailbox_name = namespace_get_name ("INBOX", &record, NULL); rc = mu_mailbox_create_from_record (&mbox, record, mailbox_name); if (rc) mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc); 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; }