bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen set->subscription_fname = DBOX_SUBSCRIPTION_FILE_NAME;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen set->mailbox_dir_name = DBOX_MAILBOX_DIR_NAME;
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainendbox_alt_path_has_changed(const char *root_dir, const char *alt_path,
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen const char *alt_path2, const char *alt_symlink_path)
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi if (t_readlink(alt_symlink_path, &linkpath, &error) < 0) {
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi i_error("t_readlink(%s) failed: %s", alt_symlink_path, error);
afc8d11e88b1e5f4b6833fabaf8e4259e8297314Timo Sirainen "but currently no ALT path set", root_dir, linkpath);
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen /* FIXME: for backwards compatibility. old versions
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen created the symlink to mailboxes/ directory, which
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen was fine with sdbox, but didn't even exist with
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen mdbox. we'll silently replace the symlink. */
afc8d11e88b1e5f4b6833fabaf8e4259e8297314Timo Sirainen "but currently ALT=%s", root_dir, linkpath, alt_path);
1fb81cb0b622cef1690c96bcc6a3e183e0b1e6ffTimo Sirainenstatic void dbox_verify_alt_path(struct mailbox_list *list)
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen const char *root_dir, *alt_symlink_path, *alt_path, *alt_path2;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
1fb81cb0b622cef1690c96bcc6a3e183e0b1e6ffTimo Sirainen t_strconcat(root_dir, "/"DBOX_ALT_SYMLINK_NAME, NULL);
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen (void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen (void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX,
9345a14605e87c749048d37965d5c92caaab2ee9Timo Sirainen if (!dbox_alt_path_has_changed(root_dir, alt_path, alt_path2,
1fb81cb0b622cef1690c96bcc6a3e183e0b1e6ffTimo Sirainen /* unlink/create the current alt path symlink */
11d4b189a3d98628828228e605fea1f91c689b05Timo Sirainen int ret = symlink(alt_path, alt_symlink_path);
11d4b189a3d98628828228e605fea1f91c689b05Timo Sirainen /* root_dir doesn't exist yet - create it */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint dbox_storage_create(struct mail_storage *_storage,
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen const char **error_r)
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(_storage);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const struct mail_storage_settings *set = _storage->set;
f504be57bf0a77b1ad055322c4aa936606fc6e4dTimo Sirainen args = strpbrk(set->mail_attachment_fs, ": ");
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen name = t_strdup_until(set->mail_attachment_fs, args++);
abceedfdab26c07b48b7156298187a204e24fafaTimo Sirainen (_storage->class_flags & MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG) != 0) {
abceedfdab26c07b48b7156298187a204e24fafaTimo Sirainen /* FIXME: the deduplication part doesn't work, because
abceedfdab26c07b48b7156298187a204e24fafaTimo Sirainen sdbox renames the files.. */
abceedfdab26c07b48b7156298187a204e24fafaTimo Sirainen "sis-queue not currently supported by sdbox";
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen storage->attachment_dir = p_strdup(_storage->pool, dir);
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen if (mailbox_list_init_fs(ns->list, name, args,
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen *error_r = t_strdup_printf("mail_attachment_fs: %s",
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvoid dbox_storage_destroy(struct mail_storage *_storage)
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(_storage);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenuint32_t dbox_get_uidvalidity_next(struct mailbox_list *list)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_CONTROL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen path = t_strconcat(path, "/"DBOX_UIDVALIDITY_FILE_NAME, NULL);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen path = t_strdup_printf("%s/"MAIL_INDEX_PREFIX".log", dir);
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainendbox_cleanup_temp_files(struct mailbox_list *list, const char *path,
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainen time_t last_scan_time, time_t last_change_time)
68b5e132f1f8bb2528482310daffcc06c2f019d3Timo Sirainen unsigned int interval = list->mail_set->mail_temp_scan_interval;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* check once in a while if there are temp files to clean up */
68b5e132f1f8bb2528482310daffcc06c2f019d3Timo Sirainen /* disabled */
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainen } else if (last_scan_time >= ioloop_time - (time_t)interval) {
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainen /* not the time to scan it yet */
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen /* Don't know the ctime yet - look it up. */
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainen if (last_scan_time > last_change_time + DBOX_TMP_DELETE_SECS) {
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainen /* there haven't been any changes to this directory
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen since we last checked it. If we did an extra stat(),
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen we need to update the last_scan_time to avoid
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen stat()ing the next time. */
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainenint dbox_mailbox_check_existence(struct mailbox *box, time_t *path_ctime_r)
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen const char *index_path, *box_path = mailbox_get_path(box);
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen /* Just because the index directory exists, it doesn't mean
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen that the mailbox is selectable. Check that by seeing if
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen dovecot.index.log exists. If it doesn't, fallback to
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen checking for the dbox-Mails in the mail root directory.
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen So this also means that if a mailbox is \NoSelect, listing
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen it will always do a stat() for dbox-Mails in the mail root
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen directory. That's not ideal, but this makes the behavior
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen safer and \NoSelect mailboxes are somewhat rare. */
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
265ca08926833c86de4311164ed031e5f5b42fcdTimo Sirainen index_path = t_strconcat(index_path, "/", box->index_prefix,
c5e2aa3148bc73f766c4a3a435c9dac2b45133e7Timo Sirainen } else if (errno == ENOENT || errno == ENAMETOOLONG) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box, "stat(%s) failed: %m", box_path);
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainenint dbox_mailbox_open(struct mailbox *box, time_t path_ctime)
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if (index_storage_mailbox_open(box, FALSE) < 0)
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainen const struct mail_index_header *hdr = mail_index_get_header(box->view);
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainen if (dbox_cleanup_temp_files(box->list, box_path,
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainen /* temp files were scanned. update the last scan timestamp. */
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainen index_mailbox_update_last_temp_file_scan(box);
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainenstatic int dir_is_empty(struct mail_storage *storage, const char *path)
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen /* race condition with DELETE/RENAME? */
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen mail_storage_set_critical(storage, "opendir(%s) failed: %m",
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen mail_storage_set_critical(storage, "closedir(%s) failed: %m",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mailbox_update *update, bool directory)
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(box->storage);
3d6fdafca17c073606b63745ca8638e035e871f4Timo Sirainen if ((ret = index_storage_mailbox_create(box, directory)) <= 0)
f3ef965d5c79680b63ceb172af60a82013c9a8d6Timo Sirainen if (mail_index_get_header(box->view)->uid_validity != 0) {
f3ef965d5c79680b63ceb172af60a82013c9a8d6Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
f3ef965d5c79680b63ceb172af60a82013c9a8d6Timo Sirainen "Mailbox already exists");
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen /* if alt path already exists and contains files, rebuild storage so
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen that we don't start overwriting files. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX, &alt_path);
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "Existing files in alt path, "
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "rebuilding storage to avoid losing messages");
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen /* dir is empty, ignore it */
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainen return dbox_mailbox_create_indexes(box, update);
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainenint dbox_mailbox_create_indexes(struct mailbox *box,
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(box->storage);
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen /* use syncing as a lock */
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen ret = mail_index_sync_begin(box->index, &sync_ctx, &view, &trans, 0);
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (mail_index_get_header(view)->uid_validity == 0) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (storage->v.mailbox_create_indexes(box, update, trans) < 0) {
755abfa2bc6c5f072519b545faa1487357046b27Timo Sirainenint dbox_verify_alt_storage(struct mailbox_list *list)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
755abfa2bc6c5f072519b545faa1487357046b27Timo Sirainen /* make sure alt storage is mounted. if it's not, abort the rebuild. */
755abfa2bc6c5f072519b545faa1487357046b27Timo Sirainen /* try to create the alt directory. if it fails, it means alt
755abfa2bc6c5f072519b545faa1487357046b27Timo Sirainen storage isn't mounted. */
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainenbool dbox_header_have_flag(struct mailbox *box, uint32_t ext_id,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen mail_index_get_header_ext(box->view, ext_id, &data, &data_size);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen flags = *((const uint8_t *)data + flags_offset);