lazy-expunge-plugin.c revision 20866bdef50b7e0e63383262fe21dc14b7242755
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "seq-range-array.h"
#include "mkdir-parents.h"
#include "mail-storage-private.h"
#include "mail-search-build.h"
#include "mailbox-list-private.h"
#include "mail-namespace.h"
#include "lazy-expunge-plugin.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <time.h>
#define LAZY_EXPUNGE_CONTEXT(obj) \
#define LAZY_EXPUNGE_LIST_CONTEXT(obj) \
#define LAZY_EXPUNGE_USER_CONTEXT(obj) \
#define LAZY_EXPUNGE_MAIL_CONTEXT(obj) \
enum lazy_namespace {
};
struct lazy_expunge_mail_user {
const char *env;
};
struct lazy_expunge_mailbox_list {
unsigned int internal_namespace:1;
unsigned int deleting:1;
};
struct lazy_expunge_transaction {
struct mailbox_transaction_context *dest_trans;
bool failed;
};
const char *lazy_expunge_plugin_version = PACKAGE_VERSION;
static struct mailbox *
const char **error_r)
{
struct mail_storage *storage;
enum mail_error error;
if (mailbox_open(box) == 0) {
return box;
}
&error);
if (error != MAIL_ERROR_NOTFOUND) {
mailbox_close(&box);
return NULL;
}
/* try creating and re-opening it. */
mailbox_open(box) < 0) {
NULL);
mailbox_close(&box);
return NULL;
}
return box;
}
static struct mail_namespace *
{
}
{
struct lazy_expunge_transaction *lt =
struct mail_namespace *dest_ns;
struct mail_save_context *save_ctx;
const char *error;
"lazy_expunge: Couldn't open expunge mailbox: "
"%s", error);
return;
}
"lazy_expunge: Couldn't sync expunge mailbox");
return;
}
}
}
static struct mailbox_transaction_context *
{
struct mailbox_transaction_context *t;
struct lazy_expunge_transaction *lt;
return t;
}
{
}
static int
struct mail_transaction_commit_changes *changes_r)
{
int ret;
}
ret = -1;
} else {
}
return ret;
}
static void
{
}
static struct mail *
struct mailbox_header_lookup_ctx *wanted_headers)
{
union mail_module_context *mmail;
struct mail_private *mail;
return _mail;
}
{
struct lazy_expunge_mailbox_list *llist =
union mailbox_module_context *mbox;
mbox);
}
}
static int
{
enum mail_error error;
/* make sure the destination root directory exists */
"mkdir_parents(%s) failed: %m", dir);
return -1;
}
switch (error) {
case MAIL_ERROR_EXISTS:
break;
case MAIL_ERROR_NOTFOUND:
return 0;
default:
return -1;
}
/* mailbox is being deleted multiple times per second.
update the filename. */
}
*_dest_name = dest_name;
return 1;
}
static int
{
struct mail_search_args *search_args;
struct mail_search_context *search_ctx;
struct mail_save_context *save_ctx;
const char *errstr;
enum mail_error error;
int ret;
if (mailbox_open(dest_box) < 0) {
i_error("lazy_expunge: Couldn't open DELETE dest mailbox "
return -1;
}
if (mailbox_open(src_box) < 0) {
if (error == MAIL_ERROR_NOTFOUND)
return 0;
i_error("lazy_expunge: Couldn't open DELETE source mailbox "
return -1;
}
ret = -1;
break;
}
}
}
if (mailbox_search_deinit(&search_ctx) < 0)
ret = -1;
(void)mailbox_transaction_commit(&src_trans);
if (ret == 0)
else
if (ret == 0)
return ret;
}
static int
{
struct lazy_expunge_mailbox_list *llist =
enum mailbox_name_status status;
const char *destname;
char timestamp[256];
int ret;
/* first do the normal sanity checks */
"INBOX can't be deleted.");
return -1;
}
return -1;
if (status == MAILBOX_NAME_INVALID) {
"Invalid mailbox name");
return -1;
}
if (expunge_ns == dest_ns) {
/* if there are no expunged messages in this mailbox,
we can simply rename the mailbox to the destination name */
} else {
/* destination mailbox name needs to contain a timestamp */
"%Y%m%d-%H%M%S", tm) == 0) {
sizeof(timestamp));
}
}
/* first move the actual mailbox */
return -1;
if (ret == 0) {
return -1;
}
}
/* next move the expunged messages mailbox, if it exists */
if (expunge_ns != dest_ns) {
}
return 0;
}
{
struct lazy_expunge_mail_user *luser =
struct lazy_expunge_mailbox_list *llist;
const char *const *p;
unsigned int i;
/* if this is one of our internal namespaces, mark it as such before
quota plugin sees it */
for (i = 0; i < LAZY_NAMESPACE_COUNT && *p != NULL; i++, p++) {
break;
}
}
llist);
}
}
static void
{
struct lazy_expunge_mail_user *luser =
struct lazy_expunge_mailbox_list *llist;
const char *const *p;
int i;
return;
for (i = 0; i < LAZY_NAMESPACE_COUNT && *p != NULL; i++, p++) {
const char *name = *p;
operations. */
}
if (i == 0)
i_fatal("lazy_expunge: No namespaces defined");
for (; i < LAZY_NAMESPACE_COUNT; i++)
}
{
struct lazy_expunge_mail_user *luser;
const char *env;
} else if (user->mail_debug) {
i_debug("lazy_expunge: No lazy_expunge setting - "
"plugin disabled");
}
}
static struct mail_storage_hooks lazy_expunge_mail_storage_hooks = {
};
{
}
void lazy_expunge_plugin_deinit(void)
{
}