dbox-storage.c revision 777ff25e82e0305e2696bcbe3c6e0274e3e8ce10
/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "str.h"
#include "mkdir-parents.h"
#include "unlink-old-files.h"
#include "index-mail.h"
#include "mail-copy.h"
#include "maildir/maildir-uidlist.h"
#include "dbox-sync.h"
#include "dbox-index.h"
#include "dbox-file.h"
#include "dbox-storage.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#define DBOX_LIST_CONTEXT(obj) \
extern struct mail_storage dbox_storage;
extern struct mailbox dbox_mailbox;
static int
static int
static int
const char *mailbox_name,
enum mailbox_list_file_type type,
enum mailbox_info_flags *flags);
static int
const char **error_r)
{
*layout_r = "fs";
/* we won't do any guessing for this format. */
if (debug)
i_info("dbox: mailbox location not given");
*error_r = "Root mail directory not given";
return -1;
}
if (debug)
}
static struct mail_storage *dbox_alloc(void)
{
struct dbox_storage *storage;
}
const char **error_r)
{
struct mailbox_list_settings list_set;
return -1;
"Root mail directory doesn't exist: %s",
} else {
"stat(%s) failed: %m",
}
return -1;
}
return -1;
}
/* can't create a new user, but we don't want to fail
the storage creation. */
} else {
return -1;
}
return -1;
/* finish list init after we've overridden vfuncs */
return 0;
}
{
if (!mail_storage_set_error_from_errno(storage)) {
"mkdir(%s) failed: %m", path);
}
return -1;
}
return 0;
}
static const char *
{
const char *root;
unsigned int len;
return NULL;
/* can't determine the alt path - shouldn't happen */
return NULL;
}
}
static struct mailbox *
enum mailbox_open_flags flags)
{
struct dbox_mailbox *mbox;
struct mail_index *index;
else
else
else
else
mbox->dbox_ext_id =
sizeof(struct dbox_mail_index_record),
sizeof(uint32_t));
sizeof(struct dbox_index_header), 0, 0);
}
static bool
{
return FALSE;
/* check once in a while if there are temp files to clean up */
/* there haven't been any changes to this directory since we
last checked it. */
/* time to scan */
const char *prefix =
}
return TRUE;
}
static struct mailbox *
{
const char *path;
"dbox doesn't support streamed mailboxes");
return NULL;
}
/* INBOX always exists, create it */
return NULL;
}
} else {
path);
}
return NULL;
}
{
return index_storage_mailbox_close(box);
}
{
"Mailbox already exists");
return -1;
}
/* make sure the alt path doesn't exist yet. it shouldn't (except with
left it lying around we don't want to start overwriting files in
it. */
"Mailbox already exists");
return -1;
}
}
static int
const char *name)
{
struct dirent *d;
unsigned int dir_len;
bool unlinked_something = FALSE;
return 0;
if (!mailbox_list_set_error_from_errno(list)) {
"opendir(%s) failed: %m", path);
}
return -1;
}
errno = 0;
if (d->d_name[0] == '.') {
/* skip . and .. */
continue;
continue;
}
/* trying to unlink() a directory gives either EPERM or EISDIR
(non-POSIX). it doesn't really work anywhere in practise,
so don't bother stat()ing the file first */
}
}
path);
}
return -1;
}
if (!unlinked_something) {
t_strdup_printf("Directory %s isn't empty, "
"can't delete it.", name));
return -1;
}
return 1;
}
static int
{
int ret;
/* Make sure the indexes are closed before trying to delete the
directory that contains them. It can still fail with some NFS
implementations if indexes are opened by another session, but
that can't really be helped. */
/* delete the index and control directories */
return -1;
/* check if the mailbox actually exists */
/* delete the mailbox first */
return -1;
}
/* everything was in the one directory that was
already deleted succesfully. */
return 0;
}
/* try to delete the directory also */
return -1;
} else {
/* mailbox not found - what about the directory? */
/* delete the directory */
return -1;
} else if (!mailbox_list_set_error_from_errno(list)) {
path);
return -1;
}
}
return 0;
if (deleted)
return 0;
t_strdup_printf("Directory %s isn't empty, "
"can't delete it.", name));
} else if (!mailbox_list_set_error_from_errno(list)) {
path);
}
return -1;
}
static bool
{
const char *path;
return FALSE;
return FALSE;
return TRUE;
}
static int
{
const char *alt_oldpath, *alt_newpath;
&alt_oldpath, &alt_newpath))
return 0;
/* race condition or a directory left there lying around?
safest to just report error. */
"Target mailbox already exists");
return -1;
return -1;
}
return 0;
}
static int
{
const char *alt_oldpath, *alt_newpath;
newname) < 0)
return -1;
&alt_oldpath, &alt_newpath))
return 0;
/* ok */
/* renaming is done already, so just log the error */
}
return 0;
}
{
const char *path;
else {
}
}
const char *mailbox_name ATTR_UNUSED,
enum mailbox_list_file_type type,
enum mailbox_info_flags *flags)
{
const char *path, *maildir_path;
int ret = 1;
/* try to avoid stat() with these checks */
if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
/* it's a file */
return 0;
}
/* need to stat() then */
/* non-directory */
ret = 0;
/* no subdirectories */
*flags |= MAILBOX_NOCHILDREN;
/* default configuration: we have one directory
containing the mailboxes. if there are 3 links,
either this is a selectable mailbox without children
or non-selectable mailbox with children */
*flags |= MAILBOX_CHILDREN;
} else {
/* non-default configuration: all subdirectories are
child mailboxes. */
*flags |= MAILBOX_CHILDREN;
}
/* doesn't exist - probably a non-existing subscribed mailbox */
*flags |= MAILBOX_NONEXISTENT;
} else {
/* non-selectable. probably either access denied, or symlink
destination not found. don't bother logging errors. */
*flags |= MAILBOX_NOSELECT;
}
/* make sure it's a selectable mailbox */
*flags |= MAILBOX_NOSELECT;
/* now we know what link count 3 means. */
if ((*flags & MAILBOX_NOSELECT) != 0)
*flags |= MAILBOX_CHILDREN;
else
*flags |= MAILBOX_NOCHILDREN;
}
}
return ret;
}
static void dbox_class_init(void)
{
}
static void dbox_class_deinit(void)
{
}
struct mail_storage dbox_storage = {
{
NULL,
}
};
struct mailbox dbox_mailbox = {
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
}
};