From: Timo Sirainen Date: Thu, 16 Sep 2010 15:28:58 +0000 (+0100) Subject: maildir: uidlist can now override message's GUID X-Git-Tag: 2.0.3~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e4e7475f646d66a257d682738fbff1f206ce4924;p=thirdparty%2Fdovecot%2Fcore.git maildir: uidlist can now override message's GUID --- diff --git a/src/lib-storage/index/maildir/maildir-mail.c b/src/lib-storage/index/maildir/maildir-mail.c index 4e1c1354f6..366774c0bf 100644 --- a/src/lib-storage/index/maildir/maildir-mail.c +++ b/src/lib-storage/index/maildir/maildir-mail.c @@ -469,11 +469,20 @@ maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field, { struct index_mail *mail = (struct index_mail *)_mail; struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box; - const char *path, *fname, *end, *uidl; + const char *path, *fname, *end, *guid, *uidl; switch (field) { - case MAIL_FETCH_UIDL_FILE_NAME: case MAIL_FETCH_GUID: + /* use GUID from uidlist if it exists */ + guid = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, + MAILDIR_UIDLIST_REC_EXT_GUID); + if (guid != NULL) { + *value_r = guid; + return 0; + } + + /* default to base filename: */ + case MAIL_FETCH_UIDL_FILE_NAME: if (mail->data.guid != NULL) { *value_r = mail->data.guid; return 0; diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c index bfb4204651..88e610c1f5 100644 --- a/src/lib-storage/index/maildir/maildir-save.c +++ b/src/lib-storage/index/maildir/maildir-save.c @@ -33,6 +33,7 @@ struct maildir_filename { uoff_t size, vsize; enum mail_flags flags; unsigned int preserve_filename:1; + unsigned int save_guid:1; /* tmp_name contains the GUID */ unsigned int keywords_count; /* unsigned int keywords[]; */ }; @@ -786,6 +787,7 @@ maildir_filename_check_conflicts(struct maildir_save_context *ctx, mf->dest_basename = p_strdup(ctx->pool, maildir_filename_generate()); mf->preserve_filename = FALSE; + mf->save_guid = TRUE; } } @@ -828,6 +830,7 @@ static void maildir_save_sync_uidlist(struct maildir_save_context *ctx) struct maildir_filename *mf; struct seq_range_iter iter; enum maildir_uidlist_rec_flag flags; + struct maildir_uidlist_rec *rec; unsigned int n = 0; uint32_t uid; bool newdir, bret; @@ -845,8 +848,13 @@ static void maildir_save_sync_uidlist(struct maildir_save_context *ctx) if (newdir) flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR; ret = maildir_uidlist_sync_next_uid(ctx->uidlist_sync_ctx, - dest, uid, flags); + dest, uid, flags, &rec); i_assert(ret > 0); + i_assert(rec != NULL); + if (mf->save_guid) { + maildir_uidlist_sync_set_ext(ctx->uidlist_sync_ctx, rec, + MAILDIR_UIDLIST_REC_EXT_GUID, mf->tmp_name); + } } T_END; i_assert(!seq_range_array_iter_nth(&iter, n, &uid)); } diff --git a/src/lib-storage/index/maildir/maildir-uidlist.c b/src/lib-storage/index/maildir/maildir-uidlist.c index 76a6675e65..59dc620f73 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.c +++ b/src/lib-storage/index/maildir/maildir-uidlist.c @@ -1141,33 +1141,16 @@ void maildir_uidlist_set_next_uid(struct maildir_uidlist *uidlist, } static void -maildir_uidlist_set_ext_real(struct maildir_uidlist *uidlist, uint32_t uid, - enum maildir_uidlist_rec_ext_key key, - const char *value) +maildir_uidlist_rec_set_ext(struct maildir_uidlist_rec *rec, pool_t pool, + enum maildir_uidlist_rec_ext_key key, + const char *value) { - struct maildir_uidlist_rec *rec; const unsigned char *p; buffer_t *buf; unsigned int len; - int ret; - - ret = maildir_uidlist_lookup_rec(uidlist, uid, &rec); - if (ret <= 0) { - if (ret < 0) - return; - - /* maybe it's a new message */ - if (maildir_uidlist_refresh(uidlist) < 0) - return; - if (maildir_uidlist_lookup_rec(uidlist, uid, &rec) <= 0) { - /* message is already expunged, ignore */ - return; - } - } - - buf = buffer_create_dynamic(pool_datastack_create(), 128); /* copy existing extensions, except for the one we're updating */ + buf = buffer_create_dynamic(pool_datastack_create(), 128); if (rec->extensions != NULL) { p = rec->extensions; while (*p != '\0') { @@ -1184,22 +1167,40 @@ maildir_uidlist_set_ext_real(struct maildir_uidlist *uidlist, uint32_t uid, } buffer_append_c(buf, '\0'); - rec->extensions = p_malloc(uidlist->record_pool, buf->used); + rec->extensions = p_malloc(pool, buf->used); memcpy(rec->extensions, buf->data, buf->used); - - if (rec->uid != (uint32_t)-1) { - /* message already exists in uidlist, need to recreate it */ - uidlist->recreate = TRUE; - } } void maildir_uidlist_set_ext(struct maildir_uidlist *uidlist, uint32_t uid, enum maildir_uidlist_rec_ext_key key, const char *value) { + struct maildir_uidlist_rec *rec; + int ret; + + ret = maildir_uidlist_lookup_rec(uidlist, uid, &rec); + if (ret <= 0) { + if (ret < 0) + return; + + /* maybe it's a new message */ + if (maildir_uidlist_refresh(uidlist) < 0) + return; + if (maildir_uidlist_lookup_rec(uidlist, uid, &rec) <= 0) { + /* message is already expunged, ignore */ + return; + } + } + T_BEGIN { - maildir_uidlist_set_ext_real(uidlist, uid, key, value); + maildir_uidlist_rec_set_ext(rec, uidlist->record_pool, + key, value); } T_END; + + if (rec->uid != (uint32_t)-1) { + /* message already exists in uidlist, need to recreate it */ + uidlist->recreate = TRUE; + } } static void @@ -1645,10 +1646,12 @@ int maildir_uidlist_sync_init(struct maildir_uidlist *uidlist, static int maildir_uidlist_sync_next_partial(struct maildir_uidlist_sync_ctx *ctx, const char *filename, uint32_t uid, - enum maildir_uidlist_rec_flag flags) + enum maildir_uidlist_rec_flag flags, + struct maildir_uidlist_rec **rec_r) { struct maildir_uidlist *uidlist = ctx->uidlist; - struct maildir_uidlist_rec *rec; + struct maildir_uidlist_rec *rec, *const *recs; + unsigned int count; /* we'll update uidlist directly */ rec = hash_table_lookup(uidlist->files, filename); @@ -1686,6 +1689,11 @@ maildir_uidlist_sync_next_partial(struct maildir_uidlist_sync_ctx *ctx, rec->uid = uid; if (uidlist->next_uid <= uid) uidlist->next_uid = uid + 1; + else { + recs = array_get(&uidlist->records, &count); + if (count > 1 && uid < recs[count-1]->uid) + uidlist->unsorted = TRUE; + } } rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED; @@ -1693,6 +1701,7 @@ maildir_uidlist_sync_next_partial(struct maildir_uidlist_sync_ctx *ctx, hash_table_insert(uidlist->files, rec->filename, rec); ctx->finished = FALSE; + *rec_r = rec; return 1; } @@ -1719,17 +1728,22 @@ int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx, const char *filename, enum maildir_uidlist_rec_flag flags) { - return maildir_uidlist_sync_next_uid(ctx, filename, 0, flags); + struct maildir_uidlist_rec *rec; + + return maildir_uidlist_sync_next_uid(ctx, filename, 0, flags, &rec); } int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx, const char *filename, uint32_t uid, - enum maildir_uidlist_rec_flag flags) + enum maildir_uidlist_rec_flag flags, + struct maildir_uidlist_rec **rec_r) { struct maildir_uidlist *uidlist = ctx->uidlist; struct maildir_uidlist_rec *rec, *old_rec; const char *p, *dir; + *rec_r = NULL; + if (ctx->failed) return -1; for (p = filename; *p != '\0'; p++) { @@ -1746,7 +1760,7 @@ int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx, if (ctx->partial) { return maildir_uidlist_sync_next_partial(ctx, filename, - uid, flags); + uid, flags, rec_r); } rec = hash_table_lookup(ctx->files, filename); @@ -1791,6 +1805,7 @@ int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx, rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED; rec->filename = p_strdup(ctx->record_pool, filename); hash_table_insert(ctx->files, rec->filename, rec); + *rec_r = rec; return 1; } @@ -1823,6 +1838,17 @@ void maildir_uidlist_sync_remove(struct maildir_uidlist_sync_ctx *ctx, ctx->uidlist->recreate = TRUE; } +void maildir_uidlist_sync_set_ext(struct maildir_uidlist_sync_ctx *ctx, + struct maildir_uidlist_rec *rec, + enum maildir_uidlist_rec_ext_key key, + const char *value) +{ + pool_t pool = ctx->partial ? + ctx->uidlist->record_pool : ctx->record_pool; + + maildir_uidlist_rec_set_ext(rec, pool, key, value); +} + const char * maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx, const char *filename) diff --git a/src/lib-storage/index/maildir/maildir-uidlist.h b/src/lib-storage/index/maildir/maildir-uidlist.h index 50f66a5005..bdd9cb8cc1 100644 --- a/src/lib-storage/index/maildir/maildir-uidlist.h +++ b/src/lib-storage/index/maildir/maildir-uidlist.h @@ -10,6 +10,7 @@ struct maildir_mailbox; struct maildir_uidlist; struct maildir_uidlist_sync_ctx; +struct maildir_uidlist_rec; enum maildir_uidlist_sync_flags { MAILDIR_UIDLIST_SYNC_PARTIAL = 0x01, @@ -44,7 +45,9 @@ enum maildir_uidlist_rec_ext_key { isn't written to uidlist. */ MAILDIR_UIDLIST_REC_EXT_VSIZE = 'W', /* POP3 UIDL overriding the default format */ - MAILDIR_UIDLIST_REC_EXT_POP3_UIDL = 'P' + MAILDIR_UIDLIST_REC_EXT_POP3_UIDL = 'P', + /* Message GUID (default is the base filename) */ + MAILDIR_UIDLIST_REC_EXT_GUID = 'G' }; int maildir_uidlist_lock(struct maildir_uidlist *uidlist); @@ -109,9 +112,14 @@ int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx, enum maildir_uidlist_rec_flag flags); int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx, const char *filename, uint32_t uid, - enum maildir_uidlist_rec_flag flags); + enum maildir_uidlist_rec_flag flags, + struct maildir_uidlist_rec **rec_r); void maildir_uidlist_sync_remove(struct maildir_uidlist_sync_ctx *ctx, const char *filename); +void maildir_uidlist_sync_set_ext(struct maildir_uidlist_sync_ctx *ctx, + struct maildir_uidlist_rec *rec, + enum maildir_uidlist_rec_ext_key key, + const char *value); const char * maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx, const char *filename);