From 380cc9af76b2a6a28bde82efca2537689c1c0ed0 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 19 Dec 2008 16:24:19 +0200 Subject: [PATCH] dbox: In Maildir migrations preserve POP3 UIDL from dovecot-uidlist. --HG-- branch : HEAD --- .../index/dbox/dbox-file-maildir.c | 28 ++++++++++++++ src/lib-storage/index/dbox/dbox-file.c | 7 ++-- src/lib-storage/index/dbox/dbox-index.c | 38 ++++++++++++++++--- src/lib-storage/index/dbox/dbox-index.h | 4 +- .../index/dbox/dbox-sync-rebuild.c | 11 +++++- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/src/lib-storage/index/dbox/dbox-file-maildir.c b/src/lib-storage/index/dbox/dbox-file-maildir.c index da64b507e2..b16fc54eb7 100644 --- a/src/lib-storage/index/dbox/dbox-file-maildir.c +++ b/src/lib-storage/index/dbox/dbox-file-maildir.c @@ -6,6 +6,7 @@ #include "dbox-storage.h" #include "../maildir/maildir-storage.h" #include "../maildir/maildir-filename.h" +#include "dbox-index.h" #include "dbox-file.h" #include "dbox-file-maildir.h" @@ -35,6 +36,29 @@ dbox_file_maildir_get_flags(struct dbox_file *file, enum dbox_metadata_key key) return str_c(str); } +static const char * +dbox_file_maildir_get_old_metadata(struct dbox_file *file, char key) +{ + struct dbox_index_record *rec; + const char *p, *end; + + rec = dbox_index_record_lookup(file->mbox->dbox_index, file->file_id); + if (rec == NULL) + return NULL; + + for (p = strchr(rec->data, ' '); *p != '\0'; p++) { + if (*p == ' ') { + if (p[1] == key) { + end = strchr(p+2, ' '); + return t_strdup_until(p+2, end); + } + if (p[1] == ':') + break; + } + } + return NULL; +} + const char *dbox_file_maildir_metadata_get(struct dbox_file *file, enum dbox_metadata_key key) { @@ -77,8 +101,12 @@ const char *dbox_file_maildir_metadata_get(struct dbox_file *file, MAILDIR_EXTRA_VIRTUAL_SIZE, &size)) value = dec2str(size); + else + value = dbox_file_maildir_get_old_metadata(file, 'W'); break; case DBOX_METADATA_POP3_UIDL: + value = dbox_file_maildir_get_old_metadata(file, 'P'); + break; case DBOX_METADATA_EXPUNGED: case DBOX_METADATA_EXT_REF: case DBOX_METADATA_SPACE: diff --git a/src/lib-storage/index/dbox/dbox-file.c b/src/lib-storage/index/dbox/dbox-file.c index 7a0c6548df..fdadea3e10 100644 --- a/src/lib-storage/index/dbox/dbox-file.c +++ b/src/lib-storage/index/dbox/dbox-file.c @@ -141,10 +141,11 @@ dbox_file_id_get_fname(struct dbox_mailbox *mbox, unsigned int file_id, rec = dbox_index_record_lookup(mbox->dbox_index, file_id); if (rec != NULL && rec->status == DBOX_INDEX_FILE_STATUS_MAILDIR) { - /* data contains */ + /* data contains [] : */ *maildir_file_r = TRUE; - p = strchr(rec->data, ' '); - return i_strdup_printf("%s", p + 1); + p = strstr(rec->data, " :"); + i_assert(p != NULL); + return i_strdup_printf("%s", p + 2); } return i_strdup_printf(DBOX_MAIL_FILE_MULTI_FORMAT, file_id); diff --git a/src/lib-storage/index/dbox/dbox-index.c b/src/lib-storage/index/dbox/dbox-index.c index 512a0db677..b45ef9ad71 100644 --- a/src/lib-storage/index/dbox/dbox-index.c +++ b/src/lib-storage/index/dbox/dbox-index.c @@ -90,7 +90,7 @@ void dbox_index_deinit(struct dbox_index **_index) static int dbox_index_parse_maildir(struct dbox_index *index, const char *line, struct dbox_index_record *rec) { - char *p; + char *p, *p2; unsigned long uid; if (*line++ != ' ') @@ -100,7 +100,14 @@ static int dbox_index_parse_maildir(struct dbox_index *index, const char *line, if (*p++ != ' ' || *p == '\0' || uid == 0 || uid >= (uint32_t)-1) return -1; - rec->data = p_strdup(index->record_data_pool, line); + p2 = strstr(p, " :"); + if (p2 != NULL) + rec->data = p_strdup(index->record_data_pool, line); + else { + /* convert to new format */ + rec->data = p_strconcat(index->record_data_pool, + t_strdup_until(line, p), ":", p, NULL); + } return 0; } @@ -762,6 +769,28 @@ void dbox_index_append_file(struct dbox_index_append_context *ctx, array_append(&ctx->files, &file, 1); } +static const char *dbox_file_maildir_get_index_data(struct dbox_file *file) +{ + const char *pop3_uidl = NULL, *const *changes; + unsigned int i, count; + + changes = array_get(&file->metadata_changes, &count); + for (i = 0; i < count; i++) { + if (*changes[i] == DBOX_METADATA_POP3_UIDL) { + pop3_uidl = changes[i] + 1; + break; + } + } + + if (pop3_uidl == NULL) { + return t_strdup_printf("%u :%s", file->last_append_uid, + file->fname); + } else { + return t_strdup_printf("%u P%s :%s", file->last_append_uid, + pop3_uidl, file->fname); + } +} + static int dbox_index_append_commit_new(struct dbox_index_append_context *ctx, struct dbox_file *file, string_t *str) { @@ -808,9 +837,8 @@ static int dbox_index_append_commit_new(struct dbox_index_append_context *ctx, rec.file_offset = ctx->output_offset + str_len(str); if (file->maildir_file) { rec.status = DBOX_INDEX_FILE_STATUS_MAILDIR; - rec.data = p_strdup_printf(ctx->index->record_data_pool, - "%u %s", file->last_append_uid, - file->fname); + rec.data = p_strdup(ctx->index->record_data_pool, + dbox_file_maildir_get_index_data(file)); } else { rec.status = dbox_file_can_append(file, 0) ? diff --git a/src/lib-storage/index/dbox/dbox-index.h b/src/lib-storage/index/dbox/dbox-index.h index f5ce996c6f..9a3a071f0a 100644 --- a/src/lib-storage/index/dbox/dbox-index.h +++ b/src/lib-storage/index/dbox/dbox-index.h @@ -43,7 +43,9 @@ enum dbox_index_file_status { DBOX_INDEX_FILE_STATUS_UNLINKED = 'U', /* File is a maildir file. Status-specific data contains - . */ + old: + new: [] : + */ DBOX_INDEX_FILE_STATUS_MAILDIR = 'M' }; diff --git a/src/lib-storage/index/dbox/dbox-sync-rebuild.c b/src/lib-storage/index/dbox/dbox-sync-rebuild.c index f39c400c3f..9abf35fe0c 100644 --- a/src/lib-storage/index/dbox/dbox-sync-rebuild.c +++ b/src/lib-storage/index/dbox/dbox-sync-rebuild.c @@ -143,7 +143,7 @@ static int dbox_sync_index_file_next(struct dbox_sync_rebuild_context *ctx, { uint32_t seq, uid; uoff_t physical_size; - const char *path; + const char *path, *value; bool expunged; int ret; @@ -190,6 +190,15 @@ static int dbox_sync_index_file_next(struct dbox_sync_rebuild_context *ctx, i_warning("%s: Ignoring broken file (metadata)", path); return 0; } + if (file->maildir_file) { + /* preserve POP3 UIDL */ + value = maildir_uidlist_lookup_ext(ctx->maildir_uidlist, uid, + MAILDIR_UIDLIST_REC_EXT_POP3_UIDL); + if (value != NULL) { + dbox_file_metadata_set(file, DBOX_METADATA_POP3_UIDL, + value); + } + } if (!expunged) { mail_index_append(ctx->trans, uid, &seq); file->maildir_append_seq = seq; -- 2.47.3