maildir-storage.c revision cafbfb142d25594144b99542c9d67f7484cad470
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2002-2006 Timo Sirainen */
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen#define CREATE_MODE 0777 /* umask() should limit it more */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILDIR_PLUSPLUS_DRIVER_NAME "maildir++"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstatic const char *maildirs[] = { "cur", "new", "tmp", NULL };
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstatic int verify_inbox(struct mail_storage *storage);
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainenstatic const char *strip_tail_slash(const char *path)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic const char *strip_tail_slash_and_cut(const char *path)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_get_list_settings(struct mailbox_list_settings *list_set,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *data, enum mail_storage_flags flags)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list_set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) != 0) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen /* we'll need to figure out the maildir location ourself.
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen It's $HOME/Maildir unless we are chrooted. */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_info("maildir: /cur exists, assuming chroot");
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* <Maildir> [:INBOX=<dir>] [:INDEX=<dir>] [:CONTROL=<dir>] */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } while (p != NULL);
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek list_set->root_dir = strip_tail_slash(list_set->root_dir);
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipekmaildir_create(const char *data, const char *user,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (maildir_get_list_settings(&list_set, data, flags) < 0)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list_set.mail_storage_lock_method = &lock_method;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen /* normally the maildir is created in verify_inbox() */
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen storage = p_new(pool, struct maildir_storage, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen getenv("MAILDIR_COPY_WITH_HARDLINKS") != NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage->stat_dirs = getenv("MAILDIR_STAT_DIRS") != NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage->temp_prefix = mailbox_list_get_temp_prefix(list);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* put the temp files into tmp/ directory preferrably */
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainen p_strconcat(pool, "tmp/", storage->temp_prefix, NULL);
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen istorage->callbacks = p_new(pool, struct mail_storage_callbacks, 1);
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen index_storage_init(istorage, list, flags, lock_method);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volkstatic void maildir_free(struct mail_storage *_storage)
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk struct index_storage *storage = (struct index_storage *) _storage;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainenstatic bool maildir_autodetect(const char *data, enum mail_storage_flags flags)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_info("maildir autodetect: stat(%s) failed: %m", path);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen i_info("maildir autodetect: %s not a directory", path);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenstatic const char *
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenmaildir_get_unlink_dest(struct mail_storage *storage, const char *name)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if ((storage->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (strcmp(mailbox_list_get_driver_name(storage->list),
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen /* Not maildir++ driver. Don't use this trick. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen root_dir = mailbox_list_get_path(storage->list, NULL,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return t_strdup_printf("%s/%c"MAILDIR_UNLINK_DIRNAME, root_dir,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen mailbox_list_get_hierarchy_sep(storage->list));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic int mkdir_verify(struct mail_storage *storage,
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen if (errno != EEXIST && (!verify || errno != ENOENT)) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen/* create or fix maildir, ignore if it already exists */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic int create_maildir(struct mail_storage *storage,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (!verify && mkdir_verify(storage, dir, verify) < 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (mkdir_verify(storage, path, verify) < 0) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* small optimization. if we're verifying, we don't
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen check that the root dir actually exists unless we
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen fail here. */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic int create_index_dir(struct mail_storage *storage, const char *name)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen index_dir = mailbox_list_get_path(storage->list, name,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen root_dir = mailbox_list_get_path(storage->list, name,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen mailbox_list_get_hierarchy_sep(storage->list),
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenstatic int create_control_dir(struct mail_storage *storage, const char *name)
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen control_dir = mailbox_list_get_path(storage->list, name,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen root_dir = mailbox_list_get_path(storage->list, name,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mailbox_list_get_hierarchy_sep(storage->list),
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainenstatic int verify_inbox(struct mail_storage *storage)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen path = mailbox_list_get_path(storage->list, "INBOX",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic bool maildir_is_recent(struct index_mailbox *ibox, uint32_t uid)
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)ibox;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen return maildir_uidlist_is_recent(mbox->uidlist, uid);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic struct mailbox *
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenmaildir_open(struct maildir_storage *storage, const char *name,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct index_storage *istorage = INDEX_STORAGE(storage);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path = mailbox_list_get_path(istorage->storage.list, name,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_dir = mailbox_list_get_path(istorage->storage.list, name,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen control_dir = mailbox_list_get_path(istorage->storage.list, name,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if ((flags & MAILBOX_OPEN_NO_INDEX_FILES) != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* for shared mailboxes get the create mode from the
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen permissions of dovecot-shared file. */
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen shared = stat(t_strconcat(path, "/dovecot-shared", NULL), &st) == 0;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen mail_index_set_permissions(index, st.st_mode & 0666, st.st_gid);
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen pool = pool_alloconly_create("mailbox", 1024);
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen mbox = p_new(pool, struct maildir_mailbox, 1);
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen mbox->ibox.mail_vfuncs = &maildir_mail_vfuncs;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (index_storage_mailbox_init(&mbox->ibox, index, name, flags,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen /* the memory was already freed */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen mbox->control_dir = p_strdup(pool, control_dir);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (maildir_uidlist_lock(mbox->uidlist) <= 0) {
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainenstatic struct mailbox *
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainenmaildir_mailbox_open(struct mail_storage *_storage, const char *name,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen struct istream *input, enum mailbox_open_flags flags)
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen struct maildir_storage *storage = (struct maildir_storage *)_storage;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen "Maildir doesn't support streamed mailboxes");
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (!mailbox_list_is_valid_existing_name(_storage->list, name)) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_storage_set_error(_storage, "Invalid mailbox name");
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* exists - make sure the required directories are also there */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (create_maildir(_storage, path, TRUE) < 0 ||
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if ((flags & MAILBOX_OPEN_NO_INDEX_FILES) == 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_storage_set_critical(_storage, "stat(%s) failed: %m",
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic int maildir_create_shared(struct mail_storage *storage,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* add the execute bit if either read or write bit is set */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (create_maildir(storage, dir, FALSE) < 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen "Mailbox already exists");
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen mail_storage_set_critical(storage, "chown(%s) failed: %m", dir);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen path = t_strconcat(dir, "/dovecot-shared", NULL);
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen fd = open(path, O_WRONLY | O_CREAT, mode & 0666);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_storage_set_critical(storage, "open(%s) failed: %m", path);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic int maildir_mailbox_create(struct mail_storage *_storage,
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (!mailbox_list_is_valid_create_name(_storage->list, name)) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen mail_storage_set_error(_storage, "Invalid mailbox name");
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen path = mailbox_list_get_path(_storage->list, name,
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen root_dir = mailbox_list_get_path(_storage->list, NULL,
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen /* if dovecot-shared exists in the root dir, create the mailbox using
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen its permissions and gid, and copy the dovecot-shared inside it. */
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen shared_path = t_strconcat(root_dir, "/dovecot-shared", NULL);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (create_maildir(_storage, path, FALSE) < 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen "Mailbox already exists");
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* Maildir++ spec want that maildirfolder named file is created for
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen all subfolders. */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen path = t_strconcat(path, "/" MAILDIR_SUBFOLDER_FILENAME, NULL);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen fd = open(path, O_CREAT | O_WRONLY, CREATE_MODE & 0666);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_error("open(%s, O_CREAT) failed: %m", path);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic int maildir_mailbox_delete(struct mail_storage *_storage,
d3e5a14ea363264dcc7640ca7226249d0c27a793Timo Sirainen mail_storage_set_error(_storage, "INBOX can't be deleted.");
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen if (!mailbox_list_is_valid_existing_name(_storage->list, name)) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_storage_set_error(_storage, "Invalid mailbox name");
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen /* check if the mailbox actually exists */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen src = mailbox_list_get_path(_storage->list, name,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* Make sure the indexes are closed before trying to delete the
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen directory that contains them. It can still fail with some NFS
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen implementations if indexes are opened by another session, but
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen that can't really be helped. */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* if there's a separate index directory, delete it before the actual
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen maildir. this way we never see partially deleted mailboxes. */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen index_dir = mailbox_list_get_path(_storage->list, name,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen "unlink_directory(%s) failed: %m", index_dir);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen dest = maildir_get_unlink_dest(_storage, name);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen /* absolute maildir path, delete the directory directly
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen without any renaming */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* rename the .maildir into ..DOVECOT-TRASH which atomically
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen marks it as being deleted. If we die before deleting the
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ..DOVECOT-TRASH directory, it gets deleted the next time
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mailbox listing sees it. */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* EBUSY is given by some NFS implementations */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* already existed, delete it and try again */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen "unlink_directory(%s) failed: %m",
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (unlink_directory(dest, TRUE) < 0 && errno != ENOTEMPTY) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* it's already renamed to ..dir, which means it's deleted
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen as far as the client is concerned. Report success. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic int rename_indexes(struct mail_storage *storage,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen oldpath = mailbox_list_get_path(storage->list, oldname,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen newpath = mailbox_list_get_path(storage->list, newname,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen mail_storage_set_critical(storage, "rename(%s, %s) failed: %m",
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainenstatic int rename_subfolders(struct mail_storage *storage,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *mask, *oldpath, *newpath, *old_listname, *new_listname;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *const *names;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen unsigned int i, count;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* first get a list of the subfolders and save them to memory, because
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen we can't rely on readdir() not skipping files while the directory
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen is being modified. this doesn't protect against modifications by
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen other processes though. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen pool = pool_alloconly_create("Maildir subfolders list", 1024);
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen mailbox_list_get_hierarchy_sep(storage->list));
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen iter = mailbox_list_iter_init(storage->list, mask,
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen name = p_strdup(pool, info->name + oldnamelen);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen for (i = 0; i < count; i++) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen old_listname = t_strconcat(oldname, names[i], NULL);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen new_listname = t_strconcat(newname, names[i], NULL);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen oldpath = mailbox_list_get_path(storage->list, old_listname,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen newpath = mailbox_list_get_path(storage->list, new_listname,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen /* FIXME: it's possible to merge two folders if either one of
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen them doesn't have existing root folder. We could check this
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen but I'm not sure if it's worth it. It could be even
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen considered as a feature.
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi Anyway, the bug with merging is that if both folders have
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen identically named subfolder they conflict. Just ignore those
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen and leave them under the old folder. */
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen "rename(%s, %s) failed: %m", oldpath, newpath);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen (void)rename_indexes(storage, old_listname, new_listname);
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainenstatic int maildir_mailbox_rename(struct mail_storage *_storage,
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen if (!mailbox_list_is_valid_existing_name(_storage->list, oldname) ||
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen !mailbox_list_is_valid_create_name(_storage->list, newname)) {
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen mail_storage_set_error(_storage, "Invalid mailbox name");
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen "Renaming INBOX isn't supported.");
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen /* NOTE: it's possible to rename a nonexisting folder which has
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen subfolders. In that case we should ignore the rename() error. */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen oldpath = mailbox_list_get_path(_storage->list, oldname,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen newpath = mailbox_list_get_path(_storage->list, newname,
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen (void)rename_indexes(_storage, oldname, newname);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen ret = rename_subfolders(_storage, oldname, newname);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen "Target mailbox already exists");
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen mail_storage_set_critical(_storage, "rename(%s, %s) failed: %m",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int maildir_storage_close(struct mailbox *box)
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /*FIXME:if (!maildir_try_flush_dirty_flags(ibox->index, TRUE)) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen mail_storage_set_index_error(ibox);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenmaildir_notify_changes(struct mailbox *box, unsigned int min_interval,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_notify_callback_t *callback, void *context)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen mbox->ibox.min_notify_interval = min_interval;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenmaildir_storage_is_mailbox(struct mail_storage *_storage,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct maildir_storage *storage = (struct maildir_storage *)_storage;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (fname[1] == mailbox_list_get_hierarchy_sep(_storage->list) &&
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen strcmp(fname+2, MAILDIR_UNLINK_DIRNAME) == 0 &&
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen strcmp(mailbox_list_get_driver_name(_storage->list),
758d8b46f9e8fd87cf58bb4912cddf6bf28918cfTimo Sirainen /* this directory is in the middle of being deleted,
758d8b46f9e8fd87cf58bb4912cddf6bf28918cfTimo Sirainen or the process trying to delete it had died.
b7c7a04bc5edb8eebea3837ff624441d9fa3721cTimo Sirainen delete it ourself if it's been there longer than
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen /* all directories are valid maildirs */
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen /* non-directories are not */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* need to check with stat() to be sure */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen /* Check files beginning with .nfs always because they may be
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen temporary files created by the kernel */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen if (storage->stat_dirs || strncmp(fname, ".nfs", 4) == 0) {
e91543761d0b7b97a1dc28e036e44d76405545c2Timo Sirainen ret = (stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) ? 0 : 1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainenstatic void maildir_class_init(void)