lazy-expunge-plugin.c revision 0f277a064942b89141caa40a8b2184fe83dc6fe7
/* Copyright (c) 2006-2015 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "hash.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) \
struct lazy_expunge_mail_user {
struct mail_namespace *lazy_ns;
const char *env;
bool copy_only_last_instance;
};
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;
HASH_TABLE(const char *, void *) guids;
bool failed;
bool copy_only_last_instance;
};
const char *lazy_expunge_plugin_version = DOVECOT_ABI_VERSION;
static struct mailbox *
const char **error_r)
{
enum mail_error error;
const char *name;
/* use the (canonical / unaliased) storage name */
/* replace hierarchy separators with destination virtual separator */
unsigned int i;
for (i = 0; name[i] != '\0'; i++) {
else
}
}
/* add expunge namespace prefix. the name is now a proper vname */
if (mailbox_open(box) == 0) {
return box;
}
if (error != MAIL_ERROR_NOTFOUND) {
mailbox_free(&box);
return NULL;
}
/* try creating and re-opening it. */
mailbox_open(box) < 0) {
mailbox_free(&box);
return NULL;
}
return box;
}
static unsigned int
const char *guid)
{
void *refcountp;
unsigned int refcount;
1024);
}
if (refcount == 1) {
} else {
}
return refcount-1;
}
{
struct lazy_expunge_transaction *lt =
const char *value;
unsigned long refcount;
"lazy_expunge: Couldn't lookup message's refcount: %s",
return -1;
}
if (*value == '\0') {
/* refcounts not supported by backend. assume all mails are
the last instance. */
return 1;
}
if (refcount > 1) {
/* this probably isn't the last instance of the mail, but
it's possible that the same mail was copied to this mailbox
multiple times and we're deleting more than one instance
within this transaction. in those cases each expunge will
see the same refcount, so we need to adjust the refcount
by tracking the expunged message GUIDs. */
"lazy_expunge: Couldn't lookup message's GUID");
return -1;
}
if (*value == '\0') {
/* GUIDs not supported by backend, but refcounts are?
not with our current backends. */
"lazy_expunge: Message unexpectedly has no GUID");
return -1;
}
}
}
{
struct lazy_expunge_mail_user *luser =
struct lazy_expunge_transaction *lt =
struct lazy_expunge_mailbox_list *llist;
struct mail_save_context *save_ctx;
const char *error;
int ret;
/* don't copy the mail if we're expunging from lazy_expunge
namespace (even if it's via a virtual mailbox) */
return;
}
return;
}
if (lt->copy_only_last_instance) {
/* we want to copy only the last instance of the mail to
lazy_expunge namespace. other instances will be expunged
immediately. */
return;
}
if (ret == 0) {
return;
}
}
"lazy_expunge: Couldn't open expunge mailbox: "
"%s", error);
return;
}
"lazy_expunge: Couldn't sync expunge mailbox");
return;
}
}
}
static struct mailbox_transaction_context *
{
struct lazy_expunge_mail_user *luser =
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 =
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;
return;
/* if this is one of our internal namespaces, mark it as such before
quota plugin sees it */
llist);
}
}
static void
{
struct lazy_expunge_mail_user *luser =
struct lazy_expunge_mailbox_list *llist;
return;
/* we don't want to override this namespace's expunge operation. */
}
{
/* mail_namespaces_created hook isn't necessarily ever called */
}
{
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)
{
}