mbox-storage.c revision 6246b93fb37890dcb2f4df9896438f3f376ab284
/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "buffer.h"
#include "istream.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 "mbox-file.h"
#include "mbox-sync-private.h"
#include "mail-copy.h"
#include "index-mail.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
/* NOTE: must be sorted for istream-header-filter. */
const char *mbox_hide_headers[] = {
"Content-Length",
"Status",
"X-IMAP",
"X-IMAPbase",
"X-Keywords",
"X-Status",
"X-UID",
};
unsigned int mbox_hide_headers_count = 7;
extern struct mail_storage mbox_storage;
extern struct mailbox mbox_mailbox;
{
return -1;
}
{
else
return FALSE;
return TRUE;
}
{
if (debug) {
i_info("mbox autodetect: %s: stat(%s) failed: %m",
}
return FALSE;
}
if (debug) {
i_info("mbox autodetect: %s: is a directory (%s)",
}
return FALSE;
}
if (debug) {
i_info("mbox autodetect: %s: no R/W access (%s)",
}
return FALSE;
}
if (debug)
return TRUE;
}
{
if (debug) {
i_info("mbox autodetect: %s: stat(%s) failed: %m",
}
return FALSE;
}
if (debug) {
i_info("mbox autodetect: %s: is not a directory (%s)",
}
return FALSE;
}
if (debug) {
i_info("mbox autodetect: %s: no R/W/X access (%s)",
}
return FALSE;
}
if (debug)
return TRUE;
}
{
const char *path;
if (debug) {
i_info("mbox autodetect: data=%s, splitting ':' -> %s",
} else {
}
}
return TRUE;
return TRUE;
return TRUE;
return TRUE;
return FALSE;
}
{
if (debug)
return path;
}
if (debug)
if (debug)
return path;
}
if (debug)
}
if (debug)
i_info("mbox: checking if we are chrooted:");
return "/";
if (debug)
i_info("mbox: root directory not found");
return NULL;
}
static const char *
{
if (debug)
return path;
}
if (debug)
if (debug)
return path;
}
if (debug)
}
if (debug)
return path;
}
static const char *create_root_dir(int debug)
{
i_error("mbox: We need root IMAP folder, "
"but can't find it or HOME environment");
return NULL;
}
return NULL;
}
if (debug)
return path;
}
static struct mail_storage *
{
struct mbox_storage *storage;
struct index_storage *istorage;
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
} else {
/* <root folder> | <INBOX path>
[:INBOX=<path>] [:INDEX=<dir>] */
if (debug)
if (p == NULL) {
return NULL;
}
else {
inbox_file = data;
}
} else {
do {
p++;
p = strchr(p, ':');
} while (p != NULL);
}
}
return NULL;
} else {
/* strip trailing '/' */
/* make sure the directory exists */
/* yep, go ahead */
return NULL;
return NULL;
}
}
if (inbox_file == NULL)
if (debug) {
i_info("mbox: root=%s, index=%s, inbox=%s",
}
}
{
}
{
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;
}
const char *name)
{
return FALSE;
}
const char *name)
{
return FALSE;
}
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 FALSE;
}
static struct mbox_mailbox *
{
struct mbox_mailbox *mbox;
/* the memory is already freed here, no need to deinit */
return NULL;
}
mbox->mbox_ext_idx =
return mbox;
}
static struct mailbox *
enum mailbox_open_flags flags)
{
struct mbox_mailbox *mbox;
struct mail_index *index;
/* name = "INBOX"
path = "<inbox_file>/INBOX"
} else {
}
return NULL;
else {
}
}
}
static struct mailbox *
{
struct mail_index *index;
struct mbox_mailbox *mbox;
return NULL;
}
static struct mailbox *
{
const char *path;
/* make sure INBOX exists */
if (verify_inbox(istorage) < 0)
return NULL;
}
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(istorage)) {
path);
}
return NULL;
}
int directory)
{
const char *path, *p;
int fd;
return -1;
}
/* We might actually be able to create mailboxes under INBOX
because the real INBOX file isn't usually named as INBOX
in the root mail directory. that would anyway be a special
case which would require special handling elsewhere, so just
don't allow it. */
"Mailbox doesn't allow inferior mailboxes");
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;
}
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;
}
{
return -1;
}
/* Not allowed - see explanation in mbox_mailbox_create */
"Target mailbox doesn't allow inferior mailboxes");
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;
"Target mailbox doesn't allow inferior mailboxes");
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;
return 0;
}
return 0;
}
return 0;
}
return 0;
return 0;
} else {
"stat(%s) failed: %m", path);
return -1;
}
}
{
const struct mail_index_header *hdr;
int ret = 0;
/* we've done changes to mbox which haven't been written yet.
do it now. */
ret = -1;
}
/* it's not in storage's index cache, so free it manually */
}
if (free_index != NULL)
return ret;
}
static void
{
else
}
struct mail_storage mbox_storage = {
{
}
};
struct mailbox mbox_mailbox = {
{
}
};