mbox-storage.c revision 00bb3f3db48a9e80a633a7c4d3d768b8ff1a72c5
/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "home-expand.h"
#include "mkdir-parents.h"
#include "unlink-directory.h"
#include "subscription-file/subscription-file.h"
#include "mail-custom-flags.h"
#include "mbox-index.h"
#include "mbox-lock.h"
#include "mbox-storage.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
extern struct mail_storage mbox_storage;
extern struct mailbox mbox_mailbox;
{
else
return FALSE;
return TRUE;
}
static int mbox_autodetect(const char *data)
{
const char *path;
/* Is it INBOX file? */
return TRUE;
/* or directory for IMAP folders? */
return TRUE;
return TRUE;
return TRUE;
return FALSE;
}
static const char *get_root_dir(void)
{
if (mbox_autodetect(""))
return "/";
return path;
return path;
}
return NULL;
}
{
if (!only_root) {
return path;
return path;
}
}
}
static const char *create_root_dir(void)
{
i_error("mbox: We need root IMAP folder, "
"but can't find it or HOME environment");
return NULL;
}
return NULL;
}
return path;
}
static struct mail_storage *
const char *namespace, char hierarchy_sep)
{
struct mail_storage *storage;
int autodetect;
if (autodetect) {
/* we'll need to figure out the mail location ourself.
it's root dir if we've already chroot()ed, otherwise
root_dir = get_root_dir();
} else {
/* <root folder> | <INBOX path>
[:INBOX=<path>] [:INDEX=<dir>] */
if (p == NULL) {
return NULL;
}
else {
root_dir = get_root_dir();
inbox_file = data;
}
} else {
do {
p++;
p = strchr(p, ':');
} while (p != NULL);
}
}
root_dir = create_root_dir();
return NULL;
}
if (inbox_file == NULL)
if (hierarchy_sep != '\0')
return storage;
}
{
}
const char *name, int remove_namespace)
{
/* don't check namespace with INBOX */
return name;
}
}
i_panic("mbox: expecting namespace '%s' in name '%s'",
}
}
return name;
if (sep == '/')
return name;
for (p = dup; *p != '\0'; p++) {
if (*p == sep)
*p = '/';
}
return dup;
}
int mbox_is_valid_mask(const char *mask)
{
const char *p;
int newdir;
return TRUE;
/* make sure it's not absolute path */
return FALSE;
/* make sure there's no "../" stuff */
for (p = mask; *p != '\0'; p++) {
return FALSE;
newdir = p[0] == '/';
}
return TRUE;
}
static int mbox_is_valid_create_name(const char *name)
{
return FALSE;
return mbox_is_valid_mask(name);
}
static int mbox_is_valid_existing_name(const char *name)
{
if (name[0] == '\0')
return FALSE;
return mbox_is_valid_mask(name);
}
const char *name)
{
const char *p;
return NULL;
}
if (p == NULL)
else {
t_strdup_until(name, p),
}
}
const char *name)
{
const char *index_dir;
return TRUE;
"mkdir_parents(%s) failed: %m", index_dir);
return FALSE;
}
return TRUE;
}
{
int fd;
/* make sure inbox file itself exists */
if (fd != -1)
/* make sure the index directories exist */
return FALSE;
return TRUE;
}
{
return storage->inbox_file;
return home_expand(name);
}
{
}
enum mailbox_open_flags flags)
{
struct index_mailbox *ibox;
struct mail_index *index;
/* name = "INBOX"
path = "<inbox_file>/INBOX"
} else {
}
}
}
static struct mailbox *
{
const char *path;
/* INBOX is always case-insensitive */
/* make sure inbox exists */
if (!verify_inbox(storage))
return FALSE;
}
if (!mbox_is_valid_existing_name(name)) {
return FALSE;
}
"Mailbox isn't selectable: %s", name);
return NULL;
}
/* exists - make sure the required directories are also there */
return NULL;
}
name);
} else if (!mbox_handle_errors(storage))
return NULL;
}
int directory)
{
const char *path, *p;
int fd;
if (!mbox_is_valid_create_name(name)) {
return FALSE;
}
/* make sure it doesn't exist already */
return FALSE;
}
"Mailbox doesn't allow inferior mailboxes");
} else {
"stat() failed for mbox file %s: %m", path);
}
return FALSE;
}
/* create the hierarchy if needed */
if (p != NULL) {
p = t_strdup_until(path, p);
if (mkdir_parents(p, CREATE_MODE) < 0) {
if (mbox_handle_errors(storage))
return FALSE;
"mkdir_parents(%s) failed: %m", p);
return FALSE;
}
if (directory) {
/* wanted to create only the directory */
return TRUE;
}
}
/* create the mailbox file */
if (fd != -1) {
return TRUE;
}
/* mailbox was just created between stat() and open() call.. */
} else if (!mbox_handle_errors(storage)) {
"Can't create mailbox %s: %m", name);
}
return FALSE;
}
{
return FALSE;
}
if (!mbox_is_valid_existing_name(name)) {
return FALSE;
}
"Mailbox doesn't exist: %s", name);
} else if (!mbox_handle_errors(storage)) {
"%s: %m", path);
}
return FALSE;
}
/* deleting a folder, only allow it if it's empty.
Delete .imap folder before to make sure it goes empty. */
"/.imap", NULL);
if (!mbox_handle_errors(storage)) {
"rmdir() failed for %s: %m", index_dir);
return FALSE;
}
}
return TRUE;
"Mailbox doesn't exist: %s", name);
"Folder %s isn't empty, can't delete it.",
name);
} else if (!mbox_handle_errors(storage)) {
"rmdir() failed for %s: %m", path);
}
return FALSE;
}
/* first unlink the mbox file */
"Mailbox doesn't exist: %s", name);
} else if (!mbox_handle_errors(storage)) {
"unlink() failed for %s: %m", path);
}
return FALSE;
}
/* next delete the index directory */
"unlink_directory(%s) failed: %m", index_dir);
/* mailbox itself is deleted, so return success
anyway */
}
}
return TRUE;
}
{
if (!mbox_is_valid_existing_name(oldname) ||
return FALSE;
}
/* create the hierarchy */
if (p != NULL) {
p = t_strdup_until(newpath, p);
if (mkdir_parents(p, CREATE_MODE) < 0) {
if (mbox_handle_errors(storage))
return FALSE;
"mkdir_parents(%s) failed: %m", p);
return FALSE;
}
}
/* 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 FALSE;
newpath);
return FALSE;
}
/* NOTE: renaming INBOX works just fine with us, it's simply recreated
the next time it's needed. */
"Mailbox doesn't exist: %s", oldname);
} else if (!mbox_handle_errors(storage)) {
}
return FALSE;
}
/* we need to rename the index directory as well */
if (old_indexdir != NULL) {
"rename(%s, %s) failed: %m",
}
}
return TRUE;
}
{
}
const char *name,
enum mailbox_name_status *status)
{
const char *path;
if (!mbox_is_valid_existing_name(name)) {
return TRUE;
}
return TRUE;
}
if (!mbox_is_valid_create_name(name)) {
return TRUE;
}
return TRUE;
return TRUE;
} else {
"stat(%s) failed: %m", path);
return FALSE;
}
}
{
/* update flags by rewrite mbox file */
}
}
}
enum mailbox_sync_flags flags,
unsigned int min_newmail_notify_interval)
{
/* flags or interval just changed. or nothing. */
}
if (flags == 0)
else
}
enum mailbox_lock_type lock_type)
{
if (lock_type == MAIL_LOCK_UNLOCK) {
return FALSE;
return TRUE;
}
return FALSE;
} else if ((lock_type & MAILBOX_LOCK_READ) != 0) {
return FALSE;
}
/* FIXME: saving doesn't have to sync it, just lock it */
return FALSE;
}
return TRUE;
}
struct mail_storage mbox_storage = {
"mbox", /* name */
NULL, /* namespace */
'/', /* default hierarchy separator */
NULL,
NULL,
NULL,
NULL,
NULL,
0
};
struct mailbox mbox_mailbox = {
NULL, /* name */
NULL, /* storage */
};