/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "hostpid.h"
#include "mail-index.h"
#include "subscription-file.h"
#include "mailbox-list-delete.h"
#include "mailbox-list-subscriptions.h"
#include "mailbox-list-index-storage.h"
#include "mailbox-list-index-sync.h"
#include <stdio.h>
struct index_mailbox_list {
const char *temp_prefix;
const char *create_mailbox_name;
};
extern struct mailbox_list index_mailbox_list;
static int
{
}
{
*error_r = "LAYOUT=index requires mailbox_list_index=yes";
return -1;
}
return 0;
}
{
}
{
}
static int
struct mail_index_view *view,
const char *name,
struct mailbox_list_index_node **node_r,
{
unsigned int i;
*seq_r = 0;
for (i = 0; i < 2; i++) {
return 0;
return 1;
/* mailbox was just expunged. refreshing should notice it. */
return -1;
}
i_panic("mailbox list index: refreshing doesn't lose expunged uid=%u",
return -1;
}
static const char *
const guid_128_t mailbox_guid)
{
}
static int
{
const char *root_dir;
int ret;
/* return root directories */
path_r) ? 1 : 0;
}
/* consistently use mailbox_dir_name as part of all mailbox
switch (type) {
break;
break;
i_unreached();
default:
break;
}
return 0;
return 1;
}
/* ilist is only required from this point onwards.
At least imapc calls index_list_get_path without this context*/
/* we could get here during sync from
index_list_mailbox_create_selectable() */
seq = 0;
ret = 0;
ret = 1;
} else {
}
} else {
return -1;
if (ret < 0) {
return -1;
}
}
if (ret == 0) {
ret = -1;
ret = -1;
} else {
ret = 1;
}
return ret;
}
static const char *
{
}
{
const char *path;
"Subscriptions not supported");
return -1;
}
}
static int
enum mailbox_existence *existence_r)
{
return -1;
return 0;
MAILBOX_LIST_INDEX_FLAG_NOSELECT)) == 0) {
/* selectable */
} else {
/* non-selectable */
}
return 0;
}
static int
{
bool created;
int ret;
return -1;
/* didn't already exist */
ret = 1;
} else {
/* already existed */
ret = 0;
}
ret = -1;
return ret;
}
static int
const guid_128_t mailbox_guid)
{
const void *data;
return -1;
if (box->corrupted_mailbox_name) {
/* an existing mailbox is being created with a "unknown" name.
opening the mailbox will hopefully find its real name and
rename it. */
}
if (!created &&
MAILBOX_LIST_INDEX_FLAG_NOSELECT)) == 0) {
/* already selectable */
return 0;
}
/* make it selectable */
/* set UIDVALIDITY if was set by the storage */
}
/* set GUID */
/* make sure we forget any changes done internally */
return -1;
}
return 1;
}
static int
{
int ret;
/* first do a quick check that it doesn't exist */
return -1;
}
/* now add the directory to index locked */
return -1;
}
/* if no GUID is requested, generate it ourself. set
UIDVALIDITY to index sometimes later. */
i_zero(&new_update);
else
new_update = *update;
/* create the backend mailbox first before it exists in the
list. the mailbox creation wants to use get_path() though,
so use a bit kludgy create_mailbox_* variables during the
creation to return the path. we'll also support recursively
creating more mailboxes in here. */
const char *old_name;
if (ret == 0) {
/* backend mailbox was successfully created. now add it
to the list. */
if (ret < 0)
if (ret <= 0) {
/* failed to add to list. rollback the backend
mailbox creation */
if (create_error)
if (mailbox_delete(box) < 0)
ret = -1;
if (create_error)
}
}
if (ret < 0)
return ret;
} else {
ret = 0;
}
if (ret == 0) {
"Mailbox already exists");
return -1;
}
return 0;
}
static int
const struct mailbox_update *update)
{
&old_path) <= 0)
return -1;
/* rename the directory */
&root_dir)) {
;
;
return -1;
} else {
return -1;
}
}
return 0;
}
static int
enum mailbox_existence *existence_r)
{
return -1;
}
return 0;
}
{
if (box->corrupted_mailbox_name)
return TRUE;
}
{
return;
/* mailbox already exists. don't give up yet, just use the newname
as prefix and add the "lost-xx" as suffix. */
/* oldname should be at the root level, but check for hierarchies
anyway to be safe. */
if (p != NULL)
oldname = p+1;
}
{
const void *data;
const unsigned char *name_hdr;
return -1;
/* FIXME: dsync-merge is performing a delete in obox - remove
this check once dsync-merging is no longer used. */
return 0;
}
/* if mailbox name has changed, update it to the header. Use \0
as the hierarchy separator in the header. This is to make sure
we don't keep rewriting the name just in case some backend switches
between separators when accessed different ways. */
/* Get the current mailbox name with \0 separators. */
for (size_t i = 0; i < box_name_len; i++) {
if (box_zerosep_name[i] == sep)
box_zerosep_name[i] = '\0';
}
/* Does it match what's in the header now? */
&data, &name_hdr_size);
/* Remove trailing \0 - header doesn't shrink always */
}
if (name_hdr_size == box_name_len &&
/* Same mailbox name */
} else if (!mailbox_has_corrupted_name(box)) {
/* Mailbox name changed - update */
(void)mail_index_transaction_commit(&trans);
} else if (name_hdr_size > 0) {
/* Mailbox name is corrupted. Rename it to the previous name. */
for (size_t i = 0; i < name_hdr_size; i++) {
if (newname[i] == '\0')
}
}
return 0;
}
enum mailbox_sync_flags flags)
{
if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0 &&
!ilist->force_resynced) {
/* try to rebuild list index only once - even if it failed */
}
}
{
if (ilist->force_resync_failed) {
/* fail this only once */
return -1;
}
return 0;
}
static void
enum mailbox_list_path_type type)
{
&mailbox_path) <= 0 ||
return;
/* this directory may contain also child mailboxes' data.
we don't want to delete that. */
rmdir_path) < 0)
return;
} else {
}
}
/* avoid leaving empty directories lying around */
}
static void
{
}
static int
bool delete_selectable)
{
int ret;
/* we're rolling back a failed create. if the name exists in the
list, it was done by somebody else so we don't want to
remove it. */
return 0;
}
return -1;
return -1;
return ret;
}
static int
{
const char *path;
int ret;
/* first delete the mailbox files */
&path);
if (ret <= 0)
return ret;
MAILBOX_LIST_FLAG_NO_DELETES)) != 0) {
ret = 0;
} else {
}
if (ret == 0) {
return -1;
}
return ret;
}
static int
{
int ret;
return -1;
if (ret == 0) {
"Mailbox has children, delete them first");
return -1;
}
return 0;
}
static int
const char *name ATTR_UNUSED)
{
"Symlinks not supported");
return -1;
}
static int
{
const void *data;
"Renaming not supported across namespaces.");
return -1;
}
"Can't rename mailbox under itself.");
return -1;
}
return -1;
return -1;
}
if (!created) {
"Target mailbox already exists");
return -1;
}
/* copy all the data from old node to new node */
/* remove the old node from existence */
/* update the old index record to contain the new name_id/parent_uid,
then expunge the added index record */
/* mailbox is renamed - clear away the corruption flag so the
new name will be written to the mailbox index header. */
}
}
static struct mailbox_list_iterate_context *
const char *const *patterns,
enum mailbox_list_iter_flags flags)
{
if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
flags);
}
return ctx;
}
static const struct mailbox_info *
{
return mailbox_list_subscriptions_iter_next(ctx);
return NULL;
}
{
return 0;
}
.v = {
.init = index_list_init,
}
};
struct mailbox_vfuncs *v)
{
return TRUE;
/* NOTE: this is using the same v as
mailbox_list_index_status_init_mailbox(), so don't have them
accidentally override each others. */
v->open = index_list_mailbox_open;
return FALSE;
}