maildir-storage.c revision f0fa0904765d41e7e6c52606400199b004ae7492
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen#include "subscription-file/subscription-file.h"
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen/* Don't allow creating too long mailbox names. They could start causing
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen problems when they reach the limit. */
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen#define MAILDIR_MAX_MAILBOX_NAME_LENGTH (PATH_MAX/2)
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainenstatic const char *maildirs[] = { "cur", "new", "tmp", NULL };
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainenstatic int verify_inbox(struct maildir_storage *storage);
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainenmaildir_create(const char *data, const char *user,
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
ddbdc644a15f56f4b43596f1b8c0fc196c101445Timo Sirainen const char *root_dir, *inbox_dir, *index_dir, *control_dir;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen inbox_dir = root_dir = index_dir = control_dir = NULL;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen /* we'll need to figure out the maildir location ourself.
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen It's $HOME/Maildir unless we are chrooted. */
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen i_info("maildir: /cur exists, assuming chroot");
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen /* <Maildir> [:INBOX=<dir>] [:INDEX=<dir>] [:CONTROL=<dir>] */
26681e71837ebbb3eb92455ec4e3cadefa710f82Timo Sirainen } while (p != NULL);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen /* strip trailing '/' */
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen i_info("maildir: root=%s, index=%s, control=%s, inbox=%s",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen storage = p_new(pool, struct maildir_storage, 1);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen storage->control_dir = p_strdup(pool, home_expand(control_dir));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* the default ".temp.xxx" prefix would be treated as directory */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen p_strconcat(pool, "temp.", my_hostname, ".", my_pid, ".", NULL);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen istorage->dir = p_strdup(pool, home_expand(root_dir));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen istorage->inbox_path = p_strdup(pool, home_expand(inbox_dir));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen istorage->index_dir = p_strdup(pool, home_expand(index_dir));
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen istorage->callbacks = p_new(pool, struct mail_storage_callbacks, 1);
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen index_storage_init(istorage, flags, lock_method);
5324117274df8564eeaebe369cb1eca76edb3165Timo Sirainenstatic void maildir_free(struct mail_storage *_storage)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen struct index_storage *storage = (struct index_storage *) _storage;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainenstatic bool maildir_autodetect(const char *data, enum mail_storage_flags flags)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen i_info("maildir autodetect: stat(%s) failed: %m", path);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen i_info("maildir autodetect: %s not a directory", path);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenstatic bool maildir_is_valid_create_name(struct mail_storage *storage,
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (len == 0 || len > MAILDIR_MAX_MAILBOX_NAME_LENGTH ||
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen name[0] == MAILDIR_FS_SEP || name[len-1] == MAILDIR_FS_SEP ||
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen strchr(name, '*') != NULL || strchr(name, '%') != NULL)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if ((storage->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (*name == '~' || strchr(name, '/') != NULL)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenstatic bool maildir_is_valid_existing_name(struct mail_storage *storage,
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (name[0] == '\0' || name[strlen(name)-1] == '/')
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen if ((storage->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0)
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen if (*name == '~' || strchr(name, '/') != NULL)
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainenstatic const char *maildir_get_absolute_path(const char *name, bool unlink)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *p;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenconst char *maildir_get_path(struct index_storage *storage, const char *name)
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen return maildir_get_absolute_path(name, FALSE);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return t_strconcat(storage->dir, "/"MAILDIR_FS_SEP_S, name, NULL);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainenstatic const char *
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainenmaildir_get_unlink_path(struct index_storage *storage, const char *name)
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic const char *maildir_get_index_path(struct index_storage *storage,
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen strcmp(storage->index_dir, storage->dir) == 0)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return maildir_get_absolute_path(name, FALSE);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainenstatic const char *maildir_get_control_path(struct maildir_storage *storage,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return maildir_get_path(INDEX_STORAGE(storage), name);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if ((STORAGE(storage)->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return maildir_get_absolute_path(name, FALSE);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic int mkdir_verify(struct index_storage *storage,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (errno != EEXIST && (!verify || errno != ENOENT)) {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen/* create or fix maildir, ignore if it already exists */
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainenstatic int create_maildir(struct index_storage *storage,
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (!verify && mkdir_verify(storage, dir, verify) < 0)
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen if (mkdir_verify(storage, path, verify) < 0) {
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen /* small optimization. if we're verifying, we don't
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen check that the root dir actually exists unless we
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen fail here. */
31750e7fddc514c68c4eaf85b4f8c00000c281e0Timo Sirainenstatic int create_index_dir(struct index_storage *storage, const char *name)
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen const char *dir;
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen if (strcmp(storage->index_dir, storage->dir) == 0 ||
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen (strcmp(name, "INBOX") == 0 && storage->inbox_path != NULL &&
737d994fb6bb0f3e87f7412e35874694013d2fc3Timo Sirainen strcmp(storage->index_dir, storage->inbox_path) == 0))
31750e7fddc514c68c4eaf85b4f8c00000c281e0Timo Sirainen dir = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
087eb3d719a5667631cc7ce9de6c372ddea19f4dTimo Sirainen if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainenstatic int create_control_dir(struct maildir_storage *storage, const char *name)
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen const char *dir;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen dir = t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenstatic int verify_inbox(struct maildir_storage *storage)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct index_storage *istorage = INDEX_STORAGE(storage);
static struct mailbox *
int shared;
if (shared)
FALSE) < 0) {
return NULL;
if (!shared)
static struct mailbox *
const char *path;
return NULL;
return NULL;
return NULL;
return NULL;
return NULL;
name);
return NULL;
path);
return NULL;
int fd;
const char *name,
const char *name)
int count;
name);
count = 0;
count++;
int ret;
ret = 0;
t_push();
t_pop();
t_pop();
return ret;
int ret;
bool found;
if (ret < 0)
const char *path;
const char *name,
const char *path;
path);
int ret = 0;
return ret;