mailbox-list-fs.c revision 7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629b
/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "hostpid.h"
#include "mkdir-parents.h"
#include "mailbox-log.h"
#include "subscription-file.h"
#include "mail-storage.h"
#include "mailbox-list-subscriptions.h"
#include "mailbox-list-delete.h"
#include "mailbox-list-fs.h"
#include <stdio.h>
#include <unistd.h>
#define GLOBAL_TEMP_PREFIX ".temp."
extern struct mailbox_list fs_mailbox_list;
static struct mailbox_list *fs_list_alloc(void)
{
struct fs_mailbox_list *list;
}
{
}
{
return FALSE;
return TRUE;
}
static bool
{
bool ret, allow_internal_dirs;
/* make sure it's not absolute path */
return FALSE;
/* make sure the mailbox name doesn't contain any foolishness:
"../" could give access outside the mailbox directory.
"./" and "//" could fool ACL checks. */
T_BEGIN {
const char *const *names;
const char *n = *names;
if (*n == '\0')
break; /* // */
if (*n == '.') {
if (n[1] == '\0')
break; /* ./ */
if (n[1] == '.' && n[2] == '\0')
break; /* ../ */
}
/* don't allow maildir_name to be used as part
of the mailbox name */
break;
}
if (!allow_internal_dirs &&
break;
}
} T_END;
return ret;
}
static bool
{
return TRUE;
}
static bool
{
return FALSE;
return TRUE;
}
static bool
{
return FALSE;
return FALSE;
return TRUE;
return FALSE;
}
{
return '/';
}
static const char *
enum mailbox_list_path_type type)
{
const char *root_dir;
/* return root directories */
}
return name;
switch (type) {
break;
return NULL;
break;
break;
return NULL;
break;
break;
return "";
}
break;
}
if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
/* don't use inbox_path */
/* If INBOX is a file, index and control directories are
located in root directory. */
return set->inbox_path;
}
} else {
set->maildir_name);
}
}
static const char *
{
}
static const char *
{
/* pattern overrides reference */
} else if (*ref != '\0') {
/* merge reference and pattern */
}
return pattern;
}
{
const char *path;
}
{
enum mailbox_info_flags flags;
return -1;
}
static int
enum mailbox_dir_create_type type)
{
struct mailbox_permissions perm;
const char *path, *p;
bool directory, create_parent_dir;
int ret;
create_parent_dir = !directory &&
if (create_parent_dir) {
/* we only need to make sure that the parent directory exists */
if (p == NULL)
return 0;
}
perm.file_create_gid_origin) == 0)
return 0;
if (create_parent_dir)
return 0;
return ret;
}
"Mailbox already exists");
"Mailbox doesn't allow inferior mailboxes");
} else if (!mailbox_list_set_error_from_errno(list)) {
}
return -1;
}
{
const char *root_dir;
}
static int
{
bool rmdir_path;
int ret;
if (ret < 0)
return -1;
if (ret > 0) {
/* try to delete the parent directory */
"rmdir(%s) failed: %m", path);
}
return 0;
}
}
}
{
int ret;
} else {
}
return ret;
}
const char *path)
{
return -1;
return 0;
}
{
char sep;
return 0;
/* mbox workaround: if only .imap/ directory is preventing the
deletion, remove it */
/* drop the "/child" part out. */
/* try again */
return 0;
}
}
"Mailbox has children, delete them first");
} else {
}
return -1;
}
{
return 0;
/* make sure the newparent exists */
const char *origin;
return -1;
"mkdir_parents(%s) failed: %m", newparent);
return -1;
}
}
return -1;
}
"rmdir(%s) failed: %m", oldpath);
}
}
/* avoid leaving empty directories lying around */
return 0;
}
const char *oldname,
struct mailbox_list *newlist,
const char *newname, bool rename_children)
{
struct mail_storage *oldstorage;
bool rmdir_parent = FALSE;
return -1;
if (rename_children) {
} else if (mail_storage_is_mailbox_file(oldstorage) ||
} else {
/* we can't do this, our children would get renamed with us */
"Can't rename mailbox without its children.");
return -1;
}
/* 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. */
"Renaming not supported across conflicting "
"directory permissions");
return -1;
}
/* create the hierarchy */
if (p != NULL) {
p = t_strdup_until(newpath, p);
new_perm.file_create_gid_origin) < 0 &&
return -1;
"mkdir_parents(%s) failed: %m", p);
return -1;
}
}
/* first check that the destination mailbox doesn't exist.
this is racy, but we need to be atomic and there's hardly any
possibility that someone actually tries to rename two mailboxes
to same new one */
"Target mailbox already exists");
return -1;
"Target mailbox doesn't allow inferior mailboxes");
return -1;
newpath);
return -1;
}
if (alt_newpath != NULL) {
/* race condition or a directory left there lying around?
safest to just report error. */
"Target mailbox already exists");
return -1;
return -1;
}
}
} else if (!mailbox_list_set_error_from_errno(oldlist)) {
}
return -1;
}
if (!rename_children) {
/* if there are no child mailboxes, get rid of the mailbox
directory entirely. */
rmdir_parent = TRUE;
"rmdir(%s) failed: %m", oldpath);
}
}
if (alt_newpath != NULL) {
}
return 0;
}
struct mailbox_list fs_mailbox_list = {
.props = 0,
{
NULL,
NULL,
}
};