Mercurial > dovecot > original-hg > dovecot-1.2
view src/plugins/expire/expire-tool.c @ 6429:65c69a53a7be HEAD
Replaced my Copyright notices. The year range always ends with 2007 now.
My name was replaced with "Dovecot authors". In many cases I didn't really
even own the copyright, so this is more correct.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 16 Sep 2007 14:34:22 +0300 |
parents | eb7c9d8ece54 |
children | 1a3604c8ee05 |
line wrap: on
line source
/* Copyright (c) 2006-2007 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "ioloop.h" #include "file-lock.h" #include "randgen.h" #include "lib-signals.h" #include "dict-client.h" #include "mail-search.h" #include "mail-storage.h" #include "mail-namespace.h" #include "auth-client.h" #include "expire-env.h" #include <stdlib.h> /* ugly, but automake doesn't like having it built as both static and dynamic object.. */ #include "expire-env.c" #define DEFAULT_AUTH_SOCKET_PATH PKG_RUNDIR"/auth-master" struct expire_context { struct auth_connection *auth_conn; char *user; pool_t namespace_pool; struct mail_namespace *ns; }; static int user_init(struct expire_context *ctx, const char *user) { int ret; if ((ret = auth_client_put_user_env(ctx->auth_conn, user)) <= 0) { if (ret < 0) return ret; /* user no longer exists */ return 0; } if (mail_namespaces_init(ctx->namespace_pool, user, &ctx->ns) < 0) return -1; return 1; } static void user_deinit(struct expire_context *ctx) { mail_namespaces_deinit(&ctx->ns); i_free_and_null(ctx->user); p_clear(ctx->namespace_pool); } static int mailbox_delete_old_mails(struct expire_context *ctx, const char *user, const char *mailbox, time_t expire_secs, time_t *oldest_r) { struct mail_namespace *ns; struct mailbox *box; struct mail_search_context *search_ctx; struct mailbox_transaction_context *t; struct mail_search_arg search_arg; struct mail *mail; time_t now, save_time; int ret; *oldest_r = 0; if (ctx->user != NULL && strcmp(user, ctx->user) != 0) user_deinit(ctx); if (ctx->user == NULL) { if ((ret = user_init(ctx, user)) <= 0) return ret; ctx->user = i_strdup(user); } memset(&search_arg, 0, sizeof(search_arg)); search_arg.type = SEARCH_ALL; search_arg.next = NULL; ns = mail_namespace_find(ctx->ns, &mailbox); if (ns == NULL) return -1; box = mailbox_open(ns->storage, mailbox, NULL, 0); t = mailbox_transaction_begin(box, 0); search_ctx = mailbox_search_init(t, NULL, &search_arg, NULL); mail = mail_alloc(t, 0, NULL); now = time(NULL); while ((ret = mailbox_search_next(search_ctx, mail)) > 0) { if (mail_get_save_date(mail, &save_time) < 0) { /* maybe just got expunged. anyway try again later. */ ret = -1; break; } if (save_time + expire_secs <= now) mail_expunge(mail); else { /* first non-expunged one. */ *oldest_r = save_time; break; } } mail_free(&mail); if (mailbox_search_deinit(&search_ctx) < 0) ret = -1; if (mailbox_transaction_commit(&t, MAILBOX_SYNC_FLAG_FULL_READ | MAILBOX_SYNC_FLAG_FULL_WRITE) < 0) ret = -1; mailbox_close(&box); return ret < 0 ? -1 : 0; } static void expire_run(void) { struct expire_context ctx; struct dict *dict = NULL; struct dict_transaction_context *trans; struct dict_iterate_context *iter; struct expire_env *env; const struct expire_box *expire_box; time_t oldest; const char *auth_socket, *p, *key, *value; const char *username, *mailbox; dict_driver_register(&dict_driver_client); mail_storage_init(); mail_storage_register_all(); mailbox_list_register_all(); if (getenv("EXPIRE") == NULL) i_fatal("expire setting not set"); if (getenv("EXPIRE_DICT") == NULL) i_fatal("expire_dict setting not set"); auth_socket = getenv("AUTH_SOCKET_PATH"); if (auth_socket == NULL) auth_socket = DEFAULT_AUTH_SOCKET_PATH; memset(&ctx, 0, sizeof(ctx)); ctx.auth_conn = auth_connection_init(auth_socket); ctx.namespace_pool = pool_alloconly_create("namespaces", 1024); env = expire_env_init(getenv("EXPIRE")); dict = dict_init(getenv("EXPIRE_DICT"), DICT_DATA_TYPE_UINT32, ""); trans = dict_transaction_begin(dict); iter = dict_iterate_init(dict, DICT_PATH_SHARED, DICT_ITERATE_FLAG_SORT_BY_VALUE); /* We'll get the oldest values (timestamps) first */ while (dict_iterate(iter, &key, &value) > 0) { /* key = DICT_PATH_SHARED<user>/<mailbox> */ username = key + strlen(DICT_PATH_SHARED); p = strchr(username, '/'); if (p == NULL) { i_error("Expire dictionary contains invalid key: %s", key); continue; } t_push(); username = t_strdup_until(username, p); mailbox = p + 1; expire_box = expire_box_find(env, mailbox); if (expire_box == NULL) { /* we're no longer expunging old messages from here */ dict_unset(trans, key); } else if (time(NULL) < (time_t)strtoul(value, NULL, 10)) { /* this and the rest of the timestamps are in future, so stop processing */ t_pop(); break; } else { if (mailbox_delete_old_mails(&ctx, username, mailbox, expire_box->expire_secs, &oldest) == 0) { /* successful update */ if (oldest == 0) { /* no more messages or we're no longer expunging messages from here */ dict_unset(trans, key); } else { const char *new_value; oldest += expire_box->expire_secs; new_value = dec2str(oldest); if (strcmp(value, new_value) != 0) dict_set(trans, key, new_value); } } } t_pop(); } dict_iterate_deinit(iter); dict_transaction_commit(trans); dict_deinit(&dict); if (ctx.user != NULL) user_deinit(&ctx); auth_connection_deinit(ctx.auth_conn); mail_storage_deinit(); dict_driver_unregister(&dict_driver_client); } int main(void) { struct ioloop *ioloop; lib_init(); lib_signals_init(); random_init(); ioloop = io_loop_create(); expire_run(); io_loop_destroy(&ioloop); lib_signals_deinit(); lib_deinit(); return 0; }