static void log_record_print(const struct mail_transaction_header *hdr, const void *data, size_t data_size, uint64_t *modseq) { unsigned int size = hdr->size - sizeof(*hdr); switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) { case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: { const struct mail_transaction_expunge *exp = data; printf(" - uids="); for (; size > 0; size -= sizeof(*exp), exp++) { printf("%u-%u,", exp->uid1, exp->uid2); } printf("\n"); break; } case MAIL_TRANSACTION_EXPUNGE_GUID|MAIL_TRANSACTION_EXPUNGE_PROT: { const struct mail_transaction_expunge_guid *exp = data; for (; size > 0; size -= sizeof(*exp), exp++) { printf(" - uid=%u (guid ", exp->uid); print_data(exp->guid_128, sizeof(exp->guid_128)); printf(")\n"); } break; } case MAIL_TRANSACTION_APPEND: { const struct mail_index_record *rec = data; printf(" - uids="); for (; size > 0; size -= sizeof(*rec), rec++) { printf("%u", rec->uid); if (rec->flags != 0) printf(" (flags=%x)", rec->flags); printf(","); } printf("\n"); break; } case MAIL_TRANSACTION_FLAG_UPDATE: { const struct mail_transaction_flag_update *u = data; for (; size > 0; size -= sizeof(*u), u++) { printf(" - uids=%u-%u (flags +%x-%x, modseq_inc_flag=%d)\n", u->uid1, u->uid2, u->add_flags, u->remove_flags, u->modseq_inc_flag); } break; } case MAIL_TRANSACTION_HEADER_UPDATE: { const struct mail_transaction_header_update *u = data; log_header_update(u, data_size); break; } case MAIL_TRANSACTION_EXT_INTRO: { const struct mail_transaction_ext_intro *intro = data; prev_intro = *intro; printf(" - ext_id = %u\n", intro->ext_id); printf(" - reset_id = %u\n", intro->reset_id); printf(" - hdr_size = %u\n", intro->hdr_size); printf(" - record_size = %u\n", intro->record_size); printf(" - record_align = %u\n", intro->record_align); printf(" - flags = %u\n", intro->flags); printf(" - name_size = %u\n", intro->name_size); if (intro->name_size > 0) { const char *name = (const char *)(intro+1); printf(" - name = '%.*s'\n", intro->name_size, name); if (*modseq == 0 && intro->name_size == 6 && memcmp(name, "modseq", 6) == 0) *modseq = 1; } break; } case MAIL_TRANSACTION_EXT_RESET: { const struct mail_transaction_ext_reset *reset = data; printf(" - new_reset_id = %u\n", reset->new_reset_id); printf(" - preserve_data = %u\n", reset->preserve_data); break; } case MAIL_TRANSACTION_EXT_HDR_UPDATE: { const struct mail_transaction_ext_hdr_update *u = data; printf(" - offset = %u, size = %u", u->offset, u->size); if (sizeof(*u) + u->size <= data_size) { printf(": "); print_data(u + 1, u->size); } else { printf(" (too large)"); } printf("\n"); break; } case MAIL_TRANSACTION_EXT_HDR_UPDATE32: { const struct mail_transaction_ext_hdr_update32 *u = data; printf(" - offset = %u, size = %u", u->offset, u->size); if (sizeof(*u) + u->size <= data_size) { printf(": "); print_data(u + 1, u->size); } else { printf(" (too large)"); } printf("\n"); break; } case MAIL_TRANSACTION_EXT_REC_UPDATE: { const struct mail_transaction_ext_rec_update *rec = data, *end; size_t record_size; end = CONST_PTR_OFFSET(data, size); record_size = (sizeof(*rec) + prev_intro.record_size + 3) & ~3; while (rec < end) { printf(" - uid=%u: ", rec->uid); if (prev_intro.record_size <= (char*)end - (char *)(rec+1)) print_data(rec + 1, prev_intro.record_size); else printf("(record_size too large)"); printf("\n"); rec = CONST_PTR_OFFSET(rec, record_size); } break; } case MAIL_TRANSACTION_EXT_ATOMIC_INC: { const struct mail_transaction_ext_atomic_inc *rec = data, *end; end = CONST_PTR_OFFSET(data, size); for (; rec < end; rec++) { printf(" - uid=%u: ", rec->uid); if (rec->diff > 0) printf("+%d\n", rec->diff); else printf("%d\n", rec->diff); } break; } case MAIL_TRANSACTION_KEYWORD_UPDATE: { const struct mail_transaction_keyword_update *u = data; const uint32_t *uid; unsigned int uid_offset; printf(" - modify=%d, name=%.*s, uids=", u->modify_type, u->name_size, (const char *)(u+1)); uid_offset = sizeof(*u) + u->name_size + ((u->name_size % 4) == 0 ? 0 : 4 - (u->name_size%4)); uid = (const uint32_t *)((const char *)u + uid_offset); size -= uid_offset; for (; size > 0; size -= sizeof(*uid)*2, uid += 2) { printf("%u-%u,", uid[0], uid[1]); } printf("\n"); break; } case MAIL_TRANSACTION_KEYWORD_RESET: { const struct mail_transaction_keyword_reset *u = data; printf(" - uids="); for (; size > 0; size -= sizeof(*u), u++) { printf("%u-%u, ", u->uid1, u->uid2); } printf("\n"); break; } case MAIL_TRANSACTION_MODSEQ_UPDATE: { const struct mail_transaction_modseq_update *rec, *end; end = CONST_PTR_OFFSET(data, size); for (rec = data; rec < end; rec++) { printf(" - uid=%u modseq=%llu\n", rec->uid, ((unsigned long long)rec->modseq_high32 << 32) | rec->modseq_low32); } break; } case MAIL_TRANSACTION_INDEX_DELETED: case MAIL_TRANSACTION_INDEX_UNDELETED: break; case MAIL_TRANSACTION_BOUNDARY: { const struct mail_transaction_boundary *rec = data; printf(" - size=%u\n", rec->size); break; } case MAIL_TRANSACTION_ATTRIBUTE_UPDATE: { const char *keys = data; const uint32_t *extra; unsigned int i, extra_pos, extra_count = 0; for (i = 0; i < size && keys[i] != '\0'; ) { if (keys[i] == '+') extra_count++; extra_count++; i += strlen(keys+i) + 1; } if (i % sizeof(uint32_t) != 0) i += sizeof(uint32_t) - i%sizeof(uint32_t); extra = (const void *)(keys+i); if ((size-i) != extra_count*sizeof(uint32_t)) { printf(" - broken entry\n"); break; } extra_pos = 0; for (i = 0; i < size && keys[i] != '\0'; ) { printf(" - %s: %s/%s : timestamp=%s", keys[i] == '+' ? "add" : keys[i] == '-' ? "remove" : "?", keys[i+1] == 'p' ? "private" : keys[i+1] == 's' ? "shared" : "?error?", keys+i+2, unixdate2str(extra[extra_pos++])); if (keys[i] == '+') printf(" value_len=%u", extra[extra_pos++]); printf("\n"); i += strlen(keys+i) + 1; } break; } default: break; } }
static void log_record_print(const struct mail_transaction_header *hdr, const void *data, uint64_t *modseq) { unsigned int size = hdr->size - sizeof(*hdr); switch (hdr->type & MAIL_TRANSACTION_TYPE_MASK) { case MAIL_TRANSACTION_EXPUNGE|MAIL_TRANSACTION_EXPUNGE_PROT: { const struct mail_transaction_expunge *exp = data; printf(" - uids="); for (; size > 0; size -= sizeof(*exp), exp++) { printf("%u-%u,", exp->uid1, exp->uid2); } printf("\n"); break; } case MAIL_TRANSACTION_EXPUNGE_GUID|MAIL_TRANSACTION_EXPUNGE_PROT: { const struct mail_transaction_expunge_guid *exp = data; for (; size > 0; size -= sizeof(*exp), exp++) { printf(" - uid=%u (guid ", exp->uid); print_data(exp->guid_128, sizeof(exp->guid_128)); printf(")\n"); } break; } case MAIL_TRANSACTION_APPEND: { const struct mail_index_record *rec = data; printf(" - uids="); for (; size > 0; size -= sizeof(*rec), rec++) { printf("%u", rec->uid); if (rec->flags != 0) printf(" (flags=%x)", rec->flags); printf(","); } printf("\n"); break; } case MAIL_TRANSACTION_FLAG_UPDATE: { const struct mail_transaction_flag_update *u = data; for (; size > 0; size -= sizeof(*u), u++) { printf(" - uids=%u-%u (flags +%x-%x)\n", u->uid1, u->uid2, u->add_flags, u->remove_flags); } break; } case MAIL_TRANSACTION_HEADER_UPDATE: { const struct mail_transaction_header_update *u = data; log_header_update(u); break; } case MAIL_TRANSACTION_EXT_INTRO: { const struct mail_transaction_ext_intro *intro = data; prev_intro = *intro; printf(" - ext_id = %u\n", intro->ext_id); printf(" - reset_id = %u\n", intro->reset_id); printf(" - hdr_size = %u\n", intro->hdr_size); printf(" - record_size = %u\n", intro->record_size); printf(" - record_align = %u\n", intro->record_align); printf(" - flags = %u\n", intro->flags); printf(" - name_size = %u\n", intro->name_size); if (intro->name_size > 0) { const char *name = (const char *)(intro+1); printf(" - name = '%.*s'\n", intro->name_size, name); if (*modseq == 0 && intro->name_size == 6 && memcmp(name, "modseq", 6) == 0) *modseq = 1; } break; } case MAIL_TRANSACTION_EXT_RESET: { const struct mail_transaction_ext_reset *reset = data; printf(" - new_reset_id = %u\n", reset->new_reset_id); printf(" - preserve_data = %u\n", reset->preserve_data); break; } case MAIL_TRANSACTION_EXT_HDR_UPDATE: { const struct mail_transaction_ext_hdr_update *u = data; printf(" - offset = %u, size = %u: ", u->offset, u->size); print_data(u + 1, u->size); printf("\n"); break; } case MAIL_TRANSACTION_EXT_HDR_UPDATE32: { const struct mail_transaction_ext_hdr_update32 *u = data; printf(" - offset = %u, size = %u: ", u->offset, u->size); print_data(u + 1, u->size); printf("\n"); break; } case MAIL_TRANSACTION_EXT_REC_UPDATE: { const struct mail_transaction_ext_rec_update *rec = data, *end; size_t record_size; end = CONST_PTR_OFFSET(data, size); record_size = (sizeof(*rec) + prev_intro.record_size + 3) & ~3; while (rec < end) { printf(" - uid=%u: ", rec->uid); print_data(rec + 1, prev_intro.record_size); printf("\n"); rec = CONST_PTR_OFFSET(rec, record_size); } break; } case MAIL_TRANSACTION_EXT_ATOMIC_INC: { const struct mail_transaction_ext_atomic_inc *rec = data, *end; end = CONST_PTR_OFFSET(data, size); for (; rec < end; rec++) { printf(" - uid=%u: ", rec->uid); if (rec->diff > 0) printf("+%d\n", rec->diff); else printf("%d\n", rec->diff); } break; } case MAIL_TRANSACTION_KEYWORD_UPDATE: { const struct mail_transaction_keyword_update *u = data; const uint32_t *uid; unsigned int uid_offset; printf(" - modify=%d, name=%.*s, uids=", u->modify_type, u->name_size, (const char *)(u+1)); uid_offset = sizeof(*u) + u->name_size + ((u->name_size % 4) == 0 ? 0 : 4 - (u->name_size%4)); uid = (const uint32_t *)((const char *)u + uid_offset); size -= uid_offset; for (; size > 0; size -= sizeof(*uid)*2, uid += 2) { printf("%u-%u,", uid[0], uid[1]); } printf("\n"); break; } case MAIL_TRANSACTION_KEYWORD_RESET: { const struct mail_transaction_keyword_reset *u = data; printf(" - uids="); for (; size > 0; size -= sizeof(*u), u++) { printf("%u-%u, ", u->uid1, u->uid2); } printf("\n"); break; } case MAIL_TRANSACTION_MODSEQ_UPDATE: { const struct mail_transaction_modseq_update *rec, *end; end = CONST_PTR_OFFSET(data, size); for (rec = data; rec < end; rec++) { printf(" - uid=%u modseq=%llu\n", rec->uid, ((unsigned long long)rec->modseq_high32 << 32) | rec->modseq_low32); } break; } case MAIL_TRANSACTION_INDEX_DELETED: case MAIL_TRANSACTION_INDEX_UNDELETED: break; case MAIL_TRANSACTION_BOUNDARY: { const struct mail_transaction_boundary *rec = data; printf(" - size=%u\n", rec->size); break; } default: break; } }