dbox-file.h revision 7c6b8ca035c443e054dae48ae7535de76b4d459e
#ifndef DBOX_FILE_H
#define DBOX_FILE_H
/* The file begins with a header followed by zero or more messages:
<dbox message header>
<LF>
<message body>
<metadata>
Metadata block begins with DBOX_MAGIC_POST, followed by zero or more lines
in format <key character><value><LF>. The block ends with an empty line.
Unknown metadata should be ignored, but preserved when copying.
There should be no duplicates for the current metadata, but future
extensions may need them so they should be preserved.
*/
#define DBOX_VERSION 2
#define DBOX_MAGIC_PRE "\001\002"
#define DBOX_MAGIC_POST "\n\001\003\n"
/* prefer flock(). fcntl() locking currently breaks if trying to access the
same file from multiple mail_storages within same process. that's why we
fallback to dotlocks. */
#ifdef HAVE_FLOCK
# define DBOX_FILE_LOCK_METHOD_FLOCK
#endif
struct dbox_file;
enum dbox_header_key {
/* Must be sizeof(struct dbox_message_header) when appending (hex) */
DBOX_HEADER_MSG_HEADER_SIZE = 'M',
/* Creation UNIX timestamp (hex) */
DBOX_HEADER_CREATE_STAMP = 'C',
/* metadata used by old Dovecot versions */
};
enum dbox_metadata_key {
/* Globally unique identifier for the message. Preserved when
copying. */
DBOX_METADATA_GUID = 'G',
/* POP3 UIDL overriding the default format */
DBOX_METADATA_POP3_UIDL = 'P',
/* Received UNIX timestamp in hex */
DBOX_METADATA_RECEIVED_TIME = 'R',
/* Physical message size in hex. Necessary only if it differs from
the dbox_message_header.message_size_hex, for example because the
message is compressed. */
DBOX_METADATA_PHYSICAL_SIZE = 'Z',
/* Virtual message size in hex (line feeds counted as CRLF) */
DBOX_METADATA_VIRTUAL_SIZE = 'V',
/* Pointer to external message data. Format is:
1*(<start offset> <byte count> <options> <ref>) */
DBOX_METADATA_EXT_REF = 'X',
/* Mailbox name where this message was originally saved to.
When rebuild finds a message whose mailbox is unknown, it's
placed to this mailbox. */
DBOX_METADATA_ORIG_MAILBOX = 'B',
/* metadata used by old Dovecot versions */
DBOX_METADATA_OLDV1_EXPUNGED = 'E',
DBOX_METADATA_OLDV1_FLAGS = 'F',
DBOX_METADATA_OLDV1_KEYWORDS = 'K',
};
enum dbox_message_type {
/* Normal message */
DBOX_MESSAGE_TYPE_NORMAL = 'N',
/* Parts of the message exists outside the following data.
See the metadata for how to find them. */
};
struct dbox_message_header {
unsigned char magic_pre[2];
unsigned char type;
unsigned char space1;
unsigned char oldv1_uid_hex[8];
unsigned char space2;
unsigned char message_size_hex[16];
/* <space reserved for future extensions, LF is always last> */
unsigned char save_lf;
};
struct dbox_metadata_header {
};
struct dbox_file {
struct dbox_storage *storage;
int refcount;
unsigned int file_version;
unsigned int file_header_size;
unsigned int msg_header_size;
const char *cur_path;
char *primary_path, *alt_path;
int fd;
#ifdef DBOX_FILE_LOCK_METHOD_FLOCK
#else
#endif
/* Metadata for the currently seeked metadata block. */
ARRAY_DEFINE(metadata, const char *);
unsigned int appending:1;
unsigned int deleted:1;
unsigned int corrupted:1;
};
struct dbox_file_append_context {
};
/* Open the file. Returns 1 if ok, 0 if file header is corrupted, -1 if error.
If file is deleted, deleted_r=TRUE and 1 is returned. */
/* Try to open file only from primary path. */
/* Close the file handle from the file, but don't free it. */
/* fstat() or stat() the file. If file is already deleted, fails with
errno=ENOENT. */
/* Try to lock the dbox file. Returns 1 if ok, 0 if already locked by someone
else, -1 if error. */
corrupted, -1 if I/O error. */
/* Start seeking at the beginning of the file. */
/* Seek to next message after current one. If there are no more messages,
returns 0 and last_r is set to TRUE. Returns 1 if ok, 0 if file is
corrupted, -1 if I/O error. */
/* Start appending to dbox file */
/* Finish writing appended mails. */
/* Truncate appended mails. */
/* Get output stream for appending a new message. Returns 1 if ok, 0 if file
can't be appended to (old file version or corruption) or -1 if error. */
/* Flush output buffer. */
/* Read current message's metadata. Returns 1 if ok, 0 if metadata is
corrupted, -1 if I/O error. */
/* Return wanted metadata value, or NULL if not found. */
enum dbox_metadata_key key);
/* Fix a broken dbox file by rename()ing over it with a fixed file. Everything
before start_offset is assumed to be valid and is simply copied. The file
is reopened afterwards. Returns 0 if ok, -1 if I/O error. */
/* Delete the given dbox file. Returns 1 if deleted, 0 if file wasn't found
or -1 if error. */
/* Fill dbox_message_header with given size. */
/* private: */
const char *dbox_generate_tmp_filename(void);
#endif