dbox-file.h revision 5a426a741960a2b067346590d9af41fc529a59f8
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* The file begins with a header followed by zero or more messages:
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen <dbox message header>
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen <message body>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen Metadata block begins with DBOX_MAGIC_POST, followed by zero or more lines
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen in format <key character><value><LF>. The block ends with an empty line.
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen Unknown metadata should be ignored, but preserved when copying.
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen There should be no duplicates for the current metadata, but future
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen extensions may need them so they should be preserved.
889437fa2b6f44ffe0a8a7bcac94c00b71856767Timo Sirainen/* prefer flock(). fcntl() locking currently breaks if trying to access the
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen same file from multiple mail_storages within same process. that's why we
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen fallback to dotlocks. */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen# define DBOX_FILE_LOCK_METHOD FILE_LOCK_METHOD_FLOCK
373492be949e159fda651807b3acda2c5c077027Timo Sirainen# define DBOX_FILE_LOCK_METHOD FILE_LOCK_METHOD_DOTLOCK
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* Must be sizeof(struct dbox_message_header) when appending (hex) */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* Creation UNIX timestamp (hex) */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* metadata used by old Dovecot versions */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Globally unique identifier for the message. Preserved when
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* POP3 UIDL overriding the default format */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Received UNIX timestamp in hex */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Physical message size in hex. Necessary only if it differs from
99430beb12dfbc6c9c160f08e2102aeab38a589cTimo Sirainen the dbox_message_header.message_size_hex, for example because the
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen message is compressed. */
f7f25f9e1a38678d0e97d2e609beac16285fac6bTimo Sirainen /* Virtual message size in hex (line feeds counted as CRLF) */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* Pointer to external message data. Format is:
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen 1*(<start offset> <byte count> <ref>) */
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen /* Mailbox name where this message was originally saved to.
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen When rebuild finds a message whose mailbox is unknown, it's
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen placed to this mailbox. */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* metadata used by old Dovecot versions */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* Normal message */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* Parts of the message exists outside the following data.
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen See the metadata for how to find them. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen unsigned char type;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen unsigned char space1;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen unsigned char space2;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* <space reserved for future extensions, LF is always last> */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen unsigned char save_lf;
ba8498efbf886ca8b69fdb20c0ba2f5dba9416e3Timo Sirainen unsigned char magic_post[sizeof(DBOX_MAGIC_POST)-1];
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#if DBOX_FILE_LOCK_METHOD == FILE_LOCK_METHOD_DOTLOCK
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* Metadata for the currently seeked metadata block. */
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen uoff_t first_append_offset, last_flush_offset;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#define dbox_file_is_open(file) ((file)->fd != -1)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen#define dbox_file_is_in_alt(file) ((file)->cur_path == (file)->alt_path)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Open the file. Returns 1 if ok, 0 if file header is corrupted, -1 if error.
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen If file is deleted, deleted_r=TRUE and 1 is returned. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_open(struct dbox_file *file, bool *deleted_r);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Try to open file only from primary path. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_open_primary(struct dbox_file *file, bool *notfound_r);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen/* Close the file handle from the file, but don't free it. */
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen/* fstat() or stat() the file. If file is already deleted, fails with
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen errno=ENOENT. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_stat(struct dbox_file *file, struct stat *st_r);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Try to lock the dbox file. Returns 1 if ok, 0 if already locked by someone
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else, -1 if error. */
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainenint dbox_file_try_lock(struct dbox_file *file);
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen/* Seek to given offset in file and return the message's input stream.
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen Returns 1 if ok/expunged, 0 if file/offset is corrupted, -1 if I/O error. */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainenint dbox_file_get_mail_stream(struct dbox_file *file, uoff_t offset,
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen/* Start seeking at the beginning of the file. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenvoid dbox_file_seek_rewind(struct dbox_file *file);
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen/* Seek to next message after current one. If there are no more messages,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen returns 0 and last_r is set to TRUE. Returns 1 if ok, 0 if file is
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen corrupted, -1 if I/O error. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenint dbox_file_seek_next(struct dbox_file *file, uoff_t *offset_r, bool *last_r);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen/* Start appending to dbox file */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenstruct dbox_file_append_context *dbox_file_append_init(struct dbox_file *file);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen/* Finish writing appended mails. */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenint dbox_file_append_commit(struct dbox_file_append_context **ctx);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Truncate appended mails. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid dbox_file_append_rollback(struct dbox_file_append_context **ctx);
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainen/* Get output stream for appending a new message. Returns 1 if ok, 0 if file
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen can't be appended to (old file version or corruption) or -1 if error. */
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainenint dbox_file_get_append_stream(struct dbox_file_append_context *ctx,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Flush output buffer. */
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainenint dbox_file_append_flush(struct dbox_file_append_context *ctx);
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen/* Read current message's metadata. Returns 1 if ok, 0 if metadata is
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen corrupted, -1 if I/O error. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_metadata_read(struct dbox_file *file);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Return wanted metadata value, or NULL if not found. */
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenconst char *dbox_file_metadata_get(struct dbox_file *file,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Move the file to alt path or back. */
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainenint dbox_file_move(struct dbox_file *file, bool alt_path);
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen/* Fix a broken dbox file by rename()ing over it with a fixed file. Everything
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen before start_offset is assumed to be valid and is simply copied. The file
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen is reopened afterwards. Returns 0 if ok, -1 if I/O error. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_fix(struct dbox_file *file, uoff_t start_offset);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Delete the given dbox file. Returns 1 if deleted, 0 if file wasn't found
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen or -1 if error. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Fill dbox_message_header with given size. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid dbox_msg_header_fill(struct dbox_message_header *dbox_msg_hdr,
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainenvoid dbox_file_set_syscall_error(struct dbox_file *file, const char *function);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid dbox_file_set_corrupted(struct dbox_file *file, const char *reason, ...)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* private: */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_header_write(struct dbox_file *file, struct ostream *output);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint dbox_file_read_mail_header(struct dbox_file *file, uoff_t *physical_size_r);