dbox-file.h revision d5b030f57cb124d130b13b42aead98dafaf3b46d
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* The file begins with a header followed by zero or more messages:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen <dbox message header>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen <message body>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen Metadata block begins with DBOX_MAGIC_POST, followed by zero or more lines
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen in format <key character><value><LF>. The block ends with an empty line.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen Unknown metadata should be ignored, but preserved when copying.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen There should be no duplicates for the current metadata, but future
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen extensions may need them so they should be preserved.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* prefer flock(). fcntl() locking currently breaks if trying to access the
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen same file from multiple mail_storages within same process. that's why we
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fallback to dotlocks. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Must be sizeof(struct dbox_message_header) when appending (hex) */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Creation UNIX timestamp (hex) */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* metadata used by old Dovecot versions */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Globally unique identifier for the message. Preserved when
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* POP3 UIDL overriding the default format */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Received UNIX timestamp in hex */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Physical message size in hex. Necessary only if it differs from
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen the dbox_message_header.message_size_hex, for example because the
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen message is compressed. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Virtual message size in hex (line feeds counted as CRLF) */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Pointer to external message data. Format is:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen 1*(<start offset> <byte count> <options> <ref>) */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Mailbox name where this message was originally saved to.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen When rebuild finds a message whose mailbox is unknown, it's
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen placed to this mailbox. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* metadata used by old Dovecot versions */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Normal message */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned char type;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned char space1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned char space2;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* <space reserved for future extensions, LF is always last> */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned char save_lf;
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen unsigned char magic_post[sizeof(DBOX_MAGIC_POST)-1];
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Metadata for the currently seeked metadata block. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uoff_t first_append_offset, last_checkpoint_offset, last_flush_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#define dbox_file_is_open(file) ((file)->fd != -1)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#define dbox_file_is_in_alt(file) ((file)->cur_path == (file)->alt_path)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Open the file. Returns 1 if ok, 0 if file header is corrupted, -1 if error.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen If file is deleted, deleted_r=TRUE and 1 is returned. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_open(struct dbox_file *file, bool *deleted_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Try to open file only from primary path. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_open_primary(struct dbox_file *file, bool *notfound_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Close the file handle from the file, but don't free it. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* fstat() or stat() the file. If file is already deleted, fails with
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen errno=ENOENT. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_stat(struct dbox_file *file, struct stat *st_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Try to lock the dbox file. Returns 1 if ok, 0 if already locked by someone
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen else, -1 if error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_try_lock(struct dbox_file *file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Seek to given offset in file. Returns 1 if ok/expunged, 0 if file/offset is
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen corrupted, -1 if I/O error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_seek(struct dbox_file *file, uoff_t offset);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Start seeking at the beginning of the file. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_file_seek_rewind(struct dbox_file *file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Seek to next message after current one. If there are no more messages,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen returns 0 and last_r is set to TRUE. Returns 1 if ok, 0 if file is
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen corrupted, -1 if I/O error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_seek_next(struct dbox_file *file, uoff_t *offset_r, bool *last_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Start appending to dbox file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct dbox_file_append_context *dbox_file_append_init(struct dbox_file *file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Finish writing appended mails. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_append_commit(struct dbox_file_append_context **ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Truncate appended mails. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_file_append_rollback(struct dbox_file_append_context **ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Get output stream for appending a new message. Returns 1 if ok, 0 if file
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen can't be appended to (old file version or corruption) or -1 if error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_get_append_stream(struct dbox_file_append_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Call after message has been fully saved. If this isn't done, the writes
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen since the last checkpoint are truncated. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_file_append_checkpoint(struct dbox_file_append_context *ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Flush output buffer. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_append_flush(struct dbox_file_append_context *ctx);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Read current message's metadata. Returns 1 if ok, 0 if metadata is
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen corrupted, -1 if I/O error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_metadata_read(struct dbox_file *file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Return wanted metadata value, or NULL if not found. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst char *dbox_file_metadata_get(struct dbox_file *file,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Returns DBOX_METADATA_PHYSICAL_SIZE if set, otherwise physical size from
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen header. They differ only for e.g. compressed mails. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenuoff_t dbox_file_get_plaintext_size(struct dbox_file *file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Fix a broken dbox file by rename()ing over it with a fixed file. Everything
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen before start_offset is assumed to be valid and is simply copied. The file
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen is reopened afterwards. Returns 0 if ok, -1 if I/O error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_fix(struct dbox_file *file, uoff_t start_offset);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Delete the given dbox file. Returns 1 if deleted, 0 if file wasn't found
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen or -1 if error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Fill dbox_message_header with given size. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_msg_header_fill(struct dbox_message_header *dbox_msg_hdr,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_file_set_syscall_error(struct dbox_file *file, const char *function);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_file_set_corrupted(struct dbox_file *file, const char *reason, ...)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* private: */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_header_write(struct dbox_file *file, struct ostream *output);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_file_read_mail_header(struct dbox_file *file, uoff_t *physical_size_r);