lazy-expunge-plugin.c revision eb453ada41017805a07c24e3d0eaad5af6b7dddf
/* Copyright (c) 2006-2010 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 allow_rename:1;
unsigned int internal_namespace:1;
};
struct lazy_expunge_transaction {
struct mailbox_transaction_context *dest_trans;
bool failed;
};
const char *lazy_expunge_plugin_version = DOVECOT_VERSION;
static struct mailbox *
const char **error_r)
{
enum mail_error error;
if (mailbox_open(box) == 0) {
return box;
}
&error);
if (error != MAIL_ERROR_NOTFOUND) {
mailbox_free(&box);
return NULL;
}
/* try creating and re-opening it. */
mailbox_open(box) < 0) {
NULL);
mailbox_free(&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
{
}
{
struct lazy_expunge_transaction *lt =
union mail_module_context *mmail;
return;
}
static int
{
struct lazy_expunge_mailbox_list *src_llist =
const char *dest_name = wanted_destname;
enum mail_error error;
int ret;
/* make sure the destination root directory exists */
"mkdir_parents(%s) failed: %m", dir);
return -1;
}
for (;;) {
if (ret == 0)
break;
switch (error) {
case MAIL_ERROR_EXISTS:
break;
case MAIL_ERROR_NOTFOUND:
return 0;
default:
return -1;
}
/* destination already exists. generate a different name. */
}
*dest_box_r = dest_box;
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;
}
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;
}
{
struct mail_index_transaction *trans;
if (mail_index_transaction_commit(&trans) < 0) {
return -1;
}
return 0;
}
{
union mailbox_module_context *lbox =
struct lazy_expunge_mailbox_list *llist =
struct mailbox *expunge_box;
enum mail_error error;
char timestamp[256];
int ret;
/* a) deleting mailbox from lazy_expunge namespaces
b) deleting a \noselect mailbox */
}
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));
}
}
/* avoid potential race conditions by marking it deleted */
return -1;
/* rename it into the lazy_expunge namespace */
if (ret < 0)
return -1;
if (ret == 0) {
return -1;
}
/* other sessions now see the mailbox completely deleted.
since it's not really deleted in the lazy-expunge namespace,
we might want to change it again. so mark the index undeleted. */
if (mailbox_open(expunge_box) < 0) {
i_error("lazy_expunge: Couldn't open DELETEd mailbox "
return -1;
}
if (mailbox_mark_index_undeleted(expunge_box) < 0) {
return -1;
}
else
ret = 0;
/* next move the expunged messages mailbox, if it exists */
if (expunge_ns != dest_ns) {
if (ret > 0)
}
return ret < 0 ? -1 : 0;
}
static int
bool rename_children)
{
struct lazy_expunge_mailbox_list *src_llist =
struct lazy_expunge_mailbox_list *dest_llist =
if (!src_llist->allow_rename &&
return -1;
}
}
{
struct lazy_expunge_mailbox_list *llist =
union mailbox_module_context *mbox;
return;
if (!llist->internal_namespace) {
} else {
}
}
{
struct lazy_expunge_mail_user *luser =
struct lazy_expunge_mailbox_list *llist;
const char *const *p;
unsigned int i;
return;
/* 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++) {
}
}
{
unsigned int i;
for (i = 0; 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)
{
}