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