mbox-storage.c revision fff95fdfb5c8ba917eb80f82b439ee3066e5a051
/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
#include "home-expand.h"
#include "mkdir-parents.h"
#include "unlink-directory.h"
#include "subscription-file/subscription-file.h"
#include "mbox-storage.h"
#include "mbox-lock.h"
#include "mail-save.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
extern struct mail_storage mbox_storage;
extern struct mailbox mbox_mailbox;
{
return -1;
}
{
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 index_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;
} else {
/* strip trailing '/' */
}
if (inbox_file == NULL)
if (hierarchy_sep != '\0')
}
{
}
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 0;
"mkdir_parents(%s) failed: %m", index_dir);
return -1;
}
return 0;
}
{
int fd;
/* make sure inbox file itself exists */
if (fd != -1)
/* make sure the index directories exist */
return -1;
return 0;
}
static const char *
{
return storage->inbox_path;
return home_expand(name);
}
{
return 0; // FIXME
}
static struct mailbox *
enum mailbox_open_flags flags)
{
struct index_mailbox *ibox;
struct mail_index *index;
/* name = "INBOX"
path = "<inbox_file>/INBOX"
} else {
}
return NULL;
}
static struct mailbox *
{
const char *path;
/* INBOX is always case-insensitive */
/* make sure inbox exists */
if (verify_inbox(storage) < 0)
return NULL;
}
if (!mbox_is_valid_existing_name(name)) {
return NULL;
}
"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)) {
path);
}
return NULL;
}
int directory)
{
const char *path, *p;
int fd;
if (!mbox_is_valid_create_name(name)) {
return -1;
}
/* make sure it doesn't exist already */
return -1;
}
"Mailbox doesn't allow inferior mailboxes");
} else {
"stat() failed for mbox file %s: %m", path);
}
return -1;
}
/* 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 -1;
"mkdir_parents(%s) failed: %m", p);
return -1;
}
if (directory) {
/* wanted to create only the directory */
return 0;
}
}
/* create the mailbox file */
if (fd != -1) {
return 0;
}
/* mailbox was just created between stat() and open() call.. */
} else if (!mbox_handle_errors(storage)) {
"Can't create mailbox %s: %m", name);
}
return -1;
}
{
return -1;
}
if (!mbox_is_valid_existing_name(name)) {
return -1;
}
"Mailbox doesn't exist: %s", name);
} else if (!mbox_handle_errors(storage)) {
"lstat() failed for %s: %m", path);
}
return -1;
}
/* 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) < 0) {
"rmdir() failed for %s: %m", index_dir);
return -1;
}
}
return 0;
"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 -1;
}
/* first unlink the mbox file */
"Mailbox doesn't exist: %s", name);
} else if (!mbox_handle_errors(storage)) {
"unlink() failed for %s: %m", path);
}
return -1;
}
/* next delete the index directory */
"unlink_directory(%s) failed: %m", index_dir);
/* mailbox itself is deleted, so return success
anyway */
}
}
return 0;
}
{
if (!mbox_is_valid_existing_name(oldname) ||
return -1;
}
/* 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 -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;
newpath);
return -1;
}
/* 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 -1;
}
/* we need to rename the index directory as well */
if (old_indexdir != NULL) {
"rename(%s, %s) failed: %m",
}
}
return 0;
}
{
const char *path;
}
const char *name,
enum mailbox_name_status *status)
{
const char *path;
if (!mbox_is_valid_existing_name(name)) {
return 0;
}
return 0;
}
if (!mbox_is_valid_create_name(name)) {
return 0;
}
return 0;
return 0;
} else {
"stat(%s) failed: %m", path);
return -1;
}
}
{
return 0;
}
enum mailbox_sync_flags flags,
unsigned int min_newmail_notify_interval)
{
/* flags or interval just changed. or nothing. */
}
if (flags == 0)
else
}
struct mail_storage mbox_storage = {
"mbox", /* name */
NULL, /* namespace */
'/', /* default hierarchy separator */
NULL,
0
};
struct mailbox mbox_mailbox = {
NULL, /* name */
NULL, /* storage */
};