maildir-uidlist.c revision 819e20e6f108db20751e19784ee5a091b3f50046
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch Version 1 format has been used for most versions of Dovecot up to v1.0.x.
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch It's also compatible with Courier IMAP's courierimapuiddb file.
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch The format is:
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch header: 1 <uid validity> <next uid>
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch entry: <uid> <filename>
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch Version 2 format was written by a few development Dovecot versions, but
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch v1.0.x still parses the format. The format has <flags> field after <uid>.
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch Version 3 format is an extensible format used by Dovecot v1.1 and later.
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch It's also parsed by v1.0.2 (and later). The format is:
eea481b7931f1a31080acfa92209662d2322a576Stephan Bosch header: 3 [<key><value> ...]
47fa7b222e197f73042e8b36ad688bf5fcbfc6f0Stephan Bosch entry: <uid> [<key><value> ...] :<filename>
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch See enum maildir_uidlist_*_ext_key for used keys.
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch/* NFS: How many times to retry reading dovecot-uidlist file if ESTALE
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch error occurs in the middle of reading it */
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch#define UIDLIST_ESTALE_RETRY_COUNT NFS_ESTALE_RETRY_COUNT
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch/* how many seconds to wait before overriding uidlist.lock */
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan Bosch char *extensions; /* <data>\0[<data>\0 ...]\0 */
5356717c7944a8527b6ea10ac54012887bcc9f75Stephan BoschARRAY_DEFINE_TYPE(maildir_uidlist_rec_p, struct maildir_uidlist_rec *);
char *path;
int fd;
unsigned int lock_count;
unsigned int change_counter;
unsigned int version;
struct maildir_uidlist_sync_ctx {
unsigned int new_files_count;
struct maildir_uidlist_iter_ctx {
unsigned int change_counter;
bool nonblock)
int i, ret;
if (ret > 0)
if (ret == 0) {
struct maildir_uidlist *
const char *control_dir;
return uidlist;
return uidlist;
unsigned int count;
const char **line_p,
line++;
return FALSE;
return TRUE;
const char *fmt, ...)
const char *line)
uid = 0;
line++;
line);
bool ret;
rec);
if (!ret) {
const char *line;
char key;
const char *value;
switch (key) {
} T_FRAME_END;
const char *line;
unsigned int orig_next_uid;
last_read_offset = 0;
if (ret > 0) {
ret = 0;
if (ret == 0) {
} else if (ret > 0) {
if (ret <= 0) {
return ret;
int ret;
if (ret <= 0)
return ret;
if (recreated)
if (!retry)
if (ret >= 0)
return ret;
static struct maildir_uidlist_rec *
unsigned int *idx_r)
return NULL;
return NULL;
const char *fname;
return NULL;
return NULL;
return fname;
unsigned int idx;
return NULL;
unsigned int idx;
const char *p, *value;
return NULL;
if (*p == (char)key)
return NULL;
const char *value)
unsigned int idx;
unsigned int len;
if (*p != (char)key)
p += len;
const char *value)
int ret;
if (ret < 0) {
if (ret == 0) {
if (ret < 0) {
return ret;
int ret;
return ret;
bool nonsynced)
unsigned int i, count;
if (nonsynced) {
for (i = 0; i < count; i++)
for (i = 0; i < count; i++)
bool locked;
int ret;
return ret;
if (ret == 0) {
if (!locked) {
const char *filename,
const char *filename,
MAILDIR_UIDLIST_REC_FLAG_MOVED)) == 0) {
const char *filename)
const char *filename)
return FALSE;
return TRUE;
const char *filename)
unsigned int count;
return ret;
const char *filename,
struct maildir_uidlist_iter_ctx *
unsigned int count;
return ctx;
idx++;
idx--;
return FALSE;
return TRUE;
const char **filename_r)
return FALSE;
return TRUE;