mail-storage-private.h revision d9a129b491613014ce5f31fe1ab20903e2899ea4
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen#ifndef MAIL_STORAGE_PRIVATE_H
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define MAIL_STORAGE_PRIVATE_H
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "module-context.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "unichar.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "file-lock.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-storage.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-storage-hooks.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-storage-settings.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-index-private.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen/* Default prefix for indexes */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define MAIL_INDEX_PREFIX "dovecot.index"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Block size when read()ing message header. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen#define MAIL_READ_HDR_BLOCK_SIZE (1024*4)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Block size when read()ing message (header and) body. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen#define MAIL_READ_FULL_BLOCK_SIZE IO_BLOCK_SIZE
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mail_storage_module_register {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen unsigned int id;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen};
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainenstruct mail_module_register {
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen unsigned int id;
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen};
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenstruct mail_storage_vfuncs {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen const struct setting_parser_info *(*get_setting_parser_info)(void);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mail_storage *(*alloc)(void);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen int (*create)(struct mail_storage *storage, struct mail_namespace *ns,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen const char **error_r);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen void (*destroy)(struct mail_storage *storage);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen void (*add_list)(struct mail_storage *storage,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mailbox_list *list);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen void (*get_list_settings)(const struct mail_namespace *ns,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mailbox_list_settings *set);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen bool (*autodetect)(const struct mail_namespace *ns,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mailbox_list_settings *set);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mailbox *(*mailbox_alloc)(struct mail_storage *storage,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen struct mailbox_list *list,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen const char *vname,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen enum mailbox_flags flags);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen int (*purge)(struct mail_storage *storage);
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen};
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainenunion mail_storage_module_context {
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen struct mail_storage_vfuncs super;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen struct mail_storage_module_register *reg;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen};
59e26ff34b05cd971a111f8a42fc60c13d9f688bTimo Sirainen
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainenenum mail_storage_class_flags {
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen /* mailboxes are files, not directories */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE = 0x01,
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen /* root_dir points to a unique directory */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT = 0x02,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen /* mailbox_open_stream() is supported */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS = 0x04,
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen /* never use quota for this storage (e.g. virtual mailboxes) */
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen MAIL_STORAGE_CLASS_FLAG_NOQUOTA = 0x08,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen /* Storage doesn't need a mail root directory */
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen MAIL_STORAGE_CLASS_FLAG_NO_ROOT = 0x10,
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen /* Storage uses one file per message */
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG = 0x20
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstruct mail_binary_cache {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct timeout *to;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mailbox *box;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen uint32_t uid;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen uoff_t orig_physical_pos;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen bool include_hdr;
571fd6ff94570ee11a72a20b649acfdac2495919Timo Sirainen struct istream *input;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen uoff_t size;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen};
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenstruct mail_storage {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen const char *name;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen enum mail_storage_class_flags class_flags;
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen struct mail_storage_vfuncs v, *vlast;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* private: */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pool_t pool;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen struct mail_storage *prev, *next;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen /* counting number of times mail_storage_create() has returned this
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen same storage. */
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen int refcount;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen /* counting number of objects (e.g. mailbox) that have a pointer
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen to this storage. */
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen int obj_refcount;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen /* Linked list of all mailboxes in the storage */
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen struct mailbox *mailboxes;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen const char *unique_root_dir;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen char *error_string;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen enum mail_error error;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen const struct mail_storage *storage_class;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mail_user *user;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *temp_path_prefix;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen const struct mail_storage_settings *set;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen enum mail_storage_flags flags;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct mail_storage_callbacks callbacks;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen void *callback_context;
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct mail_binary_cache binary_cache;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* Filled lazily by mailbox_attribute_*() when accessing shared
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen attributes. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct dict *_shared_attr_dict;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* Module-specific contexts. See mail_storage_module_id. */
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen ARRAY(union mail_storage_module_context *) module_contexts;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen /* Failed to create shared attribute dict, don't try again */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen unsigned int shared_attr_dict_failed:1;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen};
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainenstruct mail_attachment_part {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct message_part *part;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *content_type, *content_disposition;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct mailbox_vfuncs {
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen bool (*is_readonly)(struct mailbox *box);
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen int (*enable)(struct mailbox *box, enum mailbox_feature features);
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen int (*exists)(struct mailbox *box, bool auto_boxes,
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen enum mailbox_existence *existence_r);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen int (*open)(struct mailbox *box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen void (*close)(struct mailbox *box);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen void (*free)(struct mailbox *box);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen int (*create_box)(struct mailbox *box,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const struct mailbox_update *update, bool directory);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen int (*update_box)(struct mailbox *box,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen const struct mailbox_update *update);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*delete_box)(struct mailbox *box);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*rename_box)(struct mailbox *src, struct mailbox *dest);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*get_status)(struct mailbox *box, enum mailbox_status_items items,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct mailbox_status *status_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*get_metadata)(struct mailbox *box,
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen enum mailbox_metadata_items items,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mailbox_metadata *metadata_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*set_subscribed)(struct mailbox *box, bool set);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*attribute_set)(struct mailbox *box, enum mail_attribute_type type,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *key, const char *value);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen int (*attribute_get)(struct mailbox *box, enum mail_attribute_type type,
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen const char *key, const char **value_r);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen struct mailbox_attribute_iter *
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen (*attribute_iter_init)(struct mailbox *box,
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen enum mail_attribute_type type,
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen const char *prefix);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen const char *(*attribute_iter_next)(struct mailbox_attribute_iter *iter);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen int (*attribute_iter_deinit)(struct mailbox_attribute_iter *iter);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* Lookup sync extension record and figure out if it mailbox has
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen changed since. Returns 1 = yes, 0 = no, -1 = error. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*list_index_has_changed)(struct mailbox *box,
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen struct mail_index_view *list_view,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen uint32_t seq);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* Update the sync extension record. */
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen void (*list_index_update_sync)(struct mailbox *box,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_index_transaction *trans,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint32_t seq);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen struct mailbox_sync_context *
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen (*sync_init)(struct mailbox *box,
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen enum mailbox_sync_flags flags);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen bool (*sync_next)(struct mailbox_sync_context *ctx,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mailbox_sync_rec *sync_rec_r);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen int (*sync_deinit)(struct mailbox_sync_context *ctx,
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen struct mailbox_sync_status *status_r);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen /* Called once for each expunge. Called one or more times for
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen flag/keyword changes. Once the sync is finished, called with
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen uid=0 and sync_type=0. */
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen void (*sync_notify)(struct mailbox *box, uint32_t uid,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mailbox_sync_type sync_type);
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen void (*notify_changes)(struct mailbox *box);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mailbox_transaction_context *
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen (*transaction_begin)(struct mailbox *box,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen enum mailbox_transaction_flags flags);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen int (*transaction_commit)(struct mailbox_transaction_context *t,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_transaction_commit_changes *changes_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen void (*transaction_rollback)(struct mailbox_transaction_context *t);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen enum mail_flags (*get_private_flags_mask)(struct mailbox *box);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen struct mail *
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen (*mail_alloc)(struct mailbox_transaction_context *t,
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen enum mail_fetch_field wanted_fields,
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mail_search_context *
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (*search_init)(struct mailbox_transaction_context *t,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct mail_search_args *args,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const enum mail_sort_type *sort_program,
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen enum mail_fetch_field wanted_fields,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*search_deinit)(struct mail_search_context *ctx);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen bool (*search_next_nonblock)(struct mail_search_context *ctx,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail **mail_r, bool *tryagain_r);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* Internal search function which updates ctx->seq */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen bool (*search_next_update_seq)(struct mail_search_context *ctx);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen struct mail_save_context *
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen (*save_alloc)(struct mailbox_transaction_context *t);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen int (*save_begin)(struct mail_save_context *ctx, struct istream *input);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*save_continue)(struct mail_save_context *ctx);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*save_finish)(struct mail_save_context *ctx);
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen void (*save_cancel)(struct mail_save_context *ctx);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen int (*copy)(struct mail_save_context *ctx, struct mail *mail);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* Called during transaction commit/rollback if saving was done */
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen int (*transaction_save_commit_pre)(struct mail_save_context *save_ctx);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen void (*transaction_save_commit_post)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen (struct mail_save_context *save_ctx,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct mail_index_transaction_commit_result *result_r);
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen void (*transaction_save_rollback)(struct mail_save_context *save_ctx);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen bool (*is_inconsistent)(struct mailbox *box);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen};
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainenunion mailbox_module_context {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mailbox_vfuncs super;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct mail_storage_module_register *reg;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen};
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainenstruct mail_msgpart_partial_cache {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint32_t uid;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen uoff_t physical_start;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uoff_t physical_pos, virtual_pos;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen};
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainenstruct mailbox {
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen const char *name;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen /* mailbox's virtual name (from mail_namespace_get_vname()) */
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen const char *vname;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen struct mail_storage *storage;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen struct mailbox_list *list;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen struct mailbox_vfuncs v, *vlast;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen/* private: */
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen pool_t pool, metadata_pool;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Linked list of all mailboxes in this storage */
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen struct mailbox *prev, *next;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen /* these won't be set until mailbox is opened: */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_index *index;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_index_view *view;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct mail_cache *cache;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Private per-user index/view for shared mailboxes. These are synced
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen against the primary index and used to store per-user flags.
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen These are non-NULL only when mailbox has per-user flags. */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct mail_index *index_pvt;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct mail_index_view *view_pvt;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Filled lazily by mailbox_get_permissions() */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct mailbox_permissions _perm;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Filled lazily when mailbox is opened, use mailbox_get_path()
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen to access it */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen const char *_path;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen /* default vfuncs for new struct mails. */
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen const struct mail_vfuncs *mail_vfuncs;
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen /* Mailbox settings, or NULL if defaults */
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen const struct mailbox_settings *set;
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* If non-zero, fail mailbox_open() with this error. mailbox_alloc()
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen can set this to force open to fail. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen enum mail_error open_error;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct istream *input;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen const char *index_prefix;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen enum mailbox_flags flags;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int transaction_count;
4e8d6d03c2ff85448df79b181a2ea850fb5d4199Timo Sirainen enum mailbox_feature enabled_features;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct mail_msgpart_partial_cache partial_cache;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct mail_index_view *tmp_sync_view;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Mailbox notification settings: */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mailbox_notify_callback_t *notify_callback;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen void *notify_context;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Increased by one for each new struct mailbox. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int generation_sequence;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Saved search results */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen ARRAY(struct mail_search_result *) search_results;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Module-specific contexts. See mail_storage_module_id. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen ARRAY(union mailbox_module_context *) module_contexts;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* When FAST open flag is used, the mailbox isn't actually opened until
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen it's synced for the first time. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int opened:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Mailbox was deleted while we had it open. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int mailbox_deleted:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Mailbox is being created */
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen unsigned int creating:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Mailbox is being deleted */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int deleting:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Delete mailbox only if it's empty */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int deleting_must_be_empty:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Mailbox was already marked as deleted within this allocation. */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int marked_deleted:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* TRUE if this is an INBOX for this user */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int inbox_user:1;
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen /* TRUE if this is an INBOX for this namespace (user or shared) */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen unsigned int inbox_any:1;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* When copying to this mailbox, require that mailbox_copy() uses
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mailbox_save_*() to actually save a new physical copy rather than
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen simply incrementing a reference count (e.g. via hard link) */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen unsigned int disable_reflink_copy_to:1;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* Don't allow creating any new keywords */
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen unsigned int disallow_new_keywords:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* Mailbox has been synced at least once */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int synced:1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen};
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainenstruct mail_vfuncs {
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen void (*close)(struct mail *mail);
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen void (*free)(struct mail *mail);
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen void (*set_seq)(struct mail *mail, uint32_t seq, bool saving);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen bool (*set_uid)(struct mail *mail, uint32_t uid);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen void (*set_uid_cache_updates)(struct mail *mail, bool set);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen bool (*prefetch)(struct mail *mail);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen void (*precache)(struct mail *mail);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen void (*add_temp_wanted_fields)(struct mail *mail,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen enum mail_fetch_field fields,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct mailbox_header_lookup_ctx *headers);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen enum mail_flags (*get_flags)(struct mail *mail);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *const *(*get_keywords)(struct mail *mail);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const ARRAY_TYPE(keyword_indexes) *
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen (*get_keyword_indexes)(struct mail *mail);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uint64_t (*get_modseq)(struct mail *mail);
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen int (*get_parts)(struct mail *mail,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen struct message_part **parts_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*get_date)(struct mail *mail, time_t *date_r, int *timezone_r);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen int (*get_received_date)(struct mail *mail, time_t *date_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*get_save_date)(struct mail *mail, time_t *date_r);
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen int (*get_virtual_size)(struct mail *mail, uoff_t *size_r);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen int (*get_physical_size)(struct mail *mail, uoff_t *size_r);
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen int (*get_first_header)(struct mail *mail, const char *field,
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen bool decode_to_utf8, const char **value_r);
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen int (*get_headers)(struct mail *mail, const char *field,
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen bool decode_to_utf8, const char *const **value_r);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen int (*get_header_stream)(struct mail *mail,
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen struct mailbox_header_lookup_ctx *headers,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct istream **stream_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int (*get_stream)(struct mail *mail, bool get_body,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct message_size *hdr_size,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct message_size *body_size,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct istream **stream_r);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen int (*get_binary_stream)(struct mail *mail,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen const struct message_part *part,
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen bool include_hdr, uoff_t *size_r,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen unsigned int *lines_r, bool *binary_r,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct istream **stream_r);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen int (*get_special)(struct mail *mail, enum mail_fetch_field field,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen const char **value_r);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct mail *(*get_real_mail)(struct mail *mail);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen void (*update_flags)(struct mail *mail, enum modify_type modify_type,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen enum mail_flags flags);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen void (*update_keywords)(struct mail *mail, enum modify_type modify_type,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct mail_keywords *keywords);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen void (*update_modseq)(struct mail *mail, uint64_t min_modseq);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen void (*update_pop3_uidl)(struct mail *mail, const char *uidl);
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainen void (*expunge)(struct mail *mail);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen void (*set_cache_corrupted)(struct mail *mail,
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen enum mail_fetch_field field);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen int (*istream_opened)(struct mail *mail, struct istream **input);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen};
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainenunion mail_module_context {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen struct mail_vfuncs super;
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainen struct mail_module_register *reg;
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody};
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainenstruct mail_private {
db3ebf659c17fc5ca348a997e6311d20cfbb78e9Timo Sirainen struct mail mail;
db3ebf659c17fc5ca348a997e6311d20cfbb78e9Timo Sirainen struct mail_vfuncs v, *vlast;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen uint32_t seq_pvt;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen /* initial wanted fields/headers, set by mail_alloc(): */
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen enum mail_fetch_field wanted_fields;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen pool_t pool, data_pool;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen ARRAY(union mail_module_context *) module_contexts;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen};
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainenstruct mailbox_list_context {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen struct mail_storage *storage;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen enum mailbox_list_flags flags;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen bool failed;
71da447014454c84828d9dface77219875554d7dTimo Sirainen};
71da447014454c84828d9dface77219875554d7dTimo Sirainen
71da447014454c84828d9dface77219875554d7dTimo Sirainenunion mailbox_transaction_module_context {
71da447014454c84828d9dface77219875554d7dTimo Sirainen struct mail_storage_module_register *reg;
71da447014454c84828d9dface77219875554d7dTimo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mailbox_transaction_stats {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned long open_lookup_count;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen unsigned long stat_lookup_count;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen unsigned long fstat_lookup_count;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* number of files we've opened and read */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned long files_read_count;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* number of bytes we've had to read from files */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned long long files_read_bytes;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen /* number of cache lookup hits */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen unsigned long cache_hit_count;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mailbox_transaction_context {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox *box;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mailbox_transaction_flags flags;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen union mail_index_transaction_module_context module_ctx;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_index_transaction_vfuncs super;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen int mail_ref_count;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_index_transaction *itrans;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* view contains all changes done within this transaction */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_index_view *view;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* for private index updates: */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_index_transaction *itrans_pvt;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_index_view *view_pvt;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_cache_view *cache_view;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_cache_transaction_ctx *cache_trans;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_transaction_commit_changes *changes;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen ARRAY(union mailbox_transaction_module_context *) module_contexts;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_save_context *save_ctx;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* these statistics are never reset by mail-storage API: */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox_transaction_stats stats;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* Set to TRUE to update stats_* fields */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int stats_track:1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* We've done some non-transactional (e.g. dovecot-uidlist updates) */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int nontransactional_changes:1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenunion mail_search_module_context {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_storage_module_register *reg;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mail_search_context {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox_transaction_context *transaction;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen struct mail_search_args *args;
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen struct mail_search_sort_program *sort_program;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mail_fetch_field wanted_fields;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen normalizer_func_t *normalizer;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen /* if non-NULL, specifies that a search resulting is being updated.
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen this can be used as a search optimization: if searched message
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen already exists in search result, it's not necessary to check if
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen static data matches. */
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen struct mail_search_result *update_result;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen /* add matches to these search results */
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen ARRAY(struct mail_search_result *) results;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen uint32_t seq;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen uint32_t progress_cur, progress_max;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen ARRAY(union mail_search_module_context *) module_contexts;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen unsigned int seen_lost_data:1;
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen unsigned int progress_hidden:1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mail_save_data {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mail_flags flags;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_keywords *keywords;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint64_t min_modseq;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen time_t received_date, save_date;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen int received_tz_offset;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uint32_t uid;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen char *guid, *pop3_uidl, *from_envelope;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int pop3_order;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct ostream *output;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_save_attachment *attach;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mail_save_context {
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainen struct mailbox_transaction_context *transaction;
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainen struct mail *dest_mail;
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* data that changes for each saved mail */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_save_data data;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* returns TRUE if message part is an attachment. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen bool (*part_is_attachment)(struct mail_save_context *ctx,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen const struct mail_attachment_part *part);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* mail was copied using saving */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int copying_via_save:1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* mail is being saved, not copied */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int saving:1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* mail is being moved - ignore quota */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int moving:1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mailbox_sync_context {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox *box;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mailbox_sync_flags flags;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstruct mailbox_header_lookup_ctx {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox *box;
d78be924ad150840e018eda6a8a7d5e46a39bda2Timo Sirainen pool_t pool;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen int refcount;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int count;
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen const char *const *name;
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen unsigned int *idx;
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen};
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainenstruct mailbox_attribute_iter {
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen struct mailbox *box;
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen};
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen/* Modules should use do "my_id = mail_storage_module_id++" and
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen use objects' module_contexts[id] for their own purposes. */
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainenextern struct mail_storage_module_register mail_storage_module_register;
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen/* Storage's module_id for mail_index. */
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainenextern struct mail_module_register mail_module_register;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen#define MAIL_STORAGE_CONTEXT(obj) \
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen MODULE_CONTEXT(obj, mail_storage_mail_index_module)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenextern MODULE_CONTEXT_DEFINE(mail_storage_mail_index_module,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen &mail_index_module_register);
d78be924ad150840e018eda6a8a7d5e46a39bda2Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_obj_ref(struct mail_storage *storage);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_obj_unref(struct mail_storage *storage);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Set error message in storage. Critical errors are logged with i_error(),
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen but user sees only "internal error" message. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_clear_error(struct mail_storage *storage);
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainenvoid mail_storage_set_error(struct mail_storage *storage,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mail_error error, const char *string);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_set_critical(struct mail_storage *storage,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen const char *fmt, ...) ATTR_FORMAT(2, 3);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_set_internal_error(struct mail_storage *storage);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mailbox_set_index_error(struct mailbox *box);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenbool mail_storage_set_error_from_errno(struct mail_storage *storage);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_copy_list_error(struct mail_storage *storage,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mailbox_list *list);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_storage_copy_error(struct mail_storage *dest,
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen struct mail_storage *src);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen/* Returns TRUE if everything should already be in memory after this call
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen or if prefetching is not supported, i.e. the caller shouldn't do more
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen prefetching before this message is handled. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenbool mail_prefetch(struct mail *mail);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mail_set_aborted(struct mail *mail);
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainenvoid mail_set_expunged(struct mail *mail);
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainenvoid mail_set_seq_saving(struct mail *mail, uint32_t seq);
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainenvoid mailbox_set_deleted(struct mailbox *box);
f28583935a4509d3f7932738bba6c548ef455c82Timo Sirainenint mailbox_mark_index_deleted(struct mailbox *box, bool del);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen/* Easy wrapper for getting mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX.
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen The mailbox must already be opened and the caller must know that the
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen storage has mailbox files (i.e. NULL/empty path is never returned). */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenconst char *mailbox_get_path(struct mailbox *box) ATTR_PURE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Wrapper to mailbox_list_get_path() */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenint mailbox_get_path_to(struct mailbox *box, enum mailbox_list_path_type type,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen const char **path_r);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Get mailbox permissions. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenconst struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Force permissions to be refreshed on next lookup */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenvoid mailbox_refresh_permissions(struct mailbox *box);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Create path's directory with proper permissions. The root directory is also
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen created if necessary. Returns 1 if created, 0 if it already existed,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen -1 if error. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenint mailbox_mkdir(struct mailbox *box, const char *path,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mailbox_list_path_type type);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Create a non-mailbox type directory for mailbox if it's missing (e.g. index).
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen Optimized for case where the directory usually exists. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenint mailbox_create_missing_dir(struct mailbox *box,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mailbox_list_path_type type);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen/* Returns -1 if error, 0 if failed with EEXIST, 1 if ok */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenint mailbox_create_fd(struct mailbox *box, const char *path, int flags,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen int *fd_r);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenunsigned int mail_storage_get_lock_timeout(struct mail_storage *storage,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen unsigned int secs);
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainenvoid mail_storage_free_binary_cache(struct mail_storage *storage);
981139bb2e446bb2050c1158614725f8413fd709Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenenum mail_index_open_flags
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenmail_storage_settings_to_index_flags(const struct mail_storage_settings *set);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen#endif
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen