]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dbox: In Maildir migrations preserve POP3 UIDL from dovecot-uidlist.
authorTimo Sirainen <tss@iki.fi>
Fri, 19 Dec 2008 14:24:19 +0000 (16:24 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 19 Dec 2008 14:24:19 +0000 (16:24 +0200)
--HG--
branch : HEAD

src/lib-storage/index/dbox/dbox-file-maildir.c
src/lib-storage/index/dbox/dbox-file.c
src/lib-storage/index/dbox/dbox-index.c
src/lib-storage/index/dbox/dbox-index.h
src/lib-storage/index/dbox/dbox-sync-rebuild.c

index da64b507e206e69750a0bb8e2bdf4cc9a9f2c177..b16fc54eb78eefa6d9de3f04cb87a40bce2a0f9e 100644 (file)
@@ -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:
index 7a0c6548dfa7c3a90efad59a17be9e9b4dd6b94c..fdadea3e10f0492d8ff5ccae62dc96a85ae5370e 100644 (file)
@@ -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 <uid> <filename> */
+               /* data contains <uid> [<fields>] :<filename> */
                *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);
index 512a0db677347ab6e9bf8867f2a62563ea0479ec..b45ef9ad71dc5ff5f6978dc83c7c8f52685e2347 100644 (file)
@@ -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) ?
index f5ce996c6f1bed04e405741af5323759933cf819..9a3a071f0a83c5def0b9ab118e81064cc4497e1c 100644 (file)
@@ -43,7 +43,9 @@ enum dbox_index_file_status {
        DBOX_INDEX_FILE_STATUS_UNLINKED         = 'U',
 
        /* File is a maildir file. Status-specific data contains
-          <uid> <filename>. */
+          old: <uid> <filename>
+          new: <uid> [<maildir extra field>] :<filename>
+       */
        DBOX_INDEX_FILE_STATUS_MAILDIR          = 'M'
 };
 
index f39c400c3fccfbfa2d719339a2ae32ddec307ad5..9abf35fe0cc78a2d062e744bbd590d8db46f1633 100644 (file)
@@ -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;