maildir-storage.c revision ca98d6a1bbe73499da758a36bfab2963375c8d06
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic MODULE_CONTEXT_DEFINE_INIT(maildir_mailbox_list_module,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic const char *maildir_subdirs[] = { "cur", "new", "tmp" };
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic bool maildir_is_internal_name(const char *name)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic bool maildir_storage_is_valid_existing_name(struct mailbox_list *list,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *name)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct maildir_mailbox_list *mlist = MAILDIR_LIST_CONTEXT(list);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *p;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (!mlist->module_ctx.super.is_valid_existing_name(list, name))
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* Don't allow the mailbox name to end in cur/new/tmp */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic bool maildir_storage_is_valid_create_name(struct mailbox_list *list,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *name)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct maildir_mailbox_list *mlist = MAILDIR_LIST_CONTEXT(list);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (!mlist->module_ctx.super.is_valid_create_name(list, name))
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* Don't allow creating mailboxes under cur/new/tmp */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *const *tmp;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce for (tmp = t_strsplit(name, "/"); *tmp != NULL; tmp++) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic struct mail_storage *maildir_storage_alloc(void)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce pool = pool_alloconly_create("maildir storage", 512+256);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce storage = p_new(pool, struct maildir_storage, 1);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcemaildir_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct maildir_storage *storage = (struct maildir_storage *)_storage;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *dir;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce storage->set = mail_storage_get_driver_settings(_storage);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (list->set.control_dir == NULL && list->set.inbox_path == NULL &&
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* put the temp files into tmp/ directory preferrably */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce storage->temp_prefix = p_strconcat(_storage->pool, "tmp/",
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* control dir should also be writable */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _storage->temp_path_prefix = p_strconcat(_storage->pool, dir, "/",
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void maildir_storage_get_list_settings(const struct mail_namespace *ns,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce (strcmp(set->layout, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0 ||
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce strcmp(set->layout, MAILBOX_LIST_NAME_FS) == 0) &&
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* Maildir++ INBOX is the Maildir base itself */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic const char *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcemaildir_storage_find_root_dir(const struct mail_namespace *ns)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* we'll need to figure out the maildir location ourself.
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce It's ~/Maildir unless we are chrooted. */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce i_debug("maildir: access(%s, rwx): failed: %m", path);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce i_debug("maildir: /cur exists, assuming chroot");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic bool maildir_storage_autodetect(const struct mail_namespace *ns,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce i_debug("maildir autodetect: stat(%s) failed: %m", path);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce i_debug("maildir autodetect: %s not a directory", path);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcemkdir_verify(struct mail_storage *storage, struct mail_namespace *ns,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *dir, mode_t mode, gid_t gid, const char *gid_origin,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (mkdir_parents_chgrp(dir, mode, gid, gid_origin) == 0)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "Mailbox already exists");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "Mailbox was deleted while it was being created");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* shared namespace, don't log permission errors */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic int maildir_check_tmp(struct mail_storage *storage, const char *dir)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *path;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* if tmp/ directory exists, we need to clean it up once in a while */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (st.st_atime > st.st_ctime + MAILDIR_TMP_DELETE_SECS) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* the directory should be empty. we won't do anything
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce until ctime changes. */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } else if (st.st_atime < ioloop_time - MAILDIR_TMP_SCAN_SECS) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* time to scan */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce/* create or fix maildir, ignore if it already exists */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic int create_maildir(struct mailbox *box, bool verify)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const char *path;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce unsigned int i;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = maildir_check_tmp(box->storage, box->path);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce path = t_strconcat(box->path, "/", maildir_subdirs[i], NULL);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (mkdir_verify(box->storage, box->list->ns, path,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void maildir_lock_touch_timeout(struct maildir_mailbox *mbox)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic struct mailbox *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcemaildir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce pool = pool_alloconly_create("maildir mailbox", 1024+512);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mbox->ibox.box.mail_vfuncs = &maildir_mail_vfuncs;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mbox->ibox.save_commit_pre = maildir_transaction_save_commit_pre;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mbox->ibox.save_commit_post = maildir_transaction_save_commit_post;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mbox->ibox.save_rollback = maildir_transaction_save_rollback;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mbox->storage = (struct maildir_storage *)storage;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce mail_index_ext_register(mbox->ibox.box.index, "maildir",
const char *shared_path;
mbox);
int ret;
bool inbox;
if (ret > 0) {
if (ret < 0)
const char *path;
int fd;
path);
int ret;
FALSE);
if (ret == 0)
return ret;
bool directory)
if (directory &&
const char *root_dir;
char sep;
return NULL;
MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) != 0) {
return NULL;
const char *name)
struct dirent *d;
unsigned int dir_len;
errno = 0;
path);
if (!unlinked_something) {
unsigned int count;
count = 0;
count++;
int ret;
if (ret == 0) {
bool rename_children)
int ret;
switch (type) {
ret = 0;
return ret;
int ret;
const char *path;
switch (type) {
const char *path;
ret = 0;
ret = 0;
ret = 0;
return ret;
const char *path;
.class_flags = 0,
NULL,
NULL,
NULL,
NULL,
NULL,