Exemple #1
0
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;
	}
}