maildir-storage.c revision 2f5256b4770d97b0ac76614a47cbdc91b89ca790
/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "mkdir-parents.h"
#include "eacces-error.h"
#include "unlink-old-files.h"
#include "mailbox-uidvalidity.h"
#include "mailbox-list-private.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include "maildir-keywords.h"
#include "maildir-sync.h"
#include "index-mail.h"
#define MAILDIR_LIST_CONTEXT(obj) \
#define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
struct maildir_mailbox_list_context {
const struct maildir_settings *set;
};
extern struct mail_storage maildir_storage;
extern struct mailbox maildir_mailbox;
static struct mail_storage *maildir_storage_alloc(void)
{
struct maildir_storage *storage;
}
static int
const char **error_r ATTR_UNUSED)
{
const char *dir;
/* put the temp files into tmp/ directory preferrably */
} else {
/* control dir should also be writable */
}
return 0;
}
struct mailbox_list_settings *set)
{
/* Maildir++ INBOX is the Maildir base itself */
}
}
static const char *
{
/* we'll need to figure out the maildir location ourself.
It's ~/Maildir unless we are chrooted. */
if (debug)
return path;
}
if (debug)
} else {
if (debug)
i_debug("maildir: Home directory not set");
if (debug)
i_debug("maildir: /cur exists, assuming chroot");
return "/";
}
}
return NULL;
}
struct mailbox_list_settings *set)
{
else {
if (debug)
i_debug("maildir: couldn't find root dir");
return FALSE;
}
}
if (debug)
return FALSE;
}
if (debug)
return FALSE;
}
return TRUE;
}
static int
{
const struct mailbox_permissions *perm;
if (verify) {
return 0;
"stat(%s) failed: %m", dir);
return -1;
}
}
perm->file_create_gid_origin) == 0)
return 0;
if (verify)
return 0;
"Mailbox already exists");
"Mailbox was deleted while it was being created");
/* shared namespace, don't log permission errors */
return -1;
}
} else {
"mkdir(%s) failed: %m", dir);
}
return -1;
}
{
const char *path;
/* if tmp/ directory exists, we need to clean it up once in a while */
return 0;
return -1;
}
return -1;
}
if (interval == 0) {
/* disabled */
/* the directory should be empty. we won't do anything
until ctime changes. */
/* time to scan */
}
return 1;
}
/* create or fix maildir, ignore if it already exists */
{
unsigned int i;
enum mail_error error;
int ret = 0;
&box_path) < 0)
return -1;
for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
if (error != MAIL_ERROR_EXISTS)
return -1;
/* try to create all of the directories in case one
of them doesn't exist */
ret = -1;
}
}
return ret;
}
{
}
static struct mailbox *
{
struct maildir_mailbox *mbox;
}
{
return -1;
mbox);
}
return -1;
sizeof(mbox->maildir_hdr), 0, 0);
return 0;
}
{
if (index_storage_is_readonly(box))
return TRUE;
if (maildir_is_backend_readonly(mbox)) {
/* return read-only only if there are no private flags
(that are stored in index files) */
if (mailbox_get_private_flags_mask(box) == 0)
return TRUE;
}
return FALSE;
}
static int
enum mailbox_existence *existence_r)
{
}
{
const char *root_dir;
int ret;
/* begin by checking if tmp/ directory exists and if it should be
cleaned up. */
if (ret > 0) {
/* exists */
return maildir_mailbox_open_existing(box);
}
if (ret < 0)
return -1;
/* tmp/ directory doesn't exist. does the maildir? */
/* root directory. either INBOX or some other namespace root */
/* yes, we'll need to create the missing dirs */
return -1;
return maildir_mailbox_open_existing(box);
}
return -1;
} else {
"stat(%s) failed: %m", box_path);
return -1;
}
}
{
const char *path;
&path);
if (ret < 0)
return -1;
if (fd == -1) {
path);
return -1;
}
} else {
"fchown(%s) failed: %m", path);
}
}
i_close_fd(&fd);
return 0;
}
static int
{
struct maildir_uidlist *uidlist;
int ret;
if (mailbox_open(box) < 0)
return -1;
}
if (maildir_uidlist_lock(uidlist) <= 0)
return -1;
if (update->uid_validity != 0)
if (update->min_next_uid != 0) {
FALSE);
}
if (ret == 0)
return ret;
}
{
const struct mailbox_permissions *perm;
const char *path;
int fd;
/* Maildir++ spec wants that maildirfolder named file is created for
all subfolders. Do this only with Maildir++ layout. */
return 0;
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 */
} else {
"fchown(%s) failed: %m", path);
}
}
i_close_fd(&fd);
return 0;
}
static int
bool directory)
{
const char *root_dir, *shared_path;
int ret;
return ret;
/* the maildir is created now. finish the creation as best as we can */
ret = -1;
if (maildir_create_maildirfolder_file(box) < 0)
ret = -1;
/* if dovecot-shared exists in the root dir, copy it to newly
created mailboxes */
if (maildir_create_shared(box) < 0)
ret = -1;
}
ret = -1;
}
return ret;
}
static int
enum mailbox_metadata_items items,
struct mailbox_metadata *metadata_r)
{
return -1;
if ((items & MAILBOX_METADATA_GUID) != 0) {
metadata_r->guid) < 0)
return -1;
}
return 0;
}
{
}
}
{
else {
}
}
static bool
const char *name)
{
}
struct mailbox_list *list)
{
struct maildir_mailbox_list_context *mlist;
}
{
const char *path;
}
{
if (mbox->private_flags_mask_set)
return mbox->_private_flags_mask;
/* private index directory is set. we'll definitely have
private flags. */
&path2) ||
/* no separate index directory. we can't have private flags,
so don't even bother checking if dovecot-shared exists */
} else {
"/dovecot-shared", NULL);
}
return mbox->_private_flags_mask;
}
{
if (!mbox->backend_readonly_set) {
}
return mbox->backend_readonly;
}
struct mail_storage maildir_storage = {
.v = {
NULL,
}
};
struct mailbox maildir_mailbox = {
.v = {
NULL,
}
};