maildir-storage.c revision 92888ef30960c30ccc9e030fe7eab5d4d04a7d1c
/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "hostpid.h"
#include "home-expand.h"
#include "mkdir-parents.h"
#include "unlink-directory.h"
#include "subscription-file/subscription-file.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
struct rename_context {
int found;
const char *newname;
};
extern struct mail_storage maildir_storage;
extern struct mailbox maildir_mailbox;
static struct mail_storage *
const char *namespace, char hierarchy_sep)
{
struct index_storage *storage;
/* we'll need to figure out the maildir location ourself.
it's either root dir if we've already chroot()ed, or
root_dir = "/";
else {
}
}
} else {
/* <Maildir> [:INBOX=<dir>] [:INDEX=<dir>] [:CONTROL=<dir>] */
if (p == NULL)
else {
do {
p++;
p = strchr(p, ':');
} while (p != NULL);
}
}
return NULL;
/* strip trailing '/' */
if (hierarchy_sep != '\0')
/* the default ".temp.xxx" prefix would be treated as directory */
}
{
}
static int maildir_autodetect(const char *data)
{
}
static int maildir_is_valid_create_name(const char *name)
{
return FALSE;
return TRUE;
return FALSE;
return TRUE;
}
static int maildir_is_valid_existing_name(const char *name)
{
if (name[0] == '\0')
return FALSE;
return TRUE;
return FALSE;
return TRUE;
}
{
const char *p;
if (p == NULL)
return name;
}
const char *name, int remove_namespace)
{
/* use same case with all INBOX folders or we'll get
into trouble */
/* don't check namespace with INBOX */
return name;
}
}
i_panic("maildir: expecting namespace '%s' in name "
}
}
return name;
if (sep == MAILDIR_FS_SEP)
return name;
for (p = dup; *p != '\0'; p++) {
if (*p == sep)
*p = MAILDIR_FS_SEP;
}
return dup;
}
{
}
}
static const char *
{
return maildir_get_path(storage,
}
const char *name)
{
return NULL;
return storage->inbox_path;
}
const char *name)
{
}
{
if (verify) {
return 0;
"lstat(%s) failed: %m", dir);
return -1;
}
}
"mkdir(%s) failed: %m", dir);
}
return -1;
}
return 0;
}
/* create or fix maildir, ignore if it already exists */
{
return -1;
return -1;
/* small optimization. if we're verifying, we don't
check that the root dir actually exists unless we
fail here. */
return -1;
return -1;
}
}
return 0;
}
{
const char *dir;
return 0;
return 0;
"mkdir(%s) failed: %m", dir);
return -1;
}
return 0;
}
{
const char *dir;
return 0;
"mkdir(%s) failed: %m", dir);
return -1;
}
return 0;
}
{
const char *inbox;
/* first make sure the cur/ new/ and tmp/ dirs exist
in root dir */
return -1;
/* create the .INBOX directory */
return -1;
} else {
return -1;
}
/* make sure the index directories exist */
return -1;
return -1;
return 0;
}
{
}
static struct mailbox *
enum mailbox_open_flags flags)
{
struct index_mailbox *ibox;
struct mail_index *index;
return NULL;
/* for shared mailboxes get the create mode from the
permissions of dovecot-shared file */
else {
}
}
static struct mailbox *
{
const char *path;
if (verify_inbox(storage) < 0)
return NULL;
}
if (!maildir_is_valid_existing_name(name)) {
return NULL;
}
/* exists - make sure the required directories are also there */
return NULL;
name);
return NULL;
} else {
path);
return NULL;
}
}
const char *name,
int directory __attr_unused__)
{
const char *path;
if (!maildir_is_valid_create_name(name)) {
return -1;
}
"Mailbox already exists");
}
return -1;
}
return 0;
}
const char *name)
{
int count;
return -1;
}
if (!maildir_is_valid_existing_name(name)) {
return -1;
}
/* rename the .maildir into ..maildir which marks it as being
deleted. delete indexes before the actual maildir. this way we
never see partially deleted mailboxes. */
name);
return -1;
}
/* it can fail with some NFS implementations if indexes are
opened by another session.. can't really help it. */
"unlink_directory(%s) failed: %m", index_dir);
return -1;
}
}
count = 0;
return -1;
}
/* ..dir already existed? delete it and try again */
"unlink_directory(%s) failed: %m", dest);
return -1;
}
count++;
}
"unlink_directory(%s) failed: %m", dest);
/* it's already renamed to ..dir, which means it's deleted
as far as client is concerned. Report success. */
}
return 0;
}
{
return 0;
/* Rename it's index. */
"rename(%s, %s) failed: %m",
return -1;
}
return 0;
}
{
struct mailbox_list_context *ctx;
struct mailbox_list *list;
int ret;
ret = 0;
const char *list_name;
t_push();
/* FIXME: it's possible to merge two folders if either one of
them doesn't have existing root folder. We could check this
but I'm not sure if it's worth it. It could be even
considered as a feature.
Anyway, the bug with merging is that if both folders have
identically named subfolder they conflict. Just ignore those
and leave them under the old folder. */
ret = 1;
else {
"rename(%s, %s) failed: %m",
ret = -1;
t_pop();
break;
}
t_pop();
}
if (maildir_mailbox_list_deinit(ctx) < 0)
return -1;
return ret;
}
{
if (!maildir_is_valid_existing_name(oldname) ||
return -1;
}
"Renaming INBOX isn't supported.");
return -1;
}
/* NOTE: it's possible to rename a nonexisting folder which has
subfolders. In that case we should ignore the rename() error. */
if (ret < 0)
return -1;
"Mailbox doesn't exist");
return -1;
}
return 0;
}
"Target mailbox already exists");
return -1;
} else {
return -1;
}
}
{
const char *path;
}
const char *name,
enum mailbox_name_status *status)
{
const char *path;
if (!maildir_is_valid_existing_name(name)) {
return 0;
}
return 0;
}
if (!maildir_is_valid_create_name(name)) {
return 0;
}
return 0;
} else {
path);
return -1;
}
}
{
int ret = 0;
/*FIXME:if (!maildir_try_flush_dirty_flags(ibox->index, TRUE)) {
mail_storage_set_index_error(ibox);
ret = -1;
}*/
return ret;
}
enum mailbox_sync_flags flags,
unsigned int min_newmail_notify_interval)
{
/* flags or interval just changed. or nothing. */
}
if (flags == 0) {
return;
}
}
struct mail_storage maildir_storage = {
"maildir", /* name */
NULL, /* namespace */
'.', /* default hierarchy separator */
NULL,
0
};
struct mailbox maildir_mailbox = {
NULL, /* name */
NULL, /* storage */
};