sdbox-storage.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenextern struct mail_storage dbox_storage, sdbox_storage;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainenextern struct dbox_storage_vfuncs sdbox_dbox_storage_vfuncs;
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainenstatic struct mail_storage *sdbox_storage_alloc(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool = pool_alloconly_create("sdbox storage", 512+256);
8363f50d7b5d605912e55c34f7f28e9f4ce01341Timo Sirainen storage = p_new(pool, struct sdbox_storage, 1);
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainen storage->storage.v = sdbox_dbox_storage_vfuncs;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int sdbox_storage_create(struct mail_storage *_storage,
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen const char **error_r)
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen struct dbox_storage *storage = DBOX_STORAGE(_storage);
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainen if (dbox_storage_create(_storage, ns, error_r) < 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen props = fs_get_properties(storage->attachment_fs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Backend doesn't support renaming";
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainenstatic const char *
98922c5675bbbfadc84d58768bef867fe82256c2Timo Sirainensdbox_storage_find_root_dir(const struct mail_namespace *ns)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_debug("sdbox: access(%s, rwx): failed: %m", path);
f0a2d04321ba456e5c5ba821c0d1ed9e8e0e2e08Timo Sirainenstatic bool sdbox_storage_autodetect(const struct mail_namespace *ns,
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen /* NOTE: this check works for mdbox as well. we'll rely on the
f6f021c133f680cf3d559187524fd9abcbaae9b9Timo Sirainen autodetect ordering to catch mdbox before we get here. */
f6f021c133f680cf3d559187524fd9abcbaae9b9Timo Sirainen path = t_strconcat(root_dir, "/"DBOX_MAILBOX_DIR_NAME, NULL);
c60d1eda4df179d83d531647732d5e3e45064219Timo Sirainen i_debug("sdbox autodetect: stat(%s) failed: %m", path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_debug("sdbox autodetect: %s not a directory", path);
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainenstatic struct mailbox *
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainensdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* dbox can't work without index files */
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen pool = pool_alloconly_create("sdbox mailbox", 1024*3);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX);
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS |
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainenint sdbox_read_header(struct sdbox_mailbox *mbox,
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen struct sdbox_index_header *hdr, bool log_error,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen mail_index_get_header_ext(view, mbox->hdr_ext_id,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE &&
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen "sdbox: Invalid dbox header size");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* data is valid. remember it in case mailbox
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen is being reset */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic void sdbox_update_header(struct sdbox_mailbox *mbox,
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) {
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen if (update != NULL && !guid_128_is_empty(update->mailbox_guid)) {
6013fbad6638795a00e6c2a2dd2cdbee19612494Timo Sirainen memcpy(new_hdr.mailbox_guid, update->mailbox_guid,
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen } else if (guid_128_is_empty(new_hdr.mailbox_guid)) {
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen mail_index_ext_resize_hdr(trans, mbox->hdr_ext_id,
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0,
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainen memcpy(mbox->mailbox_guid, new_hdr.mailbox_guid,
9334fbad0aabb2fed88f40b2205d0d6f80bdffa2Timo Sirainenint sdbox_mailbox_create_indexes(struct mailbox *box,
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen struct sdbox_mailbox *mbox = SDBOX_MAILBOX(box);
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen struct mail_index_transaction *new_trans = NULL;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen new_trans = mail_index_transaction_begin(box->view, 0);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (update != NULL && update->uid_validity != 0)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* set uidvalidity */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen uid_validity = dbox_get_uidvalidity_next(box->list);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen offsetof(struct mail_index_header, uid_validity),
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (update != NULL && hdr->next_uid < update->min_next_uid) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (update != NULL && update->min_first_recent_uid != 0 &&
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen hdr->first_recent_uid < update->min_first_recent_uid) {
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen uint32_t first_recent_uid = update->min_first_recent_uid;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen offsetof(struct mail_index_header, first_recent_uid),
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen &first_recent_uid, sizeof(first_recent_uid), FALSE);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (update != NULL && update->min_highest_modseq != 0 &&
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* initialize pop3-uidl header when creating mailbox
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen (not on mailbox_update()) */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (mail_index_transaction_commit(&new_trans) < 0) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainenstatic const char *
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainensdbox_get_attachment_path_suffix(struct dbox_file *_file)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct sdbox_file *file = (struct sdbox_file *)_file;
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainenvoid sdbox_set_mailbox_corrupted(struct mailbox *box)
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen struct sdbox_mailbox *mbox = SDBOX_MAILBOX(box);
f567e9ad51a3b4f61580299f12b67e070fb16c5cTimo Sirainen if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0 ||
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen mbox->corrupted_rebuild_count = hdr.rebuild_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void sdbox_set_file_corrupted(struct dbox_file *_file)
80bcc6caa317a52bddcafe74fede886247dbba5bTimo Sirainen struct sdbox_file *file = (struct sdbox_file *)_file;
80bcc6caa317a52bddcafe74fede886247dbba5bTimo Sirainen sdbox_set_mailbox_corrupted(&file->mbox->box);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainenstatic int sdbox_mailbox_alloc_index(struct sdbox_mailbox *mbox)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (index_storage_mailbox_alloc_index(&mbox->box) < 0)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen mail_index_ext_register(mbox->box.index, "dbox-hdr",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sizeof(struct sdbox_index_header), 0, 0);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen /* set the initialization data in case the mailbox is created */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen mail_index_set_ext_init_data(mbox->box.index, mbox->hdr_ext_id,
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic int sdbox_mailbox_open(struct mailbox *box)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen struct sdbox_mailbox *mbox = SDBOX_MAILBOX(box);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (dbox_mailbox_check_existence(box, &path_ctime) < 0)
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen /* wait for mailbox creation to initialize the index */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* get/generate mailbox guid */
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen if (sdbox_read_header(mbox, &hdr, FALSE, &need_resize) < 0) {
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen /* looks like the mailbox is corrupted */
63aaafe7e6b201d6633f8c25610ecd30c9cda99cTimo Sirainen (void)sdbox_sync(mbox, SDBOX_SYNC_FLAG_FORCE);
cf49fc07f541c0f74578ac6c3b334ddade143aa1Timo Sirainen if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0)
7aeaf23f760d86aad525d831efcac9f860a55a39Timo Sirainen /* regenerate it */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (sdbox_mailbox_create_indexes(box, NULL, NULL) < 0 ||
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenstatic void sdbox_mailbox_close(struct mailbox *box)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen struct sdbox_mailbox *mbox = SDBOX_MAILBOX(box);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen const struct mailbox_update *update, bool directory)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct sdbox_mailbox *mbox = SDBOX_MAILBOX(box);
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen if (dbox_mailbox_create(box, update, directory) < 0)
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen if (directory || !guid_128_is_empty(mbox->mailbox_guid))
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen /* another process just created the mailbox. read the mailbox_guid. */
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (sdbox_read_header(mbox, &hdr, FALSE, &need_resize) < 0) {
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen "sdbox: Failed to read newly created dbox header");
a0aedab7cd06125e4d73638b1bd0c01c7caa2626Timo Sirainen i_assert(!guid_128_is_empty(mbox->mailbox_guid));
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainensdbox_mailbox_get_metadata(struct mailbox *box,
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct sdbox_mailbox *mbox = SDBOX_MAILBOX(box);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainendbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen if (sdbox_mailbox_create_indexes(box, update, NULL) < 0)
7e6522921c81999ec389dab54b338a6fb0f193aaTimo Sirainen return index_storage_mailbox_update_common(box, update);
6d50c4d875bb05f9076e9e0ecbacb8beb2e9ae42Timo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG |
6d50c4d875bb05f9076e9e0ecbacb8beb2e9ae42Timo Sirainen MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS |
97eb53ade9057e6966dbb77289ad0204c7e1657bTimo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG,