trash-plugin.c revision 00d58fcfe8191d6ce7efa801d289a5c0fe88d1ae
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2005 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen#include "array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "home-expand.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "mail-namespace.h"
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen#include "mail-search.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "quota-private.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "quota-plugin.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "trash-plugin.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdlib.h>
66ae183b6e895216037bd921367670f4b0665911Timo Sirainen#include <unistd.h>
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include <fcntl.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen#define INIT_TRASH_MAILBOX_COUNT 4
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MAX_RETRY_COUNT 3
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct trash_mailbox {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *name;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen int priority; /* lower number = higher priority */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen struct mail_storage *storage;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* temporarily set while cleaning: */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox *box;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_transaction_context *trans;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_search_arg search_arg;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_search_context *search_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail *mail;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int mail_set:1;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen};
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainenconst char *trash_plugin_version = PACKAGE_VERSION;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenstatic int (*trash_next_quota_test_alloc)(struct quota_transaction_context *,
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen uoff_t, bool *);
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic pool_t config_pool;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* trash_boxes ordered by priority, highest first */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY_DEFINE(trash_boxes, struct trash_mailbox);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int sync_mailbox(struct mailbox *box)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen struct mailbox_sync_context *ctx;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen struct mailbox_sync_rec sync_rec;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx = mailbox_sync_init(box, MAILBOX_SYNC_FLAG_FULL_READ);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen while (mailbox_sync_next(ctx, &sync_rec) > 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mailbox_sync_deinit(&ctx, 0, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic int trash_clean_mailbox_open(struct trash_mailbox *trash)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen trash->box = mailbox_open(trash->storage, trash->name, NULL,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen MAILBOX_OPEN_KEEP_RECENT);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (trash->box == NULL)
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen return 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (sync_mailbox(trash->box) < 0)
ba00293b85c7fb4e7a2d100991c716e17b9daaaeTimo Sirainen return -1;
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen trash->trans = mailbox_transaction_begin(trash->box, 0);
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen trash->search_ctx = mailbox_search_init(trash->trans, NULL,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &trash->search_arg, NULL);
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen trash->mail = mail_alloc(trash->trans, MAIL_FETCH_PHYSICAL_SIZE |
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen MAIL_FETCH_RECEIVED_DATE, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mailbox_search_next(trash->search_ctx, trash->mail);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int trash_clean_mailbox_get_next(struct trash_mailbox *trash,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen time_t *received_time_r)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen{
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen int ret;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (!trash->mail_set) {
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (trash->box == NULL)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen ret = trash_clean_mailbox_open(trash);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen else
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ret = mailbox_search_next(trash->search_ctx,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen trash->mail);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (ret <= 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *received_time_r = 0;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen return ret;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen trash->mail_set = TRUE;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen }
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen *received_time_r = mail_get_received_date(trash->mail);
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen return 1;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen}
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainenstatic void trash_find_storage(struct trash_mailbox *trash)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct mail_storage *const *storages;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen unsigned int i, count;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen storages = array_get(&quota_set->storages, &count);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen for (i = 0; i < count; i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mail_namespace_update_name(storages[i]->ns, &trash->name)) {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen trash->storage = storages[i];
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen i_fatal("trash: Namespace not found for mailbox '%s'", trash->name);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen}
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainenstatic int trash_try_clean_mails(struct quota_transaction_context *ctx,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen uint64_t size_needed)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen{
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen struct trash_mailbox *trashes;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen unsigned int i, j, count, oldest_idx;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen time_t oldest, received = 0;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen uint64_t size, size_expunged = 0, expunged_count = 0;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen int ret = 0;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen trashes = array_get_modifiable(&trash_boxes, &count);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen for (i = 0; i < count; ) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen /* expunge oldest mails first in all trash boxes with
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen same priority */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen oldest_idx = count;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen oldest = (time_t)-1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (j = i; j < count; j++) {
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (trashes[j].priority != trashes[i].priority)
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen break;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (trashes[j].storage == NULL)
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen trash_find_storage(&trashes[j]);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ret = trash_clean_mailbox_get_next(&trashes[j],
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen &received);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (ret < 0)
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen goto __err;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen if (ret > 0) {
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen if (oldest == (time_t)-1 || received < oldest) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen oldest = received;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen oldest_idx = j;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (oldest_idx < count) {
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen size = mail_get_physical_size(trashes[oldest_idx].mail);
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen if (size == (uoff_t)-1) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* maybe expunged already? */
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen trashes[oldest_idx].mail_set = FALSE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen continue;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (mail_expunge(trashes[oldest_idx].mail) < 0)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen expunged_count++;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen size_expunged += size;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (size_expunged >= size_needed)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen break;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen trashes[oldest_idx].mail_set = FALSE;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen } else {
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* find more mails from next priority's mailbox */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i = j;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen__err:
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen for (i = 0; i < count; i++) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct trash_mailbox *trash = &trashes[i];
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (trash->box == NULL)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen continue;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen trash->mail_set = FALSE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mail_free(&trash->mail);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (void)mailbox_search_deinit(&trash->search_ctx);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen if (size_expunged >= size_needed) {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen (void)mailbox_transaction_commit(&trash->trans,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen MAILBOX_SYNC_FLAG_FULL_WRITE);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen } else {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen /* couldn't get enough space, don't expunge anything */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mailbox_transaction_rollback(&trash->trans);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen mailbox_close(&trash->box);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (size_expunged < size_needed)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return FALSE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->bytes_used = ctx->bytes_used > (int64_t)size_expunged ?
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->bytes_used - size_expunged : 0;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->count_used = ctx->count_used > (int64_t)expunged_count ?
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->count_used - expunged_count : 0;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return TRUE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainenstatic int
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainentrash_quota_test_alloc(struct quota_transaction_context *ctx,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen uoff_t size, bool *too_large_r)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen int ret, i;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for (i = 0; ; i++) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ret = trash_next_quota_test_alloc(ctx, size, too_large_r);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ret != 0 || *too_large_r)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return ret;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (i == MAX_RETRY_COUNT) {
6825360d446542046757b06064282301c4c6b27cTimo Sirainen /* trash_try_clean_mails() should have returned 0 if
6825360d446542046757b06064282301c4c6b27cTimo Sirainen it couldn't get enough space, but allow retrying
6825360d446542046757b06064282301c4c6b27cTimo Sirainen it a couple of times if there was some extra space
6825360d446542046757b06064282301c4c6b27cTimo Sirainen that was needed.. */
6825360d446542046757b06064282301c4c6b27cTimo Sirainen break;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen }
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainen /* not enough space. try deleting some from mailbox. */
6825360d446542046757b06064282301c4c6b27cTimo Sirainen ret = trash_try_clean_mails(ctx, size);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen if (ret <= 0)
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen return 0;
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen }
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainen return 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic int trash_mailbox_priority_cmp(const void *p1, const void *p2)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct trash_mailbox *t1 = p1, *t2 = p2;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return t1->priority - t2->priority;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int read_configuration(const char *path)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct istream *input;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *line, *name;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen struct trash_mailbox *trash;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen unsigned int count;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen int fd;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen fd = open(path, O_RDONLY);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (fd == -1) {
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen i_error("open(%s) failed: %m", path);
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen return -1;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen }
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen p_clear(config_pool);
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen p_array_init(&trash_boxes, config_pool, INIT_TRASH_MAILBOX_COUNT);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen input = i_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* <priority> <mailbox name> */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen name = strchr(line, ' ');
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (name == NULL || name[1] == '\0')
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen continue;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash = array_append_space(&trash_boxes);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash->name = p_strdup(config_pool, name+1);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash->priority = atoi(t_strdup_until(line, name));
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash->search_arg.type = SEARCH_ALL;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen }
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_stream_destroy(&input);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen (void)close(fd);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen trash = array_get_modifiable(&trash_boxes, &count);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen qsort(trash, count, sizeof(*trash), trash_mailbox_priority_cmp);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainenvoid trash_plugin_init(void)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen const char *env;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen env = getenv("TRASH");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (env == NULL)
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen return;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (quota_set == NULL) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen i_error("trash plugin: quota plugin not initialized");
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen return;
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen }
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen config_pool = pool_alloconly_create("trash config",
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen sizeof(trash_boxes) +
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen BUFFER_APPROX_SIZE +
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen INIT_TRASH_MAILBOX_COUNT *
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen (sizeof(struct trash_mailbox) + 32));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (read_configuration(env) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen trash_next_quota_test_alloc = quota_set->test_alloc;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen quota_set->test_alloc = trash_quota_test_alloc;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenvoid trash_plugin_deinit(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen quota_set->test_alloc = trash_next_quota_test_alloc;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen if (config_pool != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(config_pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen