Update from mailbox format 6 with "reconstruct -V max" does not always
add GUIDs. At least shared folders without OPT_IMAP_SHAREDSEEN contain
only records with guid set to 0.

It's reproducable on a 2.5.0 installation:
- create shared folder
- add a message
- verify guid (just to be sure):
  $ /usr/lib/cyrus/bin/reconstruct -G shared-folder
  shared-folder
  $ 
- downgrade to version 6 (or 8 or 9)
  $ /usr/lib/cyrus/bin/reconstruct -V 6 shared-folder
  shared-folder
  Repacked shared-folder to version 6
  $
- upgrade
  $ /usr/lib/cyrus/bin/reconstruct -V max shared-folder
  shared-folder: updating sync_crc 0 => 3295118465
  shared-folder
  Repacked shared-folder to version 13
  $
- now "reconstruct -G" complains about GUID mismatch
  $ /usr/lib/cyrus/bin/reconstruct -G shared-folder
  shared-folder uid 1 guid mismatch
  run reconstruct with -R to fix or -U to remove
  shared-folder
  $ 

Is this intentional? 

The attached proof-of-concept patch fixes this issue but I might
have gotten the details wrong (like version boundaries <10/>=10). 
It's copy&paste from the following if-clause (+ removal of seen state
update).

Btw. the last message is a bit misleading: "-G -R" or "-G -U" are
necessary.

- Norbert

diff --git a/imap/mailbox.c b/imap/mailbox.c
index e9aa718..55eee4f 100644
--- a/imap/mailbox.c
+++ b/imap/mailbox.c
@@ -3273,6 +3273,19 @@ static int mailbox_index_repack(struct mailbox *mailbox, int version)
 	if (!record.uid) continue;
 
 	/* version changes? */
+	if (repack->old_version < 10 && repack->i.minor_version >= 10 && !repack->seqset && record.guid.status == GUID_NULL) {
+	    const char *fname = mailbox_message_fname(mailbox, record.uid);
+
+	    /* XXX - re-parse the record iff upgrading past 12 */
+	    if (message_parse(fname, &record)) {
+		/* failed to parse, don't try to write out record */
+		record.crec.len = 0;
+		/* and the record is expunged too! */
+		record.system_flags |= FLAG_EXPUNGED | FLAG_UNLINKED;
+		syslog(LOG_ERR, "IOERROR: FATAL - failed to parse file for %s %u, expunging",
+		       repack->mailbox->name, record.uid);
+	    }
+	}
 	if (repack->old_version < 12 && repack->i.minor_version >= 12 && repack->seqset) {
 	    const char *fname = mailbox_message_fname(mailbox, record.uid);
 

Reply via email to