mailbox-list-maildir.c revision 0b25846ba794ce19536a24d4065beaf2a0bd9464
/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "hostpid.h"
#include "eacces-error.h"
#include "mkdir-parents.h"
#include "str.h"
#include "subscription-file.h"
#include "mailbox-list-subscriptions.h"
#include "mailbox-list-delete.h"
#include "mailbox-list-maildir.h"
#include <stdio.h>
#define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
#define MAILDIR_GLOBAL_TEMP_PREFIX "temp."
#define IMAPDIR_GLOBAL_TEMP_PREFIX ".temp."
extern struct mailbox_list maildir_mailbox_list;
extern struct mailbox_list imapdir_mailbox_list;
static struct mailbox_list *maildir_list_alloc(void)
{
struct maildir_mailbox_list *list;
}
static struct mailbox_list *imapdir_list_alloc(void)
{
struct maildir_mailbox_list *list;
}
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
}
static const char *
const char *name)
{
if (*name == '\0')
return dir;
}
static const char *
{
const char *p;
/* fallback to using as ~name */
return name;
}
if (p == NULL)
return name;
p+1);
}
static bool
{
/* check that there are no adjacent hierarchy separators */
return FALSE;
}
return FALSE;
return FALSE;
return TRUE;
}
static bool maildir_list_is_valid_common_nonfs(const char *name)
{
return FALSE;
/* "." and ".." aren't allowed. */
return FALSE;
}
return TRUE;
}
static bool
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
return FALSE;
return TRUE;
return maildir_list_is_valid_common_nonfs(name);
}
static bool
{
/* maildir code itself doesn't care about this, but we may get here
from listing subscriptions to LAYOUT=fs namespace containing
entries for a subscriptions=no LAYOUT=maildir++ namespace */
}
static bool
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
return FALSE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
return TRUE;
}
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
}
static const char *
enum mailbox_list_path_type type)
{
const char *root_dir;
/* return root directories */
}
switch (type) {
break;
return NULL;
break;
return maildir_list_get_dirname_path(_list,
}
break;
return "";
return maildir_list_get_dirname_path(_list,
}
break;
}
if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
/* don't use inbox_path */
}
static const char *
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
}
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
const char *path;
}
static int
{
const char *path;
int fd;
/* Maildir++ spec wants that maildirfolder named file is created for
all subfolders. */
if (fd != -1) {
/* ok */
"Mailbox was deleted while it was being created");
return -1;
} else {
"open(%s, O_CREAT) failed: %m", path);
return -1;
}
/* ok */
gid, gid_origin));
} else {
"fchown(%s) failed: %m", path);
}
}
return 0;
}
static int
enum mailbox_dir_create_type type)
{
bool create_parent_dir;
if (type == MAILBOX_DIR_CREATE_TYPE_ONLY_NOSELECT) {
"Can't create non-selectable mailbox");
return -1;
}
if (create_parent_dir) {
/* we only need to make sure that the parent directory exists */
if (p == NULL)
return 0;
}
&gid, &gid_origin);
/* ok */
if (create_parent_dir)
return 0;
if (type == MAILBOX_DIR_CREATE_TYPE_MAILBOX) {
/* even though the root directory exists,
the mailbox might not */
return 0;
}
}
"Mailbox already exists");
return -1;
} else if (mailbox_list_set_error_from_errno(list)) {
return -1;
} else {
return -1;
}
gid, gid_origin);
}
static const char *
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
const char *root_dir;
}
static int
{
int ret = 0;
if (ret < 0)
return -1;
if (ret == 0) {
/* we could actually use just unlink_directory()
but error handling is easier this way :) */
return -1;
}
return 0;
}
static int
{
return -1;
} else {
return -1;
}
return 0;
}
{
const char *path;
/* with maildir++ there aren't any non-selectable mailboxes.
we'll always fail. */
"Mailbox exists");
} else {
}
return -1;
}
enum mailbox_list_path_type type)
{
return 0;
return -1;
}
return 0;
}
static int
{
struct mailbox_list_iterate_context *iter;
const struct mailbox_info *info;
ARRAY_DEFINE(names_arr, const char *);
unsigned int i, count, old_vnamelen;
char old_ns_sep;
int ret;
ret = 0;
/* first get the list of the children and save them to memory, because
we can't rely on readdir() not skipping files while the directory
is being modified. this doesn't protect against modifications by
other processes though. */
const char *name;
/* verify that the prefix matches, otherwise we could have
problems with mailbox names containing '%' and '*' chars */
}
}
if (mailbox_list_iter_deinit(&iter) < 0) {
ret = -1;
} else {
}
for (i = 0; i < count; i++) {
/* When doing RENAME "a" "a.b" we see "a.b" here.
We don't want to rename it anymore to "a.b.b". */
continue;
}
/* FIXME: it's possible to merge two mailboxes if either one of
them doesn't have existing root mailbox. 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 mailboxes have
identically named child mailbox they conflict. Just ignore
those and leave them under the old mailbox. */
ret = 1;
else {
ret = -1;
break;
}
}
pool_unref(&pool);
return ret;
}
static int
bool rename_children)
{
int ret;
bool found;
/* NOTE: it's possible to rename a nonexistent mailbox which has
children. In that case we should ignore the rename() error. */
/* most likely INBOX */
t_strdup_printf("Renaming %s isn't supported.",
oldname));
return -1;
}
/* if we're renaming under another mailbox, require its permissions
to be same as ours. */
const char *origin, *old_origin;
if ((file_mode != old_file_mode ||
"Renaming not supported across conflicting "
"directory permissions");
return -1;
}
}
if (!rename_children)
ret = 0;
else T_BEGIN {
} T_END;
if (ret < 0)
return -1;
return -1;
}
return 0;
}
if (EDESTDIREXISTS(errno)) {
"Target mailbox already exists");
} else {
}
return -1;
}
struct mailbox_list maildir_mailbox_list = {
{
NULL,
NULL,
NULL,
}
};
struct mailbox_list imapdir_mailbox_list = {
{
NULL,
NULL,
NULL,
}
};