maildir-storage.c revision 36122480cc7080b7e3d17faa9b7ced90331bd308
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen MODULE_CONTEXT(obj, maildir_mailbox_list_module)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(maildir_mailbox_list_module,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic const char *maildir_subdirs[] = { "cur", "new", "tmp" };
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic struct mail_storage *maildir_storage_alloc(void)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen pool = pool_alloconly_create("maildir storage", 512+256);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen storage = p_new(pool, struct maildir_storage, 1);
47daf6e810a4c2dd52640092092900dbcb12f265Timo Sirainenmaildir_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
47daf6e810a4c2dd52640092092900dbcb12f265Timo Sirainen struct maildir_storage *storage = (struct maildir_storage *)_storage;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen const char *dir;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen storage->set = mail_storage_get_driver_settings(_storage);
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen storage->temp_prefix = p_strdup(_storage->pool,
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen if (list->set.control_dir == NULL && list->set.inbox_path == NULL &&
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0) {
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen /* put the temp files into tmp/ directory preferrably */
1c0020171b04d14adc4966ed963361abc9a86787Timo Sirainen storage->temp_prefix = p_strconcat(_storage->pool, "tmp/",
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen /* control dir should also be writable */
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen _storage->temp_path_prefix = p_strconcat(_storage->pool, dir, "/",
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainenstatic void maildir_storage_get_list_settings(const struct mail_namespace *ns,
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen set->layout = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS;
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainen if (set->inbox_path == NULL && set->maildir_name == NULL &&
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen (strcmp(set->layout, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0 ||
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen strcmp(set->layout, MAILBOX_LIST_NAME_FS) == 0) &&
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen (ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0) {
df8046c9a4f6bc2a478ad1e74504d50f3110c906Timo Sirainen /* Maildir++ INBOX is the Maildir base itself */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic const char *
abb5d20d3155db02a1afec4066d52707ba9d4e52Timo Sirainenmaildir_storage_find_root_dir(const struct mail_namespace *ns)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* we'll need to figure out the maildir location ourself.
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen It's ~/Maildir unless we are chrooted. */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (mail_user_get_home(ns->user, &home) > 0) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen i_debug("maildir: access(%s, rwx): failed: %m", path);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen i_debug("maildir: /cur exists, assuming chroot");
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainenstatic bool maildir_storage_autodetect(const struct mail_namespace *ns,
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen i_debug("maildir autodetect: stat(%s) failed: %m", path);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen i_debug("maildir autodetect: %s not a directory", path);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmkdir_verify(struct mail_storage *storage, struct mail_namespace *ns,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen const char *dir, mode_t mode, gid_t gid, const char *gid_origin,
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (mkdir_parents_chgrp(dir, mode, gid, gid_origin) == 0)
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen "Mailbox already exists");
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen "Mailbox was deleted while it was being created");
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen /* shared namespace, don't log permission errors */
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_PERM,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic int maildir_check_tmp(struct mail_storage *storage, const char *dir)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* if tmp/ directory exists, we need to clean it up once in a while */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen mail_storage_set_critical(storage, "stat(%s) failed: %m", path);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (st.st_atime > st.st_ctime + MAILDIR_TMP_DELETE_SECS) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* the directory should be empty. we won't do anything
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen until ctime changes. */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen } else if (st.st_atime < ioloop_time - MAILDIR_TMP_SCAN_SECS) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* time to scan */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen/* create or fix maildir, ignore if it already exists */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic int create_maildir(struct mailbox *box, bool verify)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen unsigned int i;
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen path = t_strconcat(box->path, "/", maildir_subdirs[i], NULL);
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen if (mkdir_verify(box->storage, box->list->ns, path,
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen (void)mail_storage_get_last_error(box->storage, &error);
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen /* try to create all of the directories in case one
6de0cbb4a498ce0519b0f28e221164ce8d39736aTimo Sirainen of them doesn't exist */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic void maildir_lock_touch_timeout(struct maildir_mailbox *mbox)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen (void)maildir_uidlist_lock_touch(mbox->uidlist);
static struct mailbox *
const char *shared_path;
mbox);
const char *root_dir;
int ret;
if (ret > 0) {
if (ret < 0)
const char *path;
int fd;
path);
int ret;
FALSE);
if (ret == 0)
return ret;
bool directory)
int ret;
if (directory &&
if (ret > 0) {
if (ret < 0)
const char *name)
const char *cur_path;
int ret;
return ret;
const char *path;
.class_flags = 0,
NULL,
NULL,
NULL,
NULL,
NULL,