mbox-storage.c revision ca1319463a8e8dbfeff8b78b0c687980b6428ddc
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2002 Timo Sirainen */
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen#include "subscription-file/subscription-file.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen if (stat(path, &st) == 0 && S_ISDIR(st.st_mode) &&
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (stat(path, &st) == 0 && !S_ISDIR(st.st_mode) &&
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen if (stat(path, &st) == 0 && !S_ISDIR(st.st_mode) &&
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstatic MailStorage *mbox_create(const char *data, const char *user)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we'll need to figure out the mail location ourself.
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen it's root dir if we've already chroot()ed, otherwise
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen either $HOME/mail or $HOME/Mail */
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen memcpy(storage, &mbox_storage, sizeof(MailStorage));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int mbox_is_valid_name(MailStorage *storage, const char *name)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *p;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (name[0] == '\0' || name[0] == storage->hierarchy_sep)
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen /* make sure there's no "../" or "..\" stuff */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenstatic const char *mbox_get_index_dir(const char *mbox_path)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen const char *p, *rootpath;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return t_strconcat(rootpath, "/.imap/", p+1, NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int create_mbox_index_dirs(const char *mbox_path, int verify)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen imap_dir = t_strdup_until(index_dir, strstr(index_dir, ".imap/") + 5);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (mkdir(imap_dir, CREATE_MODE) == -1 && errno != EEXIST)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (mkdir(index_dir, CREATE_MODE) == -1 && (errno != EEXIST || !verify))
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen i_snprintf(path, sizeof(path), "%s/inbox", storage->dir);
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen /* make sure inbox file itself exists */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0660);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* make sure the index directories exist */
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainenstatic Mailbox *mbox_open(MailStorage *storage, const char *name,
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen mbox_path = "/mail/foo/bar"
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen index_dir = "/mail/foo/.imap/bar" */
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen path = t_strconcat(storage->dir, "/", name, NULL);
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen ibox = index_storage_init(storage, &mbox_mailbox,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic Mailbox *mbox_open_mailbox(MailStorage *storage, const char *name,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* INBOX is always case-insensitive */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* make sure inbox exists */
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen return mbox_open(storage, "inbox", readonly, fast);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen mail_storage_set_error(storage, "Invalid mailbox name");
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen i_snprintf(path, sizeof(path), "%s/%s", storage->dir, name);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen /* exists - make sure the required directories are also there */
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen return mbox_open(storage, name, readonly, fast);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen mail_storage_set_error(storage, "Mailbox doesn't exist: %s",
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen mail_storage_set_critical(storage, "Can't open mailbox %s: %m",
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainenstatic int mbox_create_mailbox(MailStorage *storage, const char *name)
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen mail_storage_set_error(storage, "Invalid mailbox name");
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen /* make sure it doesn't exist already */
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen i_snprintf(path, sizeof(path), "%s/%s", storage->dir, name);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen mail_storage_set_error(storage, "Mailbox already exists");
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen mail_storage_set_critical(storage, "stat() failed for mbox "
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen /* create the mailbox file */
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0660);
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen /* mailbox was just created between stat() and open() call.. */
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen mail_storage_set_error(storage, "Mailbox already exists");
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen mail_storage_set_critical(storage, "Can't create mailbox "
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainenstatic int mbox_delete_mailbox(MailStorage *storage, const char *name)
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen mail_storage_set_error(storage, "INBOX can't be deleted.");
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen mail_storage_set_error(storage, "Invalid mailbox name");
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen /* first unlink the mbox file */
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen i_snprintf(path, sizeof(path), "%s/%s", storage->dir, name);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen "Mailbox doesn't exist: %s",
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen mail_storage_set_critical(storage, "Can't delete mbox "
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen /* next delete the index directory */
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen if (!unlink_directory(index_dir) && errno != ENOENT) {
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen mail_storage_set_critical(storage, "unlink_directory(%s) "
a2738cdb6d2733fb3e186331d68009421a19ea00Timo Sirainenstatic int mbox_rename_mailbox(MailStorage *storage, const char *oldname,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen mail_storage_set_error(storage, "Invalid mailbox name");
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen /* NOTE: renaming INBOX works just fine with us, it's simply created
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen the next time it's needed. */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_snprintf(oldpath, sizeof(oldpath), "%s/%s", storage->dir, oldname);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_snprintf(newpath, sizeof(newpath), "%s/%s", storage->dir, newname);
c24ef531ca58abad996482f5c2e8992be9ae8981Timo Sirainen "Target mailbox already exists");
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen mail_storage_set_critical(storage, "link(%s, %s) failed: %m",
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen /* we need to rename the index directory as well */
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainenstatic int mbox_get_mailbox_name_status(MailStorage *storage, const char *name,
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen i_snprintf(path, sizeof(path), "%s/%s", storage->dir, name);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen mail_storage_set_critical(storage, "mailbox name status: "
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_EXCLUSIVE))
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* update flags by rewrite mbox file */