#ifndef MAIL_STORAGE_PRIVATE_H
#define MAIL_STORAGE_PRIVATE_H
#include "module-context.h"
#include "unichar.h"
#include "file-lock.h"
#include "mail-storage.h"
#include "mail-storage-hooks.h"
#include "mail-storage-settings.h"
#include "mailbox-attribute-private.h"
#include "mail-index-private.h"
struct file_lock;
struct file_create_settings;
/* Default prefix for indexes */
/* Block size when read()ing message header. */
/* Block size when read()ing message (header and) body. */
/* Mailbox list index was found to be corrupted. */
/* Mailbox list index doesn't have INBOX in an inbox=yes namespace.
Rebuild is done to verify whether the user really is an empty new
user, or if an existing user's mailbox list index was lost. Because
this is called in non-error conditions, the callback shouldn't log
any errors or warnings if it didn't find any missing mailboxes. */
/* MAILBOX_SYNC_FLAG_FORCE_RESYNC is run. This is called only once
per list, so that doveadm force-resync '*' won't cause it to run for
every mailbox. */
};
struct mail_storage_module_register {
unsigned int id;
};
struct mail_module_register {
unsigned int id;
};
struct mail_storage_vfuncs {
const char **error_r);
struct mailbox_list *list);
struct mailbox_list_settings *set);
struct mailbox_list_settings *set);
struct mailbox_list *list,
const char *vname,
enum mailbox_flags flags);
/* Called when mailbox list index rebuild is requested.
The callback should add any missing mailboxes to the list index.
Returns 0 on success, -1 on temporary failure that didn't properly
rebuild the index. */
};
union mail_storage_module_context {
};
enum mail_storage_class_flags {
/* mailboxes are files, not directories */
/* root_dir points to a unique directory */
/* mailbox_open_stream() is supported */
/* never use quota for this storage (e.g. virtual mailboxes) */
/* Storage doesn't need a mail root directory */
/* Storage uses one file per message */
/* Messages have GUIDs (always set mailbox_status.have_guids=TRUE) */
/* mailbox_save_set_guid() works (always set
mailbox_status.have_save_guids=TRUE) */
/* message content can be unstructured binary data
(e.g. zlib plugin is allowed to compress/decompress mails) */
/* Message GUIDs can only be 128bit (always set
mailbox_status.have_only_guid128) */
/* Storage deletes all files internally - mailbox list's
delete_mailbox() shouldn't delete anything itself. */
/* Storage supports stubs (used for caching purposes). */
};
struct mail_binary_cache {
bool include_hdr;
};
struct mail_storage_error {
char *error_string;
char *last_internal_error;
bool last_error_is_internal;
};
struct mail_storage {
const char *name;
/* Fields that the storage backend can get by other means than parsing
MAIL_FETCH_IMAP_BODYSTRUCTURE from the remote server. Adding fields
here avoids adding them to index_mail_data.access_part. */
/* private: */
/* counting number of times mail_storage_create() has returned this
same storage. */
int refcount;
/* counting number of objects (e.g. mailbox) that have a pointer
to this storage. */
int obj_refcount;
/* Linked list of all mailboxes in the storage */
/* A "root dir" to enable storage sharing. It is only ever used for
* uniqueness checking (via strcmp) and never used as a path. */
const char *unique_root_dir;
/* Last error set in mail_storage_set_critical(). */
char *last_internal_error;
char *error_string;
const char *temp_path_prefix;
void *callback_context;
/* Filled lazily by mailbox_attribute_*() when accessing shared
attributes. */
/* Module-specific contexts. See mail_storage_module_id. */
/* Failed to create shared attribute dict, don't try again */
};
struct mail_attachment_part {
};
struct virtual_mailbox_vfuncs {
/* convert backend UIDs to virtual UIDs. if some backend UID doesn't
exist in mailbox, it's simply ignored */
struct mailbox *backend_mailbox,
/* like get_virtual_uids(), but if a backend UID doesn't exist,
convert it to 0. */
struct mailbox *backend_mailbox,
bool only_with_msgs);
};
struct mailbox_vfuncs {
enum mailbox_existence *existence_r);
const struct mailbox_update *update);
struct mailbox_status *status_r);
enum mailbox_metadata_items items,
struct mailbox_metadata *metadata_r);
const struct mail_attribute_value *value);
struct mail_attribute_value *value_r);
struct mailbox_attribute_iter *
enum mail_attribute_type type,
const char *prefix);
/* Lookup sync extension record and figure out if it mailbox has
changed since. Returns 1 = yes, 0 = no, -1 = error. if quick==TRUE,
return 1 if it's too costly to find out exactly. */
struct mail_index_view *list_view,
/* Update the sync extension record. */
struct mail_index_transaction *trans,
struct mailbox_sync_context *
enum mailbox_sync_flags flags);
struct mailbox_sync_rec *sync_rec_r);
struct mailbox_sync_status *status_r);
/* Called once for each expunge. Called one or more times for
uid=0 and sync_type=0. */
enum mailbox_sync_type sync_type);
struct mailbox_transaction_context *
const char *reason);
struct mail_transaction_commit_changes *changes_r);
struct mail *
struct mailbox_header_lookup_ctx *wanted_headers);
struct mail_search_context *
struct mail_search_args *args,
const enum mail_sort_type *sort_program,
struct mailbox_header_lookup_ctx *wanted_headers);
/* Internal search function which updates ctx->seq */
struct mail_save_context *
void (*transaction_save_commit_post)
(struct mail_save_context *save_ctx,
struct mail_index_transaction_commit_result *result_r);
};
union mailbox_module_context {
};
struct mail_msgpart_partial_cache {
};
struct mailbox_index_vsize {
};
struct mailbox_index_pop3_uidl {
};
struct mailbox_index_first_saved {
};
struct mailbox {
const char *name;
/* mailbox's virtual name (from mail_namespace_get_vname()) */
const char *vname;
/* virtual mailboxes: */
/* private: */
/* Linked list of all mailboxes in this storage */
/* these won't be set until mailbox is opened: */
against the primary index and used to store per-user flags.
These are non-NULL only when mailbox has per-user flags. */
/* Filled lazily by mailbox_get_permissions() */
/* Filled lazily when mailbox is opened, use mailbox_get_path()
to access it */
const char *_path;
/* Filled lazily when mailbox is opened, use mailbox_get_index_path()
to access it */
const char *_index_path;
/* Reason for why mailbox is being accessed or NULL if unknown. */
const char *reason;
/* default vfuncs for new struct mails. */
/* Mailbox settings, or NULL if defaults */
/* If non-zero, fail mailbox_open() with this error. mailbox_alloc()
can set this to force open to fail. */
const char *index_prefix;
unsigned int transaction_count;
unsigned int attribute_iter_count;
/* MAIL_RECENT flags handling */
/* Mailbox notification settings: */
void *notify_context;
/* Increased by one for each new struct mailbox. */
unsigned int generation_sequence;
/* Saved search results */
/* Module-specific contexts. See mail_storage_module_id. */
/* When FAST open flag is used, the mailbox isn't actually opened until
it's synced for the first time. */
/* Mailbox was deleted while we had it open. */
/* Mailbox is being created */
/* Mailbox is being deleted */
/* Mailbox is being undeleted */
/* Don't use MAIL_INDEX_SYNC_FLAG_DELETING_INDEX for sync flag */
/* Delete mailbox only if it's empty */
/* The backend wants to skip checking if there are 0 messages before
calling mailbox_list.delete_mailbox() */
/* Mailbox was already marked as deleted within this allocation. */
/* TRUE if this is an INBOX for this user */
/* TRUE if this is an INBOX for this namespace (user or shared) */
/* When copying to this mailbox, require that mailbox_copy() uses
mailbox_save_*() to actually save a new physical copy rather than
simply incrementing a reference count (e.g. via hard link) */
/* Don't allow creating any new keywords */
/* Mailbox has been synced at least once */
/* Updating cache file is disabled */
/* Update first_saved field to mailbox list index. */
/* mailbox_verify_create_name() only checks for mailbox_verify_name() */
/* Using LAYOUT=index and mailbox is being opened with a corrupted
mailbox name. Try to revert to the previously known good name. */
};
struct mail_vfuncs {
enum mail_fetch_field fields,
struct mailbox_header_lookup_ctx *headers);
const ARRAY_TYPE(keyword_indexes) *
struct message_part **parts_r);
bool decode_to_utf8, const char **value_r);
bool decode_to_utf8, const char *const **value_r);
struct mailbox_header_lookup_ctx *headers,
struct message_size *hdr_size,
struct message_size *body_size,
const struct message_part *part,
const char **value_r);
enum mail_flags flags);
struct mail_keywords *keywords);
enum mail_fetch_field field,
const char *reason);
};
union mail_module_context {
};
struct mail_private {
/* normally NULL, but in case this is a "backend mail" for a mail
created by virtual storage, this points back to the original virtual
mail. at least mailbox_copy() bypasses the virtual storage, so this
allows mail_log plugin to log the copy operation using the original
mailbox name. */
const char *get_stream_reason;
};
struct mailbox_list_context {
bool failed;
};
};
struct mailbox_transaction_stats {
unsigned long open_lookup_count;
unsigned long stat_lookup_count;
unsigned long fstat_lookup_count;
/* number of files we've opened and read */
unsigned long files_read_count;
/* number of bytes we've had to read from files */
unsigned long long files_read_bytes;
/* number of cache lookup hits */
unsigned long cache_hit_count;
};
struct mail_save_private_changes {
/* first saved mail is 0, second is 1, etc. we'll map these to UIDs
using struct mail_transaction_commit_changes. */
unsigned int mailnum;
};
struct mailbox_transaction_context {
char *reason;
int mail_ref_count;
/* view contains all changes done within this transaction */
/* for private index updates: */
unsigned int save_count;
private index after committing the mails to the shared index. */
/* these statistics are never reset by mail-storage API: */
/* Set to TRUE to update stats_* fields */
};
union mail_search_module_context {
};
struct mail_search_context {
/* if non-NULL, specifies that a search resulting is being updated.
this can be used as a search optimization: if searched message
already exists in search result, it's not necessary to check if
static data matches. */
/* add matches to these search results */
};
struct mail_save_data {
int received_tz_offset;
unsigned int pop3_order;
};
struct mail_save_context {
/* Set during mailbox_copy(). This is useful when copying is
implemented via save, and the save_*() methods want to access the
source mail. */
/* data that changes for each saved mail */
/* returns TRUE if message part is an attachment. */
const struct mail_attachment_part *part);
the same context is usually returned by the backends for reuse. */
/* mailbox_save_finish() or mailbox_copy() is being called. */
/* mail was copied or moved using saving (requires:
copying_or_moving==TRUE). */
/* mail is being saved, not copied. However, this is set also with
mailbox_save_using_mail() and then copying_or_moving==TRUE. */
/* mail is being moved - ignore quota (requires:
copying_or_moving==TRUE && saving==FALSE). */
/* mail is being copied or moved. However, this is set also with
mailbox_save_using_mail() and then saving==TRUE. */
};
struct mailbox_sync_context {
bool open_failed;
};
struct mailbox_header_lookup_ctx {
int refcount;
unsigned int count;
const char *const *name;
unsigned int *idx;
};
/* Modules should use do "my_id = mail_storage_module_id++" and
use objects' module_contexts[id] for their own purposes. */
extern struct mail_storage_module_register mail_storage_module_register;
/* Storage's module_id for mail_index. */
extern struct mail_module_register mail_module_register;
extern struct event_category event_category_storage;
extern struct event_category event_category_mailbox;
extern struct event_category event_category_mail;
/* Set error message in storage. Critical errors are logged with i_error(),
but user sees only "internal error" message. */
struct mail_index *index);
struct mailbox_list *list);
struct mail_storage *src);
/* set record in mail cache corrupted */
/* Indicate mail being expunged by autoexpunge */
/* Returns TRUE if everything should already be in memory after this call
or if prefetching is not supported, i.e. the caller shouldn't do more
prefetching before this message is handled. */
/* Returns true IF and only IF the mail has EITHER one of the
attachment keywords set. If it has both, or none, it will return FALSE. */
/* Sets attachment keywords. */
/* Easy wrapper for getting mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX.
The mailbox must already be opened and the caller must know that the
/* Similar to mailbox_get_path() but for MAILBOX_LIST_PATH_TYPE_INDEX. */
/* Wrapper to mailbox_list_get_path() */
const char **path_r);
/* Get mailbox permissions. */
/* Force permissions to be refreshed on next lookup */
/* Open private index files for mailbox. Returns 1 if opened, 0 if there
are no private indexes (or flags) in this mailbox, -1 if error. */
/* Create path's directory with proper permissions. The root directory is also
created if necessary. Returns 1 if created, 0 if it already existed,
-1 if error. */
enum mailbox_list_path_type type);
/* Create a non-mailbox type directory for mailbox if it's missing (e.g. index).
Optimized for case where the directory usually exists. */
enum mailbox_list_path_type type);
/* Returns TRUE if mailbox is autocreated. */
/* Returns TRUE if mailbox is autosubscribed. */
/* Returns -1 if error, 0 if failed with EEXIST, 1 if ok */
int *fd_r);
/* Create a lock file with the given path and settings. If it succeeds,
returns 1 and lock_r, which needs to be freed once finished with the lock.
If lock_set->lock_timeout_secs is reached, returns 0 and error_r. Returns
-1 and sets error_r on other errors. */
int mail_storage_lock_create(const char *lock_path,
const struct file_create_settings *lock_set,
const struct mail_storage_settings *mail_set,
/* Create a lock file to the mailbox with the given filename. Returns the same
as mail_storage_lock_create(). */
const char **error_r);
unsigned int secs);
/* for unit testing */
#endif