maildir-storage.c revision 6913a451b76b1bdb53be55e2f2f7ad572b2c2b8a
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "subscription-file/subscription-file.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstatic const char *maildirs[] = { "cur", "new", "tmp", NULL };
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainenstatic int verify_inbox(struct index_storage *storage);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenmaildir_create(const char *data, const char *user,
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen const char *root_dir, *inbox_dir, *index_dir, *control_dir;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen inbox_dir = root_dir = index_dir = control_dir = NULL;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* we'll need to figure out the maildir location ourself.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen it's either root dir if we've already chroot()ed, or
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen $HOME/Maildir otherwise */
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen /* <Maildir> [:INBOX=<dir>] [:INDEX=<dir>] [:CONTROL=<dir>] */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } while (p != NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* strip trailing '/' */
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen storage->storage.hierarchy_sep = hierarchy_sep;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen storage->storage.namespace = i_strdup(namespace);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* the default ".temp.xxx" prefix would be treated as directory */
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen i_strconcat("temp.", my_hostname, ".", my_pid, ".", NULL);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen storage->dir = i_strdup(home_expand(root_dir));
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen storage->inbox_path = i_strdup(home_expand(inbox_dir));
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen storage->index_dir = i_strdup(home_expand(index_dir));
4b41116563110d00330896a568eff1078c382827Timo Sirainen storage->control_dir = i_strdup(home_expand(control_dir));
4b41116563110d00330896a568eff1078c382827Timo Sirainen storage->callbacks = i_new(struct mail_storage_callbacks, 1);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void maildir_free(struct mail_storage *_storage)
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen struct index_storage *storage = (struct index_storage *) _storage;
e3796bfd2bc0fd5ba664893d346df9334a5b3af0Timo Sirainenstatic int maildir_autodetect(const char *data)
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen return stat(t_strconcat(data, "/cur", NULL), &st) == 0 &&
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenstatic int maildir_is_valid_create_name(const char *name)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen strchr(name, '*') != NULL || strchr(name, '%') != NULL)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (*name == '~' || strchr(name, '/') != NULL)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int maildir_is_valid_existing_name(const char *name)
f95b3d29bc56f139c18c880aa574a0ca72b0cffbTimo Sirainen if (name[0] == '\0' || name[strlen(name)-1] == '/')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*name == '~' || strchr(name, '/') != NULL)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainenstatic const char *maildir_get_absolute_path(const char *name, int unlink)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen const char *p;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenconst char *maildir_fix_mailbox_name(struct index_storage *storage,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen (name[5] == '\0' || name[5] == storage->storage.hierarchy_sep)) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* use same case with all INBOX folders or we'll get
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen into trouble */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* don't check namespace with INBOX */
f23ede27743c1aa03eacbfc634d6a10de9110c91Timo Sirainen if (storage->storage.namespace != NULL && remove_namespace) {
f23ede27743c1aa03eacbfc634d6a10de9110c91Timo Sirainen if (strncmp(storage->storage.namespace, name, len) != 0) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i_panic("maildir: expecting namespace '%s' in name "
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (full_filesystem_access && (*name == '/' || *name == '~'))
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenconst char *maildir_get_path(struct index_storage *storage, const char *name)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (full_filesystem_access && (*name == '/' || *name == '~'))
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return maildir_get_absolute_path(name, FALSE);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return t_strconcat(storage->dir, "/"MAILDIR_FS_SEP_S, name, NULL);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic const char *
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenmaildir_get_unlink_path(struct index_storage *storage, const char *name)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (full_filesystem_access && (*name == '/' || *name == '~'))
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstatic const char *maildir_get_index_path(struct index_storage *storage,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (strcmp(name, "INBOX") == 0 && storage->inbox_path != NULL)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (full_filesystem_access && (*name == '/' || *name == '~'))
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return maildir_get_absolute_path(name, FALSE);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic const char *maildir_get_control_path(struct index_storage *storage,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (full_filesystem_access && (*name == '/' || *name == '~'))
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return maildir_get_absolute_path(name, FALSE);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic int mkdir_verify(struct index_storage *storage,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (mkdir_parents(dir, CREATE_MODE) < 0 && (errno != EEXIST || !verify)) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (errno != EEXIST && (!verify || errno != ENOENT)) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen/* create or fix maildir, ignore if it already exists */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic int create_maildir(struct index_storage *storage,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (!verify && mkdir_verify(storage, dir, verify) < 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (mkdir_verify(storage, path, verify) < 0) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* small optimization. if we're verifying, we don't
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen check that the root dir actually exists unless we
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen fail here. */
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainenstatic int create_index_dir(struct index_storage *storage, const char *name)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen const char *dir;
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if (strcmp(storage->index_dir, storage->dir) == 0 ||
b19a1420da0618a10edf67c2cfd13c8c8633057aTimo Sirainen (strcmp(name, "INBOX") == 0 && storage->inbox_path != NULL &&
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen strcmp(storage->index_dir, storage->inbox_path) == 0))
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen dir = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (mkdir_parents(dir, CREATE_MODE) == -1 && errno != EEXIST) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic int create_control_dir(struct index_storage *storage, const char *name)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen const char *dir;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen dir = t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenstatic int verify_inbox(struct index_storage *storage)
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen /* first make sure the cur/ new/ and tmp/ dirs exist
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen in root dir */
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen if (create_maildir(storage, storage->dir, TRUE) < 0)
b3b4f3875850099c9292ad74d08bb385c3988f8fTimo Sirainen /* create the .INBOX directory */
static struct mailbox *
return NULL;
static struct mailbox *
const char *path;
return NULL;
return NULL;
return NULL;
name);
return NULL;
path);
return NULL;
const char *name,
const char *path;
const char *name)
int count;
name);
count = 0;
count++;
int ret;
ret = 0;
const char *list_name;
t_push();
t_pop();
t_pop();
return ret;
if (ret < 0)
const char *path;
const char *name,
const char *path;
path);
int ret = 0;
return ret;
unsigned int min_newmail_notify_interval)
if (flags == 0) {
NULL,